Add pending apps and frontend components

- apps/captain-mobile: Mobile API service
- apps/flow-ui: Flow UI application
- apps/mindlink: Mindlink application
- apps/storage: Storage API and workers
- apps/tzzr-cli: TZZR CLI tool
- deck-frontend/backups: Historical TypeScript versions
- hst-frontend: Standalone HST frontend

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
ARCHITECT
2026-01-16 18:26:59 +00:00
parent 17506aaee2
commit 9b244138b5
177 changed files with 15063 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
import { API_BASE } from '@/config/index.ts';
interface FetchOptions {
method?: 'GET' | 'POST';
body?: Record<string, unknown>;
schema?: string; // PostgREST Accept-Profile header
}
export async function apiClient<T>(
endpoint: string,
options: FetchOptions = {}
): Promise<T> {
const { method = 'GET', body, schema } = options;
const headers: Record<string, string> = {};
if (body) headers['Content-Type'] = 'application/json';
if (schema) headers['Accept-Profile'] = schema;
const config: RequestInit = {
method,
headers: Object.keys(headers).length > 0 ? headers : undefined,
body: body ? JSON.stringify(body) : undefined,
};
const response = await fetch(`${API_BASE}${endpoint}`, config);
if (!response.ok) {
throw new Error(`API Error: ${response.status}`);
}
return response.json();
}
export async function apiClientSafe<T>(
endpoint: string,
options: FetchOptions = {},
fallback: T
): Promise<T> {
try {
return await apiClient<T>(endpoint, options);
} catch {
console.error(`API call failed: ${endpoint}`);
return fallback;
}
}

View File

@@ -0,0 +1,8 @@
import { apiClientSafe } from './client.ts';
import type { GraphEdge, TreeEdge } from '@/types/index.ts';
export const fetchGraphEdges = (): Promise<GraphEdge[]> =>
apiClientSafe<GraphEdge[]>('/graph_hst', {}, []);
export const fetchTreeEdges = (): Promise<TreeEdge[]> =>
apiClientSafe<TreeEdge[]>('/tree_hst', {}, []);

View File

@@ -0,0 +1,5 @@
import { apiClientSafe } from './client.ts';
import type { Group } from '@/types/index.ts';
export const fetchGroups = (): Promise<Group[]> =>
apiClientSafe<Group[]>('/api_groups', {}, []);

View File

@@ -0,0 +1,5 @@
export { apiClient, apiClientSafe } from './client.ts';
export { fetchTags, fetchHstTags, fetchChildren, fetchRelated } from './tags.ts';
export { fetchGroups } from './groups.ts';
export { fetchLibraries, fetchLibraryMembers } from './libraries.ts';
export { fetchGraphEdges, fetchTreeEdges } from './graph.ts';

View File

@@ -0,0 +1,26 @@
import { apiClientSafe } from './client.ts';
import type { Library, BaseType } from '@/types/index.ts';
// Base types that have library tables (public schema taxonomy tables)
const LIBRARY_BASES = new Set(['hst', 'flg', 'itm', 'loc', 'ply']);
export const fetchLibraries = (base: BaseType): Promise<Library[]> => {
// Only public schema taxonomy tables have libraries
if (!LIBRARY_BASES.has(base)) {
return Promise.resolve([]);
}
// Use base-specific view: api_library_list_hst, api_library_list_flg, etc.
return apiClientSafe<Library[]>(`/api_library_list_${base}`, {}, []);
};
export const fetchLibraryMembers = async (mrf: string, base: BaseType): Promise<string[]> => {
if (!LIBRARY_BASES.has(base)) {
return [];
}
const data = await apiClientSafe<Array<{ mrf_tag: string }>>(
`/library_${base}?mrf_library=eq.${mrf}`,
{},
[]
);
return data.map(d => d.mrf_tag);
};

View File

@@ -0,0 +1,65 @@
import { apiClientSafe } from './client.ts';
import type { Tag, ChildTag, RelatedTag, BaseType } from '@/types/index.ts';
// Schema mapping by base type
// - public (default): hst, flg, itm, loc, ply
// - secretaria_clara: atc, mst, bck
// - production_alfred: mth
// - mail_manager: mail (table: clara_registros)
// - context_manager: chat (table: messages)
interface SchemaTableConfig {
schema: string | null;
table: string;
}
const getSchemaAndTable = (base: BaseType): SchemaTableConfig => {
switch (base) {
// secretaria_clara schema
case 'atc':
case 'mst':
case 'bck':
return { schema: 'secretaria_clara', table: base };
// production_alfred schema
case 'mth':
return { schema: 'production_alfred', table: base };
// mail_manager schema
case 'mail':
return { schema: 'mail_manager', table: 'clara_registros' };
// context_manager schema
case 'chat':
return { schema: 'context_manager', table: 'messages' };
// public schema (default) - hst, flg, itm, loc, ply
default:
return { schema: null, table: base };
}
};
export const fetchTags = (base: BaseType): Promise<Tag[]> => {
const { schema, table } = getSchemaAndTable(base);
return apiClientSafe<Tag[]>(
`/${table}?order=ref.asc`,
schema ? { schema } : {},
[]
);
};
// Fetch HST tags for group name resolution (set_hst points to hst tags)
export const fetchHstTags = (): Promise<Tag[]> =>
apiClientSafe<Tag[]>('/hst?select=mrf,ref,alias,name_es,name_en,name_ch', {}, []);
export const fetchChildren = (mrf: string): Promise<ChildTag[]> =>
apiClientSafe<ChildTag[]>('/rpc/api_children', {
method: 'POST',
body: { parent_mrf: mrf }
}, []);
export const fetchRelated = (mrf: string): Promise<RelatedTag[]> =>
apiClientSafe<RelatedTag[]>('/rpc/api_related', {
method: 'POST',
body: { tag_mrf: mrf }
}, []);