@fayz-ai/core 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/access/index.js.map +1 -1
- package/dist/chunk-BEGXYHS4.js +566 -0
- package/dist/chunk-BEGXYHS4.js.map +1 -0
- package/dist/chunk-ED6NBH6U.js +348 -0
- package/dist/chunk-ED6NBH6U.js.map +1 -0
- package/dist/chunk-EWKX4VUM.js +429 -0
- package/dist/chunk-EWKX4VUM.js.map +1 -0
- package/dist/chunk-LARZWDHA.js +319 -0
- package/dist/chunk-LARZWDHA.js.map +1 -0
- package/dist/chunk-OXQGRJZT.js +125 -0
- package/dist/chunk-OXQGRJZT.js.map +1 -0
- package/dist/chunk-RRYFXUQX.js +1247 -0
- package/dist/chunk-RRYFXUQX.js.map +1 -0
- package/dist/{chunk-5RJVUC6J.js → chunk-TDI6F6PT.js} +373 -25
- package/dist/chunk-TDI6F6PT.js.map +1 -0
- package/dist/{chunk-V2MSAUHO.js → chunk-UVKH6RDX.js} +211 -335
- package/dist/chunk-UVKH6RDX.js.map +1 -0
- package/dist/chunk-V53GR4UT.js +289 -0
- package/dist/chunk-V53GR4UT.js.map +1 -0
- package/dist/connector-runtime/index.d.ts +15 -0
- package/dist/connector-runtime/index.d.ts.map +1 -0
- package/dist/connector-runtime/index.js +3 -0
- package/dist/connector-runtime/index.js.map +1 -0
- package/dist/data/archetype.d.ts.map +1 -1
- package/dist/data/backend-env.d.ts +38 -0
- package/dist/data/backend-env.d.ts.map +1 -0
- package/dist/data/bulk.d.ts +24 -0
- package/dist/data/bulk.d.ts.map +1 -1
- package/dist/data/cached.d.ts.map +1 -1
- package/dist/data/custom-fields.d.ts +5 -0
- package/dist/data/custom-fields.d.ts.map +1 -0
- package/dist/data/index.d.ts +2 -1
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +3 -1
- package/dist/data/mock.d.ts.map +1 -1
- package/dist/data/platform-api.d.ts.map +1 -1
- package/dist/data/resolve.d.ts.map +1 -1
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/data/types.d.ts +8 -0
- package/dist/data/types.d.ts.map +1 -1
- package/dist/entity/events.d.ts +14 -0
- package/dist/entity/events.d.ts.map +1 -0
- package/dist/events/envelope.d.ts +31 -0
- package/dist/events/envelope.d.ts.map +1 -0
- package/dist/events/index.d.ts +4 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/log.d.ts +44 -0
- package/dist/events/log.d.ts.map +1 -0
- package/dist/events/types.d.ts +40 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/fields/store.d.ts +45 -0
- package/dist/fields/store.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +10 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/shell-translations.en.d.ts.map +1 -1
- package/dist/i18n/shell-translations.pt-br.d.ts.map +1 -1
- package/dist/index.d.ts +45 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +543 -56
- package/dist/index.js.map +1 -1
- package/dist/integrations/events.d.ts +7 -0
- package/dist/integrations/events.d.ts.map +1 -0
- package/dist/integrations/index.d.ts +533 -29
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +3 -1
- package/dist/integrations/permissions.d.ts +132 -0
- package/dist/integrations/permissions.d.ts.map +1 -0
- package/dist/integrations/request.d.ts +170 -0
- package/dist/integrations/request.d.ts.map +1 -0
- package/dist/integrations/runtime-token.d.ts +33 -0
- package/dist/integrations/runtime-token.d.ts.map +1 -0
- package/dist/integrations/runtime.d.ts +398 -0
- package/dist/integrations/runtime.d.ts.map +1 -0
- package/dist/integrations/settings.d.ts +102 -0
- package/dist/integrations/settings.d.ts.map +1 -0
- package/dist/integrations/store.d.ts +145 -0
- package/dist/integrations/store.d.ts.map +1 -0
- package/dist/{address/index.d.ts → lib/address.d.ts} +1 -1
- package/dist/{address/index.d.ts.map → lib/address.d.ts.map} +1 -1
- package/dist/{phone/index.d.ts → lib/phone.d.ts} +1 -1
- package/dist/lib/phone.d.ts.map +1 -0
- package/dist/{seo/index.d.ts → lib/seo.d.ts} +18 -1
- package/dist/lib/seo.d.ts.map +1 -0
- package/dist/{tenant/index.d.ts → lib/tenant.d.ts} +1 -1
- package/dist/lib/tenant.d.ts.map +1 -0
- package/dist/manifest/index.d.ts +1 -1
- package/dist/manifest/index.d.ts.map +1 -1
- package/dist/messaging/index.d.ts +3 -0
- package/dist/messaging/index.d.ts.map +1 -0
- package/dist/messaging/registry.d.ts +35 -0
- package/dist/messaging/registry.d.ts.map +1 -0
- package/dist/messaging/types.d.ts +67 -0
- package/dist/messaging/types.d.ts.map +1 -0
- package/dist/plugin/index.js +3 -1
- package/dist/plugin/runtime.d.ts +17 -0
- package/dist/plugin/runtime.d.ts.map +1 -1
- package/dist/registry/block-catalog.d.ts +78 -0
- package/dist/registry/block-catalog.d.ts.map +1 -0
- package/dist/registry/block-constraints.d.ts +64 -0
- package/dist/registry/block-constraints.d.ts.map +1 -0
- package/dist/registry/block-schema.d.ts +69 -0
- package/dist/registry/block-schema.d.ts.map +1 -0
- package/dist/registry/blocks.d.ts +84 -0
- package/dist/registry/blocks.d.ts.map +1 -0
- package/dist/registry/entities.d.ts +179 -0
- package/dist/registry/entities.d.ts.map +1 -0
- package/dist/registry/extension-points.d.ts +117 -0
- package/dist/registry/extension-points.d.ts.map +1 -0
- package/dist/registry/handles.d.ts +41 -0
- package/dist/registry/handles.d.ts.map +1 -0
- package/dist/registry/index.d.ts +41 -41
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/loaders.d.ts +55 -0
- package/dist/registry/loaders.d.ts.map +1 -0
- package/dist/registry/registry-class.d.ts +157 -0
- package/dist/registry/registry-class.d.ts.map +1 -0
- package/dist/registry/schema-check.d.ts +14 -0
- package/dist/registry/schema-check.d.ts.map +1 -0
- package/dist/router/index.d.ts +78 -1
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +1 -1
- package/dist/{shell-translations.pt-br-2GWRQRRP.js → shell-translations.pt-br-BM5ZFSKJ.js} +72 -3
- package/dist/shell-translations.pt-br-BM5ZFSKJ.js.map +1 -0
- package/dist/telemetry/errors.d.ts +87 -0
- package/dist/telemetry/errors.d.ts.map +1 -0
- package/dist/testing/index.js +4 -1
- package/dist/{testing/index.d.ts → testing.d.ts} +5 -3
- package/dist/testing.d.ts.map +1 -0
- package/dist/types/analytics.d.ts +213 -0
- package/dist/types/analytics.d.ts.map +1 -0
- package/dist/types/crud.d.ts +37 -3
- package/dist/types/crud.d.ts.map +1 -1
- package/dist/types/plugins.d.ts +138 -1
- package/dist/types/plugins.d.ts.map +1 -1
- package/package.json +9 -17
- package/dist/blocks/index.d.ts +0 -25
- package/dist/blocks/index.d.ts.map +0 -1
- package/dist/chunk-5RJVUC6J.js.map +0 -1
- package/dist/chunk-L4TLMYGC.js +0 -42
- package/dist/chunk-L4TLMYGC.js.map +0 -1
- package/dist/chunk-V2MSAUHO.js.map +0 -1
- package/dist/chunk-X5THHG6T.js +0 -77
- package/dist/chunk-X5THHG6T.js.map +0 -1
- package/dist/chunk-Y2C2FBQP.js +0 -35
- package/dist/chunk-Y2C2FBQP.js.map +0 -1
- package/dist/chunk-YH25Y4FW.js +0 -311
- package/dist/chunk-YH25Y4FW.js.map +0 -1
- package/dist/phone/index.d.ts.map +0 -1
- package/dist/seo/index.d.ts.map +0 -1
- package/dist/shell-translations.pt-br-2GWRQRRP.js.map +0 -1
- package/dist/tenant/index.d.ts.map +0 -1
- package/dist/testing/index.d.ts.map +0 -1
- package/src/access/denial.ts +0 -33
- package/src/access/engine.test.ts +0 -48
- package/src/access/engine.ts +0 -136
- package/src/access/index.ts +0 -14
- package/src/access/limits.ts +0 -18
- package/src/address/index.ts +0 -188
- package/src/app/render.tsx +0 -69
- package/src/blocks/index.tsx +0 -68
- package/src/data/archetype.ts +0 -255
- package/src/data/bulk.ts +0 -35
- package/src/data/cached.ts +0 -55
- package/src/data/count.test.ts +0 -152
- package/src/data/count.ts +0 -131
- package/src/data/filters.test.ts +0 -70
- package/src/data/filters.ts +0 -90
- package/src/data/index.ts +0 -11
- package/src/data/mock.ts +0 -90
- package/src/data/platform-api.ts +0 -209
- package/src/data/refresh.ts +0 -115
- package/src/data/resolve.ts +0 -126
- package/src/data/supabase.ts +0 -230
- package/src/data/types.ts +0 -50
- package/src/entity/index.ts +0 -2
- package/src/entity/registry.ts +0 -49
- package/src/events/index.tsx +0 -82
- package/src/i18n/index.ts +0 -476
- package/src/i18n/shell-translations.en.ts +0 -875
- package/src/i18n/shell-translations.pt-br.ts +0 -873
- package/src/index.ts +0 -217
- package/src/integrations/index.ts +0 -237
- package/src/lib/cache.ts +0 -118
- package/src/lib/csv.ts +0 -54
- package/src/lib/format.ts +0 -58
- package/src/manifest/app-manifest.schema.json +0 -676
- package/src/manifest/index.ts +0 -518
- package/src/manifest/serialize.ts +0 -52
- package/src/phone/index.ts +0 -85
- package/src/plugin/createSafeDataProvider.ts +0 -30
- package/src/plugin/index.ts +0 -1
- package/src/plugin/runtime.ts +0 -331
- package/src/registry/index.ts +0 -163
- package/src/router/history.ts +0 -86
- package/src/router/index.ts +0 -29
- package/src/runtime/index.ts +0 -15
- package/src/runtime/oauth.ts +0 -219
- package/src/search/engine.ts +0 -559
- package/src/search/index.ts +0 -25
- package/src/search/text.ts +0 -206
- package/src/search/types.ts +0 -75
- package/src/seo/index.ts +0 -128
- package/src/tenant/index.ts +0 -38
- package/src/testing/index.ts +0 -116
- package/src/types/auth.ts +0 -41
- package/src/types/billing.ts +0 -39
- package/src/types/crud.ts +0 -184
- package/src/types/entities.ts +0 -142
- package/src/types/entitlements.ts +0 -45
- package/src/types/i18n.ts +0 -7
- package/src/types/index.ts +0 -11
- package/src/types/org.ts +0 -137
- package/src/types/payment.ts +0 -44
- package/src/types/permissions.ts +0 -32
- package/src/types/plugins.ts +0 -480
- package/src/types/theme.ts +0 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/data/count.ts","../src/data/platform-api.ts","../src/data/mock.ts","../src/data/archetype.ts","../src/data/cached.ts","../src/fields/store.ts","../src/data/custom-fields.ts","../src/data/resolve.ts","../src/data/bulk.ts"],"names":["options","cache","cacheKey","removed"],"mappings":"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","file":"chunk-UVKH6RDX.js","sourcesContent":["import { getSupabaseClientOptional } from './supabase'\nimport { getActiveTenantId } from '../lib/tenant'\n\n/**\n * Tenant-scoped row counter — the single cheap `count(*)` helper the access\n * engine uses to resolve quantity limits. Uses Supabase's `head:true` count so\n * no rows are transferred. Results are cached briefly per tenant+table+filter to\n * survive the burst of reads a page does (nav badge + gate + list), and can be\n * force-invalidated by creates via {@link invalidateCount}.\n *\n * MOCK MODE NEVER BLOCKS: with no global Supabase client the count is `0`, so\n * limits always read as \"well under cap\" — offline/demo apps stay fully usable.\n */\n\nexport interface CountByTenantOptions {\n /** Optional `kind` column filter for multi-kind tables. */\n kind?: string\n /** `'month'` counts rows created since the 1st of the current month; `'total'` (default) counts all. */\n period?: 'month' | 'total'\n /** Tenant override; defaults to the active tenant (getActiveTenantId). */\n tenantId?: string\n /** Skip the short-lived cache and hit the DB (used by fresh guard checks). */\n fresh?: boolean\n}\n\nconst TTL_MS = 15_000\n\ninterface CacheEntry {\n value: number\n expires: number\n}\n\nconst cache = new Map<string, CacheEntry>()\n\nfunction cacheKey(table: string, tenantId: string, kind: string | undefined, period: string): string {\n return `${tenantId}::${table}::${kind ?? ''}::${period}`\n}\n\nfunction startOfMonthISO(): string {\n const now = new Date()\n return new Date(now.getFullYear(), now.getMonth(), 1).toISOString()\n}\n\n/**\n * How long a usage count may take before we give up on it. Failing OPEN on an\n * error was always the policy (see below); a request that never settles is the\n * same failure with worse symptoms — a caller awaiting this (the create guards)\n * hangs forever, which reads to the user as a dead button. Observed on a cold\n * boot, where the query can be issued before the auth session is ready.\n */\nconst COUNT_TIMEOUT_MS = 5_000\n\n/**\n * Count rows in `table` for the given (or active) tenant.\n * Returns 0 when no Supabase client is registered (mock mode).\n */\nexport async function countByTenant(table: string, options: CountByTenantOptions = {}): Promise<number> {\n const tenantId = options.tenantId ?? getActiveTenantId()\n if (!tenantId) return 0\n\n const period = options.period ?? 'total'\n const key = cacheKey(table, tenantId, options.kind, period)\n\n if (!options.fresh) {\n const hit = cache.get(key)\n if (hit && hit.expires > Date.now()) return hit.value\n }\n\n const client = getSupabaseClientOptional() as {\n from: (t: string) => {\n select: (columns: string, opts: { count: 'exact'; head: true }) => {\n eq: (col: string, val: unknown) => unknown\n }\n }\n } | null\n\n // No client → mock/offline mode: never block.\n if (!client) return 0\n\n let query = client.from(table).select('*', { count: 'exact', head: true }).eq('tenant_id', tenantId) as {\n eq: (col: string, val: unknown) => unknown\n gte: (col: string, val: unknown) => unknown\n }\n\n if (options.kind) {\n query = query.eq('kind', options.kind) as typeof query\n }\n if (period === 'month') {\n query = query.gte('created_at', startOfMonthISO()) as typeof query\n }\n\n // On error OR timeout, fail OPEN (return 0) — a counting failure must never\n // wall a tenant out of their own product, and must never hang the UI awaiting\n // it. Enforcement's source of truth is the DB anyway.\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<{ count: null; error: unknown; timedOut: true }>((resolve) => {\n timer = setTimeout(() => resolve({ count: null, error: 'timeout', timedOut: true }), COUNT_TIMEOUT_MS)\n })\n const settled = await Promise.race([\n query as unknown as Promise<{ count: number | null; error: unknown }>,\n timeout,\n ])\n if (timer) clearTimeout(timer)\n\n const { count, error } = settled\n const value = error ? 0 : count ?? 0\n\n // A timed-out count is not a fact about the tenant — caching it would make one\n // slow request suppress the guard for the whole TTL.\n if (!(settled as { timedOut?: true }).timedOut) {\n cache.set(key, { value, expires: Date.now() + TTL_MS })\n }\n return value\n}\n\n/**\n * Drop cached counts. Called by create handlers (via invalidateLimit) so the\n * next read reflects the row they just added.\n *\n * @param tenantOrKey Substring matched against cache keys (a tenant id, a table\n * name, or any fragment). Omit to clear the entire cache.\n */\nexport function invalidateCount(tenantOrKey?: string): void {\n if (!tenantOrKey) {\n cache.clear()\n return\n }\n for (const key of cache.keys()) {\n if (key.includes(tenantOrKey)) cache.delete(key)\n }\n}\n","import type { CrudQuery, CrudResult, DataProvider } from './types'\nimport { parseRangeFilter } from './filters'\n\ntype FayzApiFilterOperator = 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'like' | 'ilike' | 'is_null' | 'is_not_null'\n\ninterface FayzApiTableFilter {\n column: string\n operator: FayzApiFilterOperator\n value?: unknown\n}\n\nexport interface FayzApiProviderConfig {\n baseUrl?: string\n projectId?: string\n tenantId?: string | (() => string | undefined)\n tenantIdColumn?: string | false\n entityKey?: string\n table?: string\n schema?: string\n idColumn?: string\n searchColumns?: string[]\n runtimeToken?: string | (() => string | undefined | Promise<string | undefined>)\n headers?: () => HeadersInit | Promise<HeadersInit>\n fetcher?: typeof fetch\n}\n\nfunction resolveTenantId(config?: FayzApiProviderConfig): string | undefined {\n const tenantId = config?.tenantId\n return typeof tenantId === 'function' ? tenantId() : tenantId\n}\n\nasync function resolveRuntimeToken(config?: FayzApiProviderConfig): Promise<string | undefined> {\n const runtimeToken = config?.runtimeToken\n return typeof runtimeToken === 'function' ? runtimeToken() : runtimeToken\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, '')\n}\n\nfunction appendQuery(\n url: URL,\n query: CrudQuery,\n tenantId?: string,\n tenantIdColumn = 'tenant_id',\n searchColumns: string[] = [],\n): void {\n const filters = normalizeFilters(query.filters)\n if (query.search && searchColumns[0]) {\n filters.push({ column: searchColumns[0], operator: 'ilike', value: `%${query.search}%` })\n }\n if (query.sortBy) url.searchParams.set('sortColumn', query.sortBy)\n if (query.sortDir) url.searchParams.set('sortDirection', query.sortDir)\n if (query.page != null) url.searchParams.set('page', String(query.page))\n if (query.pageSize != null) url.searchParams.set('limit', String(query.pageSize))\n if (tenantId) filters.push({ column: tenantIdColumn, operator: 'eq', value: tenantId })\n if (filters.length > 0) url.searchParams.set('filters', JSON.stringify(filters))\n}\n\nasync function parseResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n const text = await response.text().catch(() => '')\n throw new Error(`[@fayz-ai/core] Fayz API request failed (${response.status}): ${text || response.statusText}`)\n }\n return response.json() as Promise<T>\n}\n\nfunction isFilterOperator(value: unknown): value is FayzApiFilterOperator {\n return typeof value === 'string' && [\n 'eq',\n 'neq',\n 'gt',\n 'lt',\n 'gte',\n 'lte',\n 'like',\n 'ilike',\n 'is_null',\n 'is_not_null',\n ].includes(value)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction normalizeFilters(filters?: Record<string, unknown>): FayzApiTableFilter[] {\n if (!filters) return []\n return Object.entries(filters).flatMap(([column, raw]): FayzApiTableFilter[] => {\n if (isRecord(raw) && isFilterOperator(raw.operator)) {\n return [{ column, operator: raw.operator, value: raw.value }]\n }\n // A range is TWO bounds on one column — sending it as a single `eq` filter\n // compared the column against an object and matched nothing.\n const range = parseRangeFilter(raw)\n if (range) {\n return (['gte', 'gt', 'lte', 'lt'] as const)\n .filter((op) => range[op] !== undefined)\n .map((op) => ({ column, operator: op, value: range[op] }))\n }\n return [{ column, operator: 'eq', value: raw }]\n })\n}\n\nexport function createFayzApiProvider<T extends { id: string }>(\n entityOrTable: string,\n config: FayzApiProviderConfig = {},\n): DataProvider<T> {\n const fetcher = config.fetcher ?? fetch\n const baseUrl = trimTrailingSlash(config.baseUrl ?? '')\n const projectId = config.projectId\n const table = config.table ?? entityOrTable\n const idColumn = config.idColumn ?? 'id'\n\n async function headers(runtimeToken?: string): Promise<HeadersInit> {\n return {\n 'Content-Type': 'application/json',\n ...(config.headers ? await config.headers() : {}),\n ...(runtimeToken ? { Authorization: `Bearer ${runtimeToken}` } : {}),\n }\n }\n\n function tableRowsUrl(runtime = false): URL {\n const prefix = baseUrl || (typeof window !== 'undefined' ? window.location.origin : 'http://localhost')\n const encodedProjectId = encodeURIComponent(projectId ?? 'current')\n const encodedTable = encodeURIComponent(table)\n const route = runtime\n ? `/api/v1/runtime/projects/${encodedProjectId}/database/tables/${encodedTable}/rows`\n : `/api/projects/${encodedProjectId}/database/tables/${encodedTable}/rows`\n const url = new URL(route, prefix)\n if (config.schema) url.searchParams.set('schema', config.schema)\n return url\n }\n\n function withTenant(data: Record<string, unknown>, runtime = false): Record<string, unknown> {\n if (runtime) return data\n const tenantId = resolveTenantId(config)\n if (!tenantId || config.tenantIdColumn === false) return data\n return { ...data, [config.tenantIdColumn ?? 'tenant_id']: tenantId }\n }\n\n function primaryKeys(id: string): Record<string, unknown> {\n return { [idColumn]: id }\n }\n\n async function listRows(query: CrudQuery): Promise<CrudResult<T>> {\n const runtimeToken = await resolveRuntimeToken(config)\n const runtime = Boolean(runtimeToken)\n const url = tableRowsUrl(runtime)\n appendQuery(\n url,\n query,\n runtime || config.tenantIdColumn === false ? undefined : resolveTenantId(config),\n config.tenantIdColumn || undefined,\n config.searchColumns,\n )\n const result = await parseResponse<{ rows: T[]; total: number }>(await fetcher(url, { headers: await headers(runtimeToken) }))\n return { data: result.rows, total: result.total }\n }\n\n async function assertTenantScopedRowExists(id: string, runtime = false): Promise<void> {\n if (runtime) return\n const tenantId = config.tenantIdColumn === false ? undefined : resolveTenantId(config)\n if (!tenantId) return\n\n const result = await listRows({ filters: { [idColumn]: id }, page: 1, pageSize: 1 })\n if (result.data.length === 0) {\n throw new Error(`[@fayz-ai/core] Row \"${id}\" was not found for the active tenant.`)\n }\n }\n\n return {\n async list(query: CrudQuery): Promise<CrudResult<T>> {\n return listRows(query)\n },\n\n async create(data) {\n const runtimeToken = await resolveRuntimeToken(config)\n const runtime = Boolean(runtimeToken)\n return parseResponse<T>(await fetcher(tableRowsUrl(runtime), {\n method: 'POST',\n headers: await headers(runtimeToken),\n body: JSON.stringify(withTenant(data as Record<string, unknown>, runtime)),\n }))\n },\n\n async update(id, data) {\n const runtimeToken = await resolveRuntimeToken(config)\n const runtime = Boolean(runtimeToken)\n await assertTenantScopedRowExists(id, runtime)\n return parseResponse<T>(await fetcher(tableRowsUrl(runtime), {\n method: 'PATCH',\n headers: await headers(runtimeToken),\n body: JSON.stringify({ primaryKeys: primaryKeys(id), data }),\n }))\n },\n\n async remove(id) {\n const runtimeToken = await resolveRuntimeToken(config)\n const runtime = Boolean(runtimeToken)\n await assertTenantScopedRowExists(id, runtime)\n await parseResponse<{ deletedCount: number }>(await fetcher(tableRowsUrl(runtime), {\n method: 'DELETE',\n headers: await headers(runtimeToken),\n body: JSON.stringify({ rows: [primaryKeys(id)] }),\n }))\n },\n\n async removeMany(ids) {\n if (!ids.length) return\n const runtimeToken = await resolveRuntimeToken(config)\n const runtime = Boolean(runtimeToken)\n // The tenant guard stays per id — it is the only thing stopping a delete\n // reaching another tenant's row when there is no runtime token. It costs a\n // read each; the DELETE itself is still one request for the whole batch.\n for (const id of ids) await assertTenantScopedRowExists(id, runtime)\n await parseResponse<{ deletedCount: number }>(await fetcher(tableRowsUrl(runtime), {\n method: 'DELETE',\n headers: await headers(runtimeToken),\n body: JSON.stringify({ rows: ids.map((id) => primaryKeys(id)) }),\n }))\n },\n }\n}\n","import type { DataProvider, CrudQuery, CrudResult } from './types'\nimport type { EntityDef } from '../types/crud'\nimport { matchesRange, parseRangeFilter } from './filters'\n\nexport function createMockProvider<T extends { id: string; [key: string]: unknown }>(\n entityDefOrSearchKeys: EntityDef<T> | string[],\n initialData: T[] = [],\n): DataProvider<T> {\n let items = [...initialData]\n\n const searchableKeys = Array.isArray(entityDefOrSearchKeys)\n ? entityDefOrSearchKeys\n : entityDefOrSearchKeys.fields.filter((f) => f.searchable).map((f) => f.key)\n\n const defaultSort = Array.isArray(entityDefOrSearchKeys) ? undefined : entityDefOrSearchKeys.defaultSort\n const defaultSortDir = Array.isArray(entityDefOrSearchKeys) ? 'asc' : (entityDefOrSearchKeys.defaultSortDir ?? 'asc')\n\n return {\n async list(query: CrudQuery): Promise<CrudResult<T>> {\n let filtered = [...items]\n\n if (query.search && searchableKeys.length > 0) {\n const term = query.search.toLowerCase()\n filtered = filtered.filter((item) =>\n searchableKeys.some((key) => {\n const val = item[key]\n return typeof val === 'string' && val.toLowerCase().includes(term)\n }),\n )\n }\n\n // Faceted / dynamic filters — same grammar the SQL providers speak, so a\n // date window behaves identically on mock data instead of silently\n // matching nothing (a range object is never `===` anything).\n if (query.filters) {\n for (const [key, val] of Object.entries(query.filters)) {\n if (val == null || val === '') continue\n const range = parseRangeFilter(val)\n filtered = range\n ? filtered.filter((item) => matchesRange(item[key], range))\n : filtered.filter((item) => item[key] === val)\n }\n }\n\n const sortBy = query.sortBy ?? defaultSort\n const sortDir = query.sortDir ?? defaultSortDir\n if (sortBy) {\n filtered.sort((a, b) => {\n const av = a[sortBy] ?? ''\n const bv = b[sortBy] ?? ''\n const cmp = typeof av === 'number' && typeof bv === 'number'\n ? av - bv\n : String(av).localeCompare(String(bv))\n return sortDir === 'desc' ? -cmp : cmp\n })\n }\n\n const total = filtered.length\n const page = query.page ?? 1\n const pageSize = query.pageSize ?? 50\n const start = (page - 1) * pageSize\n const data = filtered.slice(start, start + pageSize)\n return { data, total }\n },\n\n async create(data) {\n const now = new Date().toISOString()\n const item = {\n ...data,\n id: crypto.randomUUID(),\n tenantId: 'mock-tenant',\n createdAt: now,\n updatedAt: now,\n } as unknown as T\n items.unshift(item)\n return item\n },\n\n async update(id, data) {\n const idx = items.findIndex((i) => i.id === id)\n if (idx === -1) throw new Error(`[@fayz-ai/core] Mock provider: item not found: ${id}`)\n items[idx] = { ...items[idx], ...data, updatedAt: new Date().toISOString() }\n return items[idx]!\n },\n\n async remove(id) {\n items = items.filter((i) => i.id !== id)\n },\n\n async removeMany(ids) {\n const drop = new Set(ids)\n items = items.filter((i) => !drop.has(i.id))\n },\n }\n}\n","import type { DataProvider, CrudQuery, CrudResult } from './types'\nimport { getSupabaseClientOptional } from './supabase'\nimport { applyRangeToQuery, isFilterObject, parseRangeFilter } from './filters'\nimport type { EntityArchetype } from '../types/entities'\n\n// Archetypes that have a `kind` discriminator column\nconst HAS_KIND = new Set<EntityArchetype>(['person', 'category', 'order', 'transaction', 'schedule', 'location'])\n\nconst ARCHETYPE_CONFIG: Record<EntityArchetype, { table: string; fkColumn: string }> = {\n person: { table: 'people', fkColumn: 'person_id' },\n category: { table: 'categories', fkColumn: 'category_id' },\n product: { table: 'products', fkColumn: 'product_id' },\n service: { table: 'services', fkColumn: 'service_id' },\n location: { table: 'locations', fkColumn: 'location_id' },\n order: { table: 'orders', fkColumn: 'order_id' },\n transaction: { table: 'transactions', fkColumn: 'transaction_id' },\n\n schedule: { table: 'schedules', fkColumn: 'schedule_id' },\n}\n\n// `custom_fields` is on EVERY archetype (migration 034) and must be listed on\n// every one of them here. splitFields does not drop an unknown key — it routes\n// it to the extension table, so a missing entry does not degrade, it inserts\n// into a column `clients` does not have and fails the write at runtime.\nconst CUSTOM_FIELDS_COLUMN = 'custom_fields'\n\n/** `filters: { 'custom.tipoDePele': 'oleosa' }` — see the filter loop below. */\nconst CUSTOM_FIELD_FILTER_PREFIX = 'custom.'\n\nconst ARCHETYPE_COLUMNS: Record<EntityArchetype, Set<string>> = {\n person: new Set(['name', 'email', 'phone', 'document_number', 'avatar_url', 'date_of_birth', 'address', 'city', 'state', 'country', 'postal_code', 'tags', 'is_active', 'notes', 'metadata', CUSTOM_FIELDS_COLUMN]),\n category: new Set(['name', 'slug', 'parent_id', 'icon', 'color', 'sort_order', 'is_active', 'metadata', CUSTOM_FIELDS_COLUMN]),\n product: new Set(['name', 'description', 'sku', 'price', 'cost', 'currency', 'unit', 'image_url', 'stock', 'min_stock', 'status', 'is_active', 'tags', 'metadata', 'category_id', CUSTOM_FIELDS_COLUMN]),\n service: new Set(['name', 'description', 'price', 'cost', 'currency', 'duration_minutes', 'image_url', 'status', 'is_active', 'tags', 'metadata', 'category_id', CUSTOM_FIELDS_COLUMN]),\n location: new Set(['name', 'email', 'phone', 'address', 'city', 'state', 'country', 'postal_code', 'is_headquarters', 'is_active', 'tags', 'notes', 'metadata', CUSTOM_FIELDS_COLUMN]),\n order: new Set(['reference_number', 'status', 'party_id', 'assignee_id', 'location_id', 'subtotal', 'discount', 'tax', 'total', 'currency', 'due_at', 'completed_at', 'notes', 'tags', 'metadata', CUSTOM_FIELDS_COLUMN]),\n transaction: new Set(['order_id', 'party_id', 'amount', 'currency', 'payment_method', 'reference', 'status', 'transacted_at', 'notes', 'metadata', CUSTOM_FIELDS_COLUMN]),\n\n schedule: new Set(['assignee_id', 'location_id', 'day_of_week', 'specific_date', 'starts_at', 'ends_at', 'is_active', 'metadata', CUSTOM_FIELDS_COLUMN]),\n}\n\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (c) => '_' + c.toLowerCase())\n}\n\nfunction snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase())\n}\n\nfunction mapRow<T>(row: Record<string, unknown>): T {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(row)) {\n result[snakeToCamel(key)] = value\n }\n return result as T\n}\n\nexport interface ArchetypeProviderConfig {\n archetype: EntityArchetype\n archetypeKind: string\n projectTable: string\n tenantId: () => string | undefined\n searchColumns?: string[]\n}\n\nexport function createArchetypeProvider<T extends { id: string }>(\n config: ArchetypeProviderConfig,\n): DataProvider<T> {\n const ac = ARCHETYPE_CONFIG[config.archetype]\n const archetypeColumns = ARCHETYPE_COLUMNS[config.archetype]\n const { fkColumn } = ac\n\n function getClient() {\n const supabase = getSupabaseClientOptional() as any\n if (!supabase) throw new Error('Supabase client not available')\n return supabase\n }\n\n // Core v1 lives in PUBLIC — the archetype base tables and the public extension\n // tables share one client/schema. `coreClient()` is kept as a thin alias so the\n // core/extension split below still reads clearly at each call site.\n function coreClient() {\n return getClient()\n }\n\n function splitFields(data: Record<string, unknown>): { archetypeData: Record<string, unknown>; projectData: Record<string, unknown> } {\n const archetypeData: Record<string, unknown> = {}\n const projectData: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(data)) {\n // `createdBy` entra na lista por dois motivos: quem o escreve é o gatilho\n // do banco (auth.uid()), e 'created_by' não está em ARCHETYPE_COLUMNS —\n // então, solto, ele cairia em `projectData` e o insert quebraria numa\n // coluna que a tabela de extensão não tem.\n if (['id', 'createdAt', 'updatedAt', 'createdBy', 'tenantId', fkColumn].includes(key)) continue\n const snakeKey = camelToSnake(key)\n if (archetypeColumns.has(snakeKey)) {\n archetypeData[snakeKey] = value\n } else {\n projectData[snakeKey] = value\n }\n }\n return { archetypeData, projectData }\n }\n\n // View name convention: v_{shortName} — maps project table to its view\n const VIEW_MAP: Record<string, string> = {\n clients: 'v_clients',\n staff_members: 'v_staff',\n }\n const viewName = VIEW_MAP[config.projectTable] ?? `v_${config.projectTable}`\n\n // Pure-archetype entity: the project table IS the archetype base (e.g. a\n // customers list configured with `table: 'people'`, no separate public\n // extension table). Read/write public.<base> directly — there is no public\n // extension row and no v_ view to join. Extension-table entities (clients,\n // staff_members, …) are unaffected.\n const isPure = config.projectTable === ac.table\n\n return {\n async list(query: CrudQuery): Promise<CrudResult<T>> {\n const tenantId = config.tenantId()\n if (!tenantId) return { data: [], total: 0 }\n\n // Pure archetype → read public.<base> directly (filtered by kind);\n // otherwise the v_ view (JOINs public extension with the public archetype).\n // 'none' skips PostgREST's count aggregate entirely — see CrudQuery.countMode.\n const countOpts = query.countMode === 'none' ? undefined : { count: 'exact' as const }\n let q = isPure\n ? coreClient().from(ac.table).select('*', countOpts).eq('tenant_id', tenantId)\n : getClient().from(viewName).select('*', countOpts).eq('tenant_id', tenantId)\n\n if (isPure && HAS_KIND.has(config.archetype)) {\n q = q.eq('kind', config.archetypeKind)\n }\n\n // Faceted filters — equality, or real SQL bounds for a range object.\n // Silently dropping them made every caller post-filter one page of rows,\n // which reads as \"no records match\" whenever the match sits past it.\n if (query.filters) {\n for (const [key, val] of Object.entries(query.filters)) {\n if (val == null || val === '') continue\n // `custom.tipoDePele` is a key inside the jsonb column, not a column.\n // It has to bypass camelToSnake entirely: the merchant chose that key\n // and Postgres stores it verbatim, so snake-casing it looks up a key\n // that was never written. PostgREST spells the operator this way.\n const col = key.startsWith(CUSTOM_FIELD_FILTER_PREFIX)\n ? `${CUSTOM_FIELDS_COLUMN}->>${key.slice(CUSTOM_FIELD_FILTER_PREFIX.length)}`\n : camelToSnake(key)\n const range = parseRangeFilter(val)\n if (range) {\n q = applyRangeToQuery(q, col, range)\n continue\n }\n if (isFilterObject(val)) {\n throw new Error(\n `[@fayz-ai/core] Filter \"${key}\" is an object with no recognised bound. ` +\n 'Use {from,to} / {gte,lte,gt,lt} for ranges, or a plain value for equality.',\n )\n }\n q = q.eq(col, val)\n }\n }\n\n // Search\n if (query.search && config.searchColumns && config.searchColumns.length > 0) {\n const term = `%${query.search}%`\n const orClauses = config.searchColumns\n .map((col) => camelToSnake(col))\n .map((col) => `${col}.ilike.${term}`)\n if (orClauses.length > 0) {\n q = q.or(orClauses.join(','))\n }\n }\n\n // Sort\n if (query.sortBy) {\n q = q.order(camelToSnake(query.sortBy), { ascending: query.sortDir !== 'desc' })\n } else {\n q = q.order('created_at', { ascending: false })\n }\n\n // Pagination\n const page = query.page ?? 1\n const pageSize = query.pageSize ?? 50\n const from = (page - 1) * pageSize\n q = q.range(from, from + pageSize - 1)\n\n const { data, error, count } = await q\n if (error) throw error\n\n const rows = (data ?? []).map((row: Record<string, unknown>) => mapRow<T>(row))\n return { data: rows, total: count ?? 0 }\n },\n\n async create(data) {\n const tenantId = config.tenantId()\n if (!tenantId) throw new Error('No tenant selected')\n\n const { archetypeData, projectData } = splitFields(data as Record<string, unknown>)\n\n // 1. Insert into archetype table\n archetypeData.tenant_id = tenantId\n if (HAS_KIND.has(config.archetype)) {\n archetypeData.kind = config.archetypeKind\n }\n\n const { data: archetypeRow, error: archetypeError } = await coreClient()\n .from(ac.table)\n .insert(archetypeData)\n .select()\n .single()\n\n if (archetypeError) throw archetypeError\n const archetypeId = (archetypeRow as any).id\n\n // 2. Insert into project table with archetype FK as PK.\n // Pure-archetype entities have no extension table — skip this step.\n if (!isPure) {\n projectData[fkColumn] = archetypeId\n projectData.tenant_id = tenantId\n\n const { error: projectError } = await getClient()\n .from(config.projectTable)\n .insert(projectData)\n\n if (projectError) {\n await coreClient().from(ac.table).delete().eq('id', archetypeId)\n throw projectError\n }\n }\n\n return { id: archetypeId, ...archetypeRow, ...(isPure ? {} : projectData) } as unknown as T\n },\n\n async update(id, data) {\n const { archetypeData, projectData } = splitFields(data as Record<string, unknown>)\n\n if (Object.keys(archetypeData).length > 0) {\n const { error } = await coreClient()\n .from(ac.table)\n .update(archetypeData)\n .eq('id', id)\n if (error) throw error\n }\n\n if (!isPure && Object.keys(projectData).length > 0) {\n const { error } = await getClient()\n .from(config.projectTable)\n .update(projectData)\n .eq(fkColumn, id)\n if (error) throw error\n }\n\n // Re-fetch (archetype only for pure entities; otherwise join the extension)\n const { data: archetypeRow } = await coreClient().from(ac.table).select('*').eq('id', id).single()\n if (isPure) {\n return mapRow<T>({ ...archetypeRow, id } as Record<string, unknown>)\n }\n const { data: projectRow } = await getClient().from(config.projectTable).select('*').eq(fkColumn, id).single()\n\n // The extension wins the spread, which is right for every column it owns\n // — except this one. custom_fields lives on the archetype and only there;\n // an extension table that grew a column of the same name would otherwise\n // shadow the real values with its own, silently.\n const flat = { ...archetypeRow, ...projectRow, id }\n if (archetypeRow && CUSTOM_FIELDS_COLUMN in archetypeRow) {\n ;(flat as Record<string, unknown>)[CUSTOM_FIELDS_COLUMN] =\n (archetypeRow as Record<string, unknown>)[CUSTOM_FIELDS_COLUMN]\n }\n delete (flat as any)[fkColumn]\n return mapRow<T>(flat as Record<string, unknown>)\n },\n\n async remove(id) {\n const { error } = await coreClient()\n .from(ac.table)\n .delete()\n .eq('id', id)\n if (error) throw error\n },\n\n async removeMany(ids) {\n if (!ids.length) return\n const { error } = await coreClient()\n .from(ac.table)\n .delete()\n .in('id', ids)\n if (error) throw error\n },\n }\n}\n","import type { DataProvider, CrudQuery, CrudResult } from './types'\nimport { globalCache, stableKey } from '../lib/cache'\n\nexport interface ProviderCacheOptions {\n /** Table/entity name — used as cache key namespace */\n table: string\n /** Dynamic tenant ID resolver */\n tenantId: () => string | undefined\n /** Override default TTL for this entity (ms) */\n ttl?: number\n}\n\n/**\n * Wraps a DataProvider with transparent read caching + mutation invalidation.\n *\n * - `list()` results are cached by query params\n * - `create()`, `update()`, `remove()` invalidate all cached entries for the table\n */\nexport function withCache<T extends { id: string }>(\n provider: DataProvider<T>,\n options: ProviderCacheOptions,\n): DataProvider<T> {\n function prefix(): string {\n return `${options.tenantId() ?? '_'}:${options.table}`\n }\n\n return {\n async list(query: CrudQuery): Promise<CrudResult<T>> {\n const key = `${prefix()}:${stableKey(query)}`\n const cached = globalCache.get<CrudResult<T>>(key)\n if (cached) return cached\n\n const result = await provider.list(query)\n globalCache.set(key, result, options.ttl)\n return result\n },\n\n async create(data) {\n const result = await provider.create(data)\n globalCache.invalidate(prefix())\n return result\n },\n\n // Forwarded, not dropped: an optional method that disappears behind the\n // wrapper silently downgrades every bulk write to a loop of single writes,\n // and nothing upstream can tell — `createMany` was doing exactly that.\n ...(provider.createMany && {\n async createMany(rows: Parameters<NonNullable<typeof provider.createMany>>[0], options: Parameters<NonNullable<typeof provider.createMany>>[1]) {\n const result = await provider.createMany!(rows, options)\n globalCache.invalidate(prefix())\n return result\n },\n }),\n\n async update(id, data) {\n const result = await provider.update(id, data)\n globalCache.invalidate(prefix())\n return result\n },\n\n async remove(id) {\n await provider.remove(id)\n globalCache.invalidate(prefix())\n },\n\n ...(provider.removeMany && {\n async removeMany(ids: string[]) {\n await provider.removeMany!(ids)\n globalCache.invalidate(prefix())\n },\n }),\n }\n}\n","import { getSupabaseClientOptional } from '../data/supabase'\nimport { getActiveTenantId } from '../lib/tenant'\nimport {\n declaredCustomFields,\n validateEntityRecordData,\n type EntityField,\n type EntityFieldOption,\n type EntityFieldType,\n type EntityRecordIssue,\n} from '../registry/entities'\n\n/**\n * The field registry, resolved. Two halves merge here and nowhere else:\n *\n * declared — plugin/app code, via defineCustomFields. Re-asserted on deploy.\n * merchant — plg_entity_fields rows (035), written from the admin, no deploy.\n *\n * Reads of the merchant half also pick up the vertical's own vocabulary, the\n * rows with `tenant_id IS NULL` that a pool ships with: RLS publishes them to\n * every member and lets none of them write.\n *\n * Declared wins a collision, so a deploy adopts a key a merchant invented\n * instead of either side losing work — the rule 035's `origin` column records.\n */\n\nexport const FIELDS_TABLE = 'plg_entity_fields'\n\n/** Just enough of a Supabase client, structurally — the same shape (and the\n * same reason) as the one in ../integrations/store.ts. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Client = { from: (table: string) => any }\n\n/** A write naming a key the registry does not know, or a value it refuses. */\nexport class CustomFieldsError extends Error {\n readonly issues: EntityRecordIssue[]\n constructor(reference: string, issues: EntityRecordIssue[]) {\n super(`${reference} custom fields: ${issues.map((i) => i.message).join('; ')}`)\n this.name = 'CustomFieldsError'\n this.issues = issues\n }\n}\n\ninterface FieldRow {\n reference: string\n key: string\n type: string\n label: string | null\n help: string | null\n required: boolean\n default_value: unknown\n validation: Record<string, unknown> | null\n options: unknown\n position: number\n origin: string\n}\n\nfunction readOptions(raw: unknown): EntityFieldOption[] | undefined {\n if (!Array.isArray(raw)) return undefined\n const options = raw\n .map((entry) => {\n if (typeof entry === 'string') return { value: entry }\n const record = entry as Record<string, unknown>\n return typeof record?.value === 'string'\n ? { value: record.value, label: typeof record.label === 'string' ? record.label : undefined }\n : null\n })\n .filter((option): option is EntityFieldOption => option !== null)\n return options.length ? options : undefined\n}\n\nfunction rowToField(row: FieldRow): EntityField {\n const field: EntityField = { type: row.type as EntityFieldType }\n if (row.label) field.label = row.label\n if (row.help) field.help = row.help\n if (row.required) field.required = true\n if (row.default_value !== null && row.default_value !== undefined) field.default = row.default_value\n const options = readOptions(row.options)\n if (options) field.options = options\n // `{}` is the column default, and an empty validation object means \"no\n // bounds\" — carrying it through would make every field look constrained.\n if (row.validation && Object.keys(row.validation).length) {\n field.validation = row.validation as EntityField['validation']\n }\n return field\n}\n\nexport interface ResolvedCustomFields {\n reference: string\n fields: Record<string, EntityField>\n /** Declaration order for the merchant half: what the form renders by. */\n order: string[]\n}\n\nconst EMPTY: ResolvedCustomFields = { reference: '', fields: {}, order: [] }\n\n/**\n * In-flight and resolved sets, keyed by tenant+reference. A form, a table and a\n * validator all ask for the same set on one screen; without this they are three\n * round trips. Cleared by {@link clearCustomFieldsCache} on tenant switch.\n */\nconst cache = new Map<string, Promise<ResolvedCustomFields>>()\n\nexport function clearCustomFieldsCache(): void {\n cache.clear()\n}\n\nasync function load(reference: string, tenantId: string): Promise<ResolvedCustomFields> {\n const declared = declaredCustomFields(reference)\n const supabase = getSupabaseClientOptional() as Client | null\n if (!supabase) return { reference, fields: { ...declared }, order: Object.keys(declared) }\n\n const { data, error } = await supabase\n .from(FIELDS_TABLE)\n .select('reference,key,type,label,help,required,default_value,validation,options,position,origin')\n .eq('reference', reference)\n .is('archived_at', null)\n .order('position', { ascending: true })\n\n // A pool that has not applied 035 yet has no registry, which is not the same\n // as a tenant with no fields — but for a reader they behave alike, and\n // failing the screen over it would make the column unusable during rollout.\n if (error) return { reference, fields: { ...declared }, order: Object.keys(declared) }\n\n const fields: Record<string, EntityField> = {}\n const order: string[] = []\n for (const row of (data ?? []) as FieldRow[]) {\n if (fields[row.key]) continue // a tenant row already shadowed the vocabulary\n fields[row.key] = rowToField(row)\n order.push(row.key)\n }\n // Declared last so it wins, and so a key only in code still renders.\n for (const [key, field] of Object.entries(declared)) {\n if (!fields[key]) order.push(key)\n fields[key] = field\n }\n void tenantId // RLS scopes the read; the id is here for the cache key alone.\n return { reference, fields, order }\n}\n\n/** The full field set for a record kind, declared ∪ merchant, memoised. */\nexport function resolveCustomFields(reference: string, tenantId?: string): Promise<ResolvedCustomFields> {\n const tenant = tenantId ?? getActiveTenantId()\n if (!tenant) return Promise.resolve({ ...EMPTY, reference, fields: { ...declaredCustomFields(reference) } })\n const cacheKey = `${tenant}:${reference}`\n let pending = cache.get(cacheKey)\n if (!pending) {\n pending = load(reference, tenant).catch((err) => {\n cache.delete(cacheKey)\n throw err\n })\n cache.set(cacheKey, pending)\n }\n return pending\n}\n\n/**\n * The write gate. Throws on an undeclared key or a refused value, the same\n * shape validateEntityRecordData produces — so the admin can point at the\n * offending field instead of showing a wall of text.\n */\nexport async function validateCustomFields(\n reference: string,\n values: Record<string, unknown>,\n tenantId?: string,\n): Promise<void> {\n const { fields } = await resolveCustomFields(reference, tenantId)\n const issues = validateEntityRecordData({ fields }, values)\n if (issues.length) throw new CustomFieldsError(reference, issues)\n}\n\n/**\n * Merge a partial write onto what the record already holds.\n *\n * jsonb through PostgREST is a whole-value write, so sending only the keys a\n * form touched replaces the column and drops its siblings. That is not\n * hypothetical: it is the live CRM defect on people.metadata, where dragging a\n * card wiped formId/fields/utm. An explicit null removes a key.\n */\nexport function mergeCustomFields(\n current: Record<string, unknown> | null | undefined,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...(current ?? {}) }\n for (const [key, value] of Object.entries(patch)) {\n if (value === null) delete merged[key]\n else merged[key] = value\n }\n return merged\n}\n","import type { DataProvider } from './types'\nimport { mergeCustomFields, validateCustomFields } from '../fields/store'\n\n/**\n * The write gate for `custom_fields`, wrapped around any provider.\n *\n * It goes here, on resolveDataProvider's decorator seam beside withCache,\n * because that is the only place in the SDK that sees the EntityDef and the\n * provider together — every entity declared with an archetype passes through\n * it, whichever backend wins. Providers that hand-roll their own writes\n * (plugin-agenda on appointments, plugin-crm on people) do not, and have to\n * call validateCustomFields themselves.\n *\n * Two jobs, and the second is the one that bites:\n *\n * 1. Refuse a key the registry does not declare, or a value it does not accept.\n * 2. MERGE an update instead of replacing it. jsonb through PostgREST is a\n * whole-value write, so a screen that sends only the field it edited drops\n * every sibling. That is not hypothetical — it is the live defect on\n * people.metadata in the CRM, where dragging a card wiped formId/fields/utm.\n */\n\n/** The camelCase key a caller writes; the column is `custom_fields`. */\nconst KEY = 'customFields'\n\nfunction patchOf(data: unknown): Record<string, unknown> | null {\n const value = (data as Record<string, unknown> | null)?.[KEY]\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : null\n}\n\nexport function withCustomFields<T extends { id: string }>(\n provider: DataProvider<T>,\n reference: string,\n): DataProvider<T> {\n return {\n ...provider,\n\n async create(data) {\n const patch = patchOf(data)\n if (!patch) return provider.create(data)\n await validateCustomFields(reference, patch)\n return provider.create(data)\n },\n\n async update(id, data) {\n const patch = patchOf(data)\n if (!patch) return provider.update(id, data)\n await validateCustomFields(reference, patch)\n\n // Read before write. One extra round trip, and it is what stops a partial\n // update from deleting the keys it did not mention. `list` by id rather\n // than getById because DataProvider has no getById to call.\n const { data: rows } = await provider.list({\n filters: { id },\n pageSize: 1,\n countMode: 'none',\n })\n const current = (rows[0] as Record<string, unknown> | undefined)?.[KEY]\n const merged = mergeCustomFields(current as Record<string, unknown> | undefined, patch)\n return provider.update(id, { ...data, [KEY]: merged } as Partial<T>)\n },\n }\n}\n","import type { EntityDef } from '../types/crud'\nimport type { BackendRef } from '../manifest'\nimport type { DataProvider } from './types'\nimport { getSupabaseClientOptional } from './supabase'\nimport { createSupabaseProvider } from './supabase'\nimport { createArchetypeProvider } from './archetype'\nimport { createMockProvider } from './mock'\nimport { createFayzApiProvider, type FayzApiProviderConfig } from './platform-api'\nimport { withCache } from './cached'\nimport { withCustomFields } from './custom-fields'\nimport { getActiveTenantId } from '../lib/tenant'\n\n/**\n * Resolve the best data provider for an EntityDef.\n * Supabase → Archetype → Mock (in order of preference).\n *\n * Reusable by createCrudPage, PluginRegistryManager, or any component\n * that needs a DataProvider from an EntityDef.\n */\nexport interface ResolveDataProviderOptions {\n backend?: BackendRef\n fayzApi?: Omit<FayzApiProviderConfig, 'entityKey' | 'table'>\n /**\n * Read through the shared TTL cache (default true).\n *\n * Callers that must observe writes made by ANOTHER surface pass false: the\n * cache is only invalidated by writes that go through it, so a record created\n * on the agenda screen stays invisible to the assistant for the rest of the\n * TTL — which is how \"o que tem na agenda hoje?\" answered \"nada\" over a\n * booking made seconds earlier.\n */\n cache?: boolean\n customProviders?: Record<string, <T extends { id: string }>(entityDef: EntityDef<T>, mockData?: T[]) => DataProvider<T>>\n}\n\nexport function resolveDataProvider<T extends { id: string }>(\n entityDef: EntityDef<T>,\n mockData?: T[],\n options: ResolveDataProviderOptions = {},\n): DataProvider<T> {\n const backend = options.backend\n\n if (backend?.provider === 'mock') {\n return createMockProvider(entityDef, mockData)\n }\n\n if (backend?.provider === 'fayz-api') {\n const table = entityDef.data?.table ?? entityDef.name\n return createFayzApiProvider<T>(table, {\n ...options.fayzApi,\n baseUrl: options.fayzApi?.baseUrl ?? backend.url,\n projectId: options.fayzApi?.projectId ?? backend.projectRef,\n entityKey: entityDef.name ?? table,\n table,\n schema: options.fayzApi?.schema ?? entityDef.data?.schema,\n idColumn: options.fayzApi?.idColumn ?? entityDef.data?.columnMap?.id,\n searchColumns: options.fayzApi?.searchColumns ?? entityDef.data?.searchColumns ?? entityDef.fields\n .filter((field) => field.searchable)\n .map((field) => field.key),\n tenantIdColumn: entityDef.data?.tenantScoped === false\n ? false\n : options.fayzApi?.tenantIdColumn ?? entityDef.data?.tenantIdColumn,\n tenantId: options.fayzApi?.tenantId ?? (() => getActiveTenantId()),\n })\n }\n\n if (backend?.provider === 'custom') {\n const adapterId = backend.adapterId\n const factory = adapterId ? options.customProviders?.[adapterId] : undefined\n if (!adapterId || !factory) {\n throw new Error(`[@fayz-ai/core] Custom data provider \"${adapterId ?? 'unknown'}\" is not registered.`)\n }\n return factory<T>(entityDef, mockData)\n }\n\n const client = getSupabaseClientOptional()\n\n if (client && entityDef.data?.table) {\n const tenantId = () => getActiveTenantId()\n // Archetype entities share a physical table (e.g. people) across kinds\n // (student/teacher/staff…). The cache key must carry the kind or the first\n // kind's resultset is served to every sibling entity (teachers page\n // listing students).\n const cacheOptions = {\n table: entityDef.data.archetypeKind\n ? `${entityDef.data.table}#${entityDef.data.archetypeKind}`\n : entityDef.data.table,\n tenantId,\n ttl: entityDef.data.cacheTTL,\n }\n const cached = <P extends DataProvider<T>>(p: P): DataProvider<T> =>\n options.cache === false ? p : withCache(p, cacheOptions)\n\n if (entityDef.data.archetype && entityDef.data.archetypeKind && !entityDef.data.schema) {\n // The custom-fields gate wraps INSIDE the cache: it reads the current row\n // to merge a partial write, and reading that through the cache would\n // merge onto a stale set and silently resurrect a key the merchant just\n // cleared.\n return cached(withCustomFields<T>(createArchetypeProvider<T>({\n archetype: entityDef.data.archetype,\n archetypeKind: entityDef.data.archetypeKind,\n projectTable: entityDef.data.table,\n tenantId,\n searchColumns: entityDef.data.searchColumns ?? entityDef.fields\n .filter((field) => field.searchable)\n .map((field) => field.key),\n }), entityDef.data.archetype))\n }\n\n return cached(createSupabaseProvider<T>(entityDef.data.table, {\n schema: entityDef.data.schema,\n tenantId: entityDef.data.tenantScoped === false ? undefined : tenantId,\n tenantIdColumn: entityDef.data.tenantIdColumn,\n searchColumns: entityDef.data.searchColumns ?? entityDef.fields\n .filter((field) => field.searchable)\n .map((field) => field.key),\n selectColumns: entityDef.data.selectColumns,\n columnMap: entityDef.data.columnMap,\n filters: entityDef.data.filters,\n defaults: entityDef.data.defaults,\n }))\n }\n\n if (entityDef.data?.table) {\n console.warn(\n `[fayz/core] resolveDataProvider: falling back to mock for \"${entityDef.name}\" (table: ${entityDef.data.table}). ` +\n `Supabase client ${client ? 'available' : 'NOT initialized'}.`,\n )\n }\n return createMockProvider(entityDef, mockData)\n}\n","import type { BulkWriteOptions, BulkWriteResult, DataProvider } from './types'\n\n/**\n * Write many rows through whatever the provider supports.\n *\n * `createMany` when it exists (one round-trip per chunk), otherwise a sequential\n * `create` loop. Callers never branch: a mock provider and a Supabase table\n * import the same way, only slower.\n *\n * Never all-or-nothing. A 900-row client list will contain a malformed phone\n * and a duplicate e-mail, and a single transaction would throw away the other\n * 898 — plus a statement that large risks the timeout. Failures are collected\n * with their row index so the caller can hand them back for correction.\n */\nexport async function bulkCreate<T extends { id: string }>(\n provider: DataProvider<T>,\n rows: Array<Omit<T, 'id' | 'createdAt' | 'updatedAt' | 'tenantId'>>,\n options?: BulkWriteOptions,\n): Promise<BulkWriteResult> {\n if (!rows.length) return { created: 0, failed: [] }\n if (provider.createMany) return provider.createMany(rows, options)\n\n let created = 0\n const failed: Array<{ index: number; message: string }> = []\n for (let i = 0; i < rows.length; i++) {\n try {\n await provider.create(rows[i])\n created += 1\n } catch (error) {\n failed.push({ index: i, message: error instanceof Error ? error.message : String(error) })\n }\n options?.onProgress?.(i + 1, rows.length)\n }\n return { created, failed }\n}\n\n/** Outcome of a bulk delete: how many rows went, and which ids did not and why. */\nexport interface BulkRemoveResult {\n removed: number\n failed: Array<{ id: string; message: string }>\n}\n\n/**\n * Delete many rows through whatever the provider supports.\n *\n * `removeMany` when it exists — chunked, because PostgREST puts `in.(…)` in the\n * query STRING and a few hundred uuids there is a URL no proxy promises to\n * carry. Otherwise a sequential `remove` loop.\n *\n * A chunk is all-or-nothing on the wire, so a chunk that throws is reported as\n * every id in it having failed: the caller must not tell the user rows are gone\n * when the statement rolled back.\n */\nexport async function bulkRemove<T extends { id: string }>(\n provider: DataProvider<T>,\n ids: string[],\n options?: { chunkSize?: number },\n): Promise<BulkRemoveResult> {\n if (!ids.length) return { removed: 0, failed: [] }\n\n const failed: Array<{ id: string; message: string }> = []\n const message = (error: unknown) => (error instanceof Error ? error.message : String(error))\n\n if (provider.removeMany) {\n const chunkSize = options?.chunkSize ?? 100\n let removed = 0\n for (let i = 0; i < ids.length; i += chunkSize) {\n const chunk = ids.slice(i, i + chunkSize)\n try {\n await provider.removeMany(chunk)\n removed += chunk.length\n } catch (error) {\n for (const id of chunk) failed.push({ id, message: message(error) })\n }\n }\n return { removed, failed }\n }\n\n let removed = 0\n for (const id of ids) {\n try {\n await provider.remove(id)\n removed += 1\n } catch (error) {\n failed.push({ id, message: message(error) })\n }\n }\n return { removed, failed }\n}\n"]}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { isConnectorCategory, CONNECTOR_CATEGORIES, requestPlaneSpec, connectorPlanes, invocationPlane, connectorSubscribes, permissionActions, isEventPermission, connectorEntities, connectorSubscribesTo } from './chunk-BEGXYHS4.js';
|
|
2
|
+
|
|
3
|
+
// src/testing.ts
|
|
4
|
+
var PluginContractError = class extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "PluginContractError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
function fail(scope, msg) {
|
|
11
|
+
throw new PluginContractError(`[${scope}] ${msg}`);
|
|
12
|
+
}
|
|
13
|
+
function nonEmptyString(v) {
|
|
14
|
+
return typeof v === "string" && v.trim().length > 0;
|
|
15
|
+
}
|
|
16
|
+
function assertPluginManifestContract(manifest) {
|
|
17
|
+
const id = manifest?.id;
|
|
18
|
+
const scope = nonEmptyString(id) ? id : "<unknown plugin>";
|
|
19
|
+
for (const field of ["id", "name", "icon", "version"]) {
|
|
20
|
+
if (!nonEmptyString(manifest?.[field])) fail(scope, `manifest.${field} must be a non-empty string`);
|
|
21
|
+
}
|
|
22
|
+
if (!Array.isArray(manifest.navigation)) fail(scope, "manifest.navigation must be an array (use [] for settings-only plugins)");
|
|
23
|
+
if (!Array.isArray(manifest.routes)) fail(scope, "manifest.routes must be an array (use [] for settings-only plugins)");
|
|
24
|
+
for (const [i, nav] of manifest.navigation.entries()) {
|
|
25
|
+
if (!nonEmptyString(nav?.route)) fail(scope, `navigation[${i}].route must be a non-empty string`);
|
|
26
|
+
}
|
|
27
|
+
const routePaths = /* @__PURE__ */ new Set();
|
|
28
|
+
for (const [i, route] of manifest.routes.entries()) {
|
|
29
|
+
if (!nonEmptyString(route?.path)) fail(scope, `routes[${i}].path must be a non-empty string`);
|
|
30
|
+
if (typeof route?.component !== "function") fail(scope, `routes[${i}].component must be a component`);
|
|
31
|
+
if (routePaths.has(route.path)) fail(scope, `duplicate route path "${route.path}"`);
|
|
32
|
+
routePaths.add(route.path);
|
|
33
|
+
}
|
|
34
|
+
for (const [i, nav] of manifest.navigation.entries()) {
|
|
35
|
+
const r = nav.route;
|
|
36
|
+
if (routePaths.size > 0 && !routePaths.has(r)) {
|
|
37
|
+
fail(scope, `navigation[${i}].route "${r}" has no matching route in manifest.routes`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const settingIds = /* @__PURE__ */ new Set();
|
|
41
|
+
for (const [i, tab] of (manifest.settings ?? []).entries()) {
|
|
42
|
+
if (!nonEmptyString(tab?.id)) fail(scope, `settings[${i}].id must be a non-empty string`);
|
|
43
|
+
if (!nonEmptyString(tab?.label)) fail(scope, `settings[${i}].label must be a non-empty string`);
|
|
44
|
+
if (typeof tab?.component !== "function") fail(scope, `settings[${i}].component must be a component`);
|
|
45
|
+
if (settingIds.has(tab.id)) fail(scope, `duplicate settings tab id "${tab.id}"`);
|
|
46
|
+
settingIds.add(tab.id);
|
|
47
|
+
}
|
|
48
|
+
for (const [i, feat] of (manifest.declaredFeatures ?? []).entries()) {
|
|
49
|
+
if (!nonEmptyString(feat?.id)) fail(scope, `declaredFeatures[${i}].id must be a non-empty string`);
|
|
50
|
+
}
|
|
51
|
+
for (const [i, src] of (manifest.emitsFrom ?? []).entries()) {
|
|
52
|
+
if (!nonEmptyString(src?.table)) fail(scope, `emitsFrom[${i}].table must be a non-empty string`);
|
|
53
|
+
if (!nonEmptyString(src?.entityKey)) fail(scope, `emitsFrom[${i}].entityKey must be a non-empty string`);
|
|
54
|
+
for (const action of src.actions ?? []) {
|
|
55
|
+
if (!EVENT_ACTIONS.has(action)) fail(scope, `emitsFrom[${i}] has unknown action "${action}"`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const functionSlugs = /* @__PURE__ */ new Set();
|
|
59
|
+
for (const [i, fn] of (manifest.functions ?? []).entries()) {
|
|
60
|
+
if (!SLUG.test(fn?.slug ?? "")) fail(scope, `functions[${i}].slug must be kebab-case \u2014 it becomes the deployed function name`);
|
|
61
|
+
if (functionSlugs.has(fn.slug)) fail(scope, `duplicate function slug "${fn.slug}"`);
|
|
62
|
+
functionSlugs.add(fn.slug);
|
|
63
|
+
if (typeof fn.verifyJwt !== "boolean") fail(scope, `functions[${i}].verifyJwt must be a boolean`);
|
|
64
|
+
if (!FUNCTION_INGRESS.has(fn.ingress)) fail(scope, `functions[${i}].ingress "${fn.ingress}" is not one of ${[...FUNCTION_INGRESS].join(", ")}`);
|
|
65
|
+
if (fn.ingress === "fayz" && fn.verifyJwt) fail(scope, `functions[${i}] is reached through the Fayz ingress, so verifyJwt must be false`);
|
|
66
|
+
for (const secret of fn.secrets ?? []) {
|
|
67
|
+
if (!SECRET_NAME.test(secret)) fail(scope, `functions[${i}].secrets must name secrets (SCREAMING_SNAKE_CASE), never carry their values`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (const [i, def] of (manifest.connectors ?? []).entries()) {
|
|
71
|
+
if (def.category !== void 0 && !isConnectorCategory(def.category)) {
|
|
72
|
+
fail(
|
|
73
|
+
scope,
|
|
74
|
+
`connectors[${i}].category "${def.category}" is not a catalogue category \u2014 use one of ${CONNECTOR_CATEGORIES.join(", ")}, taken from the catalogue row with this connector's slug.`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
for (const pattern of def.subscribesTo ?? []) {
|
|
78
|
+
if (!nonEmptyString(pattern)) fail(scope, `connectors[${i}].subscribesTo must hold non-empty patterns`);
|
|
79
|
+
if (pattern.includes("*") && !pattern.endsWith("*")) {
|
|
80
|
+
fail(scope, `connectors[${i}].subscribesTo "${pattern}" \u2014 "*" is only honoured at the end`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
assertConnectorPermissions(scope, `connectors[${i}]`, def);
|
|
84
|
+
if ((def.planes ?? []).includes("request")) {
|
|
85
|
+
try {
|
|
86
|
+
requestPlaneSpec(def);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
fail(scope, `connectors[${i}] ${error instanceof Error ? error.message : String(error)}`);
|
|
89
|
+
}
|
|
90
|
+
} else if (def.latencyBudgetMs !== void 0 || def.onFailure !== void 0) {
|
|
91
|
+
fail(
|
|
92
|
+
scope,
|
|
93
|
+
`connectors[${i}] declares latencyBudgetMs/onFailure but is not on the request plane \u2014 nothing enforces them, so they read as a guarantee that does not exist.`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const fieldKeys = new Set((def.fields ?? []).map((f) => f.key));
|
|
97
|
+
const settingKeys = /* @__PURE__ */ new Set();
|
|
98
|
+
for (const [j, setting] of (def.settings ?? []).entries()) {
|
|
99
|
+
const at = `connectors[${i}].settings[${j}]`;
|
|
100
|
+
if (!nonEmptyString(setting?.key)) fail(scope, `${at}.key must be a non-empty string`);
|
|
101
|
+
if (!nonEmptyString(setting?.label)) fail(scope, `${at}.label must be a non-empty string`);
|
|
102
|
+
if (!SETTING_TYPES.has(setting.type)) {
|
|
103
|
+
fail(scope, `${at}.type "${setting.type}" is not one of ${[...SETTING_TYPES].join(", ")}`);
|
|
104
|
+
}
|
|
105
|
+
if (settingKeys.has(setting.key)) fail(scope, `${at} duplicates settings key "${setting.key}"`);
|
|
106
|
+
settingKeys.add(setting.key);
|
|
107
|
+
if (fieldKeys.has(setting.key)) {
|
|
108
|
+
fail(
|
|
109
|
+
scope,
|
|
110
|
+
`${at}.key "${setting.key}" is also a credential field \u2014 a key either authorizes the connection (fields) or configures it (settings), never both.`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
if (setting.type === "select" || setting.type === "multi-select") {
|
|
114
|
+
if (!Array.isArray(setting.options) || setting.options.length === 0) {
|
|
115
|
+
fail(scope, `${at} is a ${setting.type} and must declare options \u2014 that is what replaces a free-text box`);
|
|
116
|
+
}
|
|
117
|
+
for (const [k, option] of setting.options.entries()) {
|
|
118
|
+
if (!nonEmptyString(option?.value)) fail(scope, `${at}.options[${k}].value must be a non-empty string`);
|
|
119
|
+
if (!nonEmptyString(option?.label)) fail(scope, `${at}.options[${k}].label must be a non-empty string`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (setting.pattern !== void 0) {
|
|
123
|
+
if (setting.type !== "text") fail(scope, `${at}.pattern only applies to a text setting`);
|
|
124
|
+
try {
|
|
125
|
+
new RegExp(setting.pattern);
|
|
126
|
+
} catch {
|
|
127
|
+
fail(scope, `${at}.pattern is not a valid regular expression`);
|
|
128
|
+
}
|
|
129
|
+
if (!nonEmptyString(setting.patternHint)) fail(scope, `${at} declares a pattern, so it must declare patternHint`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (settingKeys.size > 0) {
|
|
133
|
+
if (typeof def.getSettings !== "function") fail(scope, `connectors[${i}] declares settings but no getSettings()`);
|
|
134
|
+
if (typeof def.saveSettings !== "function") fail(scope, `connectors[${i}] declares settings but no saveSettings()`);
|
|
135
|
+
}
|
|
136
|
+
const planes = new Set(connectorPlanes(def));
|
|
137
|
+
const momentKeys = /* @__PURE__ */ new Set();
|
|
138
|
+
for (const [j, moment] of (def.invokedAt ?? []).entries()) {
|
|
139
|
+
const at = `connectors[${i}].invokedAt[${j}]`;
|
|
140
|
+
if (!nonEmptyString(moment?.key)) fail(scope, `${at}.key must be a non-empty string`);
|
|
141
|
+
if (!nonEmptyString(moment?.label)) fail(scope, `${at}.label must be a non-empty string`);
|
|
142
|
+
if (momentKeys.has(moment.key)) fail(scope, `${at} duplicates key "${moment.key}"`);
|
|
143
|
+
momentKeys.add(moment.key);
|
|
144
|
+
const plane = invocationPlane(moment);
|
|
145
|
+
if (!planes.has(plane)) {
|
|
146
|
+
fail(scope, `${at} is declared on the ${plane} plane, which connectors[${i}].planes does not include`);
|
|
147
|
+
}
|
|
148
|
+
if (moment.trigger !== void 0) {
|
|
149
|
+
if (plane !== "sync") fail(scope, `${at}.trigger only applies to a sync moment`);
|
|
150
|
+
if (!TRIGGERS.has(moment.trigger)) fail(scope, `${at} has unknown trigger "${moment.trigger}"`);
|
|
151
|
+
}
|
|
152
|
+
const declared = new Set((def.permissions ?? []).map((p) => p.resource));
|
|
153
|
+
for (const resource of moment.touches ?? []) {
|
|
154
|
+
if (!declared.has(resource)) {
|
|
155
|
+
fail(
|
|
156
|
+
scope,
|
|
157
|
+
`${at}.touches names "${resource}", which connectors[${i}].permissions does not declare \u2014 a call site cannot reach what the consent view never showed.`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
for (const [j, auto] of (def.managedAutomations ?? []).entries()) {
|
|
163
|
+
if (!nonEmptyString(auto?.eventKey)) fail(scope, `connectors[${i}].managedAutomations[${j}].eventKey must be a non-empty string`);
|
|
164
|
+
if (!nonEmptyString(auto?.label)) fail(scope, `connectors[${i}].managedAutomations[${j}].label must be a non-empty string`);
|
|
165
|
+
if (!connectorSubscribes(def, auto.eventKey)) {
|
|
166
|
+
fail(scope, `connectors[${i}].managedAutomations[${j}] fires on "${auto.eventKey}", which no subscribesTo pattern covers`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (const [i, mig] of (manifest.migrations ?? []).entries()) {
|
|
171
|
+
for (const table of bespokeConnectorTables(mig?.sql)) {
|
|
172
|
+
fail(
|
|
173
|
+
scope,
|
|
174
|
+
`migrations[${i}] ("${mig?.id ?? "?"}") creates public.${table} \u2014 a connector's own *_integrations / *_sync_log table. Store the connection in plg_connections / plg_sync_runs via createConnectionStore('<connector-id>'): two accounts are two rows separated by instance_key, and connector-specific counters go in stats.`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (manifest.navigation.length === 0 && manifest.routes.length === 0 && (manifest.settings ?? []).length === 0 && (manifest.connectors ?? []).length === 0) {
|
|
179
|
+
fail(scope, "plugin contributes no navigation, routes, settings, or connectors \u2014 it would mount but do nothing");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function assertConnectorPermissions(scope, path, def) {
|
|
183
|
+
const permissions = def.permissions;
|
|
184
|
+
if (permissions === void 0) return;
|
|
185
|
+
if (!Array.isArray(permissions)) fail(scope, `${path}.permissions must be an array`);
|
|
186
|
+
const seen = /* @__PURE__ */ new Set();
|
|
187
|
+
for (const [j, permission] of permissions.entries()) {
|
|
188
|
+
const at = `${path}.permissions[${j}]`;
|
|
189
|
+
if (permission?.kind !== "data" && permission?.kind !== "event") {
|
|
190
|
+
fail(scope, `${at}.kind must be "data" or "event"`);
|
|
191
|
+
}
|
|
192
|
+
if (!nonEmptyString(permission.resource)) fail(scope, `${at}.resource must be a non-empty string`);
|
|
193
|
+
if (!nonEmptyString(permission.reason)) {
|
|
194
|
+
fail(scope, `${at} must declare a reason \u2014 the sentence the tenant judges before authorizing`);
|
|
195
|
+
}
|
|
196
|
+
if (!Array.isArray(permission.actions) || permission.actions.length === 0) {
|
|
197
|
+
fail(scope, `${at}.actions must name at least one action \u2014 a resource with no access is not a permission`);
|
|
198
|
+
}
|
|
199
|
+
const legal = permissionActions(permission.kind);
|
|
200
|
+
for (const action of permission.actions) {
|
|
201
|
+
if (!legal.includes(action)) {
|
|
202
|
+
fail(scope, `${at} asks for "${action}" on the ${permission.kind} resource "${permission.resource}", which only admits ${legal.join(", ")}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (isEventPermission(permission) && permission.resource.includes("*") && !permission.resource.endsWith("*")) {
|
|
206
|
+
fail(scope, `${at}.resource "${permission.resource}" \u2014 "*" is only honoured at the end`);
|
|
207
|
+
}
|
|
208
|
+
const key = `${permission.kind}:${permission.resource}`;
|
|
209
|
+
if (seen.has(key)) fail(scope, `${at} repeats "${key}" \u2014 one resource, one row, one reason`);
|
|
210
|
+
seen.add(key);
|
|
211
|
+
}
|
|
212
|
+
if (def.entities !== void 0) {
|
|
213
|
+
const declared = new Set(connectorEntities({ permissions }));
|
|
214
|
+
const legacy = new Set(def.entities);
|
|
215
|
+
for (const entity of declared) {
|
|
216
|
+
if (!legacy.has(entity)) {
|
|
217
|
+
fail(
|
|
218
|
+
scope,
|
|
219
|
+
`${path}.permissions reaches "${entity}", which ${path}.entities does not list \u2014 the two describe the same access and must name the same set (drop entities; it is derived).`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
for (const entity of legacy) {
|
|
224
|
+
if (!declared.has(entity)) {
|
|
225
|
+
fail(
|
|
226
|
+
scope,
|
|
227
|
+
`${path}.entities lists "${entity}" with no permission saying what it does with it \u2014 a record type on the consent view with no read/write is a name, not a declaration.`
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (def.subscribesTo !== void 0) {
|
|
233
|
+
const declared = new Set(connectorSubscribesTo({ permissions }));
|
|
234
|
+
const legacy = new Set(def.subscribesTo);
|
|
235
|
+
for (const pattern of declared) {
|
|
236
|
+
if (!legacy.has(pattern)) {
|
|
237
|
+
fail(
|
|
238
|
+
scope,
|
|
239
|
+
`${path}.permissions listens to "${pattern}", which ${path}.subscribesTo does not \u2014 the ingress filters on that list, so the consent view would promise a fact never delivered.`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
for (const pattern of legacy) {
|
|
244
|
+
if (!declared.has(pattern)) {
|
|
245
|
+
fail(
|
|
246
|
+
scope,
|
|
247
|
+
`${path}.subscribesTo asks for "${pattern}" with no listen permission explaining it \u2014 the connector would receive a fact the tenant was never shown.`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
var BESPOKE_CONNECTOR_TABLE = /\bcreate\s+table\s+(?:if\s+not\s+exists\s+)?(?:[a-z0-9_]+\s*\.\s*)?([a-z0-9_]*(?:_integrations|_sync_log))\b/gi;
|
|
254
|
+
function bespokeConnectorTables(sql) {
|
|
255
|
+
const text = typeof sql === "string" ? sql.replace(/"/g, "") : "";
|
|
256
|
+
const found = /* @__PURE__ */ new Set();
|
|
257
|
+
for (const m of text.matchAll(BESPOKE_CONNECTOR_TABLE)) found.add(m[1].toLowerCase());
|
|
258
|
+
return [...found];
|
|
259
|
+
}
|
|
260
|
+
var EVENT_ACTIONS = /* @__PURE__ */ new Set(["created", "updated", "deleted"]);
|
|
261
|
+
var FUNCTION_INGRESS = /* @__PURE__ */ new Set(["fayz", "none"]);
|
|
262
|
+
var SLUG = /^[a-z0-9][a-z0-9-]*$/;
|
|
263
|
+
var SECRET_NAME = /^[A-Z][A-Z0-9_]*$/;
|
|
264
|
+
var SETTING_TYPES = /* @__PURE__ */ new Set(["text", "select", "multi-select", "toggle"]);
|
|
265
|
+
var AUTH_KINDS = /* @__PURE__ */ new Set(["oauth", "api-key", "mtls"]);
|
|
266
|
+
var DIRECTIONS = /* @__PURE__ */ new Set(["inbound", "outbound", "bidirectional"]);
|
|
267
|
+
var TRIGGERS = /* @__PURE__ */ new Set(["on-write", "scheduled", "manual", "webhook"]);
|
|
268
|
+
function assertConnectorContract(connector) {
|
|
269
|
+
const scope = nonEmptyString(connector?.id) ? `connector:${connector.id}` : "<unknown connector>";
|
|
270
|
+
for (const field of ["id", "provider", "pluginId"]) {
|
|
271
|
+
if (!nonEmptyString(connector?.[field])) fail(scope, `connector.${field} must be a non-empty string`);
|
|
272
|
+
}
|
|
273
|
+
if (!AUTH_KINDS.has(connector.authKind)) fail(scope, `connector.authKind "${connector.authKind}" is not one of ${[...AUTH_KINDS].join(", ")}`);
|
|
274
|
+
if (!Array.isArray(connector.capabilities) || connector.capabilities.length === 0) {
|
|
275
|
+
fail(scope, "connector.capabilities must list at least one capability");
|
|
276
|
+
}
|
|
277
|
+
for (const [i, cap] of connector.capabilities.entries()) {
|
|
278
|
+
if (!nonEmptyString(cap?.entity)) fail(scope, `capabilities[${i}].entity must be a non-empty string`);
|
|
279
|
+
if (!DIRECTIONS.has(cap.direction)) fail(scope, `capabilities[${i}].direction "${cap.direction}" is invalid`);
|
|
280
|
+
if (!Array.isArray(cap.triggers) || cap.triggers.length === 0) fail(scope, `capabilities[${i}].triggers must be non-empty`);
|
|
281
|
+
for (const trig of cap.triggers) {
|
|
282
|
+
if (!TRIGGERS.has(trig)) fail(scope, `capabilities[${i}] has unknown trigger "${trig}"`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export { PluginContractError, assertConnectorContract, assertPluginManifestContract, bespokeConnectorTables };
|
|
288
|
+
//# sourceMappingURL=chunk-V53GR4UT.js.map
|
|
289
|
+
//# sourceMappingURL=chunk-V53GR4UT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/testing.ts"],"names":[],"mappings":"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","file":"chunk-V53GR4UT.js","sourcesContent":["// ---------------------------------------------------------------------------\n// Plugin contract assertions — the integrity half of the deploy gate.\n// ---------------------------------------------------------------------------\n// Framework-agnostic runtime checks (no test-runner dependency) that any\n// plugin's *.test.ts calls to prove its manifest/connector conform to the\n// platform contract BEFORE it can ship. A plugin that fails these would break\n// the host app at mount time (missing route component, duplicate ids, malformed\n// settings tab). Pair with a capability test (does the plugin do its job?) — see\n// docs/plugins/PLUGIN-PATTERNS.md → capability anatomy. These throw on the first violation.\nimport type { PluginManifest } from './types/plugins'\nimport type { Connector } from './integrations'\nimport {\n CONNECTOR_CATEGORIES,\n connectorEntities,\n connectorPlanes,\n connectorSubscribes,\n connectorSubscribesTo,\n grants,\n invocationPlane,\n isConnectorCategory,\n isEventPermission,\n permissionActions,\n requestPlaneSpec,\n} from './integrations'\nimport type { ConnectorPermission } from './integrations'\n\nexport class PluginContractError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'PluginContractError'\n }\n}\n\nfunction fail(scope: string, msg: string): never {\n throw new PluginContractError(`[${scope}] ${msg}`)\n}\n\nfunction nonEmptyString(v: unknown): v is string {\n return typeof v === 'string' && v.trim().length > 0\n}\n\n/**\n * Assert a PluginManifest is structurally sound enough to mount safely.\n * Checks identity, navigation/route wiring, settings tabs, declared features,\n * and id uniqueness. Throws PluginContractError on the first problem.\n */\nexport function assertPluginManifestContract(manifest: PluginManifest): void {\n const id = manifest?.id\n const scope = nonEmptyString(id) ? id : '<unknown plugin>'\n\n for (const field of ['id', 'name', 'icon', 'version'] as const) {\n if (!nonEmptyString(manifest?.[field])) fail(scope, `manifest.${field} must be a non-empty string`)\n }\n\n if (!Array.isArray(manifest.navigation)) fail(scope, 'manifest.navigation must be an array (use [] for settings-only plugins)')\n if (!Array.isArray(manifest.routes)) fail(scope, 'manifest.routes must be an array (use [] for settings-only plugins)')\n\n // Every nav entry must point at a route; every route needs a path + component.\n for (const [i, nav] of manifest.navigation.entries()) {\n if (!nonEmptyString((nav as any)?.route)) fail(scope, `navigation[${i}].route must be a non-empty string`)\n }\n const routePaths = new Set<string>()\n for (const [i, route] of manifest.routes.entries()) {\n if (!nonEmptyString((route as any)?.path)) fail(scope, `routes[${i}].path must be a non-empty string`)\n if (typeof (route as any)?.component !== 'function') fail(scope, `routes[${i}].component must be a component`)\n if (routePaths.has((route as any).path)) fail(scope, `duplicate route path \"${(route as any).path}\"`)\n routePaths.add((route as any).path)\n }\n // A nav entry that links to a route the plugin doesn't declare is dead UI.\n for (const [i, nav] of manifest.navigation.entries()) {\n const r = (nav as any).route\n if (routePaths.size > 0 && !routePaths.has(r)) {\n fail(scope, `navigation[${i}].route \"${r}\" has no matching route in manifest.routes`)\n }\n }\n\n // Settings tabs (the only UI surface integrations need) must be renderable.\n const settingIds = new Set<string>()\n for (const [i, tab] of (manifest.settings ?? []).entries()) {\n if (!nonEmptyString((tab as any)?.id)) fail(scope, `settings[${i}].id must be a non-empty string`)\n if (!nonEmptyString((tab as any)?.label)) fail(scope, `settings[${i}].label must be a non-empty string`)\n if (typeof (tab as any)?.component !== 'function') fail(scope, `settings[${i}].component must be a component`)\n if (settingIds.has((tab as any).id)) fail(scope, `duplicate settings tab id \"${(tab as any).id}\"`)\n settingIds.add((tab as any).id)\n }\n\n for (const [i, feat] of (manifest.declaredFeatures ?? []).entries()) {\n if (!nonEmptyString((feat as any)?.id)) fail(scope, `declaredFeatures[${i}].id must be a non-empty string`)\n }\n\n for (const [i, src] of (manifest.emitsFrom ?? []).entries()) {\n if (!nonEmptyString(src?.table)) fail(scope, `emitsFrom[${i}].table must be a non-empty string`)\n if (!nonEmptyString(src?.entityKey)) fail(scope, `emitsFrom[${i}].entityKey must be a non-empty string`)\n for (const action of src.actions ?? []) {\n if (!EVENT_ACTIONS.has(action)) fail(scope, `emitsFrom[${i}] has unknown action \"${action}\"`)\n }\n }\n\n const functionSlugs = new Set<string>()\n for (const [i, fn] of (manifest.functions ?? []).entries()) {\n if (!SLUG.test(fn?.slug ?? '')) fail(scope, `functions[${i}].slug must be kebab-case — it becomes the deployed function name`)\n if (functionSlugs.has(fn.slug)) fail(scope, `duplicate function slug \"${fn.slug}\"`)\n functionSlugs.add(fn.slug)\n if (typeof fn.verifyJwt !== 'boolean') fail(scope, `functions[${i}].verifyJwt must be a boolean`)\n if (!FUNCTION_INGRESS.has(fn.ingress)) fail(scope, `functions[${i}].ingress \"${fn.ingress}\" is not one of ${[...FUNCTION_INGRESS].join(', ')}`)\n // The ingress authenticates by signature, not by a caller JWT it does not have.\n if (fn.ingress === 'fayz' && fn.verifyJwt) fail(scope, `functions[${i}] is reached through the Fayz ingress, so verifyJwt must be false`)\n for (const secret of fn.secrets ?? []) {\n // A name, never a value — this is the shape that keeps a key out of git.\n if (!SECRET_NAME.test(secret)) fail(scope, `functions[${i}].secrets must name secrets (SCREAMING_SNAKE_CASE), never carry their values`)\n }\n }\n\n for (const [i, def] of (manifest.connectors ?? []).entries()) {\n // An unlisted category renders NO badge rather than a wrong one, so the\n // mistake is invisible in a screenshot. Caught here instead.\n if (def.category !== undefined && !isConnectorCategory(def.category)) {\n fail(\n scope,\n `connectors[${i}].category \"${def.category}\" is not a catalogue category — ` +\n `use one of ${CONNECTOR_CATEGORIES.join(', ')}, taken from the catalogue row with this connector's slug.`,\n )\n }\n for (const pattern of def.subscribesTo ?? []) {\n if (!nonEmptyString(pattern)) fail(scope, `connectors[${i}].subscribesTo must hold non-empty patterns`)\n // Only a trailing star is honoured; see eventKeyMatches.\n if (pattern.includes('*') && !pattern.endsWith('*')) {\n fail(scope, `connectors[${i}].subscribesTo \"${pattern}\" — \"*\" is only honoured at the end`)\n }\n }\n\n assertConnectorPermissions(scope, `connectors[${i}]`, def)\n // The request plane's two fields are required THERE and meaningless\n // elsewhere. Checked at the manifest so a connector cannot reach a buyer\n // with an undeclared budget — the failure would otherwise be a spinner.\n if ((def.planes ?? []).includes('request')) {\n try {\n requestPlaneSpec(def)\n } catch (error) {\n fail(scope, `connectors[${i}] ${error instanceof Error ? error.message : String(error)}`)\n }\n } else if (def.latencyBudgetMs !== undefined || def.onFailure !== undefined) {\n fail(\n scope,\n `connectors[${i}] declares latencyBudgetMs/onFailure but is not on the request plane — ` +\n `nothing enforces them, so they read as a guarantee that does not exist.`,\n )\n }\n // Authorization vs configuration. Both declarations end up on the same row,\n // and a key in both is a value with two owners: the connect form would write\n // it and the settings form would overwrite it.\n const fieldKeys = new Set((def.fields ?? []).map((f) => f.key))\n const settingKeys = new Set<string>()\n for (const [j, setting] of (def.settings ?? []).entries()) {\n const at = `connectors[${i}].settings[${j}]`\n if (!nonEmptyString(setting?.key)) fail(scope, `${at}.key must be a non-empty string`)\n if (!nonEmptyString(setting?.label)) fail(scope, `${at}.label must be a non-empty string`)\n if (!SETTING_TYPES.has(setting.type)) {\n fail(scope, `${at}.type \"${setting.type}\" is not one of ${[...SETTING_TYPES].join(', ')}`)\n }\n if (settingKeys.has(setting.key)) fail(scope, `${at} duplicates settings key \"${setting.key}\"`)\n settingKeys.add(setting.key)\n if (fieldKeys.has(setting.key)) {\n fail(\n scope,\n `${at}.key \"${setting.key}\" is also a credential field — a key either authorizes the ` +\n `connection (fields) or configures it (settings), never both.`,\n )\n }\n if (setting.type === 'select' || setting.type === 'multi-select') {\n if (!Array.isArray(setting.options) || setting.options.length === 0) {\n fail(scope, `${at} is a ${setting.type} and must declare options — that is what replaces a free-text box`)\n }\n for (const [k, option] of setting.options.entries()) {\n if (!nonEmptyString(option?.value)) fail(scope, `${at}.options[${k}].value must be a non-empty string`)\n if (!nonEmptyString(option?.label)) fail(scope, `${at}.options[${k}].label must be a non-empty string`)\n }\n }\n if (setting.pattern !== undefined) {\n if (setting.type !== 'text') fail(scope, `${at}.pattern only applies to a text setting`)\n try {\n new RegExp(setting.pattern)\n } catch {\n fail(scope, `${at}.pattern is not a valid regular expression`)\n }\n // A refusal with no sentence is a form that says no and not why.\n if (!nonEmptyString(setting.patternHint)) fail(scope, `${at} declares a pattern, so it must declare patternHint`)\n }\n }\n // Declared settings nobody can read or write are a screen that renders empty.\n if (settingKeys.size > 0) {\n if (typeof def.getSettings !== 'function') fail(scope, `connectors[${i}] declares settings but no getSettings()`)\n if (typeof def.saveSettings !== 'function') fail(scope, `connectors[${i}] declares settings but no saveSettings()`)\n }\n\n // \"Acionado em quais momentos\" — a moment on a plane the connector does not\n // have is a promise the code cannot keep.\n const planes = new Set(connectorPlanes(def))\n const momentKeys = new Set<string>()\n for (const [j, moment] of (def.invokedAt ?? []).entries()) {\n const at = `connectors[${i}].invokedAt[${j}]`\n if (!nonEmptyString(moment?.key)) fail(scope, `${at}.key must be a non-empty string`)\n if (!nonEmptyString(moment?.label)) fail(scope, `${at}.label must be a non-empty string`)\n if (momentKeys.has(moment.key)) fail(scope, `${at} duplicates key \"${moment.key}\"`)\n momentKeys.add(moment.key)\n const plane = invocationPlane(moment)\n if (!planes.has(plane)) {\n fail(scope, `${at} is declared on the ${plane} plane, which connectors[${i}].planes does not include`)\n }\n if (moment.trigger !== undefined) {\n if (plane !== 'sync') fail(scope, `${at}.trigger only applies to a sync moment`)\n if (!TRIGGERS.has(moment.trigger)) fail(scope, `${at} has unknown trigger \"${moment.trigger}\"`)\n }\n // A moment that reaches something the connector never asked for is the\n // screen answering \"quando ele age\" with access nobody consented to.\n const declared = new Set((def.permissions ?? []).map((p) => p.resource))\n for (const resource of moment.touches ?? []) {\n if (!declared.has(resource)) {\n fail(\n scope,\n `${at}.touches names \"${resource}\", which connectors[${i}].permissions does not declare — ` +\n `a call site cannot reach what the consent view never showed.`,\n )\n }\n }\n }\n\n for (const [j, auto] of (def.managedAutomations ?? []).entries()) {\n if (!nonEmptyString(auto?.eventKey)) fail(scope, `connectors[${i}].managedAutomations[${j}].eventKey must be a non-empty string`)\n if (!nonEmptyString(auto?.label)) fail(scope, `connectors[${i}].managedAutomations[${j}].label must be a non-empty string`)\n // The screen would promise a reaction the ingress never delivers.\n if (!connectorSubscribes(def, auto.eventKey)) {\n fail(scope, `connectors[${i}].managedAutomations[${j}] fires on \"${auto.eventKey}\", which no subscribesTo pattern covers`)\n }\n }\n }\n\n // A connector brings a ConnectorDefinition, not a pair of tables.\n for (const [i, mig] of (manifest.migrations ?? []).entries()) {\n for (const table of bespokeConnectorTables(mig?.sql)) {\n fail(\n scope,\n `migrations[${i}] (\"${mig?.id ?? '?'}\") creates public.${table} — a connector's own ` +\n `*_integrations / *_sync_log table. Store the connection in plg_connections / ` +\n `plg_sync_runs via createConnectionStore('<connector-id>'): two accounts are two ` +\n `rows separated by instance_key, and connector-specific counters go in stats.`,\n )\n }\n }\n\n // A plugin that contributes nothing mountable is almost always a mistake.\n // (Connector-only addon plugins contribute via `connectors` instead.)\n if (\n manifest.navigation.length === 0 &&\n manifest.routes.length === 0 &&\n (manifest.settings ?? []).length === 0 &&\n (manifest.connectors ?? []).length === 0\n ) {\n fail(scope, 'plugin contributes no navigation, routes, settings, or connectors — it would mount but do nothing')\n }\n}\n\n/**\n * What a connector says it needs — and the four ways that declaration can\n * contradict the ones that already existed.\n *\n * The feature this guards is a consent view. Its whole value is that the list it\n * shows is the list, so every way of ending up with two lists is refused here:\n *\n * 1. an action that does not exist for the resource kind (`listen` on a\n * record type, `write` on an event) — a word the reader would have to guess at;\n * 2. a `data` permission naming a resource the legacy `entities` never listed,\n * or an entity with no permission — the \"writes to an entity it never\n * listed\" case, in both directions;\n * 3. a `listen` permission the legacy `subscribesTo` does not name, or a\n * `subscribesTo` pattern no permission explains — the connector would be\n * delivered facts the consent view never showed, or shown facts the ingress\n * filters out;\n * 4. two permissions for the same resource — two rows, two reasons, and no\n * answer to which one the tenant agreed to.\n *\n * Rules 2 and 3 only bite when BOTH declarations are present. A connector built\n * against an older core declares only the legacy fields and is unaffected; a\n * connector written today declares only `permissions` and both are derived from\n * it. What is refused is saying both things and saying them differently.\n */\nfunction assertConnectorPermissions(\n scope: string,\n path: string,\n def: { permissions?: ConnectorPermission[]; entities?: string[]; subscribesTo?: string[] },\n): void {\n const permissions = def.permissions\n if (permissions === undefined) return\n if (!Array.isArray(permissions)) fail(scope, `${path}.permissions must be an array`)\n\n const seen = new Set<string>()\n for (const [j, permission] of permissions.entries()) {\n const at = `${path}.permissions[${j}]`\n if (permission?.kind !== 'data' && permission?.kind !== 'event') {\n fail(scope, `${at}.kind must be \"data\" or \"event\"`)\n }\n if (!nonEmptyString(permission.resource)) fail(scope, `${at}.resource must be a non-empty string`)\n // The reason is the only part a tenant can actually judge; a blank one turns\n // the screen back into the schema dump it exists to replace.\n if (!nonEmptyString(permission.reason)) {\n fail(scope, `${at} must declare a reason — the sentence the tenant judges before authorizing`)\n }\n if (!Array.isArray(permission.actions) || permission.actions.length === 0) {\n fail(scope, `${at}.actions must name at least one action — a resource with no access is not a permission`)\n }\n const legal = permissionActions(permission.kind)\n for (const action of permission.actions) {\n if (!legal.includes(action)) {\n fail(scope, `${at} asks for \"${action}\" on the ${permission.kind} resource \"${permission.resource}\", which only admits ${legal.join(', ')}`)\n }\n }\n if (isEventPermission(permission) && permission.resource.includes('*') && !permission.resource.endsWith('*')) {\n fail(scope, `${at}.resource \"${permission.resource}\" — \"*\" is only honoured at the end`)\n }\n const key = `${permission.kind}:${permission.resource}`\n if (seen.has(key)) fail(scope, `${at} repeats \"${key}\" — one resource, one row, one reason`)\n seen.add(key)\n }\n\n // (2) data permissions ↔ the legacy entities list.\n if (def.entities !== undefined) {\n const declared = new Set(connectorEntities({ permissions }))\n const legacy = new Set(def.entities)\n for (const entity of declared) {\n if (!legacy.has(entity)) {\n fail(\n scope,\n `${path}.permissions reaches \"${entity}\", which ${path}.entities does not list — ` +\n `the two describe the same access and must name the same set (drop entities; it is derived).`,\n )\n }\n }\n for (const entity of legacy) {\n if (!declared.has(entity)) {\n fail(\n scope,\n `${path}.entities lists \"${entity}\" with no permission saying what it does with it — ` +\n `a record type on the consent view with no read/write is a name, not a declaration.`,\n )\n }\n }\n }\n\n // (3) listen permissions ↔ the legacy subscribesTo list.\n if (def.subscribesTo !== undefined) {\n const declared = new Set(connectorSubscribesTo({ permissions }))\n const legacy = new Set(def.subscribesTo)\n for (const pattern of declared) {\n if (!legacy.has(pattern)) {\n fail(\n scope,\n `${path}.permissions listens to \"${pattern}\", which ${path}.subscribesTo does not — ` +\n `the ingress filters on that list, so the consent view would promise a fact never delivered.`,\n )\n }\n }\n for (const pattern of legacy) {\n if (!declared.has(pattern)) {\n fail(\n scope,\n `${path}.subscribesTo asks for \"${pattern}\" with no listen permission explaining it — ` +\n `the connector would receive a fact the tenant was never shown.`,\n )\n }\n }\n }\n}\n\n/**\n * `CREATE TABLE [IF NOT EXISTS] [schema.]name` where name ends in `_integrations`\n * or `_sync_log` — the pair four connectors each reinvented before\n * `plg_connections` / `plg_sync_runs` existed (FAY-1376). Neither generic table\n * matches, so a connector that stores its connection in them creates nothing.\n *\n * Deliberately duplicated in scripts/check-connector-tables.mjs, which scans the\n * .sql files themselves: that runs in the `contracts` CI job with no install and\n * no build, so it cannot import this. This half catches SQL declared inline on a\n * manifest, which no .sql walk would see. The two are held in agreement by one\n * case table, asserted from both sides — see\n * packages/core/test/integrations/connector-tables.test.ts.\n */\nconst BESPOKE_CONNECTOR_TABLE =\n /\\bcreate\\s+table\\s+(?:if\\s+not\\s+exists\\s+)?(?:[a-z0-9_]+\\s*\\.\\s*)?([a-z0-9_]*(?:_integrations|_sync_log))\\b/gi\n\n/** Table names a CREATE TABLE in this SQL would bring back. Empty = conformant. */\nexport function bespokeConnectorTables(sql: unknown): string[] {\n const text = typeof sql === 'string' ? sql.replace(/\"/g, '') : ''\n const found = new Set<string>()\n for (const m of text.matchAll(BESPOKE_CONNECTOR_TABLE)) found.add(m[1].toLowerCase())\n return [...found]\n}\n\nconst EVENT_ACTIONS = new Set(['created', 'updated', 'deleted'])\nconst FUNCTION_INGRESS = new Set(['fayz', 'none'])\nconst SLUG = /^[a-z0-9][a-z0-9-]*$/\nconst SECRET_NAME = /^[A-Z][A-Z0-9_]*$/\n\nconst SETTING_TYPES = new Set(['text', 'select', 'multi-select', 'toggle'])\nconst AUTH_KINDS = new Set(['oauth', 'api-key', 'mtls'])\nconst DIRECTIONS = new Set(['inbound', 'outbound', 'bidirectional'])\nconst TRIGGERS = new Set(['on-write', 'scheduled', 'manual', 'webhook'])\n\n/**\n * Assert an integration Connector descriptor is well-formed: identity present,\n * a known auth kind, and at least one capability with a valid direction +\n * trigger set. This is the contract a connector must satisfy BEFORE its\n * data-plane (edge function) exists — the TDD anchor for an integration.\n */\nexport function assertConnectorContract(connector: Connector): void {\n const scope = nonEmptyString(connector?.id) ? `connector:${connector.id}` : '<unknown connector>'\n for (const field of ['id', 'provider', 'pluginId'] as const) {\n if (!nonEmptyString(connector?.[field])) fail(scope, `connector.${field} must be a non-empty string`)\n }\n if (!AUTH_KINDS.has(connector.authKind)) fail(scope, `connector.authKind \"${connector.authKind}\" is not one of ${[...AUTH_KINDS].join(', ')}`)\n if (!Array.isArray(connector.capabilities) || connector.capabilities.length === 0) {\n fail(scope, 'connector.capabilities must list at least one capability')\n }\n for (const [i, cap] of connector.capabilities.entries()) {\n if (!nonEmptyString(cap?.entity)) fail(scope, `capabilities[${i}].entity must be a non-empty string`)\n if (!DIRECTIONS.has(cap.direction)) fail(scope, `capabilities[${i}].direction \"${cap.direction}\" is invalid`)\n if (!Array.isArray(cap.triggers) || cap.triggers.length === 0) fail(scope, `capabilities[${i}].triggers must be non-empty`)\n for (const trig of cap.triggers) {\n if (!TRIGGERS.has(trig)) fail(scope, `capabilities[${i}] has unknown trigger \"${trig}\"`)\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `@fayz-ai/core/connector-runtime` entry, in SOURCE mode.
|
|
3
|
+
*
|
|
4
|
+
* `tsup.config.ts` builds this subpath straight from `src/integrations/runtime.ts`,
|
|
5
|
+
* so published mode never needed a directory here. Source mode did: an app
|
|
6
|
+
* resolves `@fayz-ai/core/*` to `packages/core/src/*`, so the moment
|
|
7
|
+
* `plugins/plugin-shop/src/integrations/bling/sync.ts` imported this subpath,
|
|
8
|
+
* every dev server broke on a path that exists only after a build.
|
|
9
|
+
*
|
|
10
|
+
* That is the source-mode/published-mode asymmetry AGENTS.md warns about, and
|
|
11
|
+
* the cheapest permanent fix is this file: one re-export, so both modes resolve
|
|
12
|
+
* the same module.
|
|
13
|
+
*/
|
|
14
|
+
export * from '../integrations/runtime';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/connector-runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,yBAAyB,CAAA"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { CONNECTOR_REDEMPTION_ENV_KEYS, CONNECTOR_RUNTIME_TOKEN_HEADER, ConnectorCredentialUnavailableError, ConnectorHttpError, RateLimitExceededError, advanceWindow, backoffDelay, classify, createRateLimiter, cursorCompleteness, fetchWithRetry, isExpiring, paginate, parseRetryAfter, reconcileMirror, redeemConnectorCredential, redemptionFailure, redemptionHost, serializeCursor, sliceWindow, statusNeedsBody } from '../chunk-ED6NBH6U.js';
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|