@fayz-ai/sdk 0.15.0 → 0.19.1
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/dist/agent.d.ts +29 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +1 -1
- package/dist/{chunk-QLTIO3QK.js → chunk-BTXIUI4E.js} +49 -11
- package/dist/chunk-BTXIUI4E.js.map +1 -0
- package/dist/{chunk-LSBVNW75.js → chunk-KTRZI44K.js} +2 -2
- package/dist/chunk-KTRZI44K.js.map +1 -0
- package/dist/chunk-L2FWBQU6.js +135 -0
- package/dist/{chunk-M5CVCRIL.js.map → chunk-L2FWBQU6.js.map} +1 -1
- package/dist/{chunk-HA5O3CW7.js → chunk-LCW5ZV5S.js} +3 -24
- package/dist/chunk-LCW5ZV5S.js.map +1 -0
- package/dist/deprecations.js +1 -1
- package/dist/deprecations.json +2 -23
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +19 -2
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/connector-account.d.ts +79 -0
- package/dist/lib/connector-account.d.ts.map +1 -0
- package/dist/release-channels.js +1 -1
- package/dist/release-channels.json +93 -93
- package/dist/shop.d.ts +30 -1
- package/dist/shop.d.ts.map +1 -1
- package/dist/shop.js +2 -2
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +26 -1
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-HA5O3CW7.js.map +0 -1
- package/dist/chunk-LSBVNW75.js.map +0 -1
- package/dist/chunk-M5CVCRIL.js +0 -135
- package/dist/chunk-QLTIO3QK.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/platform-url.ts","../src/lib/credentials.ts","../src/lib/connector-oauth.ts","../src/lib/runtime-token.ts"],"names":["requireValue"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Where the Fayz platform lives, from whatever the app happened to configure.\n *\n * Two spellings are already in the wild and they disagree by one segment:\n * `VITE_FAYZ_API_BASE_URL` in a published app's env is written as\n * `https://host/api` (that is what the agent broker client consumes), while the\n * sink and the token source below build paths that start with `/api`. Taking\n * either at face value produces `/api/api/public/...` in half the fleet, and a\n * 404 at connect time reads as \"the platform refused my credential\".\n *\n * So the origin is normalised once, here, rather than in each caller: trailing\n * slashes go, and a trailing `/api` is dropped because the paths add it back.\n */\nexport function fayzPlatformOrigin(baseUrl: string | undefined): string {\n const trimmed = (baseUrl ?? '').trim().replace(/\\/+$/, '')\n return trimmed.replace(/\\/api$/, '')\n}\n","/**\n * The credential sink — where a tenant's secret goes INSTEAD of into the app.\n *\n * A connector declares an \"API Key\" field, the hub renders it, and the obvious\n * next move is to hand the typed value to the connector's own `saveConnection`.\n * That move is the hole: connector-author code runs in the browser with a\n * working Supabase client in scope, so \"the connector promises not to persist\n * it\" is a convention, not a guarantee — and this repo broke it three times\n * before anyone noticed. Dropping the columns did not close it either; the\n * secret still reached the code that chose where to put it.\n *\n * So the secret never reaches that code. The hub splits the form and pushes the\n * secret half here, to a holder outside the app: Fayz keeps it, and the data\n * plane (an edge function, the agent runtime) will read it server-side per call\n * — the redeem consumer is FAY-1389; nothing redeems yet.\n *\n * A port rather than a `fetch`, for the same reason `setPostalLookupProvider` is\n * one: who holds the credential is a deployment fact, not a hub fact. An app\n * supplies its sink once at boot. Supplying none is a valid answer — the hub\n * then refuses to save, which is the only safe way to be unconfigured.\n */\n\nimport { fayzPlatformOrigin } from './platform-url'\n\n/**\n * How the tenant authorized. Mirrors `IntegrationAuthKind` in `@fayz-ai/core`,\n * declared again here because `@fayz-ai/sdk` has no dependencies.\n */\nexport type ConnectorCredentialAuthKind = 'oauth' | 'api-key' | 'mtls'\n\nexport interface StoreConnectorCredentialInput {\n /** Connector the secret belongs to, e.g. 'plugbank'. */\n connectorId: string\n /** Organization it is scoped to, when the app knows it; the holder may also derive it from the session. */\n tenantId?: string\n /**\n * How the connector authenticates, from its own `ConnectorDefinition`.\n *\n * The holder needs it and the browser must not invent it, so it is threaded\n * from the declaration rather than guessed from the shape of `secrets`.\n * Optional because a holder may not care; the Fayz sink below defaults it.\n */\n authKind?: ConnectorCredentialAuthKind\n /** Declared field key → value. The only object the secret lives in, and it is not kept after the call. */\n secrets: Record<string, string>\n}\n\n/** What an app may keep in its own database once the secret is placed: a handle. */\nexport interface ConnectorCredentialRef {\n /** Opaque id the holder gave the credential. Never the credential. */\n id: string\n}\n\nexport interface ConnectorCredentialSink {\n store(input: StoreConnectorCredentialInput): Promise<ConnectorCredentialRef>\n}\n\nlet _sink: ConnectorCredentialSink | null = null\n\nexport function setConnectorCredentialSink(sink: ConnectorCredentialSink | null): void {\n _sink = sink\n}\n\n/** Null when the app configured none — callers must refuse, never fall back. */\nexport function getConnectorCredentialSink(): ConnectorCredentialSink | null {\n return _sink\n}\n\n// ---------------------------------------------------------------------------\n// The Fayz-hosted holder — the sink most apps install\n// ---------------------------------------------------------------------------\n//\n// Everything above is the port. What follows is the one implementation the SDK\n// ships: a client for `POST /api/public/projects/:projectId/connectors/\n// connections`, the endpoint the platform added in FAY-1353.\n//\n// An app installs it once, at boot, next to wherever it already configures its\n// backend:\n//\n// import { getFayzSupabaseClientOptional } from '@fayz-ai/admin'\n// import {\n// createFayzConnectorCredentialSink,\n// createFayzRuntimeTokenSource,\n// setConnectorCredentialSink,\n// } from '@fayz-ai/sdk'\n//\n// setConnectorCredentialSink(createFayzConnectorCredentialSink({\n// projectId,\n// runtimeToken: createFayzRuntimeTokenSource({\n// projectId,\n// supabase: getFayzSupabaseClientOptional,\n// }),\n// }))\n//\n// Installing nothing stays a valid answer: the hub refuses to save an api-key\n// connector, which is the correct behaviour for an app with nowhere safe to put\n// a credential. There is no default sink for exactly that reason.\n\n/** The credential was not placed. Carries a status when the platform answered. */\nexport class ConnectorCredentialSinkError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message)\n this.name = 'ConnectorCredentialSinkError'\n }\n}\n\n/**\n * What the sink can tell a token source about the call it is authenticating.\n *\n * Only the tenant, and only as a SELECTOR: the runtime-token endpoint proves\n * membership from the session and refuses anything outside it, so naming an org\n * here narrows which of the caller's own organizations the token is for and can\n * never widen it. Without this the source would have to re-derive the active\n * org from a store it does not know about, in an app that may have several.\n */\nexport interface FayzRuntimeTokenRequest {\n tenantId?: string\n}\n\nexport type FayzRuntimeTokenSource =\n | string\n | ((\n request?: FayzRuntimeTokenRequest,\n ) => string | undefined | null | Promise<string | undefined | null>)\n\nexport interface FayzConnectorCredentialSinkOptions {\n /** The Fayz project this app was published from. */\n projectId: string\n /**\n * A Fayz **runtime-data** token — the only scheme this endpoint accepts,\n * because it is the only one on the public plane that carries tenant identity.\n * A publishable key names an APP, so it cannot say which tenant is connecting.\n *\n * Required, and resolved per call so a short-lived token can be refreshed.\n * There is deliberately no fallback: a sink that cannot authenticate looks\n * configured and is worse than none, so an empty token is a refusal, not a\n * best-effort request.\n */\n runtimeToken: FayzRuntimeTokenSource\n /** Fayz platform origin. Defaults to same-origin, which is what an app proxying `/api` wants. */\n baseUrl?: string\n fetcher?: typeof fetch\n}\n\n/**\n * Values the platform accepts.\n *\n * All three, since FAY-1381 widened `CONNECTOR_AUTH_KINDS` on the platform.\n * Until then this collapsed `mtls` into `api-key` to get past a 400, which\n * recorded something the tenant did not do — a client certificate filed as an\n * API key. Storage was always identical for the three; only the vocabulary was\n * narrow.\n */\ntype WireAuthKind = ConnectorCredentialAuthKind\n\n/**\n * The request body, spelled out because the route schema is `.strict()`.\n *\n * `tenantId` is absent and must stay absent: the platform derives the tenant\n * from the verified token claims, and a body field naming one is precisely the\n * bug FAY-1375 was. A `tenantId` handed to `store()` is therefore never\n * forwarded here — it goes to the token source instead, where the platform can\n * check it against proven memberships before it means anything.\n */\ninterface StoreConnectionBody {\n connectorSlug: string\n authKind: WireAuthKind\n secrets: Record<string, string>\n}\n\nfunction requireValue(value: string | undefined, field: string): string {\n const normalized = typeof value === 'string' ? value.trim() : ''\n if (!normalized) throw new ConnectorCredentialSinkError(`${field} is required to store a connector credential`)\n return normalized\n}\n\n/**\n * Remove every secret value from text that is about to become an error message.\n *\n * The platform does not echo values today; this is here so that a future one\n * that does cannot turn a 400 into a leak. It runs on the raw response text, so\n * nothing from the wire reaches a message unfiltered.\n */\nfunction redactSecrets(text: string, secrets: Record<string, string>): string {\n let out = text\n for (const value of Object.values(secrets)) {\n if (value) out = out.split(value).join('[redacted]')\n }\n return out\n}\n\nfunction reasonFrom(text: string, secrets: Record<string, string>): string {\n const redacted = redactSecrets(text, secrets).trim()\n if (!redacted) return ''\n return `: ${redacted.slice(0, 300)}`\n}\n\n/**\n * A sink backed by the Fayz platform's connector-connection store.\n *\n * Write-only by construction: the response is a handle, and no method here can\n * read a credential back — redemption is a separate endpoint that requires a\n * second key a browser has no way to hold.\n */\nexport function createFayzConnectorCredentialSink(\n options: FayzConnectorCredentialSinkOptions,\n): ConnectorCredentialSink {\n const projectId = requireValue(options.projectId, 'projectId')\n const origin = fayzPlatformOrigin(options.baseUrl)\n const fetcher = options.fetcher ?? fetch\n // No query string, ever. The secret travels in the body of one POST and the\n // path carries nothing but the project — a URL is logged by every proxy.\n const url = `${origin}/api/public/projects/${encodeURIComponent(projectId)}/connectors/connections`\n\n async function resolveRuntimeToken(request: FayzRuntimeTokenRequest): Promise<string> {\n const source = options.runtimeToken\n const value = typeof source === 'function' ? await source(request) : source\n const token = typeof value === 'string' ? value.trim() : ''\n if (!token) {\n throw new ConnectorCredentialSinkError(\n 'No Fayz runtime token is available, so the credential was not stored',\n )\n }\n return token\n }\n\n return {\n async store(input: StoreConnectorCredentialInput): Promise<ConnectorCredentialRef> {\n // The platform calls it `connectorSlug`; the port calls it `connectorId`.\n const connectorSlug = requireValue(input.connectorId, 'connectorId')\n const secrets = input.secrets ?? {}\n if (Object.keys(secrets).length === 0) {\n throw new ConnectorCredentialSinkError('There is no secret to store for this connector')\n }\n\n // The tenant reaches the platform through the TOKEN, which is minted\n // against a verified session, and not through the body, which is only\n // what the browser typed.\n const token = await resolveRuntimeToken({ tenantId: input.tenantId })\n const body: StoreConnectionBody = {\n connectorSlug,\n authKind: input.authKind ?? 'api-key',\n secrets,\n }\n\n const response = await fetcher(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n })\n\n const text = await response.text().catch(() => '')\n\n if (!response.ok) {\n throw new ConnectorCredentialSinkError(\n `Fayz refused the connector credential (${response.status})${reasonFrom(text, secrets)}`,\n response.status,\n )\n }\n\n let parsed: unknown\n try {\n parsed = text ? JSON.parse(text) : undefined\n } catch {\n parsed = undefined\n }\n\n const id = (parsed as { connection?: { id?: unknown } } | undefined)?.connection?.id\n // A 2xx with no handle is not a success anyone can act on — the app would\n // record the connection as live against a credential that may not exist.\n if (typeof id !== 'string' || !id) {\n throw new ConnectorCredentialSinkError(\n `Fayz accepted the credential but returned no handle (${response.status})`,\n response.status,\n )\n }\n\n return { id }\n },\n }\n}\n","/**\n * Sending a merchant to a partner's consent screen — written once.\n *\n * Every OAuth connector needs the same four moves: mint a runtime token, POST\n * the app's own start endpoint, read a URL back, hand it to the hub to navigate\n * to. Copied into each connector that is four chances to disagree about the\n * path, the token, the tenant and the failure — and the failure is the one that\n * matters, because a `startOAuth` this repo forgot to write is a Connect button\n * that renders DISABLED with nothing on screen saying why. That is exactly how\n * Bling shipped.\n *\n * So a connector declares one line:\n *\n * startOAuth: fayzConnectorOAuth('bling')\n *\n * and everything below is shared. The platform side of the contract:\n *\n * POST /api/public/projects/:projectId/oauth/:provider/start\n * Authorization: Bearer <runtime-data token>\n * { tenantId?, redirectTo } → 201 { url }\n *\n * GET /api/oauth/redirect/:provider → 302 to redirectTo\n * ?fayzConnector=<slug>&fayzConnectorStatus=connected|error\n * &fayzConnectorMessage=<slug from a closed set>\n *\n * The redirect half is read by `oauth-return.ts` in `@fayz-ai/admin`; nothing\n * here has to know about it. The provider never gets a per-request\n * `redirect_uri` — Bling ignores one outright and always uses what is registered\n * on the app — so `redirectTo` travels inside the platform's signed state and\n * comes back out at the end.\n *\n * A port and not a bare `fetch`, for the same reason the credential sink is one:\n * WHICH Fayz project this app belongs to is a deployment fact. The app installs\n * one starter at boot; installing none is a valid answer, and then the connect\n * step refuses instead of quietly opening a consent screen for a project that\n * cannot finish the flow.\n */\n\nimport type { FayzRuntimeTokenRequest, FayzRuntimeTokenSource } from './credentials'\nimport { fayzPlatformOrigin } from './platform-url'\n\n/** The consent flow did not start. Carries a status when the platform answered. */\nexport class ConnectorOAuthError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message)\n this.name = 'ConnectorOAuthError'\n }\n}\n\n/** This app has nowhere to start a consent flow, so it refuses rather than guessing. */\nexport class ConnectorOAuthStarterMissingError extends ConnectorOAuthError {\n constructor() {\n super('No connector OAuth starter configured')\n this.name = 'ConnectorOAuthStarterMissingError'\n }\n}\n\nexport interface StartConnectorOAuthInput {\n /**\n * The `:provider` path segment — the platform catalogue's slug, which is what\n * knows the client id, the consent host and the registered redirect.\n */\n provider: string\n /**\n * Which connector definition this authorizes. Usually the same word as\n * `provider`; they part when the implementation is named after us rather than\n * after them (`plugbank` is the catalogue's `tecnospeed`).\n */\n connectorId: string\n /** Where the merchant lands when it is over — the page they left from, hash and all. */\n redirectTo: string\n /** The organization being connected. A selector the platform re-checks; see the port doc. */\n tenantId?: string\n}\n\n/** Where a consent flow is started from. Supplied once at boot. */\nexport interface ConnectorOAuthStarter {\n start(input: StartConnectorOAuthInput): Promise<string>\n}\n\nlet _starter: ConnectorOAuthStarter | null = null\n\nexport function setConnectorOAuthStarter(starter: ConnectorOAuthStarter | null): void {\n _starter = starter\n}\n\n/** Null when the app configured none — callers must refuse, never fall back. */\nexport function getConnectorOAuthStarter(): ConnectorOAuthStarter | null {\n return _starter\n}\n\nexport interface FayzConnectorOAuthStarterOptions {\n /** The Fayz project this app was published from. */\n projectId: string\n /**\n * A Fayz **runtime-data** token. Same requirement, and same reason, as the\n * credential sink's: it is the only scheme on the public plane that carries\n * tenant identity, and a publishable key names an app rather than a tenant.\n * Resolved per call so a short-lived token can be refreshed.\n */\n runtimeToken: FayzRuntimeTokenSource\n /** Fayz platform origin. Defaults to same-origin, which is what an app proxying `/api` wants. */\n baseUrl?: string\n fetcher?: typeof fetch\n}\n\nfunction requireValue(value: string | undefined, field: string): string {\n const normalized = typeof value === 'string' ? value.trim() : ''\n if (!normalized) throw new ConnectorOAuthError(`${field} is required to start a connector OAuth flow`)\n return normalized\n}\n\n/**\n * The starter backed by the Fayz platform. Installed once at boot, next to the\n * credential sink:\n *\n * const runtimeToken = createFayzRuntimeTokenSource({ projectId, supabase: getFayzSupabaseClientOptional })\n * setConnectorCredentialSink(createFayzConnectorCredentialSink({ projectId, runtimeToken }))\n * setConnectorOAuthStarter(createFayzConnectorOAuthStarter({ projectId, runtimeToken }))\n */\nexport function createFayzConnectorOAuthStarter(\n options: FayzConnectorOAuthStarterOptions,\n): ConnectorOAuthStarter {\n const projectId = requireValue(options.projectId, 'projectId')\n const origin = fayzPlatformOrigin(options.baseUrl)\n const fetcher = options.fetcher ?? fetch\n\n async function resolveRuntimeToken(request: FayzRuntimeTokenRequest): Promise<string> {\n const source = options.runtimeToken\n const value = typeof source === 'function' ? await source(request) : source\n const token = typeof value === 'string' ? value.trim() : ''\n if (!token) {\n throw new ConnectorOAuthError('No Fayz runtime token is available, so no consent flow was started')\n }\n return token\n }\n\n return {\n async start(input: StartConnectorOAuthInput): Promise<string> {\n const provider = requireValue(input.provider, 'provider')\n const redirectTo = requireValue(input.redirectTo, 'redirectTo')\n const token = await resolveRuntimeToken({ tenantId: input.tenantId })\n\n const url = `${origin}/api/public/projects/${encodeURIComponent(projectId)}/oauth/${encodeURIComponent(provider)}/start`\n const response = await fetcher(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },\n // Absent rather than null: the route schema is `.strict()`.\n body: JSON.stringify(input.tenantId ? { tenantId: input.tenantId, redirectTo } : { redirectTo }),\n })\n\n const text = await response.text().catch(() => '')\n\n if (!response.ok) {\n const reason = text.trim().slice(0, 300)\n throw new ConnectorOAuthError(\n `Fayz did not start the ${provider} authorization (${response.status})${reason ? `: ${reason}` : ''}`,\n response.status,\n )\n }\n\n let parsed: { url?: unknown } | undefined\n try {\n parsed = text ? JSON.parse(text) : undefined\n } catch {\n parsed = undefined\n }\n\n const consentUrl = typeof parsed?.url === 'string' ? parsed.url.trim() : ''\n // A blank URL would navigate the merchant to the app's own root and look\n // like the consent screen never opened, which is unreadable at the\n // support desk. Fail loudly at the one place that knows why.\n if (!consentUrl) {\n throw new ConnectorOAuthError(\n `Fayz answered ${response.status} without a consent URL for ${provider}`,\n response.status,\n )\n }\n return consentUrl\n },\n }\n}\n\n/**\n * Start a consent flow through the installed starter.\n *\n * `starter` is a test seam; pass `null` to assert there is none.\n */\nexport async function startConnectorOAuth(\n input: StartConnectorOAuthInput & { starter?: ConnectorOAuthStarter | null },\n): Promise<string> {\n const starter = input.starter === undefined ? getConnectorOAuthStarter() : input.starter\n if (!starter) throw new ConnectorOAuthStarterMissingError()\n return starter.start(input)\n}\n\n/**\n * A connector's whole `startOAuth`, in one line.\n *\n * startOAuth: fayzConnectorOAuth('bling')\n * startOAuth: fayzConnectorOAuth('plugbank', { provider: 'tecnospeed' })\n *\n * `provider` defaults to the connector id because for almost every connector\n * the two are the same word, and a default that is right by construction is one\n * fewer thing for the next connector to get wrong.\n */\nexport function fayzConnectorOAuth(\n connectorId: string,\n options: { provider?: string } = {},\n): (redirectTo?: string, context?: { tenantId?: string }) => Promise<string> {\n const provider = options.provider ?? connectorId\n return (redirectTo, context) =>\n startConnectorOAuth({\n provider,\n connectorId,\n // The hub always passes the page the merchant left from. The fallback is\n // for a caller that has none — a bare origin still returns them to the app.\n redirectTo: redirectTo ?? (typeof window !== 'undefined' ? window.location.href : ''),\n tenantId: context?.tenantId,\n })\n}\n","/**\n * The key the credential sink needs — minted once, in one place.\n *\n * `ConnectorCredentialSink` requires a Fayz runtime-data token and deliberately\n * has no fallback, so until something hands it one the connect button refuses.\n * The token exists: `POST /api/public/projects/:projectId/runtime-token` trades\n * the app's OWN Supabase session for it. What did not exist is the client, and\n * writing that `fetch` per app is how five apps end up with five cache policies\n * and four of them without one.\n *\n * The exchange, as the platform actually implements it:\n *\n * Authorization: Bearer <the app's Supabase access token>\n * body: { tenantId? } → 201\n * { token, tokenType: 'Bearer', expiresIn, projectId, tenantId }\n *\n * `tenantId` in the body is a SELECTOR, never an assertion. The platform\n * verifies the session against the project's published JWKS, asks the app's own\n * database which organizations that user belongs to, and refuses a `tenantId`\n * outside that set; omitting it is resolved only when the answer is\n * unambiguous. Naming a tenant here therefore cannot widen anything — which is\n * why it is safe for the hub to pass the org the merchant is looking at.\n *\n * Fail-closed throughout: no session means no token means the sink refuses. A\n * source that quietly resolved to an empty string would leave an app looking\n * configured while every save fails, which is the failure that is hard to read.\n */\n\nimport type { FayzRuntimeTokenRequest } from './credentials'\nimport { fayzPlatformOrigin } from './platform-url'\n\n/** No token was minted. Carries a status when the platform answered. */\nexport class FayzRuntimeTokenError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message)\n this.name = 'FayzRuntimeTokenError'\n }\n}\n\n/**\n * The slice of a Supabase client this module touches.\n *\n * Duck-typed because `@fayz-ai/sdk` has no dependencies and must not grow one:\n * an app passes the client it already built (`getFayzSupabaseClientOptional()`\n * in `@fayz-ai/admin`), and nothing here needs the other four hundred methods.\n */\nexport interface SupabaseSessionClientLike {\n auth: {\n getSession(): Promise<{ data: { session: { access_token?: string | null } | null } }>\n }\n}\n\ntype Resolvable<T> = T | (() => T | Promise<T>)\n\nexport interface FayzRuntimeTokenSourceOptions {\n /** The Fayz project this app was published from. */\n projectId: string\n /**\n * The app's Supabase client, or a getter for one.\n *\n * A getter is the usual answer: the client is built when the app boots its\n * backend, which is after the module that installs the sink has run. Reading\n * it once at construction would pin `null` forever.\n */\n supabase?: Resolvable<SupabaseSessionClientLike | null | undefined>\n /**\n * Or, for an app whose session does not come from supabase-js, the access\n * token itself. Exactly one of `supabase` / `accessToken` is required.\n */\n accessToken?: Resolvable<string | null | undefined>\n /**\n * Which organization to ask for when the caller names none. Still only a\n * selector — see the header. Apps with one org per user can leave it unset.\n */\n tenantId?: Resolvable<string | null | undefined>\n /** Fayz platform origin. Defaults to same-origin, which is what an app proxying `/api` wants. */\n baseUrl?: string\n fetcher?: typeof fetch\n /**\n * How long before expiry a cached token stops being handed out. The token is\n * short-lived (15 minutes today) and the request it authenticates is a POST\n * that must not fail at the boundary, so the last stretch is not spent.\n */\n refreshLeadSeconds?: number\n /** Test seam. */\n now?: () => number\n}\n\nexport interface FayzRuntimeTokenSourceHandle {\n (request?: FayzRuntimeTokenRequest): Promise<string>\n /** Forget every cached token — after a sign-out, or an org switch that changed who is asking. */\n invalidate(): void\n}\n\ninterface CacheEntry {\n token: string\n /** Epoch ms at which this token stops being handed out (already minus the lead). */\n goodUntil: number\n}\n\nfunction requireValue(value: string | undefined, field: string): string {\n const normalized = typeof value === 'string' ? value.trim() : ''\n if (!normalized) throw new FayzRuntimeTokenError(`${field} is required to mint a Fayz runtime token`)\n return normalized\n}\n\nasync function resolve<T>(source: Resolvable<T> | undefined): Promise<T | undefined> {\n if (source === undefined) return undefined\n return typeof source === 'function' ? await (source as () => T | Promise<T>)() : source\n}\n\n/**\n * Strip the session token from text on its way into an error message.\n *\n * The platform does not echo it, and this is here so that a future one that\n * does cannot turn a 403 into a leak. The bearer being redacted is the user's\n * session — the same class of thing the sink redacts on its own side.\n */\nfunction withoutToken(text: string, token: string): string {\n return token ? text.split(token).join('[redacted]') : text\n}\n\n/**\n * Trade the app's Supabase session for a Fayz runtime-data token, and keep it\n * until shortly before it expires.\n *\n * The result is a function, so it drops straight into the sink:\n *\n * setConnectorCredentialSink(createFayzConnectorCredentialSink({\n * projectId,\n * runtimeToken: createFayzRuntimeTokenSource({ projectId, supabase: getClient }),\n * }))\n */\nexport function createFayzRuntimeTokenSource(\n options: FayzRuntimeTokenSourceOptions,\n): FayzRuntimeTokenSourceHandle {\n const projectId = requireValue(options.projectId, 'projectId')\n if (options.supabase === undefined && options.accessToken === undefined) {\n throw new FayzRuntimeTokenError(\n 'A Fayz runtime token source needs a session: pass either `supabase` or `accessToken`',\n )\n }\n\n const origin = fayzPlatformOrigin(options.baseUrl)\n const fetcher = options.fetcher ?? fetch\n const now = options.now ?? (() => Date.now())\n const leadMs = Math.max(0, options.refreshLeadSeconds ?? 60) * 1_000\n const url = `${origin}/api/public/projects/${encodeURIComponent(projectId)}/runtime-token`\n\n // Keyed by the tenant that was ASKED for, because a token minted for one org\n // is not a token for another — reusing it across an org switch would act on\n // the wrong tenant's connections with a token the platform correctly accepts.\n const cache = new Map<string, CacheEntry>()\n const inFlight = new Map<string, Promise<string>>()\n\n async function readAccessToken(): Promise<string> {\n const direct = await resolve(options.accessToken)\n if (typeof direct === 'string' && direct.trim()) return direct.trim()\n\n const client = await resolve(options.supabase)\n const session = client ? (await client.auth.getSession()).data.session : null\n const token = typeof session?.access_token === 'string' ? session.access_token.trim() : ''\n if (!token) {\n throw new FayzRuntimeTokenError('Nobody is signed in to this app, so no Fayz runtime token was minted')\n }\n return token\n }\n\n async function mint(tenantId: string | undefined): Promise<string> {\n const accessToken = await readAccessToken()\n\n const response = await fetcher(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n },\n // `.strict()` on the route: `tenantId` is the only field it accepts, and\n // an absent one must be absent rather than null.\n body: JSON.stringify(tenantId ? { tenantId } : {}),\n })\n\n const text = await response.text().catch(() => '')\n\n if (!response.ok) {\n const reason = withoutToken(text, accessToken).trim().slice(0, 300)\n throw new FayzRuntimeTokenError(\n `Fayz did not issue a runtime token (${response.status})${reason ? `: ${reason}` : ''}`,\n response.status,\n )\n }\n\n let parsed: { token?: unknown; expiresIn?: unknown; tenantId?: unknown } | undefined\n try {\n parsed = text ? JSON.parse(text) : undefined\n } catch {\n parsed = undefined\n }\n\n const token = typeof parsed?.token === 'string' ? parsed.token.trim() : ''\n if (!token) {\n throw new FayzRuntimeTokenError(\n `Fayz answered ${response.status} without a runtime token`,\n response.status,\n )\n }\n\n // An unstated or nonsensical lifetime is not cached: handing out a token\n // whose expiry is guessed is how a save fails at the one moment it matters.\n const expiresIn = typeof parsed?.expiresIn === 'number' ? parsed.expiresIn : NaN\n if (Number.isFinite(expiresIn) && expiresIn * 1_000 > leadMs) {\n const key = cacheKey(tenantId)\n cache.set(key, { token, goodUntil: now() + expiresIn * 1_000 - leadMs })\n // The platform names the tenant it decided on. When the caller asked for\n // none and the answer was unambiguous, the same token serves the explicit\n // ask that the hub makes a moment later.\n const resolved = typeof parsed?.tenantId === 'string' ? parsed.tenantId.trim() : ''\n if (resolved && !tenantId) cache.set(cacheKey(resolved), { ...cache.get(key)! })\n }\n\n return token\n }\n\n function cacheKey(tenantId: string | undefined): string {\n return tenantId ?? ''\n }\n\n const source = (async (request?: FayzRuntimeTokenRequest): Promise<string> => {\n const asked = (request?.tenantId ?? (await resolve(options.tenantId))) || undefined\n const tenantId = typeof asked === 'string' && asked.trim() ? asked.trim() : undefined\n const key = cacheKey(tenantId)\n\n const cached = cache.get(key)\n if (cached && cached.goodUntil > now()) return cached.token\n if (cached) cache.delete(key)\n\n // Two components asking at once is one exchange. Not a nicety: each call\n // reads the session and posts, and a burst of them against the token\n // endpoint is exactly the shape rate limits are written for.\n const existing = inFlight.get(key)\n if (existing) return existing\n\n const flight = mint(tenantId).finally(() => inFlight.delete(key))\n inFlight.set(key, flight)\n return flight\n }) as FayzRuntimeTokenSourceHandle\n\n source.invalidate = () => {\n cache.clear()\n }\n\n return source\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/platform-url.ts","../src/lib/credentials.ts","../src/lib/connector-oauth.ts","../src/lib/connector-account.ts","../src/lib/runtime-token.ts"],"names":["requireValue","value"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Where the Fayz platform lives, from whatever the app happened to configure.\n *\n * Two spellings are already in the wild and they disagree by one segment:\n * `VITE_FAYZ_API_BASE_URL` in a published app's env is written as\n * `https://host/api` (that is what the agent broker client consumes), while the\n * sink and the token source below build paths that start with `/api`. Taking\n * either at face value produces `/api/api/public/...` in half the fleet, and a\n * 404 at connect time reads as \"the platform refused my credential\".\n *\n * So the origin is normalised once, here, rather than in each caller: trailing\n * slashes go, and a trailing `/api` is dropped because the paths add it back.\n */\nexport function fayzPlatformOrigin(baseUrl: string | undefined): string {\n const trimmed = (baseUrl ?? '').trim().replace(/\\/+$/, '')\n return trimmed.replace(/\\/api$/, '')\n}\n","/**\n * The credential sink — where a tenant's secret goes INSTEAD of into the app.\n *\n * A connector declares an \"API Key\" field, the hub renders it, and the obvious\n * next move is to hand the typed value to the connector's own `saveConnection`.\n * That move is the hole: connector-author code runs in the browser with a\n * working Supabase client in scope, so \"the connector promises not to persist\n * it\" is a convention, not a guarantee — and this repo broke it three times\n * before anyone noticed. Dropping the columns did not close it either; the\n * secret still reached the code that chose where to put it.\n *\n * So the secret never reaches that code. The hub splits the form and pushes the\n * secret half here, to a holder outside the app: Fayz keeps it, and the data\n * plane (an edge function, the agent runtime) will read it server-side per call\n * — the redeem consumer is FAY-1389; nothing redeems yet.\n *\n * A port rather than a `fetch`, for the same reason `setPostalLookupProvider` is\n * one: who holds the credential is a deployment fact, not a hub fact. An app\n * supplies its sink once at boot. Supplying none is a valid answer — the hub\n * then refuses to save, which is the only safe way to be unconfigured.\n */\n\nimport { fayzPlatformOrigin } from './platform-url'\n\n/**\n * How the tenant authorized. Mirrors `IntegrationAuthKind` in `@fayz-ai/core`,\n * declared again here because `@fayz-ai/sdk` has no dependencies.\n */\nexport type ConnectorCredentialAuthKind = 'oauth' | 'api-key' | 'mtls'\n\nexport interface StoreConnectorCredentialInput {\n /** Connector the secret belongs to, e.g. 'plugbank'. */\n connectorId: string\n /** Organization it is scoped to, when the app knows it; the holder may also derive it from the session. */\n tenantId?: string\n /**\n * How the connector authenticates, from its own `ConnectorDefinition`.\n *\n * The holder needs it and the browser must not invent it, so it is threaded\n * from the declaration rather than guessed from the shape of `secrets`.\n * Optional because a holder may not care; the Fayz sink below defaults it.\n */\n authKind?: ConnectorCredentialAuthKind\n /** Declared field key → value. The only object the secret lives in, and it is not kept after the call. */\n secrets: Record<string, string>\n}\n\n/** What an app may keep in its own database once the secret is placed: a handle. */\nexport interface ConnectorCredentialRef {\n /** Opaque id the holder gave the credential. Never the credential. */\n id: string\n}\n\nexport interface ConnectorCredentialSink {\n store(input: StoreConnectorCredentialInput): Promise<ConnectorCredentialRef>\n}\n\nlet _sink: ConnectorCredentialSink | null = null\n\nexport function setConnectorCredentialSink(sink: ConnectorCredentialSink | null): void {\n _sink = sink\n}\n\n/** Null when the app configured none — callers must refuse, never fall back. */\nexport function getConnectorCredentialSink(): ConnectorCredentialSink | null {\n return _sink\n}\n\n// ---------------------------------------------------------------------------\n// The Fayz-hosted holder — the sink most apps install\n// ---------------------------------------------------------------------------\n//\n// Everything above is the port. What follows is the one implementation the SDK\n// ships: a client for `POST /api/public/projects/:projectId/connectors/\n// connections`, the endpoint the platform added in FAY-1353.\n//\n// An app installs it once, at boot, next to wherever it already configures its\n// backend:\n//\n// import { getFayzSupabaseClientOptional } from '@fayz-ai/admin'\n// import {\n// createFayzConnectorCredentialSink,\n// createFayzRuntimeTokenSource,\n// setConnectorCredentialSink,\n// } from '@fayz-ai/sdk'\n//\n// setConnectorCredentialSink(createFayzConnectorCredentialSink({\n// projectId,\n// runtimeToken: createFayzRuntimeTokenSource({\n// projectId,\n// supabase: getFayzSupabaseClientOptional,\n// }),\n// }))\n//\n// Installing nothing stays a valid answer: the hub refuses to save an api-key\n// connector, which is the correct behaviour for an app with nowhere safe to put\n// a credential. There is no default sink for exactly that reason.\n\n/** The credential was not placed. Carries a status when the platform answered. */\nexport class ConnectorCredentialSinkError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message)\n this.name = 'ConnectorCredentialSinkError'\n }\n}\n\n/**\n * What the sink can tell a token source about the call it is authenticating.\n *\n * Only the tenant, and only as a SELECTOR: the runtime-token endpoint proves\n * membership from the session and refuses anything outside it, so naming an org\n * here narrows which of the caller's own organizations the token is for and can\n * never widen it. Without this the source would have to re-derive the active\n * org from a store it does not know about, in an app that may have several.\n */\nexport interface FayzRuntimeTokenRequest {\n tenantId?: string\n}\n\nexport type FayzRuntimeTokenSource =\n | string\n | ((\n request?: FayzRuntimeTokenRequest,\n ) => string | undefined | null | Promise<string | undefined | null>)\n\nexport interface FayzConnectorCredentialSinkOptions {\n /** The Fayz project this app was published from. */\n projectId: string\n /**\n * A Fayz **runtime-data** token — the only scheme this endpoint accepts,\n * because it is the only one on the public plane that carries tenant identity.\n * A publishable key names an APP, so it cannot say which tenant is connecting.\n *\n * Required, and resolved per call so a short-lived token can be refreshed.\n * There is deliberately no fallback: a sink that cannot authenticate looks\n * configured and is worse than none, so an empty token is a refusal, not a\n * best-effort request.\n */\n runtimeToken: FayzRuntimeTokenSource\n /** Fayz platform origin. Defaults to same-origin, which is what an app proxying `/api` wants. */\n baseUrl?: string\n fetcher?: typeof fetch\n}\n\n/**\n * Values the platform accepts.\n *\n * All three, since FAY-1381 widened `CONNECTOR_AUTH_KINDS` on the platform.\n * Until then this collapsed `mtls` into `api-key` to get past a 400, which\n * recorded something the tenant did not do — a client certificate filed as an\n * API key. Storage was always identical for the three; only the vocabulary was\n * narrow.\n */\ntype WireAuthKind = ConnectorCredentialAuthKind\n\n/**\n * The request body, spelled out because the route schema is `.strict()`.\n *\n * `tenantId` is absent and must stay absent: the platform derives the tenant\n * from the verified token claims, and a body field naming one is precisely the\n * bug FAY-1375 was. A `tenantId` handed to `store()` is therefore never\n * forwarded here — it goes to the token source instead, where the platform can\n * check it against proven memberships before it means anything.\n */\ninterface StoreConnectionBody {\n connectorSlug: string\n authKind: WireAuthKind\n secrets: Record<string, string>\n}\n\nfunction requireValue(value: string | undefined, field: string): string {\n const normalized = typeof value === 'string' ? value.trim() : ''\n if (!normalized) throw new ConnectorCredentialSinkError(`${field} is required to store a connector credential`)\n return normalized\n}\n\n/**\n * Remove every secret value from text that is about to become an error message.\n *\n * The platform does not echo values today; this is here so that a future one\n * that does cannot turn a 400 into a leak. It runs on the raw response text, so\n * nothing from the wire reaches a message unfiltered.\n */\nfunction redactSecrets(text: string, secrets: Record<string, string>): string {\n let out = text\n for (const value of Object.values(secrets)) {\n if (value) out = out.split(value).join('[redacted]')\n }\n return out\n}\n\nfunction reasonFrom(text: string, secrets: Record<string, string>): string {\n const redacted = redactSecrets(text, secrets).trim()\n if (!redacted) return ''\n return `: ${redacted.slice(0, 300)}`\n}\n\n/**\n * A sink backed by the Fayz platform's connector-connection store.\n *\n * Write-only by construction: the response is a handle, and no method here can\n * read a credential back — redemption is a separate endpoint that requires a\n * second key a browser has no way to hold.\n */\nexport function createFayzConnectorCredentialSink(\n options: FayzConnectorCredentialSinkOptions,\n): ConnectorCredentialSink {\n const projectId = requireValue(options.projectId, 'projectId')\n const origin = fayzPlatformOrigin(options.baseUrl)\n const fetcher = options.fetcher ?? fetch\n // No query string, ever. The secret travels in the body of one POST and the\n // path carries nothing but the project — a URL is logged by every proxy.\n const url = `${origin}/api/public/projects/${encodeURIComponent(projectId)}/connectors/connections`\n\n async function resolveRuntimeToken(request: FayzRuntimeTokenRequest): Promise<string> {\n const source = options.runtimeToken\n const value = typeof source === 'function' ? await source(request) : source\n const token = typeof value === 'string' ? value.trim() : ''\n if (!token) {\n throw new ConnectorCredentialSinkError(\n 'No Fayz runtime token is available, so the credential was not stored',\n )\n }\n return token\n }\n\n return {\n async store(input: StoreConnectorCredentialInput): Promise<ConnectorCredentialRef> {\n // The platform calls it `connectorSlug`; the port calls it `connectorId`.\n const connectorSlug = requireValue(input.connectorId, 'connectorId')\n const secrets = input.secrets ?? {}\n if (Object.keys(secrets).length === 0) {\n throw new ConnectorCredentialSinkError('There is no secret to store for this connector')\n }\n\n // The tenant reaches the platform through the TOKEN, which is minted\n // against a verified session, and not through the body, which is only\n // what the browser typed.\n const token = await resolveRuntimeToken({ tenantId: input.tenantId })\n const body: StoreConnectionBody = {\n connectorSlug,\n authKind: input.authKind ?? 'api-key',\n secrets,\n }\n\n const response = await fetcher(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(body),\n })\n\n const text = await response.text().catch(() => '')\n\n if (!response.ok) {\n throw new ConnectorCredentialSinkError(\n `Fayz refused the connector credential (${response.status})${reasonFrom(text, secrets)}`,\n response.status,\n )\n }\n\n let parsed: unknown\n try {\n parsed = text ? JSON.parse(text) : undefined\n } catch {\n parsed = undefined\n }\n\n const id = (parsed as { connection?: { id?: unknown } } | undefined)?.connection?.id\n // A 2xx with no handle is not a success anyone can act on — the app would\n // record the connection as live against a credential that may not exist.\n if (typeof id !== 'string' || !id) {\n throw new ConnectorCredentialSinkError(\n `Fayz accepted the credential but returned no handle (${response.status})`,\n response.status,\n )\n }\n\n return { id }\n },\n }\n}\n","/**\n * Sending a merchant to a partner's consent screen — written once.\n *\n * Every OAuth connector needs the same four moves: mint a runtime token, POST\n * the app's own start endpoint, read a URL back, hand it to the hub to navigate\n * to. Copied into each connector that is four chances to disagree about the\n * path, the token, the tenant and the failure — and the failure is the one that\n * matters, because a `startOAuth` this repo forgot to write is a Connect button\n * that renders DISABLED with nothing on screen saying why. That is exactly how\n * Bling shipped.\n *\n * So a connector declares one line:\n *\n * startOAuth: fayzConnectorOAuth('bling')\n *\n * and everything below is shared. The platform side of the contract:\n *\n * POST /api/public/projects/:projectId/oauth/:provider/start\n * Authorization: Bearer <runtime-data token>\n * { tenantId?, redirectTo } → 201 { url }\n *\n * GET /api/oauth/redirect/:provider → 302 to redirectTo\n * ?fayzConnector=<slug>&fayzConnectorStatus=connected|error\n * &fayzConnectorMessage=<slug from a closed set>\n *\n * The redirect half is read by `oauth-return.ts` in `@fayz-ai/admin`; nothing\n * here has to know about it. The provider never gets a per-request\n * `redirect_uri` — Bling ignores one outright and always uses what is registered\n * on the app — so `redirectTo` travels inside the platform's signed state and\n * comes back out at the end.\n *\n * A port and not a bare `fetch`, for the same reason the credential sink is one:\n * WHICH Fayz project this app belongs to is a deployment fact. The app installs\n * one starter at boot; installing none is a valid answer, and then the connect\n * step refuses instead of quietly opening a consent screen for a project that\n * cannot finish the flow.\n */\n\nimport type { FayzRuntimeTokenRequest, FayzRuntimeTokenSource } from './credentials'\nimport { fayzPlatformOrigin } from './platform-url'\n\n/** The consent flow did not start. Carries a status when the platform answered. */\nexport class ConnectorOAuthError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message)\n this.name = 'ConnectorOAuthError'\n }\n}\n\n/** This app has nowhere to start a consent flow, so it refuses rather than guessing. */\nexport class ConnectorOAuthStarterMissingError extends ConnectorOAuthError {\n constructor() {\n super('No connector OAuth starter configured')\n this.name = 'ConnectorOAuthStarterMissingError'\n }\n}\n\nexport interface StartConnectorOAuthInput {\n /**\n * The `:provider` path segment — the platform catalogue's slug, which is what\n * knows the client id, the consent host and the registered redirect.\n */\n provider: string\n /**\n * Which connector definition this authorizes. Usually the same word as\n * `provider`; they part when the implementation is named after us rather than\n * after them (`plugbank` is the catalogue's `tecnospeed`).\n */\n connectorId: string\n /** Where the merchant lands when it is over — the page they left from, hash and all. */\n redirectTo: string\n /** The organization being connected. A selector the platform re-checks; see the port doc. */\n tenantId?: string\n}\n\n/** Where a consent flow is started from. Supplied once at boot. */\nexport interface ConnectorOAuthStarter {\n start(input: StartConnectorOAuthInput): Promise<string>\n}\n\nlet _starter: ConnectorOAuthStarter | null = null\n\nexport function setConnectorOAuthStarter(starter: ConnectorOAuthStarter | null): void {\n _starter = starter\n}\n\n/** Null when the app configured none — callers must refuse, never fall back. */\nexport function getConnectorOAuthStarter(): ConnectorOAuthStarter | null {\n return _starter\n}\n\nexport interface FayzConnectorOAuthStarterOptions {\n /** The Fayz project this app was published from. */\n projectId: string\n /**\n * A Fayz **runtime-data** token. Same requirement, and same reason, as the\n * credential sink's: it is the only scheme on the public plane that carries\n * tenant identity, and a publishable key names an app rather than a tenant.\n * Resolved per call so a short-lived token can be refreshed.\n */\n runtimeToken: FayzRuntimeTokenSource\n /** Fayz platform origin. Defaults to same-origin, which is what an app proxying `/api` wants. */\n baseUrl?: string\n fetcher?: typeof fetch\n}\n\nfunction requireValue(value: string | undefined, field: string): string {\n const normalized = typeof value === 'string' ? value.trim() : ''\n if (!normalized) throw new ConnectorOAuthError(`${field} is required to start a connector OAuth flow`)\n return normalized\n}\n\n/**\n * The starter backed by the Fayz platform. Installed once at boot, next to the\n * credential sink:\n *\n * const runtimeToken = createFayzRuntimeTokenSource({ projectId, supabase: getFayzSupabaseClientOptional })\n * setConnectorCredentialSink(createFayzConnectorCredentialSink({ projectId, runtimeToken }))\n * setConnectorOAuthStarter(createFayzConnectorOAuthStarter({ projectId, runtimeToken }))\n */\nexport function createFayzConnectorOAuthStarter(\n options: FayzConnectorOAuthStarterOptions,\n): ConnectorOAuthStarter {\n const projectId = requireValue(options.projectId, 'projectId')\n const origin = fayzPlatformOrigin(options.baseUrl)\n const fetcher = options.fetcher ?? fetch\n\n async function resolveRuntimeToken(request: FayzRuntimeTokenRequest): Promise<string> {\n const source = options.runtimeToken\n const value = typeof source === 'function' ? await source(request) : source\n const token = typeof value === 'string' ? value.trim() : ''\n if (!token) {\n throw new ConnectorOAuthError('No Fayz runtime token is available, so no consent flow was started')\n }\n return token\n }\n\n return {\n async start(input: StartConnectorOAuthInput): Promise<string> {\n const provider = requireValue(input.provider, 'provider')\n const redirectTo = requireValue(input.redirectTo, 'redirectTo')\n const token = await resolveRuntimeToken({ tenantId: input.tenantId })\n\n const url = `${origin}/api/public/projects/${encodeURIComponent(projectId)}/oauth/${encodeURIComponent(provider)}/start`\n const response = await fetcher(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },\n // Absent rather than null: the route schema is `.strict()`.\n body: JSON.stringify(input.tenantId ? { tenantId: input.tenantId, redirectTo } : { redirectTo }),\n })\n\n const text = await response.text().catch(() => '')\n\n if (!response.ok) {\n const reason = text.trim().slice(0, 300)\n throw new ConnectorOAuthError(\n `Fayz did not start the ${provider} authorization (${response.status})${reason ? `: ${reason}` : ''}`,\n response.status,\n )\n }\n\n let parsed: { url?: unknown } | undefined\n try {\n parsed = text ? JSON.parse(text) : undefined\n } catch {\n parsed = undefined\n }\n\n const consentUrl = typeof parsed?.url === 'string' ? parsed.url.trim() : ''\n // A blank URL would navigate the merchant to the app's own root and look\n // like the consent screen never opened, which is unreadable at the\n // support desk. Fail loudly at the one place that knows why.\n if (!consentUrl) {\n throw new ConnectorOAuthError(\n `Fayz answered ${response.status} without a consent URL for ${provider}`,\n response.status,\n )\n }\n return consentUrl\n },\n }\n}\n\n/**\n * Start a consent flow through the installed starter.\n *\n * `starter` is a test seam; pass `null` to assert there is none.\n */\nexport async function startConnectorOAuth(\n input: StartConnectorOAuthInput & { starter?: ConnectorOAuthStarter | null },\n): Promise<string> {\n const starter = input.starter === undefined ? getConnectorOAuthStarter() : input.starter\n if (!starter) throw new ConnectorOAuthStarterMissingError()\n return starter.start(input)\n}\n\n/**\n * A connector's whole `startOAuth`, in one line.\n *\n * startOAuth: fayzConnectorOAuth('bling')\n * startOAuth: fayzConnectorOAuth('plugbank', { provider: 'tecnospeed' })\n *\n * `provider` defaults to the connector id because for almost every connector\n * the two are the same word, and a default that is right by construction is one\n * fewer thing for the next connector to get wrong.\n */\nexport function fayzConnectorOAuth(\n connectorId: string,\n options: { provider?: string } = {},\n): (redirectTo?: string, context?: { tenantId?: string }) => Promise<string> {\n const provider = options.provider ?? connectorId\n return (redirectTo, context) =>\n startConnectorOAuth({\n provider,\n connectorId,\n // The hub always passes the page the merchant left from. The fallback is\n // for a caller that has none — a bare origin still returns them to the app.\n redirectTo: redirectTo ?? (typeof window !== 'undefined' ? window.location.href : ''),\n tenantId: context?.tenantId,\n })\n}\n","/**\n * WHICH account a connector is connected to — the one thing \"Conectado\" does\n * not say.\n *\n * A merchant who has a personal Mercado Pago account and a company one, or an\n * agency holding several clients, cannot tell from a green dot which of them is\n * taking the money. Connecting the WRONG account looks exactly like connecting\n * the right one, and is discovered when the money lands somewhere unexpected.\n *\n * ── why this needs a port at all ────────────────────────────────────────────\n *\n * The label cannot be read where it is needed. There are two connection records\n * and they do not talk:\n *\n * the PLATFORM's — holds the credential, and learns the account's name at\n * the moment of the grant (the only moment it can: the\n * vault never hands a token back to a screen)\n * the TENANT's — `connections` in the app's own pool, which is what\n * the connectors panel renders from\n *\n * The panel reads the second and the name lives in the first, which is why\n * every row in a live pool has `display_name: null` — nothing was ever able to\n * write it. This port is the bridge: the app asks the platform who it connected\n * to, and stores the answer locally so the panel can show it without asking\n * again.\n *\n * A port and not a bare `fetch`, for the same reason the credential sink is\n * one: WHICH Fayz project this app belongs to is a deployment fact. An app that\n * installs none simply shows no account, which is what every app does today.\n *\n * Read-only, and never credentials. `GET …/connectors/connections` answers with\n * the row's public half — name, provider account key, status — and redemption\n * remains a separate endpoint requiring a key a browser cannot hold.\n */\n\nimport type { FayzRuntimeTokenRequest, FayzRuntimeTokenSource } from './credentials'\nimport { fayzPlatformOrigin } from './platform-url'\n\n/** What the platform knows about the connected account. All of it is public. */\nexport interface ConnectorAccountInfo {\n /** Human label captured at grant time, e.g. \"ACME LTDA · financeiro@acme.com (PJ)\". */\n displayName: string | null\n /** The provider's own id for the account. A number; identifies, does not describe. */\n providerAccountKey: string | null\n /** The platform's view of the grant: `active`, `revoked`, … */\n status: string | null\n}\n\nexport interface DescribeConnectorAccountInput {\n connectorId: string\n tenantId?: string\n}\n\n/** Where an account description is read from. Supplied once at boot. */\nexport interface ConnectorAccountSource {\n describe(input: DescribeConnectorAccountInput): Promise<ConnectorAccountInfo | null>\n}\n\nlet _source: ConnectorAccountSource | null = null\n\nexport function setConnectorAccountSource(source: ConnectorAccountSource | null): void {\n _source = source\n}\n\n/** Null when the app configured none — callers must degrade, never invent a name. */\nexport function getConnectorAccountSource(): ConnectorAccountSource | null {\n return _source\n}\n\nexport interface FayzConnectorAccountSourceOptions {\n projectId: string\n runtimeToken: FayzRuntimeTokenSource\n baseUrl?: string\n fetcher?: typeof fetch\n}\n\nfunction requireValue(value: string | undefined, field: string): string {\n const normalized = typeof value === 'string' ? value.trim() : ''\n if (!normalized) throw new Error(`${field} is required to describe a connector account`)\n return normalized\n}\n\n/**\n * The source backed by the Fayz platform. Installed once at boot, next to the\n * credential sink and the OAuth starter:\n *\n * setConnectorAccountSource(createFayzConnectorAccountSource({ projectId, runtimeToken }))\n */\nexport function createFayzConnectorAccountSource(\n options: FayzConnectorAccountSourceOptions,\n): ConnectorAccountSource {\n const projectId = requireValue(options.projectId, 'projectId')\n const origin = fayzPlatformOrigin(options.baseUrl)\n const fetcher = options.fetcher ?? fetch\n\n return {\n async describe(input: DescribeConnectorAccountInput): Promise<ConnectorAccountInfo | null> {\n const connectorId = requireValue(input.connectorId, 'connectorId')\n const source = options.runtimeToken\n const request: FayzRuntimeTokenRequest = { tenantId: input.tenantId }\n const value = typeof source === 'function' ? await source(request) : source\n const token = typeof value === 'string' ? value.trim() : ''\n // No token, no answer — and no error either. This is a label; a merchant\n // whose session is not ready yet should see a connector, not a failure.\n if (!token) return null\n\n const url =\n `${origin}/api/public/projects/${encodeURIComponent(projectId)}` +\n `/connectors/connections?connectorSlug=${encodeURIComponent(connectorId)}`\n\n let response: Response\n try {\n response = await fetcher(url, { headers: { Authorization: `Bearer ${token}` } })\n } catch {\n return null\n }\n if (!response.ok) return null\n\n const payload = await response.json().catch(() => null) as\n | { connections?: Array<Record<string, unknown>> }\n | null\n\n // The platform can hold more than one row per connector when an account\n // was revoked and another connected. The live one is the answer; a\n // revoked row's name would be the account that is NOT charging.\n const rows = Array.isArray(payload?.connections) ? payload.connections : []\n const live = rows.find((row) => !row.revokedAt) ?? rows[0]\n if (!live) return null\n\n const text = (key: string): string | null => {\n const value = live[key]\n return typeof value === 'string' && value.trim() ? value.trim() : null\n }\n return {\n displayName: text('displayName'),\n providerAccountKey: text('providerAccountKey'),\n status: text('status'),\n }\n },\n }\n}\n\n/**\n * Ask the installed source who a connector is connected to.\n *\n * `source` is a test seam; pass `null` to assert there is none. Returns null\n * rather than throwing on every failure path — this decorates a screen, and no\n * connector should break because a label could not be fetched.\n */\nexport async function describeConnectorAccount(\n input: DescribeConnectorAccountInput & { source?: ConnectorAccountSource | null },\n): Promise<ConnectorAccountInfo | null> {\n const source = input.source === undefined ? getConnectorAccountSource() : input.source\n if (!source) return null\n try {\n return await source.describe(input)\n } catch {\n return null\n }\n}\n","/**\n * The key the credential sink needs — minted once, in one place.\n *\n * `ConnectorCredentialSink` requires a Fayz runtime-data token and deliberately\n * has no fallback, so until something hands it one the connect button refuses.\n * The token exists: `POST /api/public/projects/:projectId/runtime-token` trades\n * the app's OWN Supabase session for it. What did not exist is the client, and\n * writing that `fetch` per app is how five apps end up with five cache policies\n * and four of them without one.\n *\n * The exchange, as the platform actually implements it:\n *\n * Authorization: Bearer <the app's Supabase access token>\n * body: { tenantId? } → 201\n * { token, tokenType: 'Bearer', expiresIn, projectId, tenantId }\n *\n * `tenantId` in the body is a SELECTOR, never an assertion. The platform\n * verifies the session against the project's published JWKS, asks the app's own\n * database which organizations that user belongs to, and refuses a `tenantId`\n * outside that set; omitting it is resolved only when the answer is\n * unambiguous. Naming a tenant here therefore cannot widen anything — which is\n * why it is safe for the hub to pass the org the merchant is looking at.\n *\n * Fail-closed throughout: no session means no token means the sink refuses. A\n * source that quietly resolved to an empty string would leave an app looking\n * configured while every save fails, which is the failure that is hard to read.\n */\n\nimport type { FayzRuntimeTokenRequest } from './credentials'\nimport { fayzPlatformOrigin } from './platform-url'\n\n/** No token was minted. Carries a status when the platform answered. */\nexport class FayzRuntimeTokenError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message)\n this.name = 'FayzRuntimeTokenError'\n }\n}\n\n/**\n * The slice of a Supabase client this module touches.\n *\n * Duck-typed because `@fayz-ai/sdk` has no dependencies and must not grow one:\n * an app passes the client it already built (`getFayzSupabaseClientOptional()`\n * in `@fayz-ai/admin`), and nothing here needs the other four hundred methods.\n */\nexport interface SupabaseSessionClientLike {\n auth: {\n getSession(): Promise<{ data: { session: { access_token?: string | null } | null } }>\n }\n}\n\ntype Resolvable<T> = T | (() => T | Promise<T>)\n\nexport interface FayzRuntimeTokenSourceOptions {\n /** The Fayz project this app was published from. */\n projectId: string\n /**\n * The app's Supabase client, or a getter for one.\n *\n * A getter is the usual answer: the client is built when the app boots its\n * backend, which is after the module that installs the sink has run. Reading\n * it once at construction would pin `null` forever.\n */\n supabase?: Resolvable<SupabaseSessionClientLike | null | undefined>\n /**\n * Or, for an app whose session does not come from supabase-js, the access\n * token itself. Exactly one of `supabase` / `accessToken` is required.\n */\n accessToken?: Resolvable<string | null | undefined>\n /**\n * Which organization to ask for when the caller names none. Still only a\n * selector — see the header. Apps with one org per user can leave it unset.\n */\n tenantId?: Resolvable<string | null | undefined>\n /** Fayz platform origin. Defaults to same-origin, which is what an app proxying `/api` wants. */\n baseUrl?: string\n fetcher?: typeof fetch\n /**\n * How long before expiry a cached token stops being handed out. The token is\n * short-lived (15 minutes today) and the request it authenticates is a POST\n * that must not fail at the boundary, so the last stretch is not spent.\n */\n refreshLeadSeconds?: number\n /** Test seam. */\n now?: () => number\n}\n\nexport interface FayzRuntimeTokenSourceHandle {\n (request?: FayzRuntimeTokenRequest): Promise<string>\n /** Forget every cached token — after a sign-out, or an org switch that changed who is asking. */\n invalidate(): void\n}\n\ninterface CacheEntry {\n token: string\n /** Epoch ms at which this token stops being handed out (already minus the lead). */\n goodUntil: number\n}\n\nfunction requireValue(value: string | undefined, field: string): string {\n const normalized = typeof value === 'string' ? value.trim() : ''\n if (!normalized) throw new FayzRuntimeTokenError(`${field} is required to mint a Fayz runtime token`)\n return normalized\n}\n\nasync function resolve<T>(source: Resolvable<T> | undefined): Promise<T | undefined> {\n if (source === undefined) return undefined\n return typeof source === 'function' ? await (source as () => T | Promise<T>)() : source\n}\n\n/**\n * Strip the session token from text on its way into an error message.\n *\n * The platform does not echo it, and this is here so that a future one that\n * does cannot turn a 403 into a leak. The bearer being redacted is the user's\n * session — the same class of thing the sink redacts on its own side.\n */\nfunction withoutToken(text: string, token: string): string {\n return token ? text.split(token).join('[redacted]') : text\n}\n\n/**\n * Trade the app's Supabase session for a Fayz runtime-data token, and keep it\n * until shortly before it expires.\n *\n * The result is a function, so it drops straight into the sink:\n *\n * setConnectorCredentialSink(createFayzConnectorCredentialSink({\n * projectId,\n * runtimeToken: createFayzRuntimeTokenSource({ projectId, supabase: getClient }),\n * }))\n */\nexport function createFayzRuntimeTokenSource(\n options: FayzRuntimeTokenSourceOptions,\n): FayzRuntimeTokenSourceHandle {\n const projectId = requireValue(options.projectId, 'projectId')\n if (options.supabase === undefined && options.accessToken === undefined) {\n throw new FayzRuntimeTokenError(\n 'A Fayz runtime token source needs a session: pass either `supabase` or `accessToken`',\n )\n }\n\n const origin = fayzPlatformOrigin(options.baseUrl)\n const fetcher = options.fetcher ?? fetch\n const now = options.now ?? (() => Date.now())\n const leadMs = Math.max(0, options.refreshLeadSeconds ?? 60) * 1_000\n const url = `${origin}/api/public/projects/${encodeURIComponent(projectId)}/runtime-token`\n\n // Keyed by the tenant that was ASKED for, because a token minted for one org\n // is not a token for another — reusing it across an org switch would act on\n // the wrong tenant's connections with a token the platform correctly accepts.\n const cache = new Map<string, CacheEntry>()\n const inFlight = new Map<string, Promise<string>>()\n\n async function readAccessToken(): Promise<string> {\n const direct = await resolve(options.accessToken)\n if (typeof direct === 'string' && direct.trim()) return direct.trim()\n\n const client = await resolve(options.supabase)\n const session = client ? (await client.auth.getSession()).data.session : null\n const token = typeof session?.access_token === 'string' ? session.access_token.trim() : ''\n if (!token) {\n throw new FayzRuntimeTokenError('Nobody is signed in to this app, so no Fayz runtime token was minted')\n }\n return token\n }\n\n async function mint(tenantId: string | undefined): Promise<string> {\n const accessToken = await readAccessToken()\n\n const response = await fetcher(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n },\n // `.strict()` on the route: `tenantId` is the only field it accepts, and\n // an absent one must be absent rather than null.\n body: JSON.stringify(tenantId ? { tenantId } : {}),\n })\n\n const text = await response.text().catch(() => '')\n\n if (!response.ok) {\n const reason = withoutToken(text, accessToken).trim().slice(0, 300)\n throw new FayzRuntimeTokenError(\n `Fayz did not issue a runtime token (${response.status})${reason ? `: ${reason}` : ''}`,\n response.status,\n )\n }\n\n let parsed: { token?: unknown; expiresIn?: unknown; tenantId?: unknown } | undefined\n try {\n parsed = text ? JSON.parse(text) : undefined\n } catch {\n parsed = undefined\n }\n\n const token = typeof parsed?.token === 'string' ? parsed.token.trim() : ''\n if (!token) {\n throw new FayzRuntimeTokenError(\n `Fayz answered ${response.status} without a runtime token`,\n response.status,\n )\n }\n\n // An unstated or nonsensical lifetime is not cached: handing out a token\n // whose expiry is guessed is how a save fails at the one moment it matters.\n const expiresIn = typeof parsed?.expiresIn === 'number' ? parsed.expiresIn : NaN\n if (Number.isFinite(expiresIn) && expiresIn * 1_000 > leadMs) {\n const key = cacheKey(tenantId)\n cache.set(key, { token, goodUntil: now() + expiresIn * 1_000 - leadMs })\n // The platform names the tenant it decided on. When the caller asked for\n // none and the answer was unambiguous, the same token serves the explicit\n // ask that the hub makes a moment later.\n const resolved = typeof parsed?.tenantId === 'string' ? parsed.tenantId.trim() : ''\n if (resolved && !tenantId) cache.set(cacheKey(resolved), { ...cache.get(key)! })\n }\n\n return token\n }\n\n function cacheKey(tenantId: string | undefined): string {\n return tenantId ?? ''\n }\n\n const source = (async (request?: FayzRuntimeTokenRequest): Promise<string> => {\n const asked = (request?.tenantId ?? (await resolve(options.tenantId))) || undefined\n const tenantId = typeof asked === 'string' && asked.trim() ? asked.trim() : undefined\n const key = cacheKey(tenantId)\n\n const cached = cache.get(key)\n if (cached && cached.goodUntil > now()) return cached.token\n if (cached) cache.delete(key)\n\n // Two components asking at once is one exchange. Not a nicety: each call\n // reads the session and posts, and a burst of them against the token\n // endpoint is exactly the shape rate limits are written for.\n const existing = inFlight.get(key)\n if (existing) return existing\n\n const flight = mint(tenantId).finally(() => inFlight.delete(key))\n inFlight.set(key, flight)\n return flight\n }) as FayzRuntimeTokenSourceHandle\n\n source.invalidate = () => {\n cache.clear()\n }\n\n return source\n}\n"]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHICH account a connector is connected to — the one thing "Conectado" does
|
|
3
|
+
* not say.
|
|
4
|
+
*
|
|
5
|
+
* A merchant who has a personal Mercado Pago account and a company one, or an
|
|
6
|
+
* agency holding several clients, cannot tell from a green dot which of them is
|
|
7
|
+
* taking the money. Connecting the WRONG account looks exactly like connecting
|
|
8
|
+
* the right one, and is discovered when the money lands somewhere unexpected.
|
|
9
|
+
*
|
|
10
|
+
* ── why this needs a port at all ────────────────────────────────────────────
|
|
11
|
+
*
|
|
12
|
+
* The label cannot be read where it is needed. There are two connection records
|
|
13
|
+
* and they do not talk:
|
|
14
|
+
*
|
|
15
|
+
* the PLATFORM's — holds the credential, and learns the account's name at
|
|
16
|
+
* the moment of the grant (the only moment it can: the
|
|
17
|
+
* vault never hands a token back to a screen)
|
|
18
|
+
* the TENANT's — `connections` in the app's own pool, which is what
|
|
19
|
+
* the connectors panel renders from
|
|
20
|
+
*
|
|
21
|
+
* The panel reads the second and the name lives in the first, which is why
|
|
22
|
+
* every row in a live pool has `display_name: null` — nothing was ever able to
|
|
23
|
+
* write it. This port is the bridge: the app asks the platform who it connected
|
|
24
|
+
* to, and stores the answer locally so the panel can show it without asking
|
|
25
|
+
* again.
|
|
26
|
+
*
|
|
27
|
+
* A port and not a bare `fetch`, for the same reason the credential sink is
|
|
28
|
+
* one: WHICH Fayz project this app belongs to is a deployment fact. An app that
|
|
29
|
+
* installs none simply shows no account, which is what every app does today.
|
|
30
|
+
*
|
|
31
|
+
* Read-only, and never credentials. `GET …/connectors/connections` answers with
|
|
32
|
+
* the row's public half — name, provider account key, status — and redemption
|
|
33
|
+
* remains a separate endpoint requiring a key a browser cannot hold.
|
|
34
|
+
*/
|
|
35
|
+
import type { FayzRuntimeTokenSource } from './credentials';
|
|
36
|
+
/** What the platform knows about the connected account. All of it is public. */
|
|
37
|
+
export interface ConnectorAccountInfo {
|
|
38
|
+
/** Human label captured at grant time, e.g. "ACME LTDA · financeiro@acme.com (PJ)". */
|
|
39
|
+
displayName: string | null;
|
|
40
|
+
/** The provider's own id for the account. A number; identifies, does not describe. */
|
|
41
|
+
providerAccountKey: string | null;
|
|
42
|
+
/** The platform's view of the grant: `active`, `revoked`, … */
|
|
43
|
+
status: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface DescribeConnectorAccountInput {
|
|
46
|
+
connectorId: string;
|
|
47
|
+
tenantId?: string;
|
|
48
|
+
}
|
|
49
|
+
/** Where an account description is read from. Supplied once at boot. */
|
|
50
|
+
export interface ConnectorAccountSource {
|
|
51
|
+
describe(input: DescribeConnectorAccountInput): Promise<ConnectorAccountInfo | null>;
|
|
52
|
+
}
|
|
53
|
+
export declare function setConnectorAccountSource(source: ConnectorAccountSource | null): void;
|
|
54
|
+
/** Null when the app configured none — callers must degrade, never invent a name. */
|
|
55
|
+
export declare function getConnectorAccountSource(): ConnectorAccountSource | null;
|
|
56
|
+
export interface FayzConnectorAccountSourceOptions {
|
|
57
|
+
projectId: string;
|
|
58
|
+
runtimeToken: FayzRuntimeTokenSource;
|
|
59
|
+
baseUrl?: string;
|
|
60
|
+
fetcher?: typeof fetch;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The source backed by the Fayz platform. Installed once at boot, next to the
|
|
64
|
+
* credential sink and the OAuth starter:
|
|
65
|
+
*
|
|
66
|
+
* setConnectorAccountSource(createFayzConnectorAccountSource({ projectId, runtimeToken }))
|
|
67
|
+
*/
|
|
68
|
+
export declare function createFayzConnectorAccountSource(options: FayzConnectorAccountSourceOptions): ConnectorAccountSource;
|
|
69
|
+
/**
|
|
70
|
+
* Ask the installed source who a connector is connected to.
|
|
71
|
+
*
|
|
72
|
+
* `source` is a test seam; pass `null` to assert there is none. Returns null
|
|
73
|
+
* rather than throwing on every failure path — this decorates a screen, and no
|
|
74
|
+
* connector should break because a label could not be fetched.
|
|
75
|
+
*/
|
|
76
|
+
export declare function describeConnectorAccount(input: DescribeConnectorAccountInput & {
|
|
77
|
+
source?: ConnectorAccountSource | null;
|
|
78
|
+
}): Promise<ConnectorAccountInfo | null>;
|
|
79
|
+
//# sourceMappingURL=connector-account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector-account.d.ts","sourceRoot":"","sources":["../../src/lib/connector-account.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAA2B,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAGpF,gFAAgF;AAChF,MAAM,WAAW,oBAAoB;IACnC,uFAAuF;IACvF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,sFAAsF;IACtF,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,+DAA+D;IAC/D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAA;CACrF;AAID,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,GAAG,IAAI,CAErF;AAED,qFAAqF;AACrF,wBAAgB,yBAAyB,IAAI,sBAAsB,GAAG,IAAI,CAEzE;AAED,MAAM,WAAW,iCAAiC;IAChD,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,sBAAsB,CAAA;IACpC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB;AAQD;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,iCAAiC,GACzC,sBAAsB,CAkDxB;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,6BAA6B,GAAG;IAAE,MAAM,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAA;CAAE,GAChF,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAQtC"}
|
package/dist/release-channels.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { fayzPackageVersionSets, resolveFayzPackageDependencies, resolveFayzPackageVersion, resolveFayzPackageVersions } from './chunk-
|
|
1
|
+
export { fayzPackageVersionSets, resolveFayzPackageDependencies, resolveFayzPackageVersion, resolveFayzPackageVersions } from './chunk-L2FWBQU6.js';
|
|
2
2
|
//# sourceMappingURL=release-channels.js.map
|
|
3
3
|
//# sourceMappingURL=release-channels.js.map
|
|
@@ -1,103 +1,103 @@
|
|
|
1
1
|
{
|
|
2
2
|
"channels": {
|
|
3
3
|
"stable": {
|
|
4
|
-
"@fayz-ai/sdk": "^0.
|
|
5
|
-
"@fayz-ai/admin": "^0.
|
|
6
|
-
"@fayz-ai/core": "^0.
|
|
7
|
-
"@fayz-ai/auth": "^0.
|
|
8
|
-
"@fayz-ai/ui": "^0.
|
|
9
|
-
"@fayz-ai/shop": "^0.
|
|
10
|
-
"@fayz-ai/storefront": "^0.
|
|
11
|
-
"@fayz-ai/portal": "^0.
|
|
12
|
-
"@fayz-ai/courses": "^0.
|
|
13
|
-
"@fayz-ai/db": "^0.
|
|
14
|
-
"@fayz-ai/plugin-agenda": "^0.
|
|
15
|
-
"@fayz-ai/plugin-auth": "^0.
|
|
16
|
-
"@fayz-ai/plugin-automations": "^0.
|
|
17
|
-
"@fayz-ai/plugin-blog": "^0.12.
|
|
18
|
-
"@fayz-ai/plugin-conversations": "^0.
|
|
19
|
-
"@fayz-ai/plugin-courses": "^0.10.
|
|
20
|
-
"@fayz-ai/plugin-crm": "^0.
|
|
21
|
-
"@fayz-ai/plugin-dashboard": "^0.9.
|
|
22
|
-
"@fayz-ai/plugin-financial": "^0.
|
|
23
|
-
"@fayz-ai/plugin-forms": "^0.10.
|
|
24
|
-
"@fayz-ai/plugin-inventory": "^0.
|
|
25
|
-
"@fayz-ai/plugin-marketing": "^0.
|
|
26
|
-
"@fayz-ai/plugin-menu": "^0.10.
|
|
27
|
-
"@fayz-ai/plugin-orders": "^0.
|
|
28
|
-
"@fayz-ai/plugin-payments": "^0.9.
|
|
29
|
-
"@fayz-ai/plugin-reports": "^0.
|
|
30
|
-
"@fayz-ai/plugin-reputation": "^0.10.
|
|
31
|
-
"@fayz-ai/plugin-shop": "^0.
|
|
32
|
-
"@fayz-ai/plugin-sites": "^0.9.
|
|
33
|
-
"@fayz-ai/plugin-tables": "^0.10.
|
|
34
|
-
"@fayz-ai/plugin-tasks": "^0.10.
|
|
4
|
+
"@fayz-ai/sdk": "^0.19.1",
|
|
5
|
+
"@fayz-ai/admin": "^0.19.1",
|
|
6
|
+
"@fayz-ai/core": "^0.19.1",
|
|
7
|
+
"@fayz-ai/auth": "^0.19.0",
|
|
8
|
+
"@fayz-ai/ui": "^0.19.0",
|
|
9
|
+
"@fayz-ai/shop": "^0.19.0",
|
|
10
|
+
"@fayz-ai/storefront": "^0.19.1",
|
|
11
|
+
"@fayz-ai/portal": "^0.19.0",
|
|
12
|
+
"@fayz-ai/courses": "^0.19.0",
|
|
13
|
+
"@fayz-ai/db": "^0.14.0",
|
|
14
|
+
"@fayz-ai/plugin-agenda": "^0.13.0",
|
|
15
|
+
"@fayz-ai/plugin-auth": "^0.12.2",
|
|
16
|
+
"@fayz-ai/plugin-automations": "^0.12.4",
|
|
17
|
+
"@fayz-ai/plugin-blog": "^0.12.7",
|
|
18
|
+
"@fayz-ai/plugin-conversations": "^0.11.3",
|
|
19
|
+
"@fayz-ai/plugin-courses": "^0.10.7",
|
|
20
|
+
"@fayz-ai/plugin-crm": "^0.11.0",
|
|
21
|
+
"@fayz-ai/plugin-dashboard": "^0.9.9",
|
|
22
|
+
"@fayz-ai/plugin-financial": "^0.13.0",
|
|
23
|
+
"@fayz-ai/plugin-forms": "^0.10.4",
|
|
24
|
+
"@fayz-ai/plugin-inventory": "^0.12.0",
|
|
25
|
+
"@fayz-ai/plugin-marketing": "^0.12.0",
|
|
26
|
+
"@fayz-ai/plugin-menu": "^0.10.5",
|
|
27
|
+
"@fayz-ai/plugin-orders": "^0.12.1",
|
|
28
|
+
"@fayz-ai/plugin-payments": "^0.9.9",
|
|
29
|
+
"@fayz-ai/plugin-reports": "^0.13.0",
|
|
30
|
+
"@fayz-ai/plugin-reputation": "^0.10.4",
|
|
31
|
+
"@fayz-ai/plugin-shop": "^0.15.0",
|
|
32
|
+
"@fayz-ai/plugin-sites": "^0.9.7",
|
|
33
|
+
"@fayz-ai/plugin-tables": "^0.10.5",
|
|
34
|
+
"@fayz-ai/plugin-tasks": "^0.10.4"
|
|
35
35
|
},
|
|
36
36
|
"latest": {
|
|
37
|
-
"@fayz-ai/sdk": "^0.
|
|
38
|
-
"@fayz-ai/admin": "^0.
|
|
39
|
-
"@fayz-ai/core": "^0.
|
|
40
|
-
"@fayz-ai/auth": "^0.
|
|
41
|
-
"@fayz-ai/ui": "^0.
|
|
42
|
-
"@fayz-ai/shop": "^0.
|
|
43
|
-
"@fayz-ai/storefront": "^0.
|
|
44
|
-
"@fayz-ai/portal": "^0.
|
|
45
|
-
"@fayz-ai/courses": "^0.
|
|
46
|
-
"@fayz-ai/db": "^0.
|
|
47
|
-
"@fayz-ai/plugin-agenda": "^0.
|
|
48
|
-
"@fayz-ai/plugin-auth": "^0.
|
|
49
|
-
"@fayz-ai/plugin-automations": "^0.
|
|
50
|
-
"@fayz-ai/plugin-blog": "^0.12.
|
|
51
|
-
"@fayz-ai/plugin-conversations": "^0.
|
|
52
|
-
"@fayz-ai/plugin-courses": "^0.10.
|
|
53
|
-
"@fayz-ai/plugin-crm": "^0.
|
|
54
|
-
"@fayz-ai/plugin-dashboard": "^0.9.
|
|
55
|
-
"@fayz-ai/plugin-financial": "^0.
|
|
56
|
-
"@fayz-ai/plugin-forms": "^0.10.
|
|
57
|
-
"@fayz-ai/plugin-inventory": "^0.
|
|
58
|
-
"@fayz-ai/plugin-marketing": "^0.
|
|
59
|
-
"@fayz-ai/plugin-menu": "^0.10.
|
|
60
|
-
"@fayz-ai/plugin-orders": "^0.
|
|
61
|
-
"@fayz-ai/plugin-payments": "^0.9.
|
|
62
|
-
"@fayz-ai/plugin-reports": "^0.
|
|
63
|
-
"@fayz-ai/plugin-reputation": "^0.10.
|
|
64
|
-
"@fayz-ai/plugin-shop": "^0.
|
|
65
|
-
"@fayz-ai/plugin-sites": "^0.9.
|
|
66
|
-
"@fayz-ai/plugin-tables": "^0.10.
|
|
67
|
-
"@fayz-ai/plugin-tasks": "^0.10.
|
|
37
|
+
"@fayz-ai/sdk": "^0.19.1",
|
|
38
|
+
"@fayz-ai/admin": "^0.19.1",
|
|
39
|
+
"@fayz-ai/core": "^0.19.1",
|
|
40
|
+
"@fayz-ai/auth": "^0.19.0",
|
|
41
|
+
"@fayz-ai/ui": "^0.19.0",
|
|
42
|
+
"@fayz-ai/shop": "^0.19.0",
|
|
43
|
+
"@fayz-ai/storefront": "^0.19.1",
|
|
44
|
+
"@fayz-ai/portal": "^0.19.0",
|
|
45
|
+
"@fayz-ai/courses": "^0.19.0",
|
|
46
|
+
"@fayz-ai/db": "^0.14.0",
|
|
47
|
+
"@fayz-ai/plugin-agenda": "^0.13.0",
|
|
48
|
+
"@fayz-ai/plugin-auth": "^0.12.2",
|
|
49
|
+
"@fayz-ai/plugin-automations": "^0.12.4",
|
|
50
|
+
"@fayz-ai/plugin-blog": "^0.12.7",
|
|
51
|
+
"@fayz-ai/plugin-conversations": "^0.11.3",
|
|
52
|
+
"@fayz-ai/plugin-courses": "^0.10.7",
|
|
53
|
+
"@fayz-ai/plugin-crm": "^0.11.0",
|
|
54
|
+
"@fayz-ai/plugin-dashboard": "^0.9.9",
|
|
55
|
+
"@fayz-ai/plugin-financial": "^0.13.0",
|
|
56
|
+
"@fayz-ai/plugin-forms": "^0.10.4",
|
|
57
|
+
"@fayz-ai/plugin-inventory": "^0.12.0",
|
|
58
|
+
"@fayz-ai/plugin-marketing": "^0.12.0",
|
|
59
|
+
"@fayz-ai/plugin-menu": "^0.10.5",
|
|
60
|
+
"@fayz-ai/plugin-orders": "^0.12.1",
|
|
61
|
+
"@fayz-ai/plugin-payments": "^0.9.9",
|
|
62
|
+
"@fayz-ai/plugin-reports": "^0.13.0",
|
|
63
|
+
"@fayz-ai/plugin-reputation": "^0.10.4",
|
|
64
|
+
"@fayz-ai/plugin-shop": "^0.15.0",
|
|
65
|
+
"@fayz-ai/plugin-sites": "^0.9.7",
|
|
66
|
+
"@fayz-ai/plugin-tables": "^0.10.5",
|
|
67
|
+
"@fayz-ai/plugin-tasks": "^0.10.4"
|
|
68
68
|
},
|
|
69
69
|
"preview": {
|
|
70
|
-
"@fayz-ai/sdk": "^0.
|
|
71
|
-
"@fayz-ai/admin": "^0.
|
|
72
|
-
"@fayz-ai/core": "^0.
|
|
73
|
-
"@fayz-ai/auth": "^0.
|
|
74
|
-
"@fayz-ai/ui": "^0.
|
|
75
|
-
"@fayz-ai/shop": "^0.
|
|
76
|
-
"@fayz-ai/storefront": "^0.
|
|
77
|
-
"@fayz-ai/portal": "^0.
|
|
78
|
-
"@fayz-ai/courses": "^0.
|
|
79
|
-
"@fayz-ai/db": "^0.
|
|
80
|
-
"@fayz-ai/plugin-agenda": "^0.
|
|
81
|
-
"@fayz-ai/plugin-auth": "^0.
|
|
82
|
-
"@fayz-ai/plugin-automations": "^0.
|
|
83
|
-
"@fayz-ai/plugin-blog": "^0.12.
|
|
84
|
-
"@fayz-ai/plugin-conversations": "^0.
|
|
85
|
-
"@fayz-ai/plugin-courses": "^0.10.
|
|
86
|
-
"@fayz-ai/plugin-crm": "^0.
|
|
87
|
-
"@fayz-ai/plugin-dashboard": "^0.9.
|
|
88
|
-
"@fayz-ai/plugin-financial": "^0.
|
|
89
|
-
"@fayz-ai/plugin-forms": "^0.10.
|
|
90
|
-
"@fayz-ai/plugin-inventory": "^0.
|
|
91
|
-
"@fayz-ai/plugin-marketing": "^0.
|
|
92
|
-
"@fayz-ai/plugin-menu": "^0.10.
|
|
93
|
-
"@fayz-ai/plugin-orders": "^0.
|
|
94
|
-
"@fayz-ai/plugin-payments": "^0.9.
|
|
95
|
-
"@fayz-ai/plugin-reports": "^0.
|
|
96
|
-
"@fayz-ai/plugin-reputation": "^0.10.
|
|
97
|
-
"@fayz-ai/plugin-shop": "^0.
|
|
98
|
-
"@fayz-ai/plugin-sites": "^0.9.
|
|
99
|
-
"@fayz-ai/plugin-tables": "^0.10.
|
|
100
|
-
"@fayz-ai/plugin-tasks": "^0.10.
|
|
70
|
+
"@fayz-ai/sdk": "^0.19.1",
|
|
71
|
+
"@fayz-ai/admin": "^0.19.1",
|
|
72
|
+
"@fayz-ai/core": "^0.19.1",
|
|
73
|
+
"@fayz-ai/auth": "^0.19.0",
|
|
74
|
+
"@fayz-ai/ui": "^0.19.0",
|
|
75
|
+
"@fayz-ai/shop": "^0.19.0",
|
|
76
|
+
"@fayz-ai/storefront": "^0.19.1",
|
|
77
|
+
"@fayz-ai/portal": "^0.19.0",
|
|
78
|
+
"@fayz-ai/courses": "^0.19.0",
|
|
79
|
+
"@fayz-ai/db": "^0.14.0",
|
|
80
|
+
"@fayz-ai/plugin-agenda": "^0.13.0",
|
|
81
|
+
"@fayz-ai/plugin-auth": "^0.12.2",
|
|
82
|
+
"@fayz-ai/plugin-automations": "^0.12.4",
|
|
83
|
+
"@fayz-ai/plugin-blog": "^0.12.7",
|
|
84
|
+
"@fayz-ai/plugin-conversations": "^0.11.3",
|
|
85
|
+
"@fayz-ai/plugin-courses": "^0.10.7",
|
|
86
|
+
"@fayz-ai/plugin-crm": "^0.11.0",
|
|
87
|
+
"@fayz-ai/plugin-dashboard": "^0.9.9",
|
|
88
|
+
"@fayz-ai/plugin-financial": "^0.13.0",
|
|
89
|
+
"@fayz-ai/plugin-forms": "^0.10.4",
|
|
90
|
+
"@fayz-ai/plugin-inventory": "^0.12.0",
|
|
91
|
+
"@fayz-ai/plugin-marketing": "^0.12.0",
|
|
92
|
+
"@fayz-ai/plugin-menu": "^0.10.5",
|
|
93
|
+
"@fayz-ai/plugin-orders": "^0.12.1",
|
|
94
|
+
"@fayz-ai/plugin-payments": "^0.9.9",
|
|
95
|
+
"@fayz-ai/plugin-reports": "^0.13.0",
|
|
96
|
+
"@fayz-ai/plugin-reputation": "^0.10.4",
|
|
97
|
+
"@fayz-ai/plugin-shop": "^0.15.0",
|
|
98
|
+
"@fayz-ai/plugin-sites": "^0.9.7",
|
|
99
|
+
"@fayz-ai/plugin-tables": "^0.10.5",
|
|
100
|
+
"@fayz-ai/plugin-tasks": "^0.10.4"
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
}
|
package/dist/shop.d.ts
CHANGED
|
@@ -76,6 +76,32 @@ interface CheckoutSessionInput {
|
|
|
76
76
|
returnUrl?: string | null;
|
|
77
77
|
/** Em vez de cobrar agora, devolve um link para o lojista mandar ao cliente. */
|
|
78
78
|
asLink?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* O cartão, quando ele é digitado DENTRO da loja.
|
|
81
|
+
*
|
|
82
|
+
* Só o Mercado Pago chega aqui hoje, e a diferença não é de gosto: as
|
|
83
|
+
* chamadas transparentes da AbacatePay e da Vindi pedem o número do cartão no
|
|
84
|
+
* corpo da requisição, o que colocaria o pool em escopo PCI — por isso as
|
|
85
|
+
* duas redirecionam. O Mercado Pago tokeniza no NAVEGADOR, então o que sobe
|
|
86
|
+
* daqui é um código de uso único e nunca um número de cartão.
|
|
87
|
+
*
|
|
88
|
+
* Precisam estar declarados AQUI, nesta cópia, e não só no tipo público de
|
|
89
|
+
* @fayz-ai/shop: este arquivo declara o seu próprio `CheckoutSessionInput` de
|
|
90
|
+
* propósito, e o corpo da requisição é montado campo a campo logo abaixo.
|
|
91
|
+
* Tudo que não estiver nos dois lugares é descartado em silêncio — foi
|
|
92
|
+
* exatamente o que aconteceu: a vitrine mandava os cinco campos, nenhum
|
|
93
|
+
* chegava, e o comprador via "não recebemos os dados do cartão" depois de
|
|
94
|
+
* preencher o cartão certo.
|
|
95
|
+
*/
|
|
96
|
+
cardToken?: string | null;
|
|
97
|
+
/** Em quantas vezes. O servidor reconfere contra o que a conta liberou. */
|
|
98
|
+
installments?: number | null;
|
|
99
|
+
/** `master`, `visa`… — o que o Brick identificou a partir do BIN. */
|
|
100
|
+
paymentMethodId?: string | null;
|
|
101
|
+
/** O emissor, quando o adquirente distingue mais de um para a bandeira. */
|
|
102
|
+
issuerId?: string | null;
|
|
103
|
+
/** A impressão digital do aparelho — recomendação nº 1 deles para aprovação. */
|
|
104
|
+
deviceId?: string | null;
|
|
79
105
|
}
|
|
80
106
|
interface CheckoutSession {
|
|
81
107
|
sessionId: string;
|
|
@@ -617,6 +643,8 @@ export declare function createFayzShopProvider(options: FayzShopProviderOptions)
|
|
|
617
643
|
phone?: string | null;
|
|
618
644
|
document?: string | null;
|
|
619
645
|
}): Promise<void>;
|
|
646
|
+
/** The acquirer's public key, for a checkout that tokenises in the browser. */
|
|
647
|
+
paymentPublicKey(provider: string): Promise<string | null>;
|
|
620
648
|
openCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSession>;
|
|
621
649
|
/**
|
|
622
650
|
* Ask whether the money landed. Called on a timer, so a network blip must
|
|
@@ -658,9 +686,10 @@ export declare function createFayzShopProvider(options: FayzShopProviderOptions)
|
|
|
658
686
|
* id, which is why these are not table writes.
|
|
659
687
|
*/
|
|
660
688
|
validateDiscountCode(code: string, subtotal?: number): Promise<{
|
|
689
|
+
minSubtotal?: number | undefined;
|
|
661
690
|
valid: boolean;
|
|
662
691
|
code: string | null;
|
|
663
|
-
type: "percentage" | "fixed_amount" | null;
|
|
692
|
+
type: "percentage" | "fixed_amount" | "free_shipping" | null;
|
|
664
693
|
value: number;
|
|
665
694
|
reason: string | undefined;
|
|
666
695
|
}>;
|