@tailor-platform/sdk 2.2.0 → 2.4.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 +183 -0
- package/README.md +1 -1
- package/dist/{application-BpLeawBg.mjs → application-C8a0UJ-z.mjs} +312 -166
- package/dist/application-C8a0UJ-z.mjs.map +1 -0
- package/dist/application-D4zOiLLa.mjs +3 -0
- package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +47 -24
- package/dist/cli/commands/tailordb/migrate/generate.d.mts +6 -0
- package/dist/cli/commands/tailordb/migrate/rename-detection.d.mts +22 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +1 -1
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +30 -11
- package/dist/cli/commands/tailordb/truncate.d.mts +2 -2
- package/dist/cli/lib.mjs +2 -2
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +366 -137
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/ts-hook.mjs +55 -8
- package/dist/completion/zsh-worker.zsh +38 -10
- package/dist/configure/config/index.d.mts +1 -1
- package/dist/configure/index.d.mts +3 -2
- package/dist/configure/index.mjs +92 -25
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/aigateway/index.d.mts +5 -4
- package/dist/configure/services/aigateway/types.d.mts +6 -1
- package/dist/configure/services/auth/types.d.mts +2 -2
- package/dist/configure/services/index.d.mts +2 -2
- package/dist/configure/services/tailordb/permission.d.mts +1 -1
- package/dist/configure/services/tailordb/schema.d.mts +1 -1
- package/dist/configure/services/tailordb/types.d.mts +7 -4
- package/dist/configure/services/workflow/index.d.mts +2 -2
- package/dist/configure/services/workflow/wait-point.d.mts +72 -13
- package/dist/configure/types/auth-namespace-name.d.mts +18 -0
- package/dist/{crashreport-CINZ5dVN.mjs → crashreport-Cd4TqfZq.mjs} +1 -1
- package/dist/{crashreport-CIIfLnoO.mjs → crashreport-Q0pDAlrj.mjs} +8 -4
- package/dist/{crashreport-CIIfLnoO.mjs.map → crashreport-Q0pDAlrj.mjs.map} +1 -1
- package/dist/{errors-CWj21238.mjs → errors-Bxut5_Sy.mjs} +17 -3
- package/dist/{errors-CWj21238.mjs.map → errors-Bxut5_Sy.mjs.map} +1 -1
- package/dist/file-BUcmVIH2.mjs.map +1 -1
- package/dist/kysely/index.d.mts +2 -1
- package/dist/kysely/index.mjs +2 -1
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/{logger-DSdExfor.mjs → logger-D0bEznPv.mjs} +9 -5
- package/dist/{logger-DSdExfor.mjs.map → logger-D0bEznPv.mjs.map} +1 -1
- package/dist/package-json-8b0O9TlX.mjs.map +1 -1
- package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
- package/dist/plugin/builtin/enum-constants/index.mjs +5 -5
- package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -1
- package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
- package/dist/plugin/builtin/file-utils/index.mjs +14 -11
- package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
- package/dist/plugin/builtin/kysely-type/index.mjs +9 -9
- package/dist/plugin/builtin/kysely-type/index.mjs.map +1 -1
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/plugin/builtin/seed/seed-type-processor.d.mts +4 -4
- package/dist/plugin/get-generated-type.d.mts +4 -4
- package/dist/plugin/index.mjs +13 -13
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/plugin/types.d.mts +2 -2
- package/dist/plugin/with-context.d.mts +1 -1
- package/dist/{register-ts-hook-CTth1eqj.mjs → register-ts-hook-Vqjza10T.mjs} +2516 -857
- package/dist/register-ts-hook-Vqjza10T.mjs.map +1 -0
- package/dist/{repl-editor-BCozyiNq.mjs → repl-editor-F9LotMNx.mjs} +3 -2
- package/dist/{repl-editor-BCozyiNq.mjs.map → repl-editor-F9LotMNx.mjs.map} +1 -1
- package/dist/runtime/file.d.mts +14 -14
- package/dist/{schema--xYWRGfe.mjs → schema-D4TC4BC3.mjs} +4 -3
- package/dist/schema-D4TC4BC3.mjs.map +1 -0
- package/dist/seed/index.d.mts +4 -4
- package/dist/seed/index.mjs +3 -3
- package/dist/seed/index.mjs.map +1 -1
- package/dist/{seed-xqM9WIHP.mjs → seed-Cibjmtry.mjs} +46 -40
- package/dist/seed-Cibjmtry.mjs.map +1 -0
- package/dist/{service-goqlJJgA.mjs → service-2grcAOCJ.mjs} +61 -27
- package/dist/service-2grcAOCJ.mjs.map +1 -0
- package/dist/service-CaBPNDIZ.mjs +3 -0
- package/dist/{service-CCwl3Avt.mjs → service-LTfp03ZZ.mjs} +7 -5
- package/dist/{service-CCwl3Avt.mjs.map → service-LTfp03ZZ.mjs.map} +1 -1
- package/dist/types/aigateway.generated.d.mts +2 -2
- package/dist/types/auth.generated.d.mts +3 -3
- package/dist/types/executor.generated.d.mts +1 -1
- package/dist/types/tailordb.generated.d.mts +12 -12
- package/dist/utils/test/index.d.mts +4 -4
- package/dist/utils/test/index.mjs +4 -4
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/index.mjs +95 -7
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/mocks/workflow.d.mts +13 -1
- package/dist/wait-point-invoker-__oE88_P.mjs +148 -0
- package/dist/wait-point-invoker-__oE88_P.mjs.map +1 -0
- package/dist/wait-point-registry-TL99zotw.mjs +47 -0
- package/dist/wait-point-registry-TL99zotw.mjs.map +1 -0
- package/docs/cli/application.md +3 -1
- package/docs/cli/function.md +17 -13
- package/docs/cli/setup.md +14 -1
- package/docs/cli/tailordb.md +30 -27
- package/docs/cli/workspace.md +2 -2
- package/docs/cli-reference.md +23 -22
- package/docs/configuration.md +2 -2
- package/docs/github-actions.md +73 -28
- package/docs/migration/v2.md +58 -4
- package/docs/migration/v3.md +41 -0
- package/docs/quickstart.md +1 -1
- package/docs/services/aigateway.md +33 -9
- package/docs/services/executor.md +5 -1
- package/docs/services/tailordb-migration.md +146 -44
- package/docs/services/tailordb.md +7 -7
- package/docs/services/workflow.md +52 -2
- package/docs/testing.md +13 -1
- package/package.json +8 -8
- package/dist/application-BpLeawBg.mjs.map +0 -1
- package/dist/application-BxLLiLsr.mjs +0 -3
- package/dist/register-ts-hook-CTth1eqj.mjs.map +0 -1
- package/dist/schema--xYWRGfe.mjs.map +0 -1
- package/dist/seed-xqM9WIHP.mjs.map +0 -1
- package/dist/service-_XmjSEGr.mjs +0 -3
- package/dist/service-goqlJJgA.mjs.map +0 -1
- package/dist/test-env-key-D7UkZp99.mjs +0 -75
- package/dist/test-env-key-D7UkZp99.mjs.map +0 -1
|
@@ -153,23 +153,7 @@ function generateIdpTruncateScriptCode(idpNamespace) {
|
|
|
153
153
|
*/
|
|
154
154
|
function generateIdpUserSchemaFile(options) {
|
|
155
155
|
const { usernameField, userTypeName, includeUserProfileFK = true } = options;
|
|
156
|
-
|
|
157
|
-
import { t } from "@tailor-platform/sdk";
|
|
158
|
-
import { defineSchema } from "@tailor-platform/sdk/seed";
|
|
159
|
-
import { createStandardSchema } from "@tailor-platform/sdk/test";
|
|
160
|
-
|
|
161
|
-
const schemaType = t.object({
|
|
162
|
-
name: t.string(),
|
|
163
|
-
password: t.string(),
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Simple identity hook for _User (no TailorDB backing type)
|
|
167
|
-
export const hook = <T>(data: unknown) => data as T;
|
|
168
|
-
|
|
169
|
-
export const schema = defineSchema(
|
|
170
|
-
createStandardSchema(schemaType, hook),
|
|
171
|
-
{
|
|
172
|
-
${includeUserProfileFK ? multiline`
|
|
156
|
+
const schemaBody = includeUserProfileFK ? multiline`
|
|
173
157
|
primaryKey: "name",
|
|
174
158
|
indexes: [
|
|
175
159
|
{ name: "_user_name_unique_idx", columns: ["name"], unique: true },
|
|
@@ -188,7 +172,24 @@ function generateIdpUserSchemaFile(options) {
|
|
|
188
172
|
indexes: [
|
|
189
173
|
{ name: "_user_name_unique_idx", columns: ["name"], unique: true },
|
|
190
174
|
],
|
|
191
|
-
|
|
175
|
+
`;
|
|
176
|
+
return multiline`
|
|
177
|
+
import { t } from "@tailor-platform/sdk";
|
|
178
|
+
import { defineSchema } from "@tailor-platform/sdk/seed";
|
|
179
|
+
import { createStandardSchema } from "@tailor-platform/sdk/test";
|
|
180
|
+
|
|
181
|
+
const schemaType = t.object({
|
|
182
|
+
name: t.string(),
|
|
183
|
+
password: t.string(),
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Simple identity hook for _User (no TailorDB backing table)
|
|
187
|
+
export const hook = <T>(data: unknown) => data as T;
|
|
188
|
+
|
|
189
|
+
export const schema = defineSchema(
|
|
190
|
+
createStandardSchema(schemaType, hook),
|
|
191
|
+
{
|
|
192
|
+
${schemaBody}
|
|
192
193
|
}
|
|
193
194
|
);
|
|
194
195
|
|
|
@@ -198,15 +199,15 @@ function generateIdpUserSchemaFile(options) {
|
|
|
198
199
|
//#endregion
|
|
199
200
|
//#region src/plugin/builtin/seed/lines-db-processor.ts
|
|
200
201
|
/**
|
|
201
|
-
* Processes TailorDB
|
|
202
|
-
* @param type - Parsed TailorDB
|
|
202
|
+
* Processes TailorDB tables to generate lines-db metadata
|
|
203
|
+
* @param type - Parsed TailorDB table
|
|
203
204
|
* @param source - Source file info
|
|
204
205
|
* @returns Generated lines-db metadata
|
|
205
206
|
*/
|
|
206
207
|
function processLinesDb(type, source) {
|
|
207
208
|
if (isPluginGeneratedType(source)) return processLinesDbForPluginType(type, source);
|
|
208
|
-
if (!source.filePath) throw new Error(`Missing source info for
|
|
209
|
-
if (!source.exportName) throw new Error(`Missing export name for
|
|
209
|
+
if (!source.filePath) throw new Error(`Missing source info for table ${type.name}`);
|
|
210
|
+
if (!source.exportName) throw new Error(`Missing export name for table ${type.name}`);
|
|
210
211
|
const { optionalFields, omitFields, indexes, foreignKeys } = extractFieldMetadata(type);
|
|
211
212
|
return {
|
|
212
213
|
typeName: type.name,
|
|
@@ -220,8 +221,8 @@ function processLinesDb(type, source) {
|
|
|
220
221
|
}
|
|
221
222
|
/**
|
|
222
223
|
* Process lines-db metadata for plugin-generated types
|
|
223
|
-
* @param type - Parsed TailorDB
|
|
224
|
-
* @param source - Plugin-generated
|
|
224
|
+
* @param type - Parsed TailorDB table
|
|
225
|
+
* @param source - Plugin-generated table source info
|
|
225
226
|
* @returns Generated lines-db metadata with plugin source
|
|
226
227
|
*/
|
|
227
228
|
function processLinesDbForPluginType(type, source) {
|
|
@@ -238,8 +239,8 @@ function processLinesDbForPluginType(type, source) {
|
|
|
238
239
|
};
|
|
239
240
|
}
|
|
240
241
|
/**
|
|
241
|
-
* Extract field metadata from TailorDB
|
|
242
|
-
* @param type - Parsed TailorDB
|
|
242
|
+
* Extract field metadata from TailorDB table
|
|
243
|
+
* @param type - Parsed TailorDB table
|
|
243
244
|
* @returns Field metadata including optional fields, omit fields, indexes, and foreign keys
|
|
244
245
|
*/
|
|
245
246
|
function extractFieldMetadata(type) {
|
|
@@ -304,30 +305,32 @@ function generateSchemaOptions(foreignKeys, indexes) {
|
|
|
304
305
|
].join("\n") : "";
|
|
305
306
|
}
|
|
306
307
|
/**
|
|
307
|
-
* Generates the schema file content for lines-db (for user-defined
|
|
308
|
+
* Generates the schema file content for lines-db (for user-defined tables with import)
|
|
308
309
|
* @param metadata - lines-db metadata
|
|
309
|
-
* @param importPath - Import path for the TailorDB
|
|
310
|
+
* @param importPath - Import path for the TailorDB table
|
|
310
311
|
* @returns Schema file contents
|
|
311
312
|
*/
|
|
312
313
|
function generateLinesDbSchemaFile(metadata, importPath) {
|
|
313
314
|
const { exportName, optionalFields, omitFields, foreignKeys, indexes } = metadata;
|
|
315
|
+
const schemaTypeCode = multiline`
|
|
316
|
+
const schemaType = t.object({
|
|
317
|
+
...${exportName}.pickFields(${JSON.stringify(optionalFields)}, { optional: true }),
|
|
318
|
+
...${exportName}.omitFields(${JSON.stringify([...optionalFields, ...omitFields])}),
|
|
319
|
+
});
|
|
320
|
+
`;
|
|
321
|
+
const schemaOptionsCode = generateSchemaOptions(foreignKeys, indexes);
|
|
314
322
|
return multiline`
|
|
315
323
|
import { t } from "@tailor-platform/sdk";
|
|
316
324
|
import { defineSchema } from "@tailor-platform/sdk/seed";
|
|
317
325
|
import { createTailorDBHook, createStandardSchema } from "@tailor-platform/sdk/test";
|
|
318
326
|
import { ${exportName} } from "${importPath}";
|
|
319
327
|
|
|
320
|
-
${
|
|
321
|
-
const schemaType = t.object({
|
|
322
|
-
...${exportName}.pickFields(${JSON.stringify(optionalFields)}, { optional: true }),
|
|
323
|
-
...${exportName}.omitFields(${JSON.stringify([...optionalFields, ...omitFields])}),
|
|
324
|
-
});
|
|
325
|
-
`}
|
|
328
|
+
${schemaTypeCode}
|
|
326
329
|
|
|
327
330
|
export const hook = createTailorDBHook(${exportName});
|
|
328
331
|
|
|
329
332
|
export const schema = defineSchema(
|
|
330
|
-
createStandardSchema(schemaType, hook, ${exportName}),${
|
|
333
|
+
createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}
|
|
331
334
|
);
|
|
332
335
|
|
|
333
336
|
`;
|
|
@@ -421,7 +424,8 @@ function seedPlugin(options) {
|
|
|
421
424
|
const idpUser = ctx.auth ? processIdpUser(ctx.auth) ?? null : null;
|
|
422
425
|
const idpUserSyncFKs = resolveIdpUserSyncFKs(ctx.pluginConfig.disableIdpUserSync);
|
|
423
426
|
for (const ns of ctx.tailordb) for (const [typeName, type] of Object.entries(ns.types)) {
|
|
424
|
-
const
|
|
427
|
+
const source = assertDefined(ns.sourceInfo.get(typeName), `source info missing for type: ${typeName}`);
|
|
428
|
+
const linesDb = processLinesDb(type, source);
|
|
425
429
|
if (idpUserSyncFKs.emitUserToIdpFK && idpUser && typeName === idpUser.schema.userTypeName) linesDb.foreignKeys.push({
|
|
426
430
|
column: idpUser.schema.usernameField,
|
|
427
431
|
references: {
|
|
@@ -441,17 +445,19 @@ function seedPlugin(options) {
|
|
|
441
445
|
const relativePath = path.relative(path.dirname(schemaOutputPath), linesDb.pluginSource.originalFilePath);
|
|
442
446
|
originalImportPath = relativePath.replace(/\.ts$/, "").startsWith(".") ? relativePath.replace(/\.ts$/, "") : `./${relativePath.replace(/\.ts$/, "")}`;
|
|
443
447
|
}
|
|
444
|
-
const
|
|
448
|
+
const params = {
|
|
445
449
|
configImportPath: path.relative(path.dirname(schemaOutputPath), ctx.configPath),
|
|
446
450
|
originalImportPath
|
|
447
|
-
}
|
|
451
|
+
};
|
|
452
|
+
const schemaContent = generateLinesDbSchemaFileWithPluginAPI(linesDb, params);
|
|
448
453
|
files.push({
|
|
449
454
|
path: schemaOutputPath,
|
|
450
455
|
content: schemaContent
|
|
451
456
|
});
|
|
452
457
|
} else {
|
|
453
458
|
const relativePath = path.relative(path.dirname(schemaOutputPath), linesDb.importPath);
|
|
454
|
-
const
|
|
459
|
+
const typeImportPath = relativePath.replace(/\.ts$/, "").startsWith(".") ? relativePath.replace(/\.ts$/, "") : `./${relativePath.replace(/\.ts$/, "")}`;
|
|
460
|
+
const schemaContent = generateLinesDbSchemaFile(linesDb, typeImportPath);
|
|
455
461
|
files.push({
|
|
456
462
|
path: schemaOutputPath,
|
|
457
463
|
content: schemaContent
|
|
@@ -480,4 +486,4 @@ function seedPlugin(options) {
|
|
|
480
486
|
|
|
481
487
|
//#endregion
|
|
482
488
|
export { generateIdpTruncateScriptCode as a, generateIdpSeedScriptCode as i, seedPlugin as n, processIdpUser as o, processLinesDb as r, SeedGeneratorID as t };
|
|
483
|
-
//# sourceMappingURL=seed-
|
|
489
|
+
//# sourceMappingURL=seed-Cibjmtry.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-Cibjmtry.mjs","names":[],"sources":["../src/plugin/builtin/seed/idp-user-processor.ts","../src/plugin/builtin/seed/lines-db-processor.ts","../src/plugin/builtin/seed/index.ts"],"sourcesContent":["import ml from \"#/utils/multiline\";\nimport type { GeneratorAuthInput } from \"#/plugin/types\";\n\nexport interface IdpUserMetadata {\n name: \"_User\";\n dependencies: string[];\n dataFile: string;\n idpNamespace: string;\n schema: {\n usernameField: string;\n userTypeName: string;\n };\n}\n\n/**\n * Processes auth configuration to generate IdP user seed metadata\n * @param auth - Auth configuration from generator\n * @returns IdP user metadata or undefined if not applicable\n */\nexport function processIdpUser(auth: GeneratorAuthInput): IdpUserMetadata | undefined {\n // Only process if idProvider is BuiltInIdP and userProfile is defined\n if (auth.idProvider?.kind !== \"BuiltInIdP\" || !auth.userProfile) {\n return undefined;\n }\n\n const { typeName, usernameField } = auth.userProfile;\n\n return {\n name: \"_User\",\n dependencies: [typeName],\n dataFile: \"data/_User.jsonl\",\n idpNamespace: auth.idProvider.namespace,\n schema: {\n usernameField,\n userTypeName: typeName,\n },\n };\n}\n\n/**\n * Generates the server-side IDP seed script code for testExecScript execution.\n * Uses the global tailor.idp.Client - no bundling required.\n * @param idpNamespace - The IDP namespace name\n * @returns Script code string\n */\nexport function generateIdpSeedScriptCode(idpNamespace: string): string {\n return ml /* ts */ `\n export async function main(input) {\n const client = new tailor.idp.Client({ namespace: \"${idpNamespace}\" });\n const errors = [];\n let processed = 0;\n let created = 0;\n let updated = 0;\n let skipped = 0;\n const upsert = input.upsert === true;\n\n for (let i = 0; i < input.users.length; i++) {\n try {\n if (upsert) {\n let existing;\n let lookupError;\n try {\n existing = await client.userByName(input.users[i].name);\n } catch (error) {\n existing = undefined;\n lookupError = error instanceof Error ? error.message : String(error);\n }\n\n if (existing) {\n const { name, ...attributes } = input.users[i];\n if (Object.keys(attributes).length === 0) {\n skipped++;\n } else {\n await client.updateUser({ id: existing.id, ...attributes });\n updated++;\n }\n } else {\n try {\n await client.createUser(input.users[i]);\n created++;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n lookupError ? \\`create failed (\\${message}); lookup failed (\\${lookupError})\\` : message,\n );\n }\n }\n } else {\n await client.createUser(input.users[i]);\n created++;\n }\n processed++;\n console.log(\\`[_User] \\${i + 1}/\\${input.users.length}: \\${input.users[i].name}\\`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n errors.push(\\`Row \\${i} (\\${input.users[i].name}): \\${message}\\`);\n console.error(\\`[_User] Row \\${i} failed: \\${message}\\`);\n }\n }\n\n return {\n success: errors.length === 0,\n processed,\n created,\n updated,\n skipped,\n errors,\n };\n }\n `;\n}\n\n/**\n * Generates the server-side IDP truncation script code for testExecScript execution.\n * Lists all users with pagination and deletes each one.\n * @param idpNamespace - The IDP namespace name\n * @returns Script code string\n */\nexport function generateIdpTruncateScriptCode(idpNamespace: string): string {\n return ml /* ts */ `\n export async function main() {\n const client = new tailor.idp.Client({ namespace: \"${idpNamespace}\" });\n const errors = [];\n let deleted = 0;\n\n // List all users with pagination\n let after = undefined;\n const allUsers = [];\n do {\n const response = await client.users(after ? { after } : undefined);\n allUsers.push(...(response.users || []));\n after = response.nextPageToken;\n } while (after);\n\n console.log(\\`Found \\${allUsers.length} IDP users to delete\\`);\n\n for (const user of allUsers) {\n try {\n await client.deleteUser(user.id);\n deleted++;\n console.log(\\`[_User] Deleted \\${deleted}/\\${allUsers.length}: \\${user.name}\\`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n errors.push(\\`User \\${user.id} (\\${user.name}): \\${message}\\`);\n console.error(\\`[_User] Delete failed for \\${user.name}: \\${message}\\`);\n }\n }\n\n return {\n success: errors.length === 0,\n deleted,\n total: allUsers.length,\n errors,\n };\n }\n `;\n}\n\ntype GenerateIdpUserSchemaFileOptions = {\n usernameField: string;\n userTypeName: string;\n /**\n * When `true` (default), emit a foreign key from `_User.name` to the\n * userProfile type's username field so that seed validation rejects `_User`\n * rows without a matching userProfile row. Set to `false` to seed `_User`\n * rows that do not yet have a corresponding userProfile row.\n */\n includeUserProfileFK?: boolean;\n};\n\n/**\n * Generates the schema file content for IdP users. Emits the\n * `_User.name -> <userProfile>.<usernameField>` foreign key by default; pass\n * `includeUserProfileFK: false` to omit it (e.g. when seeding `_User` rows\n * that do not yet have a corresponding userProfile row).\n * @param options - Schema generation options\n * @param options.usernameField - Username field name\n * @param options.userTypeName - TailorDB user type name\n * @param options.includeUserProfileFK - Whether to emit the `_User -> userProfile` foreign key (default `true`)\n * @returns Schema file contents\n */\nexport function generateIdpUserSchemaFile(options: GenerateIdpUserSchemaFileOptions): string {\n const { usernameField, userTypeName, includeUserProfileFK = true } = options;\n const schemaBody = includeUserProfileFK\n ? ml`\n primaryKey: \"name\",\n indexes: [\n { name: \"_user_name_unique_idx\", columns: [\"name\"], unique: true },\n ],\n foreignKeys: [\n {\n column: \"name\",\n references: {\n table: \"${userTypeName}\",\n column: \"${usernameField}\",\n },\n },\n ],\n `\n : ml`\n primaryKey: \"name\",\n indexes: [\n { name: \"_user_name_unique_idx\", columns: [\"name\"], unique: true },\n ],\n `;\n\n return ml /* ts */ `\n import { t } from \"@tailor-platform/sdk\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createStandardSchema } from \"@tailor-platform/sdk/test\";\n\n const schemaType = t.object({\n name: t.string(),\n password: t.string(),\n });\n\n // Simple identity hook for _User (no TailorDB backing table)\n export const hook = <T>(data: unknown) => data as T;\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),\n {\n ${schemaBody}\n }\n );\n\n `;\n}\n","import { isPluginGeneratedType } from \"#/parser/service/tailordb/type-source\";\nimport ml from \"#/utils/multiline\";\nimport type {\n PluginGeneratedTypeSource,\n TailorDBType,\n TypeSourceInfoEntry,\n} from \"#/parser/service/tailordb/types\";\nimport type { LinesDbMetadata } from \"./types\";\nimport type { ForeignKeyDefinition, IndexDefinition } from \"@toiroakr/lines-db\";\n\n/**\n * Processes TailorDB tables to generate lines-db metadata\n * @param type - Parsed TailorDB table\n * @param source - Source file info\n * @returns Generated lines-db metadata\n */\nexport function processLinesDb(type: TailorDBType, source: TypeSourceInfoEntry): LinesDbMetadata {\n if (isPluginGeneratedType(source)) {\n // Plugin-generated table\n return processLinesDbForPluginType(type, source);\n }\n\n // User-defined table\n if (!source.filePath) {\n throw new Error(`Missing source info for table ${type.name}`);\n }\n if (!source.exportName) {\n throw new Error(`Missing export name for table ${type.name}`);\n }\n\n const { optionalFields, omitFields, indexes, foreignKeys } = extractFieldMetadata(type);\n\n return {\n typeName: type.name,\n exportName: source.exportName,\n importPath: source.filePath,\n optionalFields,\n omitFields,\n foreignKeys,\n indexes,\n };\n}\n\n/**\n * Process lines-db metadata for plugin-generated types\n * @param type - Parsed TailorDB table\n * @param source - Plugin-generated table source info\n * @returns Generated lines-db metadata with plugin source\n */\nfunction processLinesDbForPluginType(\n type: TailorDBType,\n source: PluginGeneratedTypeSource,\n): LinesDbMetadata {\n const { optionalFields, omitFields, indexes, foreignKeys } = extractFieldMetadata(type);\n\n return {\n typeName: type.name,\n exportName: source.exportName,\n importPath: \"\",\n optionalFields,\n omitFields,\n foreignKeys,\n indexes,\n pluginSource: source,\n };\n}\n\n/**\n * Extract field metadata from TailorDB table\n * @param type - Parsed TailorDB table\n * @returns Field metadata including optional fields, omit fields, indexes, and foreign keys\n */\nfunction extractFieldMetadata(type: TailorDBType): {\n optionalFields: string[];\n omitFields: string[];\n indexes: IndexDefinition[];\n foreignKeys: ForeignKeyDefinition[];\n} {\n const optionalFields = [\"id\"]; // id is always optional\n const omitFields: string[] = [];\n const indexes: IndexDefinition[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n\n // Find fields with hooks.create or serial\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.config.hooks?.create) {\n optionalFields.push(fieldName);\n }\n // Serial fields are auto-generated, so they should be optional in seed data\n if (field.config.serial) {\n omitFields.push(fieldName);\n }\n if (field.config.unique) {\n indexes.push({\n name: `${type.name.toLowerCase()}_${fieldName}_unique_idx`,\n columns: [fieldName],\n unique: true,\n });\n }\n }\n\n // Extract indexes\n if (type.indexes) {\n for (const [indexName, indexDef] of Object.entries(type.indexes)) {\n indexes.push({\n name: indexName,\n columns: indexDef.fields,\n unique: indexDef.unique,\n });\n }\n }\n\n // Extract foreign keys from relations\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.relation) {\n foreignKeys.push({\n column: fieldName,\n references: {\n table: field.relation.targetType,\n column: field.relation.key,\n },\n });\n }\n }\n\n return { optionalFields, omitFields, indexes, foreignKeys };\n}\n\n/**\n * Generate schema options code for lines-db\n * @param foreignKeys - Foreign key definitions\n * @param indexes - Index definitions\n * @returns Schema options code string\n */\nfunction generateSchemaOptions(\n foreignKeys: ForeignKeyDefinition[],\n indexes: IndexDefinition[],\n): string {\n const schemaOptions: string[] = [];\n\n if (foreignKeys.length > 0) {\n schemaOptions.push(`foreignKeys: [`);\n foreignKeys.forEach((fk) => {\n schemaOptions.push(` ${JSON.stringify(fk)},`);\n });\n schemaOptions.push(`],`);\n }\n\n if (indexes.length > 0) {\n schemaOptions.push(`indexes: [`);\n indexes.forEach((index) => {\n schemaOptions.push(` ${JSON.stringify(index)},`);\n });\n schemaOptions.push(\"],\");\n }\n\n return schemaOptions.length > 0\n ? [\"\\n {\", ...schemaOptions.map((option) => ` ${option}`), \" }\"].join(\"\\n\")\n : \"\";\n}\n\n/**\n * Generates the schema file content for lines-db (for user-defined tables with import)\n * @param metadata - lines-db metadata\n * @param importPath - Import path for the TailorDB table\n * @returns Schema file contents\n */\nexport function generateLinesDbSchemaFile(metadata: LinesDbMetadata, importPath: string): string {\n const { exportName, optionalFields, omitFields, foreignKeys, indexes } = metadata;\n\n const schemaTypeCode = ml /* ts */ `\n const schemaType = t.object({\n ...${exportName}.pickFields(${JSON.stringify(optionalFields)}, { optional: true }),\n ...${exportName}.omitFields(${JSON.stringify([...optionalFields, ...omitFields])}),\n });\n `;\n\n const schemaOptionsCode = generateSchemaOptions(foreignKeys, indexes);\n\n return ml /* ts */ `\n import { t } from \"@tailor-platform/sdk\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { ${exportName} } from \"${importPath}\";\n\n ${schemaTypeCode}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n}\n\n/**\n * Parameters for generating plugin-type schema file\n */\nexport interface PluginSchemaParams {\n /** Relative path from schema output to tailor.config.ts */\n configImportPath: string;\n /** Relative import path to the original table file (for type-attached plugins) */\n originalImportPath?: string;\n}\n\n/**\n * Generates the schema file content using getGeneratedType API\n * (for plugin-generated types)\n * @param metadata - lines-db metadata (must have pluginSource)\n * @param params - Plugin import paths\n * @returns Schema file contents\n */\nexport function generateLinesDbSchemaFileWithPluginAPI(\n metadata: LinesDbMetadata,\n params: PluginSchemaParams,\n): string {\n const { typeName, exportName, optionalFields, omitFields, foreignKeys, indexes, pluginSource } =\n metadata;\n\n if (!pluginSource) {\n throw new Error(`pluginSource is required for plugin-generated type \"${typeName}\"`);\n }\n\n const { configImportPath, originalImportPath } = params;\n\n const schemaTypeCode = ml /* ts */ `\n const schemaType = t.object({\n ...${exportName}.pickFields(${JSON.stringify(optionalFields)}, { optional: true }),\n ...${exportName}.omitFields(${JSON.stringify([...optionalFields, ...omitFields])}),\n });\n `;\n\n const schemaOptionsCode = generateSchemaOptions(foreignKeys, indexes);\n\n // Type-attached plugin (e.g., changeset): import the original table and use getGeneratedType(configPath, pluginId, type, kind)\n if (pluginSource.originalExportName && originalImportPath && pluginSource.generatedTypeKind) {\n return ml /* ts */ `\n import { join } from \"node:path\";\n import { t } from \"@tailor-platform/sdk\";\n import { getGeneratedType } from \"@tailor-platform/sdk/plugin\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { ${pluginSource.originalExportName} } from \"${originalImportPath}\";\n\n const configPath = join(import.meta.dirname, \"${configImportPath}\");\n const ${exportName} = await getGeneratedType(configPath, \"${pluginSource.pluginId}\", ${pluginSource.originalExportName}, \"${pluginSource.generatedTypeKind}\");\n\n ${schemaTypeCode}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n }\n\n // Namespace plugin (e.g., audit-log): use getGeneratedType(configPath, pluginId, null, kind)\n // For namespace plugins, generatedTypeKind is required\n if (!pluginSource.generatedTypeKind) {\n throw new Error(\n `Namespace plugin \"${pluginSource.pluginId}\" must provide generatedTypeKind for type \"${typeName}\"`,\n );\n }\n\n return ml /* ts */ `\n import { join } from \"node:path\";\n import { t } from \"@tailor-platform/sdk\";\n import { getGeneratedType } from \"@tailor-platform/sdk/plugin\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n\n const configPath = join(import.meta.dirname, \"${configImportPath}\");\n const ${exportName} = await getGeneratedType(configPath, \"${pluginSource.pluginId}\", null, \"${pluginSource.generatedTypeKind}\");\n\n ${schemaTypeCode}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n}\n","import * as path from \"pathe\";\nimport { assertDefined } from \"#/utils/assert\";\nimport { processIdpUser, generateIdpUserSchemaFile } from \"./idp-user-processor\";\nimport {\n processLinesDb,\n generateLinesDbSchemaFile,\n generateLinesDbSchemaFileWithPluginAPI,\n type PluginSchemaParams,\n} from \"./lines-db-processor\";\nimport type { Plugin, GeneratorResult, TailorDBReadyContext } from \"#/plugin/types\";\n\n/** Unique identifier for the seed generator plugin. */\nexport const SeedGeneratorID = \"@tailor-platform/seed\";\n\ntype DisableIdpUserSyncDirections = {\n /**\n * Skip emitting the foreign key from `<userProfile>.<usernameField>` to\n * `_User.name`. Defaults to `false` (FK emitted).\n *\n * Set to `true` to seed pre-registration states such as\n * invited-but-not-registered users.\n */\n userToIdp?: boolean;\n /**\n * Skip emitting the foreign key from `_User.name` to\n * `<userProfile>.<usernameField>`. Defaults to `false` (FK emitted).\n *\n * Set to `true` to seed `_User` rows that do not yet have a corresponding\n * userProfile row.\n */\n idpToUser?: boolean;\n};\n\nexport type SeedPluginOptions = {\n distPath: string;\n machineUserName?: string;\n /**\n * Disable individual `_User <-> userProfile` foreign keys emitted into\n * the generated seed schema. Both directions are emitted by default.\n *\n * Set a direction to `true` to relax it — for example to seed invited\n * users that do not yet have an IdP credential.\n */\n disableIdpUserSync?: DisableIdpUserSyncDirections;\n};\n\nfunction resolveIdpUserSyncFKs(option: SeedPluginOptions[\"disableIdpUserSync\"]): {\n emitUserToIdpFK: boolean;\n emitIdpToUserFK: boolean;\n} {\n return {\n emitUserToIdpFK: !(option?.userToIdp ?? false),\n emitIdpToUserFK: !(option?.idpToUser ?? false),\n };\n}\n/**\n * Plugin that generates seed data and schema files consumed by the\n * `tailor seed` commands (@tailor-platform/sdk-plugin-seed).\n * @param options - Plugin options\n * @param options.distPath - Output directory path for generated seed files\n * @param options.machineUserName - Default machine user name for authentication\n * @param options.disableIdpUserSync - Skip emitting individual `_User <-> userProfile` foreign keys. Both directions are emitted by default; set a direction to `true` to relax that side.\n * @returns Plugin instance with onTailorDBReady hook\n */\nexport function seedPlugin(options: SeedPluginOptions): Plugin<unknown, SeedPluginOptions> {\n return {\n id: SeedGeneratorID,\n description: \"Generates seed data and schema files for the tailor seed CLI plugin\",\n pluginConfig: options,\n\n async onTailorDBReady(ctx: TailorDBReadyContext<SeedPluginOptions>): Promise<GeneratorResult> {\n const files: GeneratorResult[\"files\"] = [];\n\n // Process IdP user early so we can add reverse FK to the user profile type\n const idpUser = ctx.auth ? (processIdpUser(ctx.auth) ?? null) : null;\n const idpUserSyncFKs = resolveIdpUserSyncFKs(ctx.pluginConfig.disableIdpUserSync);\n\n for (const ns of ctx.tailordb) {\n for (const [typeName, type] of Object.entries(ns.types)) {\n const source = assertDefined(\n ns.sourceInfo.get(typeName),\n `source info missing for type: ${typeName}`,\n );\n const linesDb = processLinesDb(type, source);\n\n // Add reverse FK from userProfile type to _User (opt-out via disableIdpUserSync.userToIdp: true)\n if (\n idpUserSyncFKs.emitUserToIdpFK &&\n idpUser &&\n typeName === idpUser.schema.userTypeName\n ) {\n linesDb.foreignKeys.push({\n column: idpUser.schema.usernameField,\n references: {\n table: \"_User\",\n column: \"name\",\n },\n });\n }\n\n // Generate empty JSONL data file\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"data\", `${linesDb.typeName}.jsonl`),\n content: \"\",\n skipIfExists: true,\n });\n\n const schemaOutputPath = path.join(\n ctx.pluginConfig.distPath,\n \"data\",\n `${linesDb.typeName}.schema.ts`,\n );\n\n // Plugin-generated type: use getGeneratedType API\n if (linesDb.pluginSource && linesDb.pluginSource.pluginImportPath) {\n // Build original type import path\n let originalImportPath: string | undefined;\n if (linesDb.pluginSource.originalFilePath && linesDb.pluginSource.originalExportName) {\n const relativePath = path.relative(\n path.dirname(schemaOutputPath),\n linesDb.pluginSource.originalFilePath,\n );\n originalImportPath = relativePath.replace(/\\.ts$/, \"\").startsWith(\".\")\n ? relativePath.replace(/\\.ts$/, \"\")\n : `./${relativePath.replace(/\\.ts$/, \"\")}`;\n }\n\n // Compute relative path from schema output to config file\n const configImportPath = path.relative(path.dirname(schemaOutputPath), ctx.configPath);\n\n const params: PluginSchemaParams = {\n configImportPath,\n originalImportPath,\n };\n\n const schemaContent = generateLinesDbSchemaFileWithPluginAPI(linesDb, params);\n\n files.push({\n path: schemaOutputPath,\n content: schemaContent,\n });\n } else {\n // User-defined type: import from source file\n const relativePath = path.relative(path.dirname(schemaOutputPath), linesDb.importPath);\n const typeImportPath = relativePath.replace(/\\.ts$/, \"\").startsWith(\".\")\n ? relativePath.replace(/\\.ts$/, \"\")\n : `./${relativePath.replace(/\\.ts$/, \"\")}`;\n const schemaContent = generateLinesDbSchemaFile(linesDb, typeImportPath);\n\n files.push({\n path: schemaOutputPath,\n content: schemaContent,\n });\n }\n }\n }\n\n if (idpUser) {\n // Generate empty JSONL data file\n files.push({\n path: path.join(ctx.pluginConfig.distPath, idpUser.dataFile),\n content: \"\",\n skipIfExists: true,\n });\n\n // Generate schema file with foreign key (opt-out via disableIdpUserSync.idpToUser: true)\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"data\", `${idpUser.name}.schema.ts`),\n content: generateIdpUserSchemaFile({\n usernameField: idpUser.schema.usernameField,\n userTypeName: idpUser.schema.userTypeName,\n includeUserProfileFK: idpUserSyncFKs.emitIdpToUserFK,\n }),\n });\n }\n\n return { files };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;AAmBA,SAAgB,eAAe,MAAuD;CAEpF,IAAI,KAAK,YAAY,SAAS,gBAAgB,CAAC,KAAK,aAClD;CAGF,MAAM,EAAE,UAAU,kBAAkB,KAAK;CAEzC,OAAO;EACL,MAAM;EACN,cAAc,CAAC,QAAQ;EACvB,UAAU;EACV,cAAc,KAAK,WAAW;EAC9B,QAAQ;GACN;GACA,cAAc;EAChB;CACF;AACF;;;;;;;AAQA,SAAgB,0BAA0B,cAA8B;CACtE,OAAO,SAAY;;2DAEsC,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DxE;;;;;;;AAQA,SAAgB,8BAA8B,cAA8B;CAC1E,OAAO,SAAY;;2DAEsC,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCxE;;;;;;;;;;;;AAyBA,SAAgB,0BAA0B,SAAmD;CAC3F,MAAM,EAAE,eAAe,cAAc,uBAAuB,SAAS;CACrE,MAAM,aAAa,uBACf,SAAE;;;;;;;;;sBASc,aAAa;uBACZ,cAAc;;;;QAK/B,SAAE;;;;;;CAON,OAAO,SAAY;;;;;;;;;;;;;;;;UAgBX,WAAW;;;;;AAKrB;;;;;;;;;;ACnNA,SAAgB,eAAe,MAAoB,QAA8C;CAC/F,IAAI,sBAAsB,MAAM,GAE9B,OAAO,4BAA4B,MAAM,MAAM;CAIjD,IAAI,CAAC,OAAO,UACV,MAAM,IAAI,MAAM,iCAAiC,KAAK,MAAM;CAE9D,IAAI,CAAC,OAAO,YACV,MAAM,IAAI,MAAM,iCAAiC,KAAK,MAAM;CAG9D,MAAM,EAAE,gBAAgB,YAAY,SAAS,gBAAgB,qBAAqB,IAAI;CAEtF,OAAO;EACL,UAAU,KAAK;EACf,YAAY,OAAO;EACnB,YAAY,OAAO;EACnB;EACA;EACA;EACA;CACF;AACF;;;;;;;AAQA,SAAS,4BACP,MACA,QACiB;CACjB,MAAM,EAAE,gBAAgB,YAAY,SAAS,gBAAgB,qBAAqB,IAAI;CAEtF,OAAO;EACL,UAAU,KAAK;EACf,YAAY,OAAO;EACnB,YAAY;EACZ;EACA;EACA;EACA;EACA,cAAc;CAChB;AACF;;;;;;AAOA,SAAS,qBAAqB,MAK5B;CACA,MAAM,iBAAiB,CAAC,IAAI;CAC5B,MAAM,aAAuB,CAAC;CAC9B,MAAM,UAA6B,CAAC;CACpC,MAAM,cAAsC,CAAC;CAG7C,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,KAAK,MAAM,GAAG;EAC5D,IAAI,MAAM,OAAO,OAAO,QACtB,eAAe,KAAK,SAAS;EAG/B,IAAI,MAAM,OAAO,QACf,WAAW,KAAK,SAAS;EAE3B,IAAI,MAAM,OAAO,QACf,QAAQ,KAAK;GACX,MAAM,GAAG,KAAK,KAAK,YAAY,EAAE,GAAG,UAAU;GAC9C,SAAS,CAAC,SAAS;GACnB,QAAQ;EACV,CAAC;CAEL;CAGA,IAAI,KAAK,SACP,KAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,KAAK,OAAO,GAC7D,QAAQ,KAAK;EACX,MAAM;EACN,SAAS,SAAS;EAClB,QAAQ,SAAS;CACnB,CAAC;CAKL,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,KAAK,MAAM,GACzD,IAAI,MAAM,UACR,YAAY,KAAK;EACf,QAAQ;EACR,YAAY;GACV,OAAO,MAAM,SAAS;GACtB,QAAQ,MAAM,SAAS;EACzB;CACF,CAAC;CAIL,OAAO;EAAE;EAAgB;EAAY;EAAS;CAAY;AAC5D;;;;;;;AAQA,SAAS,sBACP,aACA,SACQ;CACR,MAAM,gBAA0B,CAAC;CAEjC,IAAI,YAAY,SAAS,GAAG;EAC1B,cAAc,KAAK,gBAAgB;EACnC,YAAY,SAAS,OAAO;GAC1B,cAAc,KAAK,KAAK,KAAK,UAAU,EAAE,EAAE,EAAE;EAC/C,CAAC;EACD,cAAc,KAAK,IAAI;CACzB;CAEA,IAAI,QAAQ,SAAS,GAAG;EACtB,cAAc,KAAK,YAAY;EAC/B,QAAQ,SAAS,UAAU;GACzB,cAAc,KAAK,KAAK,KAAK,UAAU,KAAK,EAAE,EAAE;EAClD,CAAC;EACD,cAAc,KAAK,IAAI;CACzB;CAEA,OAAO,cAAc,SAAS,IAC1B;EAAC;EAAS,GAAG,cAAc,KAAK,WAAW,OAAO,QAAQ;EAAG;CAAK,CAAC,CAAC,KAAK,IAAI,IAC7E;AACN;;;;;;;AAQA,SAAgB,0BAA0B,UAA2B,YAA4B;CAC/F,MAAM,EAAE,YAAY,gBAAgB,YAAY,aAAa,YAAY;CAEzE,MAAM,iBAAiB,SAAY;;WAE1B,WAAW,cAAc,KAAK,UAAU,cAAc,EAAE;WACxD,WAAW,cAAc,KAAK,UAAU,CAAC,GAAG,gBAAgB,GAAG,UAAU,CAAC,EAAE;;;CAIrF,MAAM,oBAAoB,sBAAsB,aAAa,OAAO;CAEpE,OAAO,SAAY;;;;eAIN,WAAW,WAAW,WAAW;;MAE1C,eAAe;;6CAEwB,WAAW;;;+CAGT,WAAW,IAAI,kBAAkB;;;;AAIhF;;;;;;;;AAmBA,SAAgB,uCACd,UACA,QACQ;CACR,MAAM,EAAE,UAAU,YAAY,gBAAgB,YAAY,aAAa,SAAS,iBAC9E;CAEF,IAAI,CAAC,cACH,MAAM,IAAI,MAAM,uDAAuD,SAAS,EAAE;CAGpF,MAAM,EAAE,kBAAkB,uBAAuB;CAEjD,MAAM,iBAAiB,SAAY;;WAE1B,WAAW,cAAc,KAAK,UAAU,cAAc,EAAE;WACxD,WAAW,cAAc,KAAK,UAAU,CAAC,GAAG,gBAAgB,GAAG,UAAU,CAAC,EAAE;;;CAIrF,MAAM,oBAAoB,sBAAsB,aAAa,OAAO;CAGpE,IAAI,aAAa,sBAAsB,sBAAsB,aAAa,mBACxE,OAAO,SAAY;;;;;;eAMR,aAAa,mBAAmB,WAAW,mBAAmB;;oDAEzB,iBAAiB;YACzD,WAAW,yCAAyC,aAAa,SAAS,KAAK,aAAa,mBAAmB,KAAK,aAAa,kBAAkB;;MAEzJ,eAAe;;6CAEwB,WAAW;;;+CAGT,WAAW,IAAI,kBAAkB;;;;CAQ9E,IAAI,CAAC,aAAa,mBAChB,MAAM,IAAI,MACR,qBAAqB,aAAa,SAAS,6CAA6C,SAAS,EACnG;CAGF,OAAO,SAAY;;;;;;;oDAO+B,iBAAiB;YACzD,WAAW,yCAAyC,aAAa,SAAS,YAAY,aAAa,kBAAkB;;MAE3H,eAAe;;6CAEwB,WAAW;;;+CAGT,WAAW,IAAI,kBAAkB;;;;AAIhF;;;;;AClRA,MAAa,kBAAkB;AAkC/B,SAAS,sBAAsB,QAG7B;CACA,OAAO;EACL,iBAAiB,EAAE,QAAQ,aAAa;EACxC,iBAAiB,EAAE,QAAQ,aAAa;CAC1C;AACF;;;;;;;;;;AAUA,SAAgB,WAAW,SAAgE;CACzF,OAAO;EACL,IAAI;EACJ,aAAa;EACb,cAAc;EAEd,MAAM,gBAAgB,KAAwE;GAC5F,MAAM,QAAkC,CAAC;GAGzC,MAAM,UAAU,IAAI,OAAQ,eAAe,IAAI,IAAI,KAAK,OAAQ;GAChE,MAAM,iBAAiB,sBAAsB,IAAI,aAAa,kBAAkB;GAEhF,KAAK,MAAM,MAAM,IAAI,UACnB,KAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,GAAG,KAAK,GAAG;IACvD,MAAM,SAAS,cACb,GAAG,WAAW,IAAI,QAAQ,GAC1B,iCAAiC,UACnC;IACA,MAAM,UAAU,eAAe,MAAM,MAAM;IAG3C,IACE,eAAe,mBACf,WACA,aAAa,QAAQ,OAAO,cAE5B,QAAQ,YAAY,KAAK;KACvB,QAAQ,QAAQ,OAAO;KACvB,YAAY;MACV,OAAO;MACP,QAAQ;KACV;IACF,CAAC;IAIH,MAAM,KAAK;KACT,MAAM,KAAK,KAAK,IAAI,aAAa,UAAU,QAAQ,GAAG,QAAQ,SAAS,OAAO;KAC9E,SAAS;KACT,cAAc;IAChB,CAAC;IAED,MAAM,mBAAmB,KAAK,KAC5B,IAAI,aAAa,UACjB,QACA,GAAG,QAAQ,SAAS,WACtB;IAGA,IAAI,QAAQ,gBAAgB,QAAQ,aAAa,kBAAkB;KAEjE,IAAI;KACJ,IAAI,QAAQ,aAAa,oBAAoB,QAAQ,aAAa,oBAAoB;MACpF,MAAM,eAAe,KAAK,SACxB,KAAK,QAAQ,gBAAgB,GAC7B,QAAQ,aAAa,gBACvB;MACA,qBAAqB,aAAa,QAAQ,SAAS,EAAE,CAAC,CAAC,WAAW,GAAG,IACjE,aAAa,QAAQ,SAAS,EAAE,IAChC,KAAK,aAAa,QAAQ,SAAS,EAAE;KAC3C;KAKA,MAAM,SAA6B;MACjC,kBAHuB,KAAK,SAAS,KAAK,QAAQ,gBAAgB,GAAG,IAAI,UAG1D;MACf;KACF;KAEA,MAAM,gBAAgB,uCAAuC,SAAS,MAAM;KAE5E,MAAM,KAAK;MACT,MAAM;MACN,SAAS;KACX,CAAC;IACH,OAAO;KAEL,MAAM,eAAe,KAAK,SAAS,KAAK,QAAQ,gBAAgB,GAAG,QAAQ,UAAU;KACrF,MAAM,iBAAiB,aAAa,QAAQ,SAAS,EAAE,CAAC,CAAC,WAAW,GAAG,IACnE,aAAa,QAAQ,SAAS,EAAE,IAChC,KAAK,aAAa,QAAQ,SAAS,EAAE;KACzC,MAAM,gBAAgB,0BAA0B,SAAS,cAAc;KAEvE,MAAM,KAAK;MACT,MAAM;MACN,SAAS;KACX,CAAC;IACH;GACF;GAGF,IAAI,SAAS;IAEX,MAAM,KAAK;KACT,MAAM,KAAK,KAAK,IAAI,aAAa,UAAU,QAAQ,QAAQ;KAC3D,SAAS;KACT,cAAc;IAChB,CAAC;IAGD,MAAM,KAAK;KACT,MAAM,KAAK,KAAK,IAAI,aAAa,UAAU,QAAQ,GAAG,QAAQ,KAAK,WAAW;KAC9E,SAAS,0BAA0B;MACjC,eAAe,QAAQ,OAAO;MAC9B,cAAc,QAAQ,OAAO;MAC7B,sBAAsB,eAAe;KACvC,CAAC;IACH,CAAC;GACH;GAEA,OAAO,EAAE,MAAM;EACjB;CACF;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as isSdkBranded } from "./brand-Eo4pLXPJ.mjs";
|
|
2
|
-
import { n as logger, r as styles } from "./logger-
|
|
2
|
+
import { n as logger, r as styles } from "./logger-D0bEznPv.mjs";
|
|
3
3
|
import * as path from "pathe";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import * as fs from "node:fs";
|
|
@@ -8,6 +8,40 @@ import { pathToFileURL } from "node:url";
|
|
|
8
8
|
//#region src/parser/service/common.ts
|
|
9
9
|
const functionSchema = z.custom((val) => typeof val === "function");
|
|
10
10
|
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/cli/shared/user-modules.ts
|
|
13
|
+
const IMPORT_NONCE_PARAM = "tailorImportNonce";
|
|
14
|
+
let runCounter = 0;
|
|
15
|
+
/**
|
|
16
|
+
* Start a fresh user-module run. Modules imported through
|
|
17
|
+
* {@link importUserModule} after this call bypass the ESM cache entries of
|
|
18
|
+
* earlier runs, so a repeated in-process run re-evaluates user code instead
|
|
19
|
+
* of reusing stale modules.
|
|
20
|
+
*/
|
|
21
|
+
function beginUserModuleRun() {
|
|
22
|
+
runCounter += 1;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Read the cache-busting nonce of the current user-module run.
|
|
26
|
+
* @returns The nonce, or undefined when no run was started
|
|
27
|
+
*/
|
|
28
|
+
function currentImportNonce() {
|
|
29
|
+
return runCounter === 0 ? void 0 : String(runCounter);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Import a user module (config, workflow, resolver, executor, ...) with the
|
|
33
|
+
* current run's cache-busting nonce applied. Outside a run this is a plain
|
|
34
|
+
* import.
|
|
35
|
+
* @param filePath - Absolute path of the user module
|
|
36
|
+
* @returns The imported module namespace
|
|
37
|
+
*/
|
|
38
|
+
function importUserModule(filePath) {
|
|
39
|
+
const url = pathToFileURL(filePath);
|
|
40
|
+
const nonce = currentImportNonce();
|
|
41
|
+
if (nonce) url.searchParams.set(IMPORT_NONCE_PARAM, nonce);
|
|
42
|
+
return import(url.href);
|
|
43
|
+
}
|
|
44
|
+
|
|
11
45
|
//#endregion
|
|
12
46
|
//#region src/cli/services/file-loader.ts
|
|
13
47
|
const DEFAULT_IGNORE_PATTERNS = ["**/*.test.ts", "**/*.spec.ts"];
|
|
@@ -67,17 +101,17 @@ const relationTypes = {
|
|
|
67
101
|
};
|
|
68
102
|
const relationTypesKeys = Object.keys(relationTypes);
|
|
69
103
|
function fieldRef(context) {
|
|
70
|
-
return `Field "${context.fieldName}" on
|
|
104
|
+
return `Field "${context.fieldName}" on table "${context.typeName}"`;
|
|
71
105
|
}
|
|
72
106
|
/**
|
|
73
107
|
* Validate relation configuration.
|
|
74
|
-
* @param rawRelation - Raw relation configuration from TailorDB
|
|
75
|
-
* @param context - Context information for the relation (
|
|
108
|
+
* @param rawRelation - Raw relation configuration from TailorDB table definition
|
|
109
|
+
* @param context - Context information for the relation (table name, field name, all type names)
|
|
76
110
|
*/
|
|
77
111
|
function validateRelationConfig(rawRelation, context) {
|
|
78
112
|
if (!rawRelation.type) throw new Error(`${fieldRef(context)} has a relation but is missing the required 'type' property. Valid values: ${relationTypesKeys.join(", ")}.`);
|
|
79
113
|
if (!(rawRelation.type in relationTypes)) throw new Error(`${fieldRef(context)} has invalid relation type '${rawRelation.type}'. Valid values: ${relationTypesKeys.join(", ")}.`);
|
|
80
|
-
if (rawRelation.toward.type !== "self" && !context.allTypeNames.has(rawRelation.toward.type)) throw new Error(`${fieldRef(context)} references unknown
|
|
114
|
+
if (rawRelation.toward.type !== "self" && !context.allTypeNames.has(rawRelation.toward.type)) throw new Error(`${fieldRef(context)} references unknown table "${rawRelation.toward.type}".`);
|
|
81
115
|
}
|
|
82
116
|
/**
|
|
83
117
|
* Process raw relation config and compute derived metadata values.
|
|
@@ -166,7 +200,7 @@ const GqlOperationsSchema = z.union([z.literal("query"), z.strictObject({
|
|
|
166
200
|
update: z.boolean().optional().describe("Enable update mutation (default: true)"),
|
|
167
201
|
delete: z.boolean().optional().describe("Enable delete mutation (default: true)"),
|
|
168
202
|
read: z.boolean().optional().describe("Enable read queries - get, list, aggregation (default: true)")
|
|
169
|
-
})]).describe("Configuration for GraphQL operations on a TailorDB
|
|
203
|
+
})]).describe("Configuration for GraphQL operations on a TailorDB table.\nAll operations are enabled by default (undefined or true = enabled, false = disabled).").transform((val) => normalizeGqlOperations(val));
|
|
170
204
|
const TailorFieldTypeSchema$1 = z.enum([
|
|
171
205
|
"uuid",
|
|
172
206
|
"string",
|
|
@@ -194,7 +228,7 @@ const DBFieldMetadataSchema = z.strictObject({
|
|
|
194
228
|
unique: z.boolean().optional().describe("Whether the field value must be unique"),
|
|
195
229
|
vector: z.boolean().optional().describe("Whether the field is a vector field for similarity search"),
|
|
196
230
|
foreignKey: z.boolean().optional().describe("Whether the field is a foreign key"),
|
|
197
|
-
foreignKeyType: z.string().optional().describe("Target
|
|
231
|
+
foreignKeyType: z.string().optional().describe("Target table name for foreign key relations"),
|
|
198
232
|
foreignKeyField: z.string().optional().describe("Target field name for foreign key relations"),
|
|
199
233
|
hooks: z.strictObject({
|
|
200
234
|
create: functionSchema.optional().describe("Hook function called on record creation"),
|
|
@@ -213,11 +247,11 @@ const RelationTypeSchema = z.enum(relationTypesKeys);
|
|
|
213
247
|
const RawRelationConfigSchema = z.strictObject({
|
|
214
248
|
type: RelationTypeSchema.describe("Relation cardinality type"),
|
|
215
249
|
toward: z.strictObject({
|
|
216
|
-
type: z.string().describe("Target
|
|
250
|
+
type: z.string().describe("Target table name, or 'self' for self-relations"),
|
|
217
251
|
as: z.string().optional().describe("Custom forward relation name"),
|
|
218
252
|
key: z.string().optional().describe("Target field to join on (default: 'id')")
|
|
219
253
|
}),
|
|
220
|
-
backward: z.string().optional().describe("Backward relation name on the target
|
|
254
|
+
backward: z.string().optional().describe("Backward relation name on the target table")
|
|
221
255
|
});
|
|
222
256
|
const TailorDBFieldSchema = z.lazy(() => z.object({
|
|
223
257
|
type: TailorFieldTypeSchema$1,
|
|
@@ -226,15 +260,15 @@ const TailorDBFieldSchema = z.lazy(() => z.object({
|
|
|
226
260
|
rawRelation: RawRelationConfigSchema.optional()
|
|
227
261
|
}));
|
|
228
262
|
/**
|
|
229
|
-
* Schema for TailorDB
|
|
263
|
+
* Schema for TailorDB table settings.
|
|
230
264
|
* Normalizes gqlOperations from alias ("query") to object format.
|
|
231
265
|
*/
|
|
232
266
|
const TailorDBTypeSettingsSchema = z.strictObject({
|
|
233
|
-
pluralForm: z.string().optional().describe("Custom plural form of the
|
|
234
|
-
aggregation: z.boolean().optional().describe("Enable aggregation queries for this
|
|
235
|
-
bulkUpsert: z.boolean().optional().describe("Enable bulk upsert mutation for this
|
|
236
|
-
gqlOperations: GqlOperationsSchema.optional().describe("Configure GraphQL operations for this
|
|
237
|
-
publishEvents: z.boolean().optional().describe("Enable publishing events for this
|
|
267
|
+
pluralForm: z.string().optional().describe("Custom plural form of the table name for GraphQL"),
|
|
268
|
+
aggregation: z.boolean().optional().describe("Enable aggregation queries for this table"),
|
|
269
|
+
bulkUpsert: z.boolean().optional().describe("Enable bulk upsert mutation for this table"),
|
|
270
|
+
gqlOperations: GqlOperationsSchema.optional().describe("Configure GraphQL operations for this table. Use \"query\" for read-only mode, or an object for granular control."),
|
|
271
|
+
publishEvents: z.boolean().optional().describe("Enable publishing events for this table.\nWhen enabled, record creation/update/deletion events are published.\nIf not specified, this is automatically set to true when an executor uses this table\nwith recordCreated/recordUpdated/recordDeleted triggers. If explicitly set to false\nwhile an executor uses this table, an error will be thrown during apply.")
|
|
238
272
|
});
|
|
239
273
|
const GQL_PERMISSION_INVALID_OPERAND_MESSAGE = "operand is not supported in gqlPermission. Use permission() for record-level conditions.";
|
|
240
274
|
const GqlPermissionOperandSchema = z.union([
|
|
@@ -349,10 +383,10 @@ const TailorDBMigrationConfigSchema = z.strictObject({
|
|
|
349
383
|
* Normalizes gqlOperations from alias ("query") to object format.
|
|
350
384
|
*/
|
|
351
385
|
const TailorDBServiceConfigSchema = z.strictObject({
|
|
352
|
-
files: z.array(z.string()).describe("Glob patterns for TailorDB
|
|
353
|
-
ignores: z.array(z.string()).optional().describe("Glob patterns to exclude from
|
|
386
|
+
files: z.array(z.string()).describe("Glob patterns for TailorDB table definition files"),
|
|
387
|
+
ignores: z.array(z.string()).optional().describe("Glob patterns to exclude from table discovery"),
|
|
354
388
|
migration: TailorDBMigrationConfigSchema.optional().describe("Migration configuration"),
|
|
355
|
-
gqlOperations: GqlOperationsSchema.optional().describe("Default GraphQL operations for all
|
|
389
|
+
gqlOperations: GqlOperationsSchema.optional().describe("Default GraphQL operations for all tables in this service")
|
|
356
390
|
});
|
|
357
391
|
|
|
358
392
|
//#endregion
|
|
@@ -543,7 +577,7 @@ const SCIMAttributeMappingSchema = z.strictObject({
|
|
|
543
577
|
const SCIMResourceSchema = z.strictObject({
|
|
544
578
|
name: z.string().describe("SCIM resource name"),
|
|
545
579
|
tailorDBNamespace: z.string().describe("TailorDB namespace for the resource"),
|
|
546
|
-
tailorDBType: z.string().describe("TailorDB
|
|
580
|
+
tailorDBType: z.string().describe("TailorDB table name for the resource"),
|
|
547
581
|
coreSchema: SCIMSchemaSchema.describe("Core SCIM schema definition"),
|
|
548
582
|
attributeMapping: z.array(SCIMAttributeMappingSchema).describe("Attribute mapping configuration")
|
|
549
583
|
});
|
|
@@ -553,12 +587,12 @@ const SCIMSchema = z.strictObject({
|
|
|
553
587
|
resources: z.array(SCIMResourceSchema).describe("SCIM resource definitions")
|
|
554
588
|
});
|
|
555
589
|
const TenantProviderSchema = z.strictObject({
|
|
556
|
-
namespace: z.string().describe("TailorDB namespace for the tenant
|
|
557
|
-
type: z.string().describe("TailorDB
|
|
590
|
+
namespace: z.string().describe("TailorDB namespace for the tenant table"),
|
|
591
|
+
type: z.string().describe("TailorDB table name for tenants"),
|
|
558
592
|
signatureField: z.string().describe("Field used as the tenant signature")
|
|
559
593
|
});
|
|
560
594
|
const UserProfileSchema = z.strictObject({
|
|
561
|
-
namespace: z.string().optional().describe("TailorDB namespace where the user
|
|
595
|
+
namespace: z.string().optional().describe("TailorDB namespace where the user table is defined"),
|
|
562
596
|
type: z.custom().transform(stripTailorDBTypeBuilderHelpers).pipe(TailorDBTypeSchema),
|
|
563
597
|
usernameField: z.string(),
|
|
564
598
|
attributes: z.record(z.string(), z.literal(true)).optional(),
|
|
@@ -610,7 +644,7 @@ const TailorDBTriggerSchema = z.strictObject({
|
|
|
610
644
|
"tailordb.type_record.updated",
|
|
611
645
|
"tailordb.type_record.deleted"
|
|
612
646
|
])).min(1).transform((arr) => [...new Set(arr)]).describe("TailorDB event types to trigger on"),
|
|
613
|
-
typeName: z.string().describe("TailorDB
|
|
647
|
+
typeName: z.string().describe("TailorDB table name to watch for events"),
|
|
614
648
|
condition: functionSchema.optional().describe("Condition function to filter events")
|
|
615
649
|
});
|
|
616
650
|
const ResolverExecutedTriggerSchema = z.strictObject({
|
|
@@ -771,7 +805,7 @@ function stripExecutorTriggerArgs(executor) {
|
|
|
771
805
|
* @returns Parsed executor or null if invalid
|
|
772
806
|
*/
|
|
773
807
|
async function loadExecutor(executorFilePath) {
|
|
774
|
-
const executor = (await
|
|
808
|
+
const executor = (await importUserModule(executorFilePath)).default;
|
|
775
809
|
const parseResult = ExecutorSchema.safeParse(stripExecutorTriggerArgs(executor));
|
|
776
810
|
if (!parseResult.success) return null;
|
|
777
811
|
return parseResult.data;
|
|
@@ -791,7 +825,7 @@ function createExecutorService(params) {
|
|
|
791
825
|
let loadPromise;
|
|
792
826
|
const loadExecutorForFile = async (executorFile) => {
|
|
793
827
|
try {
|
|
794
|
-
const executorModule = await
|
|
828
|
+
const executorModule = await importUserModule(executorFile);
|
|
795
829
|
const result = ExecutorSchema.safeParse(stripExecutorTriggerArgs(executorModule.default));
|
|
796
830
|
if (result.success) {
|
|
797
831
|
const relativePath = path.relative(process.cwd(), executorFile);
|
|
@@ -860,5 +894,5 @@ function assertUniqueExecutorNames(executors) {
|
|
|
860
894
|
}
|
|
861
895
|
|
|
862
896
|
//#endregion
|
|
863
|
-
export { AuthConfigSchema as a, stripTailorDBTypeBuilderHelpers as c, applyRelationMetadataToFieldConfig as d, buildRelationInfo as f,
|
|
864
|
-
//# sourceMappingURL=service-
|
|
897
|
+
export { beginUserModuleRun as _, AuthConfigSchema as a, functionSchema as b, stripTailorDBTypeBuilderHelpers as c, applyRelationMetadataToFieldConfig as d, buildRelationInfo as f, IMPORT_NONCE_PARAM as g, loadFilesWithIgnores as h, ExecutorSchema as i, TailorDBServiceConfigSchema as l, validateRelationConfig as m, loadExecutor as n, AuthInvokerSchema as o, processRelationMetadata as p, stripExecutorTriggerArgs as r, TailorFieldSchema as s, createExecutorService as t, TailorDBTypeSchema as u, currentImportNonce as v, importUserModule as y };
|
|
898
|
+
//# sourceMappingURL=service-2grcAOCJ.mjs.map
|