@tailor-platform/sdk 1.54.3 → 1.55.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/CHANGELOG.md +18 -0
- package/dist/{actor-Cjae_LGD.d.mts → actor-J2gJ0eK5.d.mts} +2 -2
- package/dist/application-DM8q9GDI.mjs +4 -0
- package/dist/{application-BfGje3iZ.mjs → application-DzUlASfA.mjs} +333 -4
- package/dist/application-DzUlASfA.mjs.map +1 -0
- package/dist/brand-DlnJ375c.mjs.map +1 -1
- package/dist/cli/index.mjs +5 -5
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +1334 -176
- package/dist/cli/lib.mjs +3 -3
- package/dist/{client-CGO7gniI.mjs → client-DLPEPJ_s.mjs} +24 -19
- package/dist/client-DLPEPJ_s.mjs.map +1 -0
- package/dist/{client-yfFdZU9s.mjs → client-DrzwCD1W.mjs} +1 -1
- package/dist/configure/index.d.mts +5 -4
- package/dist/configure/index.mjs +47 -1
- package/dist/configure/index.mjs.map +1 -1
- package/dist/{crashreport-DGdAgX8Y.mjs → crashreport-Bm2mN5tg.mjs} +2 -2
- package/dist/{crashreport-DGdAgX8Y.mjs.map → crashreport-Bm2mN5tg.mjs.map} +1 -1
- package/dist/{crashreport-DnwIxpzF.mjs → crashreport-C5oHvHUC.mjs} +1 -1
- package/dist/{index-qQYMbkT-.d.mts → index-BE-fpxIo.d.mts} +2 -2
- package/dist/{index-DJUoIn_v.d.mts → index-BLsnrEtc.d.mts} +97 -5
- package/dist/{index-DrYHpTja.d.mts → index-D9xG-a6Y.d.mts} +2 -2
- package/dist/{index-CyyoHrPK.d.mts → index-S6-FtUpA.d.mts} +2 -2
- package/dist/{index-Cf1Lo_XT.d.mts → index-cHqh66cF.d.mts} +2 -2
- package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
- package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
- package/dist/plugin/builtin/seed/index.d.mts +1 -1
- package/dist/plugin/index.d.mts +2 -2
- package/dist/plugin-BuE5ZOnW.d.mts +634 -0
- package/dist/{runtime-DpbAj_8a.mjs → runtime-BZsl7Mh9.mjs} +319 -154
- package/dist/runtime-BZsl7Mh9.mjs.map +1 -0
- package/dist/seed-DfLyRh63.mjs.map +1 -1
- package/dist/tailordb-BlBGmQK-.d.mts +863 -0
- package/dist/utils/test/index.d.mts +3 -3
- package/dist/vitest/index.d.mts +25 -1
- package/dist/vitest/index.mjs +57 -12
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/{workflow.generated-CWi2rivQ.d.mts → workflow.generated-CQg1_Ami.d.mts} +183 -8
- package/docs/services/http-adapter.md +100 -0
- package/package.json +1 -1
- package/dist/application-BfGje3iZ.mjs.map +0 -1
- package/dist/application-BsipSxp3.mjs +0 -4
- package/dist/client-CGO7gniI.mjs.map +0 -1
- package/dist/runtime-DpbAj_8a.mjs.map +0 -1
- package/dist/tailor-db-field-D0qg8s4U.d.mts +0 -1639
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { M as TailorInvoker } from "../../tailordb-BlBGmQK-.mjs";
|
|
2
|
+
import { W as TailorDBType } from "../../workflow.generated-CQg1_Ami.mjs";
|
|
3
|
+
import { At as TailorField, bt as WORKFLOW_TEST_ENV_KEY, n as output } from "../../index-BLsnrEtc.mjs";
|
|
4
4
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
5
5
|
|
|
6
6
|
//#region src/utils/test/mock.d.ts
|
package/dist/vitest/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as TailorEnv } from "../env-B-g-qgE4.mjs";
|
|
2
|
-
import { Kysely, OperationNodeKind } from "kysely";
|
|
2
|
+
import { Kysely, OperationNode, OperationNodeKind, Transaction } from "kysely";
|
|
3
3
|
import { Plugin } from "vitest/config";
|
|
4
4
|
|
|
5
5
|
//#region src/vitest/mock.d.ts
|
|
@@ -285,9 +285,20 @@ declare const iconvMock: {
|
|
|
285
285
|
//#region src/vitest/mock-kysely.d.ts
|
|
286
286
|
/** A single statement executed against the mock, captured in order. */
|
|
287
287
|
interface ExecutedQuery {
|
|
288
|
+
/** The Kysely operation node kind, e.g. `"SelectQueryNode"`. */
|
|
288
289
|
kind: OperationNodeKind;
|
|
290
|
+
/** The compiled SQL string. */
|
|
289
291
|
sql: string;
|
|
292
|
+
/** The bound parameter values, in positional order. */
|
|
290
293
|
parameters: readonly unknown[];
|
|
294
|
+
/** The compiled Kysely operation node. */
|
|
295
|
+
node: OperationNode;
|
|
296
|
+
/** One `{ column: value }` map per row written by an insert. */
|
|
297
|
+
insertRows: () => Record<string, unknown>[];
|
|
298
|
+
/** The `{ column: value }` map written by a single-row insert. */
|
|
299
|
+
insertValues: () => Record<string, unknown>;
|
|
300
|
+
/** The `{ column: value }` map written by an update's SET clause. */
|
|
301
|
+
updateValues: () => Record<string, unknown>;
|
|
291
302
|
}
|
|
292
303
|
type MockRow = Record<string, unknown>;
|
|
293
304
|
type MockResult = MockRow[] | {
|
|
@@ -297,16 +308,29 @@ type MockResult = MockRow[] | {
|
|
|
297
308
|
type QueryResolver = (query: ExecutedQuery) => MockResult | undefined;
|
|
298
309
|
/** Controls and assertions for a {@link createKyselyMock} instance. */
|
|
299
310
|
interface KyselyMock<DB> {
|
|
311
|
+
/** The mock Kysely instance to run queries against. */
|
|
300
312
|
db: Kysely<DB>;
|
|
313
|
+
/** Every recorded query, in execution order. */
|
|
301
314
|
executedQueries: ExecutedQuery[];
|
|
315
|
+
/** Recorded SELECT queries. */
|
|
302
316
|
selects: ExecutedQuery[];
|
|
317
|
+
/** Recorded INSERT queries. */
|
|
303
318
|
inserts: ExecutedQuery[];
|
|
319
|
+
/** Recorded UPDATE queries. */
|
|
304
320
|
updates: ExecutedQuery[];
|
|
321
|
+
/** Recorded DELETE queries. */
|
|
305
322
|
deletes: ExecutedQuery[];
|
|
323
|
+
/** Stage the rows the next query returns. */
|
|
306
324
|
enqueueResult: (result: MockResult) => void;
|
|
325
|
+
/** Stage the rows for several upcoming queries, consumed in order. */
|
|
307
326
|
enqueueResults: (...results: MockResult[]) => void;
|
|
327
|
+
/** Set a resolver that returns rows by inspecting each query. */
|
|
308
328
|
setQueryResolver: (resolver: QueryResolver) => void;
|
|
329
|
+
/** Run `fn` inside a real transaction and return its result. */
|
|
330
|
+
withTx: <R>(fn: (trx: Transaction<DB>) => Promise<R>) => Promise<R>;
|
|
331
|
+
/** Clear recorded queries and staged results. */
|
|
309
332
|
reset: () => void;
|
|
333
|
+
/** Same as {@link KyselyMock.reset}; enables `using` disposal. */
|
|
310
334
|
[Symbol.dispose]: () => void;
|
|
311
335
|
}
|
|
312
336
|
/**
|
package/dist/vitest/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { a as fileMock, d as workflowMock, l as secretmanagerMock, o as iconvMoc
|
|
|
3
3
|
import { builtinModules } from "node:module";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { dirname, isAbsolute, matchesGlob, relative, resolve } from "node:path";
|
|
6
|
-
import { Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler } from "kysely";
|
|
6
|
+
import { ColumnNode, InsertQueryNode, Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler, PrimitiveValueListNode, ReferenceNode, UpdateQueryNode, ValueListNode, ValueNode, ValuesNode } from "kysely";
|
|
7
7
|
|
|
8
8
|
//#region src/vitest/blocked-modules.ts
|
|
9
9
|
/**
|
|
@@ -295,6 +295,53 @@ function createEnvironmentPlugin(options) {
|
|
|
295
295
|
* type-check normally, but execution returns staged rows and records every
|
|
296
296
|
* query for assertions.
|
|
297
297
|
*/
|
|
298
|
+
function unwrapValue(node) {
|
|
299
|
+
return ValueNode.is(node) ? node.value : node;
|
|
300
|
+
}
|
|
301
|
+
function insertRows(node) {
|
|
302
|
+
if (!InsertQueryNode.is(node)) throw new Error(`insertRows: expected InsertQueryNode, got ${node.kind}`);
|
|
303
|
+
const columns = node.columns;
|
|
304
|
+
const valuesNode = node.values;
|
|
305
|
+
if (columns === void 0 || valuesNode === void 0 || !ValuesNode.is(valuesNode)) throw new Error("insertRows: unsupported insert shape; inspect query.node instead");
|
|
306
|
+
return valuesNode.values.map((row) => {
|
|
307
|
+
if (!PrimitiveValueListNode.is(row) && !ValueListNode.is(row)) throw new Error("insertRows: unsupported insert shape; inspect query.node instead");
|
|
308
|
+
const values = PrimitiveValueListNode.is(row) ? row.values : row.values.map(unwrapValue);
|
|
309
|
+
const result = {};
|
|
310
|
+
columns.forEach((col, i) => {
|
|
311
|
+
result[col.column.name] = values[i];
|
|
312
|
+
});
|
|
313
|
+
return result;
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function insertValues(node) {
|
|
317
|
+
const rows = insertRows(node);
|
|
318
|
+
if (rows.length !== 1) throw new Error(`insertValues: query inserts ${rows.length} rows; use insertRows() for multi-row inserts`);
|
|
319
|
+
return rows[0];
|
|
320
|
+
}
|
|
321
|
+
function updateValues(node) {
|
|
322
|
+
if (!UpdateQueryNode.is(node)) throw new Error(`updateValues: expected UpdateQueryNode, got ${node.kind}`);
|
|
323
|
+
if (node.updates === void 0) throw new Error("updateValues: unsupported update shape; inspect query.node instead");
|
|
324
|
+
const result = {};
|
|
325
|
+
for (const update of node.updates) {
|
|
326
|
+
const col = update.column;
|
|
327
|
+
const name = ColumnNode.is(col) ? col.column.name : ReferenceNode.is(col) && ColumnNode.is(col.column) ? col.column.column.name : void 0;
|
|
328
|
+
if (name === void 0) throw new Error("updateValues: unsupported update shape; inspect query.node instead");
|
|
329
|
+
result[name] = unwrapValue(update.value);
|
|
330
|
+
}
|
|
331
|
+
return result;
|
|
332
|
+
}
|
|
333
|
+
function toExecutedQuery(compiledQuery) {
|
|
334
|
+
const node = compiledQuery.query;
|
|
335
|
+
return {
|
|
336
|
+
kind: node.kind,
|
|
337
|
+
sql: compiledQuery.sql,
|
|
338
|
+
parameters: compiledQuery.parameters,
|
|
339
|
+
node,
|
|
340
|
+
insertRows: () => insertRows(node),
|
|
341
|
+
insertValues: () => insertValues(node),
|
|
342
|
+
updateValues: () => updateValues(node)
|
|
343
|
+
};
|
|
344
|
+
}
|
|
298
345
|
function toStagedResult(result) {
|
|
299
346
|
if (Array.isArray(result)) return {
|
|
300
347
|
rows: result,
|
|
@@ -336,11 +383,7 @@ var MockConnection = class {
|
|
|
336
383
|
this.state = state;
|
|
337
384
|
}
|
|
338
385
|
async executeQuery(compiledQuery) {
|
|
339
|
-
const query =
|
|
340
|
-
kind: compiledQuery.query.kind,
|
|
341
|
-
sql: compiledQuery.sql,
|
|
342
|
-
parameters: compiledQuery.parameters
|
|
343
|
-
};
|
|
386
|
+
const query = toExecutedQuery(compiledQuery);
|
|
344
387
|
this.state.executed.push(query);
|
|
345
388
|
const { rows, numAffectedRows } = this.state.next(query);
|
|
346
389
|
return {
|
|
@@ -378,13 +421,14 @@ function byKind(state, kind) {
|
|
|
378
421
|
*/
|
|
379
422
|
function createKyselyMock() {
|
|
380
423
|
const state = new MockState();
|
|
424
|
+
const kysely = new Kysely({ dialect: {
|
|
425
|
+
createDriver: () => new MockDriver(state),
|
|
426
|
+
createQueryCompiler: () => new PostgresQueryCompiler(),
|
|
427
|
+
createAdapter: () => new PostgresAdapter(),
|
|
428
|
+
createIntrospector: (db) => new PostgresIntrospector(db)
|
|
429
|
+
} });
|
|
381
430
|
return {
|
|
382
|
-
db:
|
|
383
|
-
createDriver: () => new MockDriver(state),
|
|
384
|
-
createQueryCompiler: () => new PostgresQueryCompiler(),
|
|
385
|
-
createAdapter: () => new PostgresAdapter(),
|
|
386
|
-
createIntrospector: (db) => new PostgresIntrospector(db)
|
|
387
|
-
} }),
|
|
431
|
+
db: kysely,
|
|
388
432
|
get executedQueries() {
|
|
389
433
|
return state.executed;
|
|
390
434
|
},
|
|
@@ -403,6 +447,7 @@ function createKyselyMock() {
|
|
|
403
447
|
enqueueResult: (result) => state.enqueue(result),
|
|
404
448
|
enqueueResults: (...results) => state.enqueue(...results),
|
|
405
449
|
setQueryResolver: (resolver) => state.setResolver(resolver),
|
|
450
|
+
withTx: (fn) => kysely.transaction().execute(fn),
|
|
406
451
|
reset: () => state.reset(),
|
|
407
452
|
[Symbol.dispose]: () => state.reset()
|
|
408
453
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/vitest/blocked-modules.ts","../../src/vitest/plugin.ts","../../src/vitest/mock-kysely.ts","../../src/vitest/index.ts"],"sourcesContent":["/**\n * Blocked Node.js built-in modules and their Web Standard API alternatives.\n *\n * The Tailor Platform runtime only provides Web Standard APIs.\n * These Node.js modules are not available and should be replaced with\n * the suggested alternatives.\n */\nimport { builtinModules } from \"node:module\";\n\n// Suggestions keyed by bare specifier. Lookup also checks with \"node:\" prefix stripped.\nconst SUGGESTIONS: Record<string, string> = {\n crypto: \"Use the Web Crypto API (globalThis.crypto) instead.\",\n buffer: \"Use Uint8Array or ArrayBuffer instead.\",\n fs: \"File system access is not available in the Tailor Platform runtime.\",\n \"fs/promises\": \"File system access is not available in the Tailor Platform runtime.\",\n path: \"Use URL or URLPattern for path manipulation.\",\n http: \"Use the Fetch API (globalThis.fetch) for HTTP requests instead.\",\n https: \"Use the Fetch API (globalThis.fetch) for HTTPS requests instead.\",\n url: \"Use the URL and URLSearchParams Web APIs instead.\",\n util: \"Use Web Standard APIs instead.\",\n stream: \"Use Web Streams API (ReadableStream, WritableStream, TransformStream) instead.\",\n \"stream/web\": \"Use Web Streams API (ReadableStream, WritableStream, TransformStream) instead.\",\n events: \"Use EventTarget instead.\",\n zlib: \"Use CompressionStream and DecompressionStream Web APIs instead.\",\n querystring: \"Use URLSearchParams instead.\",\n string_decoder: \"Use TextDecoder instead.\",\n};\n\nconst BLOCKED_MODULES = new Set<string>();\nfor (const mod of builtinModules) {\n BLOCKED_MODULES.add(mod);\n BLOCKED_MODULES.add(`node:${mod}`);\n}\n\n/**\n * Check if a module specifier is a blocked Node.js built-in.\n * @param specifier - Module specifier to check (e.g. \"node:crypto\", \"fs\")\n * @returns Whether the specifier is blocked\n */\nexport function isBlockedModule(specifier: string): boolean {\n return BLOCKED_MODULES.has(specifier);\n}\n\n/**\n * Get the error message for a blocked module import.\n * @param specifier - Module specifier that was blocked\n * @returns Error message with optional suggestion for the Web Standard API alternative\n */\nexport function getBlockedMessage(specifier: string): string {\n const bare = specifier.startsWith(\"node:\") ? specifier.slice(5) : specifier;\n const suggestion = SUGGESTIONS[bare];\n const base = `\"${specifier}\" is not available in the Tailor Platform runtime.`;\n return suggestion ? `${base} ${suggestion}` : base;\n}\n","import { dirname, isAbsolute, matchesGlob, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { isBlockedModule, getBlockedMessage } from \"./blocked-modules\";\nimport type { Plugin } from \"vitest/config\";\n\nconst DEFAULT_TEST_INCLUDE = [\"**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\"];\n\ninterface ExportSpecifierNode {\n type?: string;\n exported?: { name?: unknown } | null;\n}\n\ninterface ImportLikeNode {\n type: string;\n start: number;\n end: number;\n source?: { value?: unknown } | null;\n specifiers?: ExportSpecifierNode[] | null;\n exported?: { name?: unknown } | null;\n}\n\nconst IMPORT_LIKE_TYPES = new Set([\n \"ImportDeclaration\",\n \"ExportNamedDeclaration\",\n \"ExportAllDeclaration\",\n]);\n\n// Re-export specifiers (`export { x as Y } from \"...\"`) accept any\n// `IdentifierName` for `Y` — including reserved words like `delete`. But\n// `export const Y = ...` requires a `BindingIdentifier`, which forbids\n// reserved words and the strict-mode-banned `arguments` / `eval`. Synthesizing\n// `export const delete = ...` would yield a syntax error, so we fall back to\n// plain `throw` for unsafe names.\nconst UNSAFE_BINDING_NAMES = new Set([\n // ReservedWord (ES2022+)\n \"break\",\n \"case\",\n \"catch\",\n \"class\",\n \"const\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"delete\",\n \"do\",\n \"else\",\n \"enum\",\n \"export\",\n \"extends\",\n \"false\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"import\",\n \"in\",\n \"instanceof\",\n \"new\",\n \"null\",\n \"return\",\n \"super\",\n \"switch\",\n \"this\",\n \"throw\",\n \"true\",\n \"try\",\n \"typeof\",\n \"var\",\n \"void\",\n \"while\",\n \"with\",\n \"yield\",\n // Strict-mode reserved (ESM is always strict)\n \"let\",\n \"static\",\n \"implements\",\n \"interface\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n // Module-specific reserved\n \"await\",\n // Banned as binding names in strict mode\n \"arguments\",\n \"eval\",\n]);\n\nconst ID_START = /^[A-Za-z_$]/;\nconst ID_CONT = /^[A-Za-z0-9_$]*$/;\n\nfunction isSafeBindingName(name: string): boolean {\n if (UNSAFE_BINDING_NAMES.has(name)) return false;\n if (name.length === 0) return false;\n // Restrict to ASCII identifiers — Unicode bindings are valid JS but rare\n // for re-exports of node:* modules, and a regex over the full\n // ID_Start/ID_Continue sets adds substantial weight for marginal gain.\n return ID_START.test(name[0] ?? \"\") && ID_CONT.test(name.slice(1));\n}\n\nfunction buildBlockedReplacement(node: ImportLikeNode, message: string): string {\n // JSON.stringify yields a fully-escaped string literal (including the\n // surrounding quotes), so we don't need to manually handle backslashes,\n // newlines, or other control characters that may appear in the message.\n const literal = JSON.stringify(message);\n const throwStmt = `throw new Error(${literal});`;\n const throwExpr = `(() => { throw new Error(${literal}); })()`;\n\n if (node.type === \"ExportNamedDeclaration\") {\n const specs = node.specifiers ?? [];\n const stubs: string[] = [];\n for (const spec of specs) {\n const exportedName = spec.exported?.name;\n if (typeof exportedName !== \"string\") continue;\n if (exportedName === \"default\") {\n stubs.push(`export default ${throwExpr};`);\n continue;\n }\n // Reserved words can be re-export names but not binding names.\n // Bail to a plain throw rather than emit invalid syntax.\n if (!isSafeBindingName(exportedName)) return throwStmt;\n stubs.push(`export const ${exportedName} = ${throwExpr};`);\n }\n return stubs.length > 0 ? stubs.join(\" \") : throwStmt;\n }\n\n if (node.type === \"ExportAllDeclaration\") {\n const exportedName = node.exported?.name;\n if (typeof exportedName === \"string\" && isSafeBindingName(exportedName)) {\n return `export const ${exportedName} = ${throwExpr};`;\n }\n return throwStmt;\n }\n\n return throwStmt;\n}\n\n/**\n * Vite plugin that blocks Node.js built-in module imports from production code.\n *\n * Uses the `transform` hook to walk the Rollup-provided AST of non-test source\n * files for static `node:*` imports and re-exports.\n * `ImportDeclaration` and bare `export * from \"...\"` are replaced with a\n * `throw new Error(...)` statement so the failure surfaces at evaluation time.\n * `ExportNamedDeclaration` (`export { x, y as z } from \"...\"`) and namespaced\n * `export * as ns from \"...\"` are rewritten to per-binding stub exports\n * (`export const x = (() => { throw new Error(...) })();`). The IIFE throws\n * eagerly during module evaluation (same timing as a top-level `throw`), but\n * preserving the declared export bindings ensures the surfaced error is the\n * actual \"node:* not available\" message rather than an opaque\n * \"missing export\" raised by the loader.\n * Vitest treats `node:*` as external SSR modules (skipping `resolveId`), so\n * source-level transformation is the only reliable interception point.\n * Runs in the default phase (no `enforce: \"pre\"`) so esbuild's TypeScript\n * transform strips `import type` first; only runtime imports reach this hook.\n * Node.js globals not in the platform runtime are removed by the environment (whitelist-based).\n * Test file patterns are read from the resolved Vitest config (`test.include`).\n * Vitest setup files (`test.setupFiles`) and global-setup files\n * (`test.globalSetup`) are also exempted: they run in the test runner host,\n * not in the emulated platform runtime, so they may freely use `node:*`\n * modules (e.g. `node:url` for `pathToFileURL`).\n * @returns Vite plugin\n */\nexport function createBlockPlugin(): Plugin {\n let isTestFile: (id: string) => boolean = () => false;\n let isUserSourceFile: (id: string) => boolean = () => false;\n\n return {\n name: \"tailor-runtime-block-node\",\n\n configResolved(config) {\n type HostFileTestConfig = {\n include?: string[];\n setupFiles?: string | string[];\n globalSetup?: string | string[];\n root?: string;\n };\n const testConfig = (\n config as typeof config & {\n test?: HostFileTestConfig & {\n projects?: { test?: HostFileTestConfig }[];\n };\n }\n ).test;\n const root = testConfig?.root ?? config.root;\n // Setup files and global-setup files run in the Vitest host (not the\n // emulated runtime), so they may freely import node:* modules. Collect\n // them from the top-level config AND from each `test.projects[i]` —\n // per-project setup files run in the host too and would otherwise be\n // transformed as production code, breaking node:* imports inside them.\n const toAbsolutePaths = (value: string | string[] | undefined, baseRoot: string) =>\n (Array.isArray(value) ? value : value ? [value] : []).map((f) => resolve(baseRoot, f));\n const exemptHostFiles = new Set<string>([\n ...toAbsolutePaths(testConfig?.setupFiles, root),\n ...toAbsolutePaths(testConfig?.globalSetup, root),\n ]);\n // Vitest projects can each define their own `test.include` (and root).\n // A project that uses non-default patterns (e.g. `tests/**/*.spec.ts`)\n // must also be considered when classifying test files — otherwise its\n // tests would be treated as production code and have node:* imports\n // rewritten. Build a list of (root, patterns) pairs covering top-level\n // + every project, and accept a file if any pair matches.\n const includePairs: { root: string; patterns: string[] }[] = [\n { root, patterns: testConfig?.include ?? DEFAULT_TEST_INCLUDE },\n ];\n for (const project of testConfig?.projects ?? []) {\n const projectTest = project?.test;\n if (!projectTest) continue;\n const projectRoot = projectTest.root ?? root;\n for (const f of toAbsolutePaths(projectTest.setupFiles, projectRoot)) {\n exemptHostFiles.add(f);\n }\n for (const f of toAbsolutePaths(projectTest.globalSetup, projectRoot)) {\n exemptHostFiles.add(f);\n }\n includePairs.push({\n root: projectRoot,\n patterns: projectTest.include ?? DEFAULT_TEST_INCLUDE,\n });\n }\n isTestFile = (id: string) => {\n if (exemptHostFiles.has(id)) return true;\n return includePairs.some(({ root: r, patterns }) => {\n const candidate = isAbsolute(id) ? relative(r, id) : id;\n return patterns.some((pattern) => matchesGlob(candidate, pattern));\n });\n };\n // Only transform files inside the project root. With pnpm workspaces,\n // dependencies are symlinked and Vite resolves them to absolute paths\n // outside `node_modules`, so the substring check alone is insufficient.\n // Non-absolute ids are Vite-internal: virtual modules (`\\0...`,\n // `virtual:...`), bare specifiers, etc. Those are never user source\n // files and must not be parsed/transformed.\n isUserSourceFile = (id: string) => {\n if (!isAbsolute(id)) return false;\n const rel = relative(root, id);\n return rel !== \"\" && !rel.startsWith(\"..\") && !isAbsolute(rel);\n };\n },\n\n transform(code, id) {\n // Vite can pass ids with query/hash suffixes (e.g. `file.ts?import`,\n // `file.ts?v=hash`). Strip them so exact-path lookups (Set membership,\n // glob matching, absolute-path checks) match what callers configured.\n const queryIdx = id.search(/[?#]/);\n const cleanId = queryIdx === -1 ? id : id.slice(0, queryIdx);\n\n if (isTestFile(cleanId)) return undefined;\n if (cleanId.includes(\"node_modules\")) return undefined;\n if (!isUserSourceFile(cleanId)) return undefined;\n\n let ast: { body: ImportLikeNode[] };\n try {\n ast = this.parse(code) as unknown as { body: ImportLikeNode[] };\n } catch {\n // Not parseable as ESM (e.g. JSON, asset). Let other plugins handle it.\n return undefined;\n }\n\n const replacements: { start: number; end: number; replacement: string }[] = [];\n for (const node of ast.body) {\n if (!IMPORT_LIKE_TYPES.has(node.type)) continue;\n const specifier = node.source?.value;\n if (typeof specifier !== \"string\") continue;\n if (isBlockedModule(specifier)) {\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: buildBlockedReplacement(node, getBlockedMessage(specifier)),\n });\n }\n }\n\n if (replacements.length === 0) return undefined;\n\n let transformed = code;\n for (const r of replacements.sort((a, b) => b.start - a.start)) {\n transformed = transformed.slice(0, r.start) + r.replacement + transformed.slice(r.end);\n }\n\n return { code: transformed, map: null };\n },\n };\n}\n\nconst ENVIRONMENT_NAME = \"tailor-runtime\";\n\n/**\n * Vite plugin that resolves the tailor-runtime environment and injects setup files.\n *\n * Vitest resolves environments starting with \".\" or \"/\" as file paths.\n * This plugin rewrites `environment: \"tailor-runtime\"` to the absolute path\n * of the bundled environment module, both at the top-level and per-project.\n * It also injects the setup file that removes Vitest-dependent globals\n * (like `performance`) per-test via beforeEach/afterEach hooks.\n * @param options - Optional configuration\n * @param options.config - Path to tailor.config.ts to load SecretManager values into mock\n * @returns Vite plugin\n */\nexport function createEnvironmentPlugin(options?: { config?: string }): Plugin {\n const currentDir = dirname(fileURLToPath(import.meta.url));\n const environmentPath = resolve(currentDir, \"environment.mjs\");\n const setupPath = resolve(currentDir, \"setup.mjs\");\n\n return {\n name: \"tailor-runtime-environment\",\n\n config(config) {\n const testConfig = config.test as\n | (Record<string, unknown> & {\n projects?: Record<string, unknown>[];\n setupFiles?: string | string[];\n })\n | undefined;\n\n // Rewrite environment name to absolute path at top-level\n let usesTailorRuntime = false;\n if (testConfig?.environment === ENVIRONMENT_NAME) {\n testConfig.environment = environmentPath;\n usesTailorRuntime = true;\n }\n\n // Rewrite in each project config\n if (testConfig?.projects) {\n for (const project of testConfig.projects) {\n const projectTest = project.test as Record<string, unknown> | undefined;\n if (projectTest?.environment === ENVIRONMENT_NAME) {\n projectTest.environment = environmentPath;\n usesTailorRuntime = true;\n }\n }\n }\n\n // Pass config path to setup.ts via env var (cross-process compatible).\n // Always clear first, then set only when tailor-runtime is actually\n // selected. This makes the env var deterministic across Vite config\n // reloads (watch mode, programmatic re-init): a stale value from a\n // prior iteration cannot make setup.ts load secrets from an old config.\n // The leading `__` marks this as plugin-private, so deleting any\n // pre-existing value is safe.\n delete process.env.__TAILOR_RUNTIME_CONFIG;\n if (options?.config && usesTailorRuntime) {\n // Resolve against the user-provided Vite root when present (falling\n // back to cwd). Vitest projects with a non-cwd `root` would otherwise\n // resolve a relative options.config against the wrong directory.\n const configRoot = (config.root as string | undefined) ?? process.cwd();\n const configAbsPath = resolve(configRoot, options.config);\n process.env.__TAILOR_RUNTIME_CONFIG = configAbsPath;\n }\n\n // Normalize a user-provided string `setupFiles` into an array so Vite's\n // array-concat merge sees both sides as arrays (the string form would\n // otherwise be replaced rather than concatenated by some merge paths).\n // Vite then concatenates the user's array with our [setupPath].\n if (testConfig && typeof testConfig.setupFiles === \"string\") {\n testConfig.setupFiles = [testConfig.setupFiles];\n }\n\n return {\n test: {\n setupFiles: [setupPath],\n },\n };\n },\n };\n}\n","/**\n * Kysely-layer mock for unit testing.\n *\n * Builds a real Kysely instance backed by a mock driver: queries compile and\n * type-check normally, but execution returns staged rows and records every\n * query for assertions.\n */\n\nimport {\n type CompiledQuery,\n type DatabaseConnection,\n type Dialect,\n type Driver,\n Kysely,\n type OperationNodeKind,\n PostgresAdapter,\n PostgresIntrospector,\n PostgresQueryCompiler,\n type QueryResult,\n} from \"kysely\";\n\n/** A single statement executed against the mock, captured in order. */\nexport interface ExecutedQuery {\n kind: OperationNodeKind;\n sql: string;\n parameters: readonly unknown[];\n}\n\ntype MockRow = Record<string, unknown>;\ntype MockResult = MockRow[] | { rows?: MockRow[]; numAffectedRows?: number | bigint };\ntype QueryResolver = (query: ExecutedQuery) => MockResult | undefined;\n\ninterface StagedResult {\n rows: MockRow[];\n numAffectedRows: bigint | undefined;\n}\n\nfunction toStagedResult(result: MockResult): StagedResult {\n if (Array.isArray(result)) return { rows: result, numAffectedRows: undefined };\n return {\n rows: result.rows ?? [],\n numAffectedRows:\n result.numAffectedRows === undefined ? undefined : BigInt(result.numAffectedRows),\n };\n}\n\n/** Controls and assertions for a {@link createKyselyMock} instance. */\nexport interface KyselyMock<DB> {\n db: Kysely<DB>;\n executedQueries: ExecutedQuery[];\n selects: ExecutedQuery[];\n inserts: ExecutedQuery[];\n updates: ExecutedQuery[];\n deletes: ExecutedQuery[];\n enqueueResult: (result: MockResult) => void;\n enqueueResults: (...results: MockResult[]) => void;\n setQueryResolver: (resolver: QueryResolver) => void;\n reset: () => void;\n [Symbol.dispose]: () => void;\n}\n\nclass MockState {\n readonly executed: ExecutedQuery[] = [];\n private readonly queue: MockResult[] = [];\n private resolver: QueryResolver | undefined;\n\n enqueue(...results: MockResult[]): void {\n this.queue.push(...results);\n }\n\n setResolver(resolver: QueryResolver): void {\n this.resolver = resolver;\n }\n\n next(query: ExecutedQuery): StagedResult {\n const resolved = this.resolver?.(query);\n if (resolved !== undefined) return toStagedResult(resolved);\n const queued = this.queue.shift();\n return queued === undefined ? { rows: [], numAffectedRows: undefined } : toStagedResult(queued);\n }\n\n reset(): void {\n this.executed.length = 0;\n this.queue.length = 0;\n this.resolver = undefined;\n }\n}\n\nclass MockConnection implements DatabaseConnection {\n constructor(private readonly state: MockState) {}\n\n async executeQuery<R>(compiledQuery: CompiledQuery): Promise<QueryResult<R>> {\n const query: ExecutedQuery = {\n kind: compiledQuery.query.kind,\n sql: compiledQuery.sql,\n parameters: compiledQuery.parameters,\n };\n this.state.executed.push(query);\n const { rows, numAffectedRows } = this.state.next(query);\n return {\n rows: rows as R[],\n numAffectedRows: numAffectedRows ?? BigInt(rows.length),\n };\n }\n\n streamQuery<R>(): AsyncIterableIterator<QueryResult<R>> {\n throw new Error(\"createKyselyMock: streaming is not supported\");\n }\n}\n\nclass MockDriver implements Driver {\n constructor(private readonly state: MockState) {}\n\n async init(): Promise<void> {}\n\n async acquireConnection(): Promise<DatabaseConnection> {\n return new MockConnection(this.state);\n }\n\n // No-ops so begin/commit/rollback never enter `executed` and pollute counts.\n async beginTransaction(): Promise<void> {}\n async commitTransaction(): Promise<void> {}\n async rollbackTransaction(): Promise<void> {}\n\n async releaseConnection(): Promise<void> {}\n async destroy(): Promise<void> {}\n}\n\nfunction byKind(state: MockState, kind: OperationNodeKind): ExecutedQuery[] {\n return state.executed.filter((query) => query.kind === kind);\n}\n\n/**\n * Create a mock Kysely instance for unit-testing code that runs Kysely queries.\n * Pass the namespace schema as the type argument, e.g.\n * `createKyselyMock<Namespace[\"main-db\"]>()`.\n * @returns A {@link KyselyMock} with the mock `db`, recorded queries, and result staging.\n */\nexport function createKyselyMock<DB = Record<string, never>>(): KyselyMock<DB> {\n const state = new MockState();\n const dialect: Dialect = {\n createDriver: () => new MockDriver(state),\n createQueryCompiler: () => new PostgresQueryCompiler(),\n createAdapter: () => new PostgresAdapter(),\n createIntrospector: (db) => new PostgresIntrospector(db),\n };\n const kysely = new Kysely<DB>({ dialect });\n\n return {\n db: kysely,\n get executedQueries() {\n return state.executed;\n },\n get selects() {\n return byKind(state, \"SelectQueryNode\");\n },\n get inserts() {\n return byKind(state, \"InsertQueryNode\");\n },\n get updates() {\n return byKind(state, \"UpdateQueryNode\");\n },\n get deletes() {\n return byKind(state, \"DeleteQueryNode\");\n },\n enqueueResult: (result) => state.enqueue(result),\n enqueueResults: (...results) => state.enqueue(...results),\n setQueryResolver: (resolver) => state.setResolver(resolver),\n reset: () => state.reset(),\n [Symbol.dispose]: () => state.reset(),\n };\n}\n","import { createBlockPlugin, createEnvironmentPlugin } from \"./plugin\";\nimport type { Plugin } from \"vitest/config\";\n\n/**\n * Creates Vitest plugins that emulate the Tailor Platform function runtime environment.\n *\n * **Beta:** This API may change in future releases.\n *\n * ## What it does\n *\n * 1. **Node.js module blocking** (transform hook) — Imports of `node:*` modules\n * (and bare builtins like `crypto`, `fs`) in non-test source files are replaced\n * with code that throws an error with a suggestion for the Web Standard API alternative.\n * Test files are exempt and can use `node:*` freely. Test file patterns are read\n * from the resolved Vitest config (`test.include`).\n *\n * 2. **Node.js globals removal** (environment + setup) — Only globals available in the\n * Tailor Platform runtime are kept (whitelist: ECMAScript standard, Web Standard APIs\n * from bootstrap.js, platform mocks). All others (`Buffer`, `global`, `setImmediate`,\n * `__dirname`, `__filename`, etc.) are removed. `performance` is removed per-test\n * via beforeEach/afterEach since Vitest needs it during initialization.\n *\n * 3. **Platform API mocks** (environment) — All platform APIs are auto-injected with\n * control objects: `tailordbMock`, `workflowMock`, `secretmanagerMock`,\n * `authconnectionMock`, `idpMock`, `fileMock`, `iconvMock`. Each\n * provides response configuration, call recording, and reset.\n *\n * 4. **Environment resolution** — Rewrites `environment: \"tailor-runtime\"` to the\n * absolute path of the bundled environment module via the config hook.\n *\n * ## Known limitations\n *\n * - **`process`** and **`require`** are NOT removed or blocked. Vitest's internal\n * runner depends on them. On the real Tailor Platform runtime, they do not exist.\n * - **Dynamic `import()`** of bundled files (via `createImportMain()`) bypasses\n * the transform hook since those files are loaded through Node.js native loader.\n * ## Options\n *\n * - **`config`** — Path to `tailor.config.ts`. Loads `defineSecretManager()` values\n * into `secretmanagerMock` so `getSecret()` returns the configured values.\n * @example\n * ```typescript\n * // vitest.config.ts\n * import { defineConfig } from \"vitest/config\";\n * import { tailorRuntime } from \"@tailor-platform/sdk/vitest\";\n *\n * export default defineConfig({\n * plugins: [tailorRuntime({ config: \"./tailor.config.ts\" })],\n * test: {\n * environment: \"tailor-runtime\",\n * },\n * });\n * ```\n * @param options - Optional configuration\n * @param options.config - Path to tailor.config.ts to load SecretManager values into mock\n * @returns Array of Vite plugins\n */\nexport function tailorRuntime(options?: { config?: string }): Plugin[] {\n return [createBlockPlugin(), createEnvironmentPlugin(options)];\n}\n\nexport {\n tailordbMock,\n workflowMock,\n secretmanagerMock,\n authconnectionMock,\n idpMock,\n fileMock,\n iconvMock,\n} from \"./mock\";\n\nexport { createKyselyMock, type KyselyMock, type ExecutedQuery } from \"./mock-kysely\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/vitest/blocked-modules.ts","../../src/vitest/plugin.ts","../../src/vitest/mock-kysely.ts","../../src/vitest/index.ts"],"sourcesContent":["/**\n * Blocked Node.js built-in modules and their Web Standard API alternatives.\n *\n * The Tailor Platform runtime only provides Web Standard APIs.\n * These Node.js modules are not available and should be replaced with\n * the suggested alternatives.\n */\nimport { builtinModules } from \"node:module\";\n\n// Suggestions keyed by bare specifier. Lookup also checks with \"node:\" prefix stripped.\nconst SUGGESTIONS: Record<string, string> = {\n crypto: \"Use the Web Crypto API (globalThis.crypto) instead.\",\n buffer: \"Use Uint8Array or ArrayBuffer instead.\",\n fs: \"File system access is not available in the Tailor Platform runtime.\",\n \"fs/promises\": \"File system access is not available in the Tailor Platform runtime.\",\n path: \"Use URL or URLPattern for path manipulation.\",\n http: \"Use the Fetch API (globalThis.fetch) for HTTP requests instead.\",\n https: \"Use the Fetch API (globalThis.fetch) for HTTPS requests instead.\",\n url: \"Use the URL and URLSearchParams Web APIs instead.\",\n util: \"Use Web Standard APIs instead.\",\n stream: \"Use Web Streams API (ReadableStream, WritableStream, TransformStream) instead.\",\n \"stream/web\": \"Use Web Streams API (ReadableStream, WritableStream, TransformStream) instead.\",\n events: \"Use EventTarget instead.\",\n zlib: \"Use CompressionStream and DecompressionStream Web APIs instead.\",\n querystring: \"Use URLSearchParams instead.\",\n string_decoder: \"Use TextDecoder instead.\",\n};\n\nconst BLOCKED_MODULES = new Set<string>();\nfor (const mod of builtinModules) {\n BLOCKED_MODULES.add(mod);\n BLOCKED_MODULES.add(`node:${mod}`);\n}\n\n/**\n * Check if a module specifier is a blocked Node.js built-in.\n * @param specifier - Module specifier to check (e.g. \"node:crypto\", \"fs\")\n * @returns Whether the specifier is blocked\n */\nexport function isBlockedModule(specifier: string): boolean {\n return BLOCKED_MODULES.has(specifier);\n}\n\n/**\n * Get the error message for a blocked module import.\n * @param specifier - Module specifier that was blocked\n * @returns Error message with optional suggestion for the Web Standard API alternative\n */\nexport function getBlockedMessage(specifier: string): string {\n const bare = specifier.startsWith(\"node:\") ? specifier.slice(5) : specifier;\n const suggestion = SUGGESTIONS[bare];\n const base = `\"${specifier}\" is not available in the Tailor Platform runtime.`;\n return suggestion ? `${base} ${suggestion}` : base;\n}\n","import { dirname, isAbsolute, matchesGlob, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { isBlockedModule, getBlockedMessage } from \"./blocked-modules\";\nimport type { Plugin } from \"vitest/config\";\n\nconst DEFAULT_TEST_INCLUDE = [\"**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\"];\n\ninterface ExportSpecifierNode {\n type?: string;\n exported?: { name?: unknown } | null;\n}\n\ninterface ImportLikeNode {\n type: string;\n start: number;\n end: number;\n source?: { value?: unknown } | null;\n specifiers?: ExportSpecifierNode[] | null;\n exported?: { name?: unknown } | null;\n}\n\nconst IMPORT_LIKE_TYPES = new Set([\n \"ImportDeclaration\",\n \"ExportNamedDeclaration\",\n \"ExportAllDeclaration\",\n]);\n\n// Re-export specifiers (`export { x as Y } from \"...\"`) accept any\n// `IdentifierName` for `Y` — including reserved words like `delete`. But\n// `export const Y = ...` requires a `BindingIdentifier`, which forbids\n// reserved words and the strict-mode-banned `arguments` / `eval`. Synthesizing\n// `export const delete = ...` would yield a syntax error, so we fall back to\n// plain `throw` for unsafe names.\nconst UNSAFE_BINDING_NAMES = new Set([\n // ReservedWord (ES2022+)\n \"break\",\n \"case\",\n \"catch\",\n \"class\",\n \"const\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"delete\",\n \"do\",\n \"else\",\n \"enum\",\n \"export\",\n \"extends\",\n \"false\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"import\",\n \"in\",\n \"instanceof\",\n \"new\",\n \"null\",\n \"return\",\n \"super\",\n \"switch\",\n \"this\",\n \"throw\",\n \"true\",\n \"try\",\n \"typeof\",\n \"var\",\n \"void\",\n \"while\",\n \"with\",\n \"yield\",\n // Strict-mode reserved (ESM is always strict)\n \"let\",\n \"static\",\n \"implements\",\n \"interface\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n // Module-specific reserved\n \"await\",\n // Banned as binding names in strict mode\n \"arguments\",\n \"eval\",\n]);\n\nconst ID_START = /^[A-Za-z_$]/;\nconst ID_CONT = /^[A-Za-z0-9_$]*$/;\n\nfunction isSafeBindingName(name: string): boolean {\n if (UNSAFE_BINDING_NAMES.has(name)) return false;\n if (name.length === 0) return false;\n // Restrict to ASCII identifiers — Unicode bindings are valid JS but rare\n // for re-exports of node:* modules, and a regex over the full\n // ID_Start/ID_Continue sets adds substantial weight for marginal gain.\n return ID_START.test(name[0] ?? \"\") && ID_CONT.test(name.slice(1));\n}\n\nfunction buildBlockedReplacement(node: ImportLikeNode, message: string): string {\n // JSON.stringify yields a fully-escaped string literal (including the\n // surrounding quotes), so we don't need to manually handle backslashes,\n // newlines, or other control characters that may appear in the message.\n const literal = JSON.stringify(message);\n const throwStmt = `throw new Error(${literal});`;\n const throwExpr = `(() => { throw new Error(${literal}); })()`;\n\n if (node.type === \"ExportNamedDeclaration\") {\n const specs = node.specifiers ?? [];\n const stubs: string[] = [];\n for (const spec of specs) {\n const exportedName = spec.exported?.name;\n if (typeof exportedName !== \"string\") continue;\n if (exportedName === \"default\") {\n stubs.push(`export default ${throwExpr};`);\n continue;\n }\n // Reserved words can be re-export names but not binding names.\n // Bail to a plain throw rather than emit invalid syntax.\n if (!isSafeBindingName(exportedName)) return throwStmt;\n stubs.push(`export const ${exportedName} = ${throwExpr};`);\n }\n return stubs.length > 0 ? stubs.join(\" \") : throwStmt;\n }\n\n if (node.type === \"ExportAllDeclaration\") {\n const exportedName = node.exported?.name;\n if (typeof exportedName === \"string\" && isSafeBindingName(exportedName)) {\n return `export const ${exportedName} = ${throwExpr};`;\n }\n return throwStmt;\n }\n\n return throwStmt;\n}\n\n/**\n * Vite plugin that blocks Node.js built-in module imports from production code.\n *\n * Uses the `transform` hook to walk the Rollup-provided AST of non-test source\n * files for static `node:*` imports and re-exports.\n * `ImportDeclaration` and bare `export * from \"...\"` are replaced with a\n * `throw new Error(...)` statement so the failure surfaces at evaluation time.\n * `ExportNamedDeclaration` (`export { x, y as z } from \"...\"`) and namespaced\n * `export * as ns from \"...\"` are rewritten to per-binding stub exports\n * (`export const x = (() => { throw new Error(...) })();`). The IIFE throws\n * eagerly during module evaluation (same timing as a top-level `throw`), but\n * preserving the declared export bindings ensures the surfaced error is the\n * actual \"node:* not available\" message rather than an opaque\n * \"missing export\" raised by the loader.\n * Vitest treats `node:*` as external SSR modules (skipping `resolveId`), so\n * source-level transformation is the only reliable interception point.\n * Runs in the default phase (no `enforce: \"pre\"`) so esbuild's TypeScript\n * transform strips `import type` first; only runtime imports reach this hook.\n * Node.js globals not in the platform runtime are removed by the environment (whitelist-based).\n * Test file patterns are read from the resolved Vitest config (`test.include`).\n * Vitest setup files (`test.setupFiles`) and global-setup files\n * (`test.globalSetup`) are also exempted: they run in the test runner host,\n * not in the emulated platform runtime, so they may freely use `node:*`\n * modules (e.g. `node:url` for `pathToFileURL`).\n * @returns Vite plugin\n */\nexport function createBlockPlugin(): Plugin {\n let isTestFile: (id: string) => boolean = () => false;\n let isUserSourceFile: (id: string) => boolean = () => false;\n\n return {\n name: \"tailor-runtime-block-node\",\n\n configResolved(config) {\n type HostFileTestConfig = {\n include?: string[];\n setupFiles?: string | string[];\n globalSetup?: string | string[];\n root?: string;\n };\n const testConfig = (\n config as typeof config & {\n test?: HostFileTestConfig & {\n projects?: { test?: HostFileTestConfig }[];\n };\n }\n ).test;\n const root = testConfig?.root ?? config.root;\n // Setup files and global-setup files run in the Vitest host (not the\n // emulated runtime), so they may freely import node:* modules. Collect\n // them from the top-level config AND from each `test.projects[i]` —\n // per-project setup files run in the host too and would otherwise be\n // transformed as production code, breaking node:* imports inside them.\n const toAbsolutePaths = (value: string | string[] | undefined, baseRoot: string) =>\n (Array.isArray(value) ? value : value ? [value] : []).map((f) => resolve(baseRoot, f));\n const exemptHostFiles = new Set<string>([\n ...toAbsolutePaths(testConfig?.setupFiles, root),\n ...toAbsolutePaths(testConfig?.globalSetup, root),\n ]);\n // Vitest projects can each define their own `test.include` (and root).\n // A project that uses non-default patterns (e.g. `tests/**/*.spec.ts`)\n // must also be considered when classifying test files — otherwise its\n // tests would be treated as production code and have node:* imports\n // rewritten. Build a list of (root, patterns) pairs covering top-level\n // + every project, and accept a file if any pair matches.\n const includePairs: { root: string; patterns: string[] }[] = [\n { root, patterns: testConfig?.include ?? DEFAULT_TEST_INCLUDE },\n ];\n for (const project of testConfig?.projects ?? []) {\n const projectTest = project?.test;\n if (!projectTest) continue;\n const projectRoot = projectTest.root ?? root;\n for (const f of toAbsolutePaths(projectTest.setupFiles, projectRoot)) {\n exemptHostFiles.add(f);\n }\n for (const f of toAbsolutePaths(projectTest.globalSetup, projectRoot)) {\n exemptHostFiles.add(f);\n }\n includePairs.push({\n root: projectRoot,\n patterns: projectTest.include ?? DEFAULT_TEST_INCLUDE,\n });\n }\n isTestFile = (id: string) => {\n if (exemptHostFiles.has(id)) return true;\n return includePairs.some(({ root: r, patterns }) => {\n const candidate = isAbsolute(id) ? relative(r, id) : id;\n return patterns.some((pattern) => matchesGlob(candidate, pattern));\n });\n };\n // Only transform files inside the project root. With pnpm workspaces,\n // dependencies are symlinked and Vite resolves them to absolute paths\n // outside `node_modules`, so the substring check alone is insufficient.\n // Non-absolute ids are Vite-internal: virtual modules (`\\0...`,\n // `virtual:...`), bare specifiers, etc. Those are never user source\n // files and must not be parsed/transformed.\n isUserSourceFile = (id: string) => {\n if (!isAbsolute(id)) return false;\n const rel = relative(root, id);\n return rel !== \"\" && !rel.startsWith(\"..\") && !isAbsolute(rel);\n };\n },\n\n transform(code, id) {\n // Vite can pass ids with query/hash suffixes (e.g. `file.ts?import`,\n // `file.ts?v=hash`). Strip them so exact-path lookups (Set membership,\n // glob matching, absolute-path checks) match what callers configured.\n const queryIdx = id.search(/[?#]/);\n const cleanId = queryIdx === -1 ? id : id.slice(0, queryIdx);\n\n if (isTestFile(cleanId)) return undefined;\n if (cleanId.includes(\"node_modules\")) return undefined;\n if (!isUserSourceFile(cleanId)) return undefined;\n\n let ast: { body: ImportLikeNode[] };\n try {\n ast = this.parse(code) as unknown as { body: ImportLikeNode[] };\n } catch {\n // Not parseable as ESM (e.g. JSON, asset). Let other plugins handle it.\n return undefined;\n }\n\n const replacements: { start: number; end: number; replacement: string }[] = [];\n for (const node of ast.body) {\n if (!IMPORT_LIKE_TYPES.has(node.type)) continue;\n const specifier = node.source?.value;\n if (typeof specifier !== \"string\") continue;\n if (isBlockedModule(specifier)) {\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: buildBlockedReplacement(node, getBlockedMessage(specifier)),\n });\n }\n }\n\n if (replacements.length === 0) return undefined;\n\n let transformed = code;\n for (const r of replacements.sort((a, b) => b.start - a.start)) {\n transformed = transformed.slice(0, r.start) + r.replacement + transformed.slice(r.end);\n }\n\n return { code: transformed, map: null };\n },\n };\n}\n\nconst ENVIRONMENT_NAME = \"tailor-runtime\";\n\n/**\n * Vite plugin that resolves the tailor-runtime environment and injects setup files.\n *\n * Vitest resolves environments starting with \".\" or \"/\" as file paths.\n * This plugin rewrites `environment: \"tailor-runtime\"` to the absolute path\n * of the bundled environment module, both at the top-level and per-project.\n * It also injects the setup file that removes Vitest-dependent globals\n * (like `performance`) per-test via beforeEach/afterEach hooks.\n * @param options - Optional configuration\n * @param options.config - Path to tailor.config.ts to load SecretManager values into mock\n * @returns Vite plugin\n */\nexport function createEnvironmentPlugin(options?: { config?: string }): Plugin {\n const currentDir = dirname(fileURLToPath(import.meta.url));\n const environmentPath = resolve(currentDir, \"environment.mjs\");\n const setupPath = resolve(currentDir, \"setup.mjs\");\n\n return {\n name: \"tailor-runtime-environment\",\n\n config(config) {\n const testConfig = config.test as\n | (Record<string, unknown> & {\n projects?: Record<string, unknown>[];\n setupFiles?: string | string[];\n })\n | undefined;\n\n // Rewrite environment name to absolute path at top-level\n let usesTailorRuntime = false;\n if (testConfig?.environment === ENVIRONMENT_NAME) {\n testConfig.environment = environmentPath;\n usesTailorRuntime = true;\n }\n\n // Rewrite in each project config\n if (testConfig?.projects) {\n for (const project of testConfig.projects) {\n const projectTest = project.test as Record<string, unknown> | undefined;\n if (projectTest?.environment === ENVIRONMENT_NAME) {\n projectTest.environment = environmentPath;\n usesTailorRuntime = true;\n }\n }\n }\n\n // Pass config path to setup.ts via env var (cross-process compatible).\n // Always clear first, then set only when tailor-runtime is actually\n // selected. This makes the env var deterministic across Vite config\n // reloads (watch mode, programmatic re-init): a stale value from a\n // prior iteration cannot make setup.ts load secrets from an old config.\n // The leading `__` marks this as plugin-private, so deleting any\n // pre-existing value is safe.\n delete process.env.__TAILOR_RUNTIME_CONFIG;\n if (options?.config && usesTailorRuntime) {\n // Resolve against the user-provided Vite root when present (falling\n // back to cwd). Vitest projects with a non-cwd `root` would otherwise\n // resolve a relative options.config against the wrong directory.\n const configRoot = (config.root as string | undefined) ?? process.cwd();\n const configAbsPath = resolve(configRoot, options.config);\n process.env.__TAILOR_RUNTIME_CONFIG = configAbsPath;\n }\n\n // Normalize a user-provided string `setupFiles` into an array so Vite's\n // array-concat merge sees both sides as arrays (the string form would\n // otherwise be replaced rather than concatenated by some merge paths).\n // Vite then concatenates the user's array with our [setupPath].\n if (testConfig && typeof testConfig.setupFiles === \"string\") {\n testConfig.setupFiles = [testConfig.setupFiles];\n }\n\n return {\n test: {\n setupFiles: [setupPath],\n },\n };\n },\n };\n}\n","/**\n * Kysely-layer mock for unit testing.\n *\n * Builds a real Kysely instance backed by a mock driver: queries compile and\n * type-check normally, but execution returns staged rows and records every\n * query for assertions.\n */\n\nimport {\n ColumnNode,\n type CompiledQuery,\n type DatabaseConnection,\n type Dialect,\n type Driver,\n InsertQueryNode,\n Kysely,\n type OperationNode,\n type OperationNodeKind,\n PostgresAdapter,\n PostgresIntrospector,\n PostgresQueryCompiler,\n PrimitiveValueListNode,\n type QueryResult,\n ReferenceNode,\n type Transaction,\n UpdateQueryNode,\n ValueListNode,\n ValueNode,\n ValuesNode,\n} from \"kysely\";\n\nfunction unwrapValue(node: OperationNode): unknown {\n return ValueNode.is(node) ? node.value : node;\n}\n\nfunction insertRows(node: OperationNode): Record<string, unknown>[] {\n if (!InsertQueryNode.is(node)) {\n throw new Error(`insertRows: expected InsertQueryNode, got ${node.kind}`);\n }\n const columns = node.columns;\n const valuesNode = node.values;\n if (columns === undefined || valuesNode === undefined || !ValuesNode.is(valuesNode)) {\n throw new Error(\"insertRows: unsupported insert shape; inspect query.node instead\");\n }\n return valuesNode.values.map((row) => {\n if (!PrimitiveValueListNode.is(row) && !ValueListNode.is(row)) {\n throw new Error(\"insertRows: unsupported insert shape; inspect query.node instead\");\n }\n const values = PrimitiveValueListNode.is(row) ? row.values : row.values.map(unwrapValue);\n const result: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n result[col.column.name] = values[i];\n });\n return result;\n });\n}\n\nfunction insertValues(node: OperationNode): Record<string, unknown> {\n const rows = insertRows(node);\n if (rows.length !== 1) {\n throw new Error(\n `insertValues: query inserts ${rows.length} rows; use insertRows() for multi-row inserts`,\n );\n }\n return rows[0];\n}\n\nfunction updateValues(node: OperationNode): Record<string, unknown> {\n if (!UpdateQueryNode.is(node)) {\n throw new Error(`updateValues: expected UpdateQueryNode, got ${node.kind}`);\n }\n if (node.updates === undefined) {\n throw new Error(\"updateValues: unsupported update shape; inspect query.node instead\");\n }\n const result: Record<string, unknown> = {};\n for (const update of node.updates) {\n const col = update.column;\n const name = ColumnNode.is(col)\n ? col.column.name\n : ReferenceNode.is(col) && ColumnNode.is(col.column)\n ? col.column.column.name\n : undefined;\n if (name === undefined) {\n throw new Error(\"updateValues: unsupported update shape; inspect query.node instead\");\n }\n result[name] = unwrapValue(update.value);\n }\n return result;\n}\n\n/** A single statement executed against the mock, captured in order. */\nexport interface ExecutedQuery {\n /** The Kysely operation node kind, e.g. `\"SelectQueryNode\"`. */\n kind: OperationNodeKind;\n /** The compiled SQL string. */\n sql: string;\n /** The bound parameter values, in positional order. */\n parameters: readonly unknown[];\n /** The compiled Kysely operation node. */\n node: OperationNode;\n /** One `{ column: value }` map per row written by an insert. */\n insertRows: () => Record<string, unknown>[];\n /** The `{ column: value }` map written by a single-row insert. */\n insertValues: () => Record<string, unknown>;\n /** The `{ column: value }` map written by an update's SET clause. */\n updateValues: () => Record<string, unknown>;\n}\n\nfunction toExecutedQuery(compiledQuery: CompiledQuery): ExecutedQuery {\n const node = compiledQuery.query;\n return {\n kind: node.kind,\n sql: compiledQuery.sql,\n parameters: compiledQuery.parameters,\n node,\n insertRows: () => insertRows(node),\n insertValues: () => insertValues(node),\n updateValues: () => updateValues(node),\n };\n}\n\ntype MockRow = Record<string, unknown>;\ntype MockResult = MockRow[] | { rows?: MockRow[]; numAffectedRows?: number | bigint };\ntype QueryResolver = (query: ExecutedQuery) => MockResult | undefined;\n\ninterface StagedResult {\n rows: MockRow[];\n numAffectedRows: bigint | undefined;\n}\n\nfunction toStagedResult(result: MockResult): StagedResult {\n if (Array.isArray(result)) return { rows: result, numAffectedRows: undefined };\n return {\n rows: result.rows ?? [],\n numAffectedRows:\n result.numAffectedRows === undefined ? undefined : BigInt(result.numAffectedRows),\n };\n}\n\n/** Controls and assertions for a {@link createKyselyMock} instance. */\nexport interface KyselyMock<DB> {\n /** The mock Kysely instance to run queries against. */\n db: Kysely<DB>;\n /** Every recorded query, in execution order. */\n executedQueries: ExecutedQuery[];\n /** Recorded SELECT queries. */\n selects: ExecutedQuery[];\n /** Recorded INSERT queries. */\n inserts: ExecutedQuery[];\n /** Recorded UPDATE queries. */\n updates: ExecutedQuery[];\n /** Recorded DELETE queries. */\n deletes: ExecutedQuery[];\n /** Stage the rows the next query returns. */\n enqueueResult: (result: MockResult) => void;\n /** Stage the rows for several upcoming queries, consumed in order. */\n enqueueResults: (...results: MockResult[]) => void;\n /** Set a resolver that returns rows by inspecting each query. */\n setQueryResolver: (resolver: QueryResolver) => void;\n /** Run `fn` inside a real transaction and return its result. */\n withTx: <R>(fn: (trx: Transaction<DB>) => Promise<R>) => Promise<R>;\n /** Clear recorded queries and staged results. */\n reset: () => void;\n /** Same as {@link KyselyMock.reset}; enables `using` disposal. */\n [Symbol.dispose]: () => void;\n}\n\nclass MockState {\n readonly executed: ExecutedQuery[] = [];\n private readonly queue: MockResult[] = [];\n private resolver: QueryResolver | undefined;\n\n enqueue(...results: MockResult[]): void {\n this.queue.push(...results);\n }\n\n setResolver(resolver: QueryResolver): void {\n this.resolver = resolver;\n }\n\n next(query: ExecutedQuery): StagedResult {\n const resolved = this.resolver?.(query);\n if (resolved !== undefined) return toStagedResult(resolved);\n const queued = this.queue.shift();\n return queued === undefined ? { rows: [], numAffectedRows: undefined } : toStagedResult(queued);\n }\n\n reset(): void {\n this.executed.length = 0;\n this.queue.length = 0;\n this.resolver = undefined;\n }\n}\n\nclass MockConnection implements DatabaseConnection {\n constructor(private readonly state: MockState) {}\n\n async executeQuery<R>(compiledQuery: CompiledQuery): Promise<QueryResult<R>> {\n const query = toExecutedQuery(compiledQuery);\n this.state.executed.push(query);\n const { rows, numAffectedRows } = this.state.next(query);\n return {\n rows: rows as R[],\n numAffectedRows: numAffectedRows ?? BigInt(rows.length),\n };\n }\n\n streamQuery<R>(): AsyncIterableIterator<QueryResult<R>> {\n throw new Error(\"createKyselyMock: streaming is not supported\");\n }\n}\n\nclass MockDriver implements Driver {\n constructor(private readonly state: MockState) {}\n\n async init(): Promise<void> {}\n\n async acquireConnection(): Promise<DatabaseConnection> {\n return new MockConnection(this.state);\n }\n\n // No-ops so begin/commit/rollback never enter `executed` and pollute counts.\n async beginTransaction(): Promise<void> {}\n async commitTransaction(): Promise<void> {}\n async rollbackTransaction(): Promise<void> {}\n\n async releaseConnection(): Promise<void> {}\n async destroy(): Promise<void> {}\n}\n\nfunction byKind(state: MockState, kind: OperationNodeKind): ExecutedQuery[] {\n return state.executed.filter((query) => query.kind === kind);\n}\n\n/**\n * Create a mock Kysely instance for unit-testing code that runs Kysely queries.\n * Pass the namespace schema as the type argument, e.g.\n * `createKyselyMock<Namespace[\"main-db\"]>()`.\n * @returns A {@link KyselyMock} with the mock `db`, recorded queries, and result staging.\n */\nexport function createKyselyMock<DB = Record<string, never>>(): KyselyMock<DB> {\n const state = new MockState();\n const dialect: Dialect = {\n createDriver: () => new MockDriver(state),\n createQueryCompiler: () => new PostgresQueryCompiler(),\n createAdapter: () => new PostgresAdapter(),\n createIntrospector: (db) => new PostgresIntrospector(db),\n };\n const kysely = new Kysely<DB>({ dialect });\n\n return {\n db: kysely,\n get executedQueries() {\n return state.executed;\n },\n get selects() {\n return byKind(state, \"SelectQueryNode\");\n },\n get inserts() {\n return byKind(state, \"InsertQueryNode\");\n },\n get updates() {\n return byKind(state, \"UpdateQueryNode\");\n },\n get deletes() {\n return byKind(state, \"DeleteQueryNode\");\n },\n enqueueResult: (result) => state.enqueue(result),\n enqueueResults: (...results) => state.enqueue(...results),\n setQueryResolver: (resolver) => state.setResolver(resolver),\n withTx: (fn) => kysely.transaction().execute(fn),\n reset: () => state.reset(),\n [Symbol.dispose]: () => state.reset(),\n };\n}\n","import { createBlockPlugin, createEnvironmentPlugin } from \"./plugin\";\nimport type { Plugin } from \"vitest/config\";\n\n/**\n * Creates Vitest plugins that emulate the Tailor Platform function runtime environment.\n *\n * **Beta:** This API may change in future releases.\n *\n * ## What it does\n *\n * 1. **Node.js module blocking** (transform hook) — Imports of `node:*` modules\n * (and bare builtins like `crypto`, `fs`) in non-test source files are replaced\n * with code that throws an error with a suggestion for the Web Standard API alternative.\n * Test files are exempt and can use `node:*` freely. Test file patterns are read\n * from the resolved Vitest config (`test.include`).\n *\n * 2. **Node.js globals removal** (environment + setup) — Only globals available in the\n * Tailor Platform runtime are kept (whitelist: ECMAScript standard, Web Standard APIs\n * from bootstrap.js, platform mocks). All others (`Buffer`, `global`, `setImmediate`,\n * `__dirname`, `__filename`, etc.) are removed. `performance` is removed per-test\n * via beforeEach/afterEach since Vitest needs it during initialization.\n *\n * 3. **Platform API mocks** (environment) — All platform APIs are auto-injected with\n * control objects: `tailordbMock`, `workflowMock`, `secretmanagerMock`,\n * `authconnectionMock`, `idpMock`, `fileMock`, `iconvMock`. Each\n * provides response configuration, call recording, and reset.\n *\n * 4. **Environment resolution** — Rewrites `environment: \"tailor-runtime\"` to the\n * absolute path of the bundled environment module via the config hook.\n *\n * ## Known limitations\n *\n * - **`process`** and **`require`** are NOT removed or blocked. Vitest's internal\n * runner depends on them. On the real Tailor Platform runtime, they do not exist.\n * - **Dynamic `import()`** of bundled files (via `createImportMain()`) bypasses\n * the transform hook since those files are loaded through Node.js native loader.\n * ## Options\n *\n * - **`config`** — Path to `tailor.config.ts`. Loads `defineSecretManager()` values\n * into `secretmanagerMock` so `getSecret()` returns the configured values.\n * @example\n * ```typescript\n * // vitest.config.ts\n * import { defineConfig } from \"vitest/config\";\n * import { tailorRuntime } from \"@tailor-platform/sdk/vitest\";\n *\n * export default defineConfig({\n * plugins: [tailorRuntime({ config: \"./tailor.config.ts\" })],\n * test: {\n * environment: \"tailor-runtime\",\n * },\n * });\n * ```\n * @param options - Optional configuration\n * @param options.config - Path to tailor.config.ts to load SecretManager values into mock\n * @returns Array of Vite plugins\n */\nexport function tailorRuntime(options?: { config?: string }): Plugin[] {\n return [createBlockPlugin(), createEnvironmentPlugin(options)];\n}\n\nexport {\n tailordbMock,\n workflowMock,\n secretmanagerMock,\n authconnectionMock,\n idpMock,\n fileMock,\n iconvMock,\n} from \"./mock\";\n\nexport { createKyselyMock, type KyselyMock, type ExecutedQuery } from \"./mock-kysely\";\n"],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { C as FieldOutput$1, D as Validators, E as FieldValidateInput, F as InferFieldsOutput, N as TailorUser, R as Prettify, S as FieldOptions, T as TailorToTs, b as EnumValue, d as TailorDBType$1, f as DBFieldMetadata, g as TailorField, h as SerialConfig, j as InferredAttributeMap, l as TailorDBField$1, m as GqlOperationsConfig, n as RelationType, o as ValueOperand, p as DefinedDBFieldMetadata, r as TailorDBServiceInput, s as TailorAnyDBField$1, t as IndexDef, u as TailorDBInstance$1, v as ArrayFieldOutput, w as TailorFieldType, x as FieldMetadata, y as DefinedFieldMetadata, z as output } from "./tailordb-BlBGmQK-.mjs";
|
|
2
|
+
import { B as IdProvider, G as SCIMAttribute, H as OAuth2ClientInput, J as SCIMConfig, L as AuthInvoker, R as BuiltinIdP, V as OAuth2Client, X as TenantProvider, r as PluginConfigs } from "./plugin-BuE5ZOnW.mjs";
|
|
3
|
+
import { n as TailorEnv } from "./env-B-g-qgE4.mjs";
|
|
4
|
+
import { IsAny, JsonObject, NonEmptyObject } from "type-fest";
|
|
3
5
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
4
6
|
|
|
5
7
|
//#region src/configure/types/field.d.ts
|
|
@@ -288,7 +290,7 @@ interface TailorDBField<Defined extends DefinedDBFieldMetadata = DefinedDBFieldM
|
|
|
288
290
|
array: NewOpt extends {
|
|
289
291
|
array: true;
|
|
290
292
|
} ? true : Defined["array"];
|
|
291
|
-
}>, FieldOutput<TailorToTs[Defined["type"]], NewOpt>>;
|
|
293
|
+
}>, FieldOutput$1<TailorToTs[Defined["type"]], NewOpt>>;
|
|
292
294
|
}
|
|
293
295
|
/**
|
|
294
296
|
* Full TailorDBType interface with builder methods.
|
|
@@ -309,7 +311,7 @@ interface TailorDBType<Fields extends Record<string, TailorAnyDBField> = any, Us
|
|
|
309
311
|
array: Opt extends {
|
|
310
312
|
array: true;
|
|
311
313
|
} ? true : D["array"];
|
|
312
|
-
}, FieldOutput<TailorToTs[D["type"]], Opt>> : never };
|
|
314
|
+
}, FieldOutput$1<TailorToTs[D["type"]], Opt>> : never };
|
|
313
315
|
omitFields<K extends keyof Fields>(keys: K[]): Omit<Fields, K>;
|
|
314
316
|
plugin<P extends keyof PluginConfigs<keyof Fields & string>>(config: { [K in P]: PluginConfigs<keyof Fields & string>[K] }): TailorDBType<Fields, User>;
|
|
315
317
|
}
|
|
@@ -478,7 +480,7 @@ declare function _enum<const V extends AllowedValues, const Opt extends FieldOpt
|
|
|
478
480
|
array: Opt extends {
|
|
479
481
|
array: true;
|
|
480
482
|
} ? true : false;
|
|
481
|
-
}, FieldOutput<AllowedValuesOutput<V>, Opt>>;
|
|
483
|
+
}, FieldOutput$1<AllowedValuesOutput<V>, Opt>>;
|
|
482
484
|
/**
|
|
483
485
|
* Create a nested object field with sub-fields.
|
|
484
486
|
* @param fields - Record of nested field definitions
|
|
@@ -492,7 +494,7 @@ declare function object<const F extends Record<string, TailorAnyDBField> & Exclu
|
|
|
492
494
|
array: Opt extends {
|
|
493
495
|
array: true;
|
|
494
496
|
} ? true : false;
|
|
495
|
-
}, FieldOutput<InferFieldsOutput<F>, Opt>>;
|
|
497
|
+
}, FieldOutput$1<InferFieldsOutput<F>, Opt>>;
|
|
496
498
|
declare const idField: TailorDBField<{
|
|
497
499
|
type: "uuid";
|
|
498
500
|
array: false;
|
|
@@ -586,6 +588,157 @@ declare const db: {
|
|
|
586
588
|
};
|
|
587
589
|
};
|
|
588
590
|
//#endregion
|
|
591
|
+
//#region src/types/auth-connection.generated.d.ts
|
|
592
|
+
type AuthConnectionOAuth2Config = {
|
|
593
|
+
/** OAuth2 provider URL */providerUrl: string; /** OAuth2 issuer URL */
|
|
594
|
+
issuerUrl: string; /** OAuth2 client ID */
|
|
595
|
+
clientId: string; /** OAuth2 client secret */
|
|
596
|
+
clientSecret: string; /** OAuth2 authorization endpoint override */
|
|
597
|
+
authUrl?: string | undefined; /** OAuth2 token endpoint override */
|
|
598
|
+
tokenUrl?: string | undefined;
|
|
599
|
+
};
|
|
600
|
+
type AuthConnectionConfig = {
|
|
601
|
+
type: "oauth2";
|
|
602
|
+
providerUrl: string;
|
|
603
|
+
issuerUrl: string;
|
|
604
|
+
clientId: string;
|
|
605
|
+
clientSecret: string;
|
|
606
|
+
authUrl?: string | undefined;
|
|
607
|
+
tokenUrl?: string | undefined;
|
|
608
|
+
};
|
|
609
|
+
//#endregion
|
|
610
|
+
//#region src/types/auth.d.ts
|
|
611
|
+
type OAuth2ClientGrantType = OAuth2Client["grantTypes"][number];
|
|
612
|
+
type SCIMAttributeType = SCIMAttribute["type"];
|
|
613
|
+
type AuthInvokerWithName<M extends string> = Omit<AuthInvoker, "machineUserName"> & {
|
|
614
|
+
machineUserName: M;
|
|
615
|
+
};
|
|
616
|
+
/** Result of retrieving a connection token at runtime. */
|
|
617
|
+
type AuthConnectionTokenResult = {
|
|
618
|
+
access_token: string;
|
|
619
|
+
refresh_token?: string;
|
|
620
|
+
token_type?: string;
|
|
621
|
+
expiry?: string;
|
|
622
|
+
};
|
|
623
|
+
type AuthAttributeValue = ValueOperand | null | undefined;
|
|
624
|
+
type UserFieldKeys<User extends TailorDBInstance$1> = keyof output<User> & string;
|
|
625
|
+
type FieldDefined<User extends TailorDBInstance$1, Key extends UserFieldKeys<User>> = User["fields"][Key] extends {
|
|
626
|
+
_defined: infer Defined;
|
|
627
|
+
} ? Defined : never;
|
|
628
|
+
type FieldOutput<User extends TailorDBInstance$1, Key extends UserFieldKeys<User>> = output<User>[Key];
|
|
629
|
+
type FieldIsRequired<User extends TailorDBInstance$1, Key extends UserFieldKeys<User>> = undefined extends FieldOutput<User, Key> ? false : true;
|
|
630
|
+
type FieldIsOfType<User extends TailorDBInstance$1, Key extends UserFieldKeys<User>, Type extends string> = FieldDefined<User, Key> extends {
|
|
631
|
+
type: Type;
|
|
632
|
+
} ? true : false;
|
|
633
|
+
type FieldIsArray<User extends TailorDBInstance$1, Key extends UserFieldKeys<User>> = FieldDefined<User, Key> extends {
|
|
634
|
+
array: true;
|
|
635
|
+
} ? true : false;
|
|
636
|
+
type FieldIsUnique<User extends TailorDBInstance$1, Key extends UserFieldKeys<User>> = FieldDefined<User, Key> extends {
|
|
637
|
+
unique: true;
|
|
638
|
+
} ? true : false;
|
|
639
|
+
type FieldSupportsValueOperand<User extends TailorDBInstance$1, Key extends UserFieldKeys<User>> = FieldOutput<User, Key> extends ValueOperand | null | undefined ? true : false;
|
|
640
|
+
type UsernameFieldKey<User extends TailorDBInstance$1> = IsAny<User> extends true ? string : { [K in UserFieldKeys<User>]: FieldIsRequired<User, K> extends true ? FieldIsOfType<User, K, "string"> extends true ? FieldIsArray<User, K> extends true ? never : FieldIsUnique<User, K> extends true ? K : never : never : never }[UserFieldKeys<User>];
|
|
641
|
+
type UserAttributeKey<User extends TailorDBInstance$1> = { [K in UserFieldKeys<User>]: K extends "id" ? never : FieldSupportsValueOperand<User, K> extends true ? FieldIsOfType<User, K, "datetime" | "date" | "time"> extends true ? never : K : never }[UserFieldKeys<User>];
|
|
642
|
+
type UserAttributeListKey<User extends TailorDBInstance$1> = { [K in UserFieldKeys<User>]: K extends "id" ? never : FieldIsOfType<User, K, "uuid"> extends true ? FieldIsArray<User, K> extends true ? never : K : never }[UserFieldKeys<User>];
|
|
643
|
+
type UserAttributeMap<User extends TailorDBInstance$1> = { [K in UserAttributeKey<User>]?: true };
|
|
644
|
+
type DisallowExtraKeys<T, Allowed extends PropertyKey> = T & { [K in Exclude<keyof T, Allowed>]: never };
|
|
645
|
+
type AttributeListValue<User extends TailorDBInstance$1, Key extends UserAttributeListKey<User>> = Key extends keyof output<User> ? output<User>[Key] : never;
|
|
646
|
+
type AttributeListToTuple<User extends TailorDBInstance$1, AttributeList extends readonly UserAttributeListKey<User>[]> = { [Index in keyof AttributeList]: AttributeList[Index] extends UserAttributeListKey<User> ? AttributeListValue<User, AttributeList[Index]> : never };
|
|
647
|
+
type AttributeMapSelectedKeys<User extends TailorDBInstance$1, AttributeMap extends UserAttributeMap<User>> = Extract<{ [K in keyof AttributeMap]-?: undefined extends AttributeMap[K] ? never : K }[keyof AttributeMap], UserAttributeKey<User>>;
|
|
648
|
+
type UserProfile<User extends TailorDBInstance$1, AttributeMap extends UserAttributeMap<User>, AttributeList extends UserAttributeListKey<User>[]> = {
|
|
649
|
+
/**
|
|
650
|
+
* TailorDB namespace where the user type is defined.
|
|
651
|
+
*
|
|
652
|
+
* Usually auto-resolved, so you don't need to specify this.
|
|
653
|
+
* Required only when multiple TailorDBs exist and the type is in an external TailorDB.
|
|
654
|
+
*/
|
|
655
|
+
namespace?: string;
|
|
656
|
+
type: User;
|
|
657
|
+
usernameField: UsernameFieldKey<User>;
|
|
658
|
+
attributes?: DisallowExtraKeys<AttributeMap, UserAttributeKey<User>>;
|
|
659
|
+
attributeList?: AttributeList;
|
|
660
|
+
};
|
|
661
|
+
type MachineUserAttributeFields = Record<string, TailorField<DefinedFieldMetadata, unknown, FieldMetadata, TailorFieldType>>;
|
|
662
|
+
type TailorFieldOutputValue<Field> = Field extends TailorField<DefinedFieldMetadata, infer Output, FieldMetadata, TailorFieldType> ? Output : never;
|
|
663
|
+
type MachineUserAttributeValues<Fields extends MachineUserAttributeFields> = { [K in keyof Fields]: TailorFieldOutputValue<Fields[K]> extends ValueOperand | null | undefined ? TailorFieldOutputValue<Fields[K]> : never };
|
|
664
|
+
type MachineUserFromAttributes<Fields extends MachineUserAttributeFields> = (keyof Fields extends never ? {
|
|
665
|
+
attributes?: never;
|
|
666
|
+
} : {
|
|
667
|
+
attributes: DisallowExtraKeys<MachineUserAttributeValues<Fields>, keyof Fields>;
|
|
668
|
+
}) & {
|
|
669
|
+
attributeList?: string[];
|
|
670
|
+
};
|
|
671
|
+
type MachineUser<User extends TailorDBInstance$1, AttributeMap extends UserAttributeMap<User> = UserAttributeMap<User>, AttributeList extends UserAttributeListKey<User>[] = [], MachineUserAttributes extends MachineUserAttributeFields | undefined = undefined> = IsAny<MachineUserAttributes> extends true ? IsAny<User> extends true ? {
|
|
672
|
+
attributes: Record<string, AuthAttributeValue>;
|
|
673
|
+
attributeList?: string[];
|
|
674
|
+
} : (AttributeMapSelectedKeys<User, AttributeMap> extends never ? {
|
|
675
|
+
attributes?: never;
|
|
676
|
+
} : {
|
|
677
|
+
attributes: { [K in AttributeMapSelectedKeys<User, AttributeMap>]: K extends keyof output<User> ? output<User>[K] : never } & { [K in Exclude<keyof output<User>, AttributeMapSelectedKeys<User, AttributeMap>>]?: never };
|
|
678
|
+
}) & ([] extends AttributeList ? {
|
|
679
|
+
attributeList?: never;
|
|
680
|
+
} : {
|
|
681
|
+
attributeList: AttributeListToTuple<User, AttributeList>;
|
|
682
|
+
}) : [MachineUserAttributes] extends [MachineUserAttributeFields] ? MachineUserFromAttributes<MachineUserAttributes> : IsAny<User> extends true ? {
|
|
683
|
+
attributes: Record<string, AuthAttributeValue>;
|
|
684
|
+
attributeList?: string[];
|
|
685
|
+
} : (AttributeMapSelectedKeys<User, AttributeMap> extends never ? {
|
|
686
|
+
attributes?: never;
|
|
687
|
+
} : {
|
|
688
|
+
attributes: { [K in AttributeMapSelectedKeys<User, AttributeMap>]: K extends keyof output<User> ? output<User>[K] : never } & { [K in Exclude<keyof output<User>, AttributeMapSelectedKeys<User, AttributeMap>>]?: never };
|
|
689
|
+
}) & ([] extends AttributeList ? {
|
|
690
|
+
attributeList?: never;
|
|
691
|
+
} : {
|
|
692
|
+
attributeList: AttributeListToTuple<User, AttributeList>;
|
|
693
|
+
});
|
|
694
|
+
type BeforeLoginHookArgs = {
|
|
695
|
+
claims: JsonObject;
|
|
696
|
+
idpConfigName: string; /** Environment variables defined in `defineConfig({ env })`. */
|
|
697
|
+
env: TailorEnv;
|
|
698
|
+
};
|
|
699
|
+
type BeforeLoginHook<MachineUserNames extends string> = {
|
|
700
|
+
handler(args: BeforeLoginHookArgs): Promise<void>;
|
|
701
|
+
invoker: NoInfer<MachineUserNames>;
|
|
702
|
+
};
|
|
703
|
+
type AuthHooks<MachineUserNames extends string> = {
|
|
704
|
+
beforeLogin?: BeforeLoginHook<MachineUserNames>;
|
|
705
|
+
};
|
|
706
|
+
type AuthServiceInput<User extends TailorDBInstance$1, AttributeMap extends UserAttributeMap<User>, AttributeList extends UserAttributeListKey<User>[], MachineUserNames extends string, MachineUserAttributes extends MachineUserAttributeFields | undefined = MachineUserAttributeFields | undefined, ConnectionNames extends string = string> = {
|
|
707
|
+
hooks?: AuthHooks<MachineUserNames>;
|
|
708
|
+
userProfile?: UserProfile<User, AttributeMap, AttributeList>;
|
|
709
|
+
machineUserAttributes?: MachineUserAttributes;
|
|
710
|
+
machineUsers?: Record<MachineUserNames, MachineUser<User, AttributeMap, AttributeList, MachineUserAttributes>>;
|
|
711
|
+
oauth2Clients?: Record<string, OAuth2ClientInput>;
|
|
712
|
+
idProvider?: IdProvider;
|
|
713
|
+
scim?: SCIMConfig;
|
|
714
|
+
tenantProvider?: TenantProvider;
|
|
715
|
+
connections?: Record<ConnectionNames, AuthConnectionConfig>;
|
|
716
|
+
publishSessionEvents?: boolean;
|
|
717
|
+
};
|
|
718
|
+
declare const authDefinitionBrand: unique symbol;
|
|
719
|
+
type AuthDefinitionBrand = {
|
|
720
|
+
readonly [authDefinitionBrand]: true;
|
|
721
|
+
};
|
|
722
|
+
type ConnectionNames<Config> = Config extends {
|
|
723
|
+
connections?: Record<infer K, unknown>;
|
|
724
|
+
} ? K & string : string;
|
|
725
|
+
type DefinedAuth<Name extends string, Config, MachineUserNames extends string> = Config & {
|
|
726
|
+
name: Name;
|
|
727
|
+
/**
|
|
728
|
+
* @deprecated Pass the machine user name directly as a string instead, e.g. `authInvoker: "machine-user-name"`.
|
|
729
|
+
* Using this function pulls config-layer (Node-only) dependencies into runtime bundles.
|
|
730
|
+
*/
|
|
731
|
+
invoker<M extends MachineUserNames>(machineUser: M): AuthInvokerWithName<M>;
|
|
732
|
+
getConnectionToken<C extends ConnectionNames<Config>>(connectionName: C): Promise<AuthConnectionTokenResult>;
|
|
733
|
+
} & AuthDefinitionBrand;
|
|
734
|
+
type AuthExternalConfig = {
|
|
735
|
+
name: string;
|
|
736
|
+
external: true;
|
|
737
|
+
};
|
|
738
|
+
type AuthServiceInputLoose = AuthServiceInput<any, any, any, string, any>;
|
|
739
|
+
type AuthOwnConfig = DefinedAuth<string, AuthServiceInputLoose, string>;
|
|
740
|
+
type AuthConfig = AuthOwnConfig | AuthExternalConfig;
|
|
741
|
+
//#endregion
|
|
589
742
|
//#region src/types/idp.generated.d.ts
|
|
590
743
|
/**
|
|
591
744
|
* Configuration for GraphQL operations on IdP users.
|
|
@@ -1134,6 +1287,10 @@ type ExecutorServiceConfig = {
|
|
|
1134
1287
|
ignores?: string[];
|
|
1135
1288
|
};
|
|
1136
1289
|
type ExecutorServiceInput = ExecutorServiceConfig;
|
|
1290
|
+
type HttpAdapterServiceInput = {
|
|
1291
|
+
files: string[];
|
|
1292
|
+
ignores?: string[];
|
|
1293
|
+
};
|
|
1137
1294
|
type ResolverServiceConfig = {
|
|
1138
1295
|
files: string[];
|
|
1139
1296
|
ignores?: string[];
|
|
@@ -1195,6 +1352,8 @@ interface AppConfig<Auth extends AuthConfig = AuthConfig, Idp extends IdPConfig[
|
|
|
1195
1352
|
executor?: ExecutorServiceInput;
|
|
1196
1353
|
/** Workflow service configuration with workflow files. */
|
|
1197
1354
|
workflow?: WorkflowServiceInput;
|
|
1355
|
+
/** HTTP adapter service configuration with adapter files. */
|
|
1356
|
+
httpAdapter?: HttpAdapterServiceInput;
|
|
1198
1357
|
/** Static website configurations. Must be an array, e.g. `[website]`. */
|
|
1199
1358
|
staticWebsites?: StaticWebsites;
|
|
1200
1359
|
/** Secret Manager vault configurations. Keys are vault names, values are records of secret names to values. */
|
|
@@ -1206,6 +1365,22 @@ interface AppConfig<Auth extends AuthConfig = AuthConfig, Idp extends IdPConfig[
|
|
|
1206
1365
|
inlineSourcemap?: boolean;
|
|
1207
1366
|
}
|
|
1208
1367
|
//#endregion
|
|
1368
|
+
//#region src/types/http-adapter.generated.d.ts
|
|
1369
|
+
type HttpAdapterConfigInput = {
|
|
1370
|
+
/** Unique adapter name within the domain */name: string; /** Path pattern with segment wildcards (trailing or single-segment) */
|
|
1371
|
+
pathPattern: string; /** Per-method functions that transform HTTP requests to GraphQL requests */
|
|
1372
|
+
input: {
|
|
1373
|
+
get?: Function | undefined;
|
|
1374
|
+
post?: Function | undefined;
|
|
1375
|
+
put?: Function | undefined;
|
|
1376
|
+
patch?: Function | undefined;
|
|
1377
|
+
delete?: Function | undefined;
|
|
1378
|
+
}; /** Whether the adapter is active */
|
|
1379
|
+
enabled?: boolean | undefined; /** Matching priority; the lowest value wins when multiple adapters match */
|
|
1380
|
+
priority?: number | undefined; /** Function that transforms GraphQL response to HTTP response */
|
|
1381
|
+
output?: Function | undefined;
|
|
1382
|
+
};
|
|
1383
|
+
//#endregion
|
|
1209
1384
|
//#region src/types/workflow.generated.d.ts
|
|
1210
1385
|
type RetryPolicy = {
|
|
1211
1386
|
/** Maximum number of retries (1-10) */maxRetries: number; /** Initial backoff duration (e.g., '1s', '500ms', '1m', max 1h) */
|
|
@@ -1217,5 +1392,5 @@ type ConcurrencyPolicy = {
|
|
|
1217
1392
|
/** Maximum number of concurrent executions (1-1000) */maxConcurrentExecutions: number;
|
|
1218
1393
|
};
|
|
1219
1394
|
//#endregion
|
|
1220
|
-
export {
|
|
1221
|
-
//# sourceMappingURL=workflow.generated-
|
|
1395
|
+
export { BeforeLoginHookArgs as A, TailorAnyDBField as B, IdPGqlOperationsInput as C, AuthExternalConfig as D, AuthConnectionTokenResult as E, UserAttributeListKey as F, db as G, TailorDBField as H, UserAttributeMap as I, TailorTypePermission as J, PermissionCondition as K, UsernameFieldKey as L, OAuth2ClientGrantType as M, SCIMAttributeType as N, AuthOwnConfig as O, UserAttributeKey as P, AllowedValuesOutput as Q, AuthConnectionConfig as R, IdPGqlOperations as S, AuthConfig as T, TailorDBInstance as U, TailorAnyDBType as V, TailorDBType as W, unsafeAllowAllTypePermission as X, unsafeAllowAllGqlPermission as Y, AllowedValues as Z, IdPConfig as _, ExecutorServiceConfig as a, IdpDefinitionBrand as b, ResolverServiceConfig as c, WorkflowServiceInput as d, StaticWebsiteConfig as f, SecretsDefinitionBrand as g, SecretsConfig as h, AppConfig as i, DefinedAuth as j, AuthServiceInput as k, ResolverServiceInput as l, StaticWebsiteInput as m, RetryPolicy as n, ExecutorServiceInput as o, StaticWebsiteDefinitionBrand as p, TailorTypeGqlPermission as q, HttpAdapterConfigInput as r, ResolverExternalConfig as s, ConcurrencyPolicy as t, WorkflowServiceConfig as u, IdPExternalConfig as v, IdPInput as w, IdPEmailConfig as x, IdPUserField as y, AuthConnectionOAuth2Config as z };
|
|
1396
|
+
//# sourceMappingURL=workflow.generated-CQg1_Ami.d.mts.map
|