@tailor-platform/sdk 1.19.0 → 1.21.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/{application-A6PZjujv.mjs → application-CEv5c7TU.mjs} +97929 -97634
  3. package/dist/application-CEv5c7TU.mjs.map +1 -0
  4. package/dist/{application-nPS5veK6.mjs → application-DiCzM9b0.mjs} +3 -3
  5. package/dist/cli/index.mjs +118 -63
  6. package/dist/cli/index.mjs.map +1 -1
  7. package/dist/cli/lib.d.mts +117 -58
  8. package/dist/cli/lib.mjs +7 -7
  9. package/dist/cli/lib.mjs.map +1 -1
  10. package/dist/cli/skills.mjs +1 -1
  11. package/dist/cli/skills.mjs.map +1 -1
  12. package/dist/configure/index.d.mts +4 -4
  13. package/dist/configure/index.mjs +5 -0
  14. package/dist/configure/index.mjs.map +1 -1
  15. package/dist/{index-B91ZpOcd.d.mts → index-BWVAwea4.d.mts} +2 -2
  16. package/dist/{index-ClLZCbcm.d.mts → index-CnHd6BNg.d.mts} +9 -43
  17. package/dist/{index-DDqKNFh4.d.mts → index-Dn61THJK.d.mts} +2 -2
  18. package/dist/{index-B6pvy1MK.d.mts → index-DxlmLUag.d.mts} +2 -2
  19. package/dist/{index-CPzbMghQ.d.mts → index-oZXVKyfX.d.mts} +2 -2
  20. package/dist/{package-json-DUY2kB6z.mjs → package-json-3H5gfhA4.mjs} +2 -2
  21. package/dist/package-json-3H5gfhA4.mjs.map +1 -0
  22. package/dist/package-json-DTDAqRRJ.mjs +3 -0
  23. package/dist/plugin/builtin/enum-constants/index.d.mts +2 -2
  24. package/dist/plugin/builtin/file-utils/index.d.mts +2 -2
  25. package/dist/plugin/builtin/kysely-type/index.d.mts +2 -2
  26. package/dist/plugin/builtin/seed/index.d.mts +2 -2
  27. package/dist/plugin/builtin/seed/index.mjs +1 -1
  28. package/dist/plugin/index.d.mts +1 -1
  29. package/dist/{seed-CeUEANfQ.mjs → seed-D-rYCN5F.mjs} +2 -2
  30. package/dist/{seed-CeUEANfQ.mjs.map → seed-D-rYCN5F.mjs.map} +1 -1
  31. package/dist/telemetry-Dhzj9Ncm.mjs +3 -0
  32. package/dist/{telemetry-rFq0QdvJ.mjs → telemetry-DuBhnd0X.mjs} +2 -2
  33. package/dist/telemetry-DuBhnd0X.mjs.map +1 -0
  34. package/dist/{types-CJF3Y1x8.d.mts → types-C0o90Cmb.d.mts} +87 -3
  35. package/dist/types-ClK_HJ0G.mjs.map +1 -1
  36. package/dist/{types-CblXasFV.d.mts → types-QKq1usl7.d.mts} +20 -9
  37. package/dist/{update-Cr5c7h1r.mjs → update-9MTRN1UA.mjs} +456 -244
  38. package/dist/update-9MTRN1UA.mjs.map +1 -0
  39. package/dist/utils/test/index.d.mts +3 -3
  40. package/docs/cli/application.md +2 -0
  41. package/docs/services/resolver.md +61 -0
  42. package/docs/services/tailordb.md +55 -0
  43. package/package.json +1 -1
  44. package/dist/application-A6PZjujv.mjs.map +0 -1
  45. package/dist/package-json-DUY2kB6z.mjs.map +0 -1
  46. package/dist/package-json-Dd1AnA5F.mjs +0 -3
  47. package/dist/telemetry-9A1BZqbl.mjs +0 -3
  48. package/dist/telemetry-rFq0QdvJ.mjs.map +0 -1
  49. package/dist/update-Cr5c7h1r.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-json-3H5gfhA4.mjs","names":[],"sources":["../src/cli/shared/package-json.ts"],"sourcesContent":["import { readPackageJSON, type PackageJson } from \"pkg-types\";\n\nlet packageJson: PackageJson | null = null;\n\n/**\n * Read and cache the package.json of the SDK package.\n * @returns Parsed package.json contents\n */\nexport async function readPackageJson() {\n if (packageJson) {\n return packageJson;\n }\n packageJson = await readPackageJSON(import.meta.url);\n return packageJson;\n}\n"],"mappings":";;;AAEA,IAAI,cAAkC;;;;;AAMtC,eAAsB,kBAAkB;AACtC,KAAI,YACF,QAAO;AAET,eAAc,MAAM,gBAAgB,OAAO,KAAK,IAAI;AACpD,QAAO"}
@@ -0,0 +1,3 @@
1
+ import { t as readPackageJson } from "./package-json-3H5gfhA4.mjs";
2
+
3
+ export { readPackageJson };
@@ -1,4 +1,4 @@
1
1
  /// <reference path="./../../../user-defined.d.ts" />
2
- import "../../../types-CblXasFV.mjs";
3
- import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "../../../index-B91ZpOcd.mjs";
2
+ import "../../../types-QKq1usl7.mjs";
3
+ import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "../../../index-BWVAwea4.mjs";
4
4
  export { EnumConstantsGeneratorID, enumConstantsPlugin };
@@ -1,4 +1,4 @@
1
1
  /// <reference path="./../../../user-defined.d.ts" />
2
- import "../../../types-CblXasFV.mjs";
3
- import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "../../../index-DDqKNFh4.mjs";
2
+ import "../../../types-QKq1usl7.mjs";
3
+ import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "../../../index-Dn61THJK.mjs";
4
4
  export { FileUtilsGeneratorID, fileUtilsPlugin };
@@ -1,4 +1,4 @@
1
1
  /// <reference path="./../../../user-defined.d.ts" />
2
- import "../../../types-CblXasFV.mjs";
3
- import { n as kyselyTypePlugin, t as KyselyGeneratorID } from "../../../index-CPzbMghQ.mjs";
2
+ import "../../../types-QKq1usl7.mjs";
3
+ import { n as kyselyTypePlugin, t as KyselyGeneratorID } from "../../../index-oZXVKyfX.mjs";
4
4
  export { KyselyGeneratorID, kyselyTypePlugin };
@@ -1,4 +1,4 @@
1
1
  /// <reference path="./../../../user-defined.d.ts" />
2
- import "../../../types-CblXasFV.mjs";
3
- import { n as seedPlugin, t as SeedGeneratorID } from "../../../index-B6pvy1MK.mjs";
2
+ import "../../../types-QKq1usl7.mjs";
3
+ import { n as seedPlugin, t as SeedGeneratorID } from "../../../index-DxlmLUag.mjs";
4
4
  export { SeedGeneratorID, seedPlugin };
@@ -1,3 +1,3 @@
1
- import { n as seedPlugin, t as SeedGeneratorID } from "../../../seed-CeUEANfQ.mjs";
1
+ import { n as seedPlugin, t as SeedGeneratorID } from "../../../seed-D-rYCN5F.mjs";
2
2
 
3
3
  export { SeedGeneratorID, seedPlugin };
@@ -1,5 +1,5 @@
1
1
  /// <reference path="./../user-defined.d.ts" />
2
- import { Bt as TailorActor, i as TailorAnyDBType, zt as TailorEnv } from "../types-CblXasFV.mjs";
2
+ import { Bt as TailorActor, i as TailorAnyDBType, zt as TailorEnv } from "../types-QKq1usl7.mjs";
3
3
 
4
4
  //#region src/plugin/with-context.d.ts
5
5
 
@@ -1022,7 +1022,7 @@ function seedPlugin(options) {
1022
1022
  dependencies
1023
1023
  });
1024
1024
  }
1025
- const idpUser = ctx.auth ? processIdpUser(ctx.auth) : null;
1025
+ const idpUser = ctx.auth ? processIdpUser(ctx.auth) ?? null : null;
1026
1026
  const hasIdpUser = idpUser !== null;
1027
1027
  if (idpUser) {
1028
1028
  files.push({
@@ -1047,4 +1047,4 @@ function seedPlugin(options) {
1047
1047
 
1048
1048
  //#endregion
1049
1049
  export { seedPlugin as n, SeedGeneratorID as t };
1050
- //# sourceMappingURL=seed-CeUEANfQ.mjs.map
1050
+ //# sourceMappingURL=seed-D-rYCN5F.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"seed-CeUEANfQ.mjs","names":[],"sources":["../src/plugin/builtin/seed/idp-user-processor.ts","../src/plugin/builtin/seed/lines-db-processor.ts","../src/plugin/builtin/seed/seed-type-processor.ts","../src/plugin/builtin/seed/index.ts"],"sourcesContent":["import ml from \"multiline-ts\";\nimport type { GeneratorAuthInput } from \"@/parser/plugin-config/generation-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\n for (let i = 0; i < input.users.length; i++) {\n try {\n await client.createUser(input.users[i]);\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 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 nextToken = undefined;\n const allUsers = [];\n do {\n const response = await client.users(nextToken ? { nextToken } : undefined);\n allUsers.push(...(response.users || []));\n nextToken = response.nextToken;\n } while (nextToken);\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\n/**\n * Generates the schema file content for IdP users with foreign key\n * @param usernameField - Username field name\n * @param userTypeName - TailorDB user type name\n * @returns Schema file contents\n */\nexport function generateIdpUserSchemaFile(usernameField: string, userTypeName: string): string {\n return ml /* ts */ `\n import { t } from \"@tailor-platform/sdk\";\n import { createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { defineSchema } from \"@toiroakr/lines-db\";\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 type)\n const hook = <T>(data: unknown) => data as T;\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),\n {\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 );\n\n `;\n}\n","import ml from \"multiline-ts\";\nimport {\n isPluginGeneratedType,\n type PluginGeneratedTypeSource,\n type TailorDBType,\n type 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 types to generate lines-db metadata\n * @param type - Parsed TailorDB type\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 type\n return processLinesDbForPluginType(type, source);\n }\n\n // User-defined type\n if (!source.filePath) {\n throw new Error(`Missing source info for type ${type.name}`);\n }\n if (!source.exportName) {\n throw new Error(`Missing export name for type ${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 type\n * @param source - Plugin-generated type 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 type\n * @param type - Parsed TailorDB type\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 types with import)\n * @param metadata - lines-db metadata\n * @param importPath - Import path for the TailorDB type\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 { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { defineSchema } from \"@toiroakr/lines-db\";\n import { ${exportName} } from \"${importPath}\";\n\n ${schemaTypeCode}\n\n const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),${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 type 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 original type 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 { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { defineSchema } from \"@toiroakr/lines-db\";\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 const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),${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 { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { defineSchema } from \"@toiroakr/lines-db\";\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 const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),${schemaOptionsCode}\n );\n\n `;\n}\n","import type { SeedTypeInfo } from \"./types\";\nimport type { TailorDBType } from \"@/parser/service/tailordb/types\";\n\n/**\n * Processes TailorDB types to extract seed type information\n * @param type - Parsed TailorDB type\n * @param namespace - Namespace of the type\n * @returns Seed type information\n */\nexport function processSeedTypeInfo(type: TailorDBType, namespace: string): SeedTypeInfo {\n // Extract dependencies from relations (including keyOnly which only sets foreignKeyType)\n const dependencies = Array.from(\n Object.values(type.fields).reduce<Set<string>>((set, field) => {\n const targetType = field.relation?.targetType ?? field.config.foreignKeyType;\n if (targetType && targetType !== type.name) {\n set.add(targetType);\n }\n return set;\n }, new Set<string>()),\n );\n\n return {\n name: type.name,\n namespace,\n dependencies,\n dataFile: `data/${type.name}.jsonl`,\n };\n}\n","import ml from \"multiline-ts\";\nimport * as path from \"pathe\";\nimport {\n processIdpUser,\n generateIdpUserSchemaFile,\n generateIdpSeedScriptCode,\n generateIdpTruncateScriptCode,\n} from \"./idp-user-processor\";\nimport {\n processLinesDb,\n generateLinesDbSchemaFile,\n generateLinesDbSchemaFileWithPluginAPI,\n type PluginSchemaParams,\n} from \"./lines-db-processor\";\nimport { processSeedTypeInfo } from \"./seed-type-processor\";\nimport type {\n GeneratorResult,\n TailorDBReadyContext,\n} from \"@/parser/plugin-config/generation-types\";\nimport type { Plugin } from \"@/parser/plugin-config/types\";\n\nexport const SeedGeneratorID = \"@tailor-platform/seed\";\n\ntype SeedPluginOptions = {\n distPath: string;\n machineUserName?: string;\n};\n\ntype NamespaceConfig = {\n namespace: string;\n types: string[];\n dependencies: Record<string, string[]>;\n};\n\n/**\n * Generate the IdP user seed function code using tailor.idp.Client via testExecScript\n * @param hasIdpUser - Whether IdP user is included\n * @param idpNamespace - The IDP namespace name\n * @returns JavaScript code for IdP user seeding function\n */\nfunction generateIdpUserSeedFunction(hasIdpUser: boolean, idpNamespace: string | null): string {\n if (!hasIdpUser || !idpNamespace) return \"\";\n\n const scriptCode = generateIdpSeedScriptCode(idpNamespace);\n\n return ml`\n // Seed _User via tailor.idp.Client (server-side)\n const seedIdpUser = async () => {\n console.log(styleText(\"cyan\", \" Seeding _User via tailor.idp.Client...\"));\n const dataDir = join(configDir, \"data\");\n const data = loadSeedData(dataDir, [\"_User\"]);\n const rows = data[\"_User\"] || [];\n if (rows.length === 0) {\n console.log(styleText(\"dim\", \" No _User data to seed\"));\n return { success: true };\n }\n console.log(styleText(\"dim\", \\` Processing \\${rows.length} _User records...\\`));\n\n const idpSeedCode = \\/* js *\\/\\`${scriptCode.replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\")}\\`;\n\n const result = await executeScript({\n client: operatorClient,\n workspaceId,\n name: \"seed-idp-user.ts\",\n code: idpSeedCode,\n arg: JSON.stringify({ users: rows }),\n invoker: {\n namespace: authNamespace,\n machineUserName,\n },\n });\n\n if (result.logs) {\n for (const line of result.logs.split(\"\\\\n\").filter(Boolean)) {\n console.log(styleText(\"dim\", \\` \\${line}\\`));\n }\n }\n\n if (result.success) {\n let parsed;\n try {\n parsed = JSON.parse(result.result || \"{}\");\n } catch (e) {\n console.error(styleText(\"red\", \\` ✗ Failed to parse seed result: \\${e.message}\\`));\n return { success: false };\n }\n\n if (parsed.processed) {\n console.log(styleText(\"green\", \\` ✓ _User: \\${parsed.processed} rows processed\\`));\n }\n\n if (!parsed.success) {\n const errors = Array.isArray(parsed.errors) ? parsed.errors : [];\n for (const err of errors) {\n console.error(styleText(\"red\", \\` ✗ \\${err}\\`));\n }\n return { success: false };\n }\n\n return { success: true };\n } else {\n console.error(styleText(\"red\", \\` ✗ Seed failed: \\${result.error}\\`));\n return { success: false };\n }\n };\n `;\n}\n\n/**\n * Generate the IdP user seed call code\n * @param hasIdpUser - Whether IdP user is included\n * @returns JavaScript code for calling IdP user seeding\n */\nfunction generateIdpUserSeedCall(hasIdpUser: boolean): string {\n if (!hasIdpUser) return \"\";\n\n return ml`\n // Seed _User if included and not skipped\n const shouldSeedUser = !skipIdp && (!entitiesToProcess || entitiesToProcess.includes(\"_User\"));\n if (hasIdpUser && shouldSeedUser) {\n const result = await seedIdpUser();\n if (!result.success) {\n allSuccess = false;\n }\n }\n `;\n}\n\n/**\n * Generate the IdP user truncation function code using tailor.idp.Client via testExecScript\n * @param hasIdpUser - Whether IdP user is included\n * @param idpNamespace - The IDP namespace name\n * @returns JavaScript code for IdP user truncation function\n */\nfunction generateIdpUserTruncateFunction(hasIdpUser: boolean, idpNamespace: string | null): string {\n if (!hasIdpUser || !idpNamespace) return \"\";\n\n const scriptCode = generateIdpTruncateScriptCode(idpNamespace);\n\n return ml`\n // Truncate _User via tailor.idp.Client (server-side)\n const truncateIdpUser = async () => {\n console.log(styleText(\"cyan\", \"Truncating _User via tailor.idp.Client...\"));\n\n const idpTruncateCode = \\/* js *\\/\\`${scriptCode.replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\")}\\`;\n\n const result = await executeScript({\n client: operatorClient,\n workspaceId,\n name: \"truncate-idp-user.ts\",\n code: idpTruncateCode,\n arg: JSON.stringify({}),\n invoker: {\n namespace: authNamespace,\n machineUserName,\n },\n });\n\n if (result.logs) {\n for (const line of result.logs.split(\"\\\\n\").filter(Boolean)) {\n console.log(styleText(\"dim\", \\` \\${line}\\`));\n }\n }\n\n if (result.success) {\n let parsed;\n try {\n parsed = JSON.parse(result.result || \"{}\");\n } catch (e) {\n console.error(styleText(\"red\", \\` ✗ Failed to parse truncation result: \\${e.message}\\`));\n return { success: false };\n }\n\n if (parsed.deleted !== undefined) {\n console.log(styleText(\"green\", \\` ✓ _User: \\${parsed.deleted} users deleted\\`));\n }\n\n if (!parsed.success) {\n const errors = Array.isArray(parsed.errors) ? parsed.errors : [];\n for (const err of errors) {\n console.error(styleText(\"red\", \\` ✗ \\${err}\\`));\n }\n return { success: false };\n }\n\n return { success: true };\n } else {\n console.error(styleText(\"red\", \\` ✗ Truncation failed: \\${result.error}\\`));\n return { success: false };\n }\n };\n `;\n}\n\n/**\n * Generate the IdP user truncation call code within the truncate block\n * @param hasIdpUser - Whether IdP user is included\n * @returns JavaScript code for calling IdP user truncation\n */\nfunction generateIdpUserTruncateCall(hasIdpUser: boolean): string {\n if (!hasIdpUser) return \"\";\n\n return ml`\n // Truncate _User if applicable\n const shouldTruncateUser = !skipIdp && !hasNamespace && (!hasTypes || entitiesToProcess.includes(\"_User\"));\n if (hasIdpUser && shouldTruncateUser) {\n const truncResult = await truncateIdpUser();\n if (!truncResult.success) {\n console.error(styleText(\"red\", \"IDP user truncation failed.\"));\n process.exit(1);\n }\n }\n `;\n}\n\n/**\n * Generates the exec.mjs script content using testExecScript API for TailorDB types\n * and tailor.idp.Client for _User (IdP managed)\n * @param defaultMachineUserName - Default machine user name from generator config (can be overridden at runtime)\n * @param relativeConfigPath - Config path relative to exec script\n * @param namespaceConfigs - Namespace configurations with types and dependencies\n * @param hasIdpUser - Whether _User is included\n * @param idpNamespace - The IDP namespace name, or null if not applicable\n * @returns exec.mjs file contents\n */\nfunction generateExecScript(\n defaultMachineUserName: string | undefined,\n relativeConfigPath: string,\n namespaceConfigs: NamespaceConfig[],\n hasIdpUser: boolean,\n idpNamespace: string | null,\n): string {\n // Generate namespaceEntities object\n const namespaceEntitiesEntries = namespaceConfigs\n .map(({ namespace, types }) => {\n const entitiesFormatted = types.map((e) => ` \"${e}\",`).join(\"\\n\");\n return ` \"${namespace}\": [\\n${entitiesFormatted}\\n ]`;\n })\n .join(\",\\n\");\n\n // Generate dependency map for each namespace\n const namespaceDepsEntries = namespaceConfigs\n .map(({ namespace, dependencies }) => {\n const depsObj = Object.entries(dependencies)\n .map(([type, deps]) => ` \"${type}\": [${deps.map((d) => `\"${d}\"`).join(\", \")}]`)\n .join(\",\\n\");\n return ` \"${namespace}\": {\\n${depsObj}\\n }`;\n })\n .join(\",\\n\");\n\n return ml /* js */ `\n import { readFileSync } from \"node:fs\";\n import { join } from \"node:path\";\n import { parseArgs, styleText } from \"node:util\";\n import { createInterface } from \"node:readline\";\n import {\n show,\n truncate,\n bundleSeedScript,\n chunkSeedData,\n executeScript,\n initOperatorClient,\n loadAccessToken,\n loadWorkspaceId,\n } from \"@tailor-platform/sdk/cli\";\n\n // Parse command-line arguments\n const { values, positionals } = parseArgs({\n options: {\n \"machine-user\": { type: \"string\", short: \"m\" },\n namespace: { type: \"string\", short: \"n\" },\n \"skip-idp\": { type: \"boolean\", default: false },\n truncate: { type: \"boolean\", default: false },\n yes: { type: \"boolean\", default: false },\n profile: { type: \"string\", short: \"p\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n allowPositionals: true,\n });\n\n if (values.help) {\n console.log(\\`\n Usage: node exec.mjs [options] [types...]\n\n Options:\n -m, --machine-user <name> Machine user name for authentication (required if not configured)\n -n, --namespace <ns> Process all types in specified namespace (excludes _User)\n --skip-idp Skip IdP user (_User) entity\n --truncate Truncate tables before seeding\n --yes Skip confirmation prompts (for truncate)\n -p, --profile <name> Workspace profile name\n -h, --help Show help\n\n Examples:\n node exec.mjs -m admin # Process all types with machine user\n node exec.mjs --namespace <namespace> # Process tailordb namespace only (no _User)\n node exec.mjs User Order # Process specific types only\n node exec.mjs --skip-idp # Process all except _User\n node exec.mjs --truncate # Truncate all tables, then seed all\n node exec.mjs --truncate --yes # Truncate all tables without confirmation, then seed all\n node exec.mjs --truncate --namespace <namespace> # Truncate tailordb, then seed tailordb\n node exec.mjs --truncate User Order # Truncate User and Order, then seed them\n \\`);\n process.exit(0);\n }\n\n // Helper function to prompt for y/n confirmation\n const promptConfirmation = (question) => {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(styleText(\"yellow\", question), (answer) => {\n rl.close();\n resolve(answer.toLowerCase().trim());\n });\n });\n };\n\n const configDir = import.meta.dirname;\n const configPath = join(configDir, \"${relativeConfigPath}\");\n\n // Determine machine user name (CLI argument takes precedence over config default)\n const defaultMachineUser = ${defaultMachineUserName ? `\"${defaultMachineUserName}\"` : \"undefined\"};\n const machineUserName = values[\"machine-user\"] || defaultMachineUser;\n\n if (!machineUserName) {\n console.error(styleText(\"red\", \"Error: Machine user name is required.\"));\n console.error(styleText(\"yellow\", \"Specify --machine-user <name> or configure machineUserName in generator options.\"));\n process.exit(1);\n }\n\n // Entity configuration\n const namespaceEntities = {\n${namespaceEntitiesEntries}\n };\n const namespaceDeps = {\n${namespaceDepsEntries}\n };\n const entities = Object.values(namespaceEntities).flat();\n const hasIdpUser = ${String(hasIdpUser)};\n\n // Determine which entities to process\n let entitiesToProcess = null;\n\n const hasNamespace = !!values.namespace;\n const hasTypes = positionals.length > 0;\n const skipIdp = values[\"skip-idp\"];\n\n // Validate mutually exclusive options\n const optionCount = [hasNamespace, hasTypes].filter(Boolean).length;\n if (optionCount > 1) {\n console.error(styleText(\"red\", \"Error: Options --namespace and type names are mutually exclusive.\"));\n process.exit(1);\n }\n\n // --skip-idp and --namespace are redundant (namespace already excludes _User)\n if (skipIdp && hasNamespace) {\n console.warn(styleText(\"yellow\", \"Warning: --skip-idp is redundant with --namespace (namespace filtering already excludes _User).\"));\n }\n\n // Filter by namespace (automatically excludes _User as it has no namespace)\n if (hasNamespace) {\n const namespace = values.namespace;\n entitiesToProcess = namespaceEntities[namespace];\n\n if (!entitiesToProcess || entitiesToProcess.length === 0) {\n console.error(styleText(\"red\", \\`Error: No entities found in namespace \"\\${namespace}\"\\`));\n console.error(styleText(\"yellow\", \\`Available namespaces: \\${Object.keys(namespaceEntities).join(\", \")}\\`));\n process.exit(1);\n }\n\n console.log(styleText(\"cyan\", \\`Filtering by namespace: \\${namespace}\\`));\n console.log(styleText(\"dim\", \\`Entities: \\${entitiesToProcess.join(\", \")}\\`));\n }\n\n // Filter by specific types\n if (hasTypes) {\n const requestedTypes = positionals;\n const notFoundTypes = [];\n const allTypes = hasIdpUser ? [...entities, \"_User\"] : entities;\n\n entitiesToProcess = requestedTypes.filter((type) => {\n if (!allTypes.includes(type)) {\n notFoundTypes.push(type);\n return false;\n }\n return true;\n });\n\n if (notFoundTypes.length > 0) {\n console.error(styleText(\"red\", \\`Error: The following types were not found: \\${notFoundTypes.join(\", \")}\\`));\n console.error(styleText(\"yellow\", \\`Available types: \\${allTypes.join(\", \")}\\`));\n process.exit(1);\n }\n\n console.log(styleText(\"cyan\", \\`Filtering by types: \\${entitiesToProcess.join(\", \")}\\`));\n }\n\n // Apply --skip-idp filter\n if (skipIdp) {\n if (entitiesToProcess) {\n entitiesToProcess = entitiesToProcess.filter((entity) => entity !== \"_User\");\n } else {\n entitiesToProcess = entities.filter((entity) => entity !== \"_User\");\n }\n }\n\n // Get application info\n const appInfo = await show({ configPath, profile: values.profile });\n const authNamespace = appInfo.auth;\n\n // Initialize operator client (once for all namespaces)\n const accessToken = await loadAccessToken({ profile: values.profile, useProfile: true });\n const workspaceId = await loadWorkspaceId({ profile: values.profile });\n const operatorClient = await initOperatorClient(accessToken);\n\n ${generateIdpUserTruncateFunction(hasIdpUser, idpNamespace)}\n\n // Truncate tables if requested\n if (values.truncate) {\n const answer = values.yes ? \"y\" : await promptConfirmation(\"Are you sure you want to truncate? (y/n): \");\n if (answer !== \"y\") {\n console.log(styleText(\"yellow\", \"Truncate cancelled.\"));\n process.exit(0);\n }\n\n console.log(styleText(\"cyan\", \"Truncating tables...\"));\n\n try {\n if (hasNamespace) {\n await truncate({\n configPath,\n profile: values.profile,\n namespace: values.namespace,\n });\n } else if (hasTypes) {\n const typesToTruncate = entitiesToProcess.filter((t) => t !== \"_User\");\n if (typesToTruncate.length > 0) {\n await truncate({\n configPath,\n profile: values.profile,\n types: typesToTruncate,\n });\n } else {\n console.log(styleText(\"dim\", \"No TailorDB types to truncate (only _User was specified).\"));\n }\n } else {\n await truncate({\n configPath,\n profile: values.profile,\n all: true,\n });\n }\n } catch (error) {\n console.error(styleText(\"red\", \\`Truncate failed: \\${error.message}\\`));\n process.exit(1);\n }\n\n ${generateIdpUserTruncateCall(hasIdpUser)}\n\n console.log(styleText(\"green\", \"Truncate completed.\"));\n }\n\n console.log(styleText(\"cyan\", \"\\\\nStarting seed data generation...\"));\n if (skipIdp) {\n console.log(styleText(\"dim\", \\` Skipping IdP user (_User)\\`));\n }\n\n // Load seed data from JSONL files\n const loadSeedData = (dataDir, typeNames) => {\n const data = {};\n for (const typeName of typeNames) {\n const jsonlPath = join(dataDir, \\`\\${typeName}.jsonl\\`);\n try {\n const content = readFileSync(jsonlPath, \"utf-8\").trim();\n if (content) {\n data[typeName] = content.split(\"\\\\n\").map((line) => JSON.parse(line));\n } else {\n data[typeName] = [];\n }\n } catch (error) {\n if (error.code === \"ENOENT\") {\n data[typeName] = [];\n } else {\n throw error;\n }\n }\n }\n return data;\n };\n\n // Topological sort for dependency order\n const topologicalSort = (types, deps) => {\n const visited = new Set();\n const result = [];\n\n const visit = (type) => {\n if (visited.has(type)) return;\n visited.add(type);\n const typeDeps = deps[type] || [];\n for (const dep of typeDeps) {\n if (types.includes(dep)) {\n visit(dep);\n }\n }\n result.push(type);\n };\n\n for (const type of types) {\n visit(type);\n }\n return result;\n };\n\n // Seed TailorDB types via testExecScript\n const seedViaTestExecScript = async (namespace, typesToSeed, deps) => {\n const dataDir = join(configDir, \"data\");\n const sortedTypes = topologicalSort(typesToSeed, deps);\n const data = loadSeedData(dataDir, sortedTypes);\n\n // Skip if no data\n const typesWithData = sortedTypes.filter((t) => data[t] && data[t].length > 0);\n if (typesWithData.length === 0) {\n console.log(styleText(\"dim\", \\` [\\${namespace}] No data to seed\\`));\n return { success: true, processed: {} };\n }\n\n console.log(styleText(\"cyan\", \\` [\\${namespace}] Seeding \\${typesWithData.length} types via Kysely batch insert...\\`));\n\n // Bundle seed script\n const bundled = await bundleSeedScript(namespace, typesWithData);\n\n // Chunk seed data to fit within gRPC message size limits\n const chunks = chunkSeedData({\n data,\n order: sortedTypes,\n codeByteSize: new TextEncoder().encode(bundled.bundledCode).length,\n });\n\n if (chunks.length === 0) {\n console.log(styleText(\"dim\", \\` [\\${namespace}] No data to seed\\`));\n return { success: true, processed: {} };\n }\n\n if (chunks.length > 1) {\n console.log(styleText(\"dim\", \\` Split into \\${chunks.length} chunks\\`));\n }\n\n const allProcessed = {};\n let hasError = false;\n const allErrors = [];\n\n for (const chunk of chunks) {\n if (chunks.length > 1) {\n console.log(styleText(\"dim\", \\` Chunk \\${chunk.index + 1}/\\${chunk.total}: \\${chunk.order.join(\", \")}\\`));\n }\n\n // Execute seed script for this chunk\n const result = await executeScript({\n client: operatorClient,\n workspaceId,\n name: \\`seed-\\${namespace}.ts\\`,\n code: bundled.bundledCode,\n arg: JSON.stringify({ data: chunk.data, order: chunk.order }),\n invoker: {\n namespace: authNamespace,\n machineUserName,\n },\n });\n\n // Parse result and display logs\n if (result.logs) {\n for (const line of result.logs.split(\"\\\\n\").filter(Boolean)) {\n console.log(styleText(\"dim\", \\` \\${line}\\`));\n }\n }\n\n if (result.success) {\n let parsed;\n try {\n const parsedResult = JSON.parse(result.result || \"{}\");\n parsed = parsedResult && typeof parsedResult === \"object\" ? parsedResult : {};\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(styleText(\"red\", \\` ✗ Failed to parse seed result: \\${message}\\`));\n hasError = true;\n allErrors.push(message);\n continue;\n }\n\n const processed = parsed.processed || {};\n for (const [type, count] of Object.entries(processed)) {\n allProcessed[type] = (allProcessed[type] || 0) + count;\n console.log(styleText(\"green\", \\` ✓ \\${type}: \\${count} rows inserted\\`));\n }\n\n if (!parsed.success) {\n const errors = Array.isArray(parsed.errors) ? parsed.errors : [];\n const errorMessage =\n errors.length > 0 ? errors.join(\"\\\\n \") : \"Seed script reported failure\";\n console.error(styleText(\"red\", \\` ✗ Seed failed:\\\\n \\${errorMessage}\\`));\n hasError = true;\n allErrors.push(errorMessage);\n }\n } else {\n console.error(styleText(\"red\", \\` ✗ Seed failed: \\${result.error}\\`));\n hasError = true;\n allErrors.push(result.error);\n }\n }\n\n if (hasError) {\n return { success: false, error: allErrors.join(\"\\\\n\") };\n }\n return { success: true, processed: allProcessed };\n };\n\n ${generateIdpUserSeedFunction(hasIdpUser, idpNamespace)}\n\n // Main execution\n try {\n let allSuccess = true;\n\n // Determine which namespaces and types to process\n const namespacesToProcess = hasNamespace\n ? [values.namespace]\n : Object.keys(namespaceEntities);\n\n for (const namespace of namespacesToProcess) {\n const nsTypes = namespaceEntities[namespace] || [];\n const nsDeps = namespaceDeps[namespace] || {};\n\n // Filter types if specific types requested\n let typesToSeed = entitiesToProcess\n ? nsTypes.filter((t) => entitiesToProcess.includes(t))\n : nsTypes;\n\n if (typesToSeed.length === 0) continue;\n\n const result = await seedViaTestExecScript(namespace, typesToSeed, nsDeps);\n if (!result.success) {\n allSuccess = false;\n }\n }\n\n ${generateIdpUserSeedCall(hasIdpUser)}\n\n if (allSuccess) {\n console.log(styleText(\"green\", \"\\\\n✓ Seed data generation completed successfully\"));\n } else {\n console.error(styleText(\"red\", \"\\\\n✗ Seed data generation completed with errors\"));\n process.exit(1);\n }\n } catch (error) {\n console.error(styleText(\"red\", \\`\\\\n✗ Seed data generation failed: \\${error.message}\\`));\n process.exit(1);\n }\n\n `;\n}\n\n/**\n * Plugin that generates seed data files with Kysely batch insert and tailor.idp.Client for _User.\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 * @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 files (Kysely batch insert + tailor.idp.Client for _User)\",\n pluginConfig: options,\n\n async onTailorDBReady(ctx: TailorDBReadyContext<SeedPluginOptions>): Promise<GeneratorResult> {\n const files: GeneratorResult[\"files\"] = [];\n const namespaceConfigs: NamespaceConfig[] = [];\n\n for (const ns of ctx.tailordb) {\n const types: string[] = [];\n const dependencies: Record<string, string[]> = {};\n\n for (const [typeName, type] of Object.entries(ns.types)) {\n const source = ns.sourceInfo.get(typeName)!;\n const typeInfo = processSeedTypeInfo(type, ns.namespace);\n const linesDb = processLinesDb(type, source);\n\n types.push(typeInfo.name);\n dependencies[typeInfo.name] = typeInfo.dependencies;\n\n // Generate empty JSONL data file\n files.push({\n path: path.join(ctx.pluginConfig.distPath, typeInfo.dataFile),\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 namespaceConfigs.push({\n namespace: ns.namespace,\n types,\n dependencies,\n });\n }\n\n // Process IdP user if configured\n const idpUser = ctx.auth ? processIdpUser(ctx.auth) : null;\n const hasIdpUser = idpUser !== null;\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\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"data\", `${idpUser.name}.schema.ts`),\n content: generateIdpUserSchemaFile(\n idpUser.schema.usernameField,\n idpUser.schema.userTypeName,\n ),\n });\n }\n\n // Generate exec.mjs (machineUserName can be provided at runtime if not configured)\n const relativeConfigPath = path.relative(ctx.pluginConfig.distPath, ctx.configPath);\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"exec.mjs\"),\n content: generateExecScript(\n ctx.pluginConfig.machineUserName,\n relativeConfigPath,\n namespaceConfigs,\n hasIdpUser,\n idpUser?.idpNamespace ?? null,\n ),\n });\n\n return { files };\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"seed-D-rYCN5F.mjs","names":[],"sources":["../src/plugin/builtin/seed/idp-user-processor.ts","../src/plugin/builtin/seed/lines-db-processor.ts","../src/plugin/builtin/seed/seed-type-processor.ts","../src/plugin/builtin/seed/index.ts"],"sourcesContent":["import ml from \"multiline-ts\";\nimport type { GeneratorAuthInput } from \"@/parser/plugin-config/generation-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\n for (let i = 0; i < input.users.length; i++) {\n try {\n await client.createUser(input.users[i]);\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 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 nextToken = undefined;\n const allUsers = [];\n do {\n const response = await client.users(nextToken ? { nextToken } : undefined);\n allUsers.push(...(response.users || []));\n nextToken = response.nextToken;\n } while (nextToken);\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\n/**\n * Generates the schema file content for IdP users with foreign key\n * @param usernameField - Username field name\n * @param userTypeName - TailorDB user type name\n * @returns Schema file contents\n */\nexport function generateIdpUserSchemaFile(usernameField: string, userTypeName: string): string {\n return ml /* ts */ `\n import { t } from \"@tailor-platform/sdk\";\n import { createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { defineSchema } from \"@toiroakr/lines-db\";\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 type)\n const hook = <T>(data: unknown) => data as T;\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),\n {\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 );\n\n `;\n}\n","import ml from \"multiline-ts\";\nimport {\n isPluginGeneratedType,\n type PluginGeneratedTypeSource,\n type TailorDBType,\n type 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 types to generate lines-db metadata\n * @param type - Parsed TailorDB type\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 type\n return processLinesDbForPluginType(type, source);\n }\n\n // User-defined type\n if (!source.filePath) {\n throw new Error(`Missing source info for type ${type.name}`);\n }\n if (!source.exportName) {\n throw new Error(`Missing export name for type ${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 type\n * @param source - Plugin-generated type 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 type\n * @param type - Parsed TailorDB type\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 types with import)\n * @param metadata - lines-db metadata\n * @param importPath - Import path for the TailorDB type\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 { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { defineSchema } from \"@toiroakr/lines-db\";\n import { ${exportName} } from \"${importPath}\";\n\n ${schemaTypeCode}\n\n const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),${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 type 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 original type 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 { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { defineSchema } from \"@toiroakr/lines-db\";\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 const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),${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 { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { defineSchema } from \"@toiroakr/lines-db\";\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 const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),${schemaOptionsCode}\n );\n\n `;\n}\n","import type { SeedTypeInfo } from \"./types\";\nimport type { TailorDBType } from \"@/parser/service/tailordb/types\";\n\n/**\n * Processes TailorDB types to extract seed type information\n * @param type - Parsed TailorDB type\n * @param namespace - Namespace of the type\n * @returns Seed type information\n */\nexport function processSeedTypeInfo(type: TailorDBType, namespace: string): SeedTypeInfo {\n // Extract dependencies from relations (including keyOnly which only sets foreignKeyType)\n const dependencies = Array.from(\n Object.values(type.fields).reduce<Set<string>>((set, field) => {\n const targetType = field.relation?.targetType ?? field.config.foreignKeyType;\n if (targetType && targetType !== type.name) {\n set.add(targetType);\n }\n return set;\n }, new Set<string>()),\n );\n\n return {\n name: type.name,\n namespace,\n dependencies,\n dataFile: `data/${type.name}.jsonl`,\n };\n}\n","import ml from \"multiline-ts\";\nimport * as path from \"pathe\";\nimport {\n processIdpUser,\n generateIdpUserSchemaFile,\n generateIdpSeedScriptCode,\n generateIdpTruncateScriptCode,\n} from \"./idp-user-processor\";\nimport {\n processLinesDb,\n generateLinesDbSchemaFile,\n generateLinesDbSchemaFileWithPluginAPI,\n type PluginSchemaParams,\n} from \"./lines-db-processor\";\nimport { processSeedTypeInfo } from \"./seed-type-processor\";\nimport type {\n GeneratorResult,\n TailorDBReadyContext,\n} from \"@/parser/plugin-config/generation-types\";\nimport type { Plugin } from \"@/parser/plugin-config/types\";\n\nexport const SeedGeneratorID = \"@tailor-platform/seed\";\n\ntype SeedPluginOptions = {\n distPath: string;\n machineUserName?: string;\n};\n\ntype NamespaceConfig = {\n namespace: string;\n types: string[];\n dependencies: Record<string, string[]>;\n};\n\n/**\n * Generate the IdP user seed function code using tailor.idp.Client via testExecScript\n * @param hasIdpUser - Whether IdP user is included\n * @param idpNamespace - The IDP namespace name\n * @returns JavaScript code for IdP user seeding function\n */\nfunction generateIdpUserSeedFunction(hasIdpUser: boolean, idpNamespace: string | null): string {\n if (!hasIdpUser || !idpNamespace) return \"\";\n\n const scriptCode = generateIdpSeedScriptCode(idpNamespace);\n\n return ml`\n // Seed _User via tailor.idp.Client (server-side)\n const seedIdpUser = async () => {\n console.log(styleText(\"cyan\", \" Seeding _User via tailor.idp.Client...\"));\n const dataDir = join(configDir, \"data\");\n const data = loadSeedData(dataDir, [\"_User\"]);\n const rows = data[\"_User\"] || [];\n if (rows.length === 0) {\n console.log(styleText(\"dim\", \" No _User data to seed\"));\n return { success: true };\n }\n console.log(styleText(\"dim\", \\` Processing \\${rows.length} _User records...\\`));\n\n const idpSeedCode = \\/* js *\\/\\`${scriptCode.replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\")}\\`;\n\n const result = await executeScript({\n client: operatorClient,\n workspaceId,\n name: \"seed-idp-user.ts\",\n code: idpSeedCode,\n arg: JSON.stringify({ users: rows }),\n invoker: {\n namespace: authNamespace,\n machineUserName,\n },\n });\n\n if (result.logs) {\n for (const line of result.logs.split(\"\\\\n\").filter(Boolean)) {\n console.log(styleText(\"dim\", \\` \\${line}\\`));\n }\n }\n\n if (result.success) {\n let parsed;\n try {\n parsed = JSON.parse(result.result || \"{}\");\n } catch (e) {\n console.error(styleText(\"red\", \\` ✗ Failed to parse seed result: \\${e.message}\\`));\n return { success: false };\n }\n\n if (parsed.processed) {\n console.log(styleText(\"green\", \\` ✓ _User: \\${parsed.processed} rows processed\\`));\n }\n\n if (!parsed.success) {\n const errors = Array.isArray(parsed.errors) ? parsed.errors : [];\n for (const err of errors) {\n console.error(styleText(\"red\", \\` ✗ \\${err}\\`));\n }\n return { success: false };\n }\n\n return { success: true };\n } else {\n console.error(styleText(\"red\", \\` ✗ Seed failed: \\${result.error}\\`));\n return { success: false };\n }\n };\n `;\n}\n\n/**\n * Generate the IdP user seed call code\n * @param hasIdpUser - Whether IdP user is included\n * @returns JavaScript code for calling IdP user seeding\n */\nfunction generateIdpUserSeedCall(hasIdpUser: boolean): string {\n if (!hasIdpUser) return \"\";\n\n return ml`\n // Seed _User if included and not skipped\n const shouldSeedUser = !skipIdp && (!entitiesToProcess || entitiesToProcess.includes(\"_User\"));\n if (hasIdpUser && shouldSeedUser) {\n const result = await seedIdpUser();\n if (!result.success) {\n allSuccess = false;\n }\n }\n `;\n}\n\n/**\n * Generate the IdP user truncation function code using tailor.idp.Client via testExecScript\n * @param hasIdpUser - Whether IdP user is included\n * @param idpNamespace - The IDP namespace name\n * @returns JavaScript code for IdP user truncation function\n */\nfunction generateIdpUserTruncateFunction(hasIdpUser: boolean, idpNamespace: string | null): string {\n if (!hasIdpUser || !idpNamespace) return \"\";\n\n const scriptCode = generateIdpTruncateScriptCode(idpNamespace);\n\n return ml`\n // Truncate _User via tailor.idp.Client (server-side)\n const truncateIdpUser = async () => {\n console.log(styleText(\"cyan\", \"Truncating _User via tailor.idp.Client...\"));\n\n const idpTruncateCode = \\/* js *\\/\\`${scriptCode.replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\")}\\`;\n\n const result = await executeScript({\n client: operatorClient,\n workspaceId,\n name: \"truncate-idp-user.ts\",\n code: idpTruncateCode,\n arg: JSON.stringify({}),\n invoker: {\n namespace: authNamespace,\n machineUserName,\n },\n });\n\n if (result.logs) {\n for (const line of result.logs.split(\"\\\\n\").filter(Boolean)) {\n console.log(styleText(\"dim\", \\` \\${line}\\`));\n }\n }\n\n if (result.success) {\n let parsed;\n try {\n parsed = JSON.parse(result.result || \"{}\");\n } catch (e) {\n console.error(styleText(\"red\", \\` ✗ Failed to parse truncation result: \\${e.message}\\`));\n return { success: false };\n }\n\n if (parsed.deleted !== undefined) {\n console.log(styleText(\"green\", \\` ✓ _User: \\${parsed.deleted} users deleted\\`));\n }\n\n if (!parsed.success) {\n const errors = Array.isArray(parsed.errors) ? parsed.errors : [];\n for (const err of errors) {\n console.error(styleText(\"red\", \\` ✗ \\${err}\\`));\n }\n return { success: false };\n }\n\n return { success: true };\n } else {\n console.error(styleText(\"red\", \\` ✗ Truncation failed: \\${result.error}\\`));\n return { success: false };\n }\n };\n `;\n}\n\n/**\n * Generate the IdP user truncation call code within the truncate block\n * @param hasIdpUser - Whether IdP user is included\n * @returns JavaScript code for calling IdP user truncation\n */\nfunction generateIdpUserTruncateCall(hasIdpUser: boolean): string {\n if (!hasIdpUser) return \"\";\n\n return ml`\n // Truncate _User if applicable\n const shouldTruncateUser = !skipIdp && !hasNamespace && (!hasTypes || entitiesToProcess.includes(\"_User\"));\n if (hasIdpUser && shouldTruncateUser) {\n const truncResult = await truncateIdpUser();\n if (!truncResult.success) {\n console.error(styleText(\"red\", \"IDP user truncation failed.\"));\n process.exit(1);\n }\n }\n `;\n}\n\n/**\n * Generates the exec.mjs script content using testExecScript API for TailorDB types\n * and tailor.idp.Client for _User (IdP managed)\n * @param defaultMachineUserName - Default machine user name from generator config (can be overridden at runtime)\n * @param relativeConfigPath - Config path relative to exec script\n * @param namespaceConfigs - Namespace configurations with types and dependencies\n * @param hasIdpUser - Whether _User is included\n * @param idpNamespace - The IDP namespace name, or null if not applicable\n * @returns exec.mjs file contents\n */\nfunction generateExecScript(\n defaultMachineUserName: string | undefined,\n relativeConfigPath: string,\n namespaceConfigs: NamespaceConfig[],\n hasIdpUser: boolean,\n idpNamespace: string | null,\n): string {\n // Generate namespaceEntities object\n const namespaceEntitiesEntries = namespaceConfigs\n .map(({ namespace, types }) => {\n const entitiesFormatted = types.map((e) => ` \"${e}\",`).join(\"\\n\");\n return ` \"${namespace}\": [\\n${entitiesFormatted}\\n ]`;\n })\n .join(\",\\n\");\n\n // Generate dependency map for each namespace\n const namespaceDepsEntries = namespaceConfigs\n .map(({ namespace, dependencies }) => {\n const depsObj = Object.entries(dependencies)\n .map(([type, deps]) => ` \"${type}\": [${deps.map((d) => `\"${d}\"`).join(\", \")}]`)\n .join(\",\\n\");\n return ` \"${namespace}\": {\\n${depsObj}\\n }`;\n })\n .join(\",\\n\");\n\n return ml /* js */ `\n import { readFileSync } from \"node:fs\";\n import { join } from \"node:path\";\n import { parseArgs, styleText } from \"node:util\";\n import { createInterface } from \"node:readline\";\n import {\n show,\n truncate,\n bundleSeedScript,\n chunkSeedData,\n executeScript,\n initOperatorClient,\n loadAccessToken,\n loadWorkspaceId,\n } from \"@tailor-platform/sdk/cli\";\n\n // Parse command-line arguments\n const { values, positionals } = parseArgs({\n options: {\n \"machine-user\": { type: \"string\", short: \"m\" },\n namespace: { type: \"string\", short: \"n\" },\n \"skip-idp\": { type: \"boolean\", default: false },\n truncate: { type: \"boolean\", default: false },\n yes: { type: \"boolean\", default: false },\n profile: { type: \"string\", short: \"p\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n allowPositionals: true,\n });\n\n if (values.help) {\n console.log(\\`\n Usage: node exec.mjs [options] [types...]\n\n Options:\n -m, --machine-user <name> Machine user name for authentication (required if not configured)\n -n, --namespace <ns> Process all types in specified namespace (excludes _User)\n --skip-idp Skip IdP user (_User) entity\n --truncate Truncate tables before seeding\n --yes Skip confirmation prompts (for truncate)\n -p, --profile <name> Workspace profile name\n -h, --help Show help\n\n Examples:\n node exec.mjs -m admin # Process all types with machine user\n node exec.mjs --namespace <namespace> # Process tailordb namespace only (no _User)\n node exec.mjs User Order # Process specific types only\n node exec.mjs --skip-idp # Process all except _User\n node exec.mjs --truncate # Truncate all tables, then seed all\n node exec.mjs --truncate --yes # Truncate all tables without confirmation, then seed all\n node exec.mjs --truncate --namespace <namespace> # Truncate tailordb, then seed tailordb\n node exec.mjs --truncate User Order # Truncate User and Order, then seed them\n \\`);\n process.exit(0);\n }\n\n // Helper function to prompt for y/n confirmation\n const promptConfirmation = (question) => {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(styleText(\"yellow\", question), (answer) => {\n rl.close();\n resolve(answer.toLowerCase().trim());\n });\n });\n };\n\n const configDir = import.meta.dirname;\n const configPath = join(configDir, \"${relativeConfigPath}\");\n\n // Determine machine user name (CLI argument takes precedence over config default)\n const defaultMachineUser = ${defaultMachineUserName ? `\"${defaultMachineUserName}\"` : \"undefined\"};\n const machineUserName = values[\"machine-user\"] || defaultMachineUser;\n\n if (!machineUserName) {\n console.error(styleText(\"red\", \"Error: Machine user name is required.\"));\n console.error(styleText(\"yellow\", \"Specify --machine-user <name> or configure machineUserName in generator options.\"));\n process.exit(1);\n }\n\n // Entity configuration\n const namespaceEntities = {\n${namespaceEntitiesEntries}\n };\n const namespaceDeps = {\n${namespaceDepsEntries}\n };\n const entities = Object.values(namespaceEntities).flat();\n const hasIdpUser = ${String(hasIdpUser)};\n\n // Determine which entities to process\n let entitiesToProcess = null;\n\n const hasNamespace = !!values.namespace;\n const hasTypes = positionals.length > 0;\n const skipIdp = values[\"skip-idp\"];\n\n // Validate mutually exclusive options\n const optionCount = [hasNamespace, hasTypes].filter(Boolean).length;\n if (optionCount > 1) {\n console.error(styleText(\"red\", \"Error: Options --namespace and type names are mutually exclusive.\"));\n process.exit(1);\n }\n\n // --skip-idp and --namespace are redundant (namespace already excludes _User)\n if (skipIdp && hasNamespace) {\n console.warn(styleText(\"yellow\", \"Warning: --skip-idp is redundant with --namespace (namespace filtering already excludes _User).\"));\n }\n\n // Filter by namespace (automatically excludes _User as it has no namespace)\n if (hasNamespace) {\n const namespace = values.namespace;\n entitiesToProcess = namespaceEntities[namespace];\n\n if (!entitiesToProcess || entitiesToProcess.length === 0) {\n console.error(styleText(\"red\", \\`Error: No entities found in namespace \"\\${namespace}\"\\`));\n console.error(styleText(\"yellow\", \\`Available namespaces: \\${Object.keys(namespaceEntities).join(\", \")}\\`));\n process.exit(1);\n }\n\n console.log(styleText(\"cyan\", \\`Filtering by namespace: \\${namespace}\\`));\n console.log(styleText(\"dim\", \\`Entities: \\${entitiesToProcess.join(\", \")}\\`));\n }\n\n // Filter by specific types\n if (hasTypes) {\n const requestedTypes = positionals;\n const notFoundTypes = [];\n const allTypes = hasIdpUser ? [...entities, \"_User\"] : entities;\n\n entitiesToProcess = requestedTypes.filter((type) => {\n if (!allTypes.includes(type)) {\n notFoundTypes.push(type);\n return false;\n }\n return true;\n });\n\n if (notFoundTypes.length > 0) {\n console.error(styleText(\"red\", \\`Error: The following types were not found: \\${notFoundTypes.join(\", \")}\\`));\n console.error(styleText(\"yellow\", \\`Available types: \\${allTypes.join(\", \")}\\`));\n process.exit(1);\n }\n\n console.log(styleText(\"cyan\", \\`Filtering by types: \\${entitiesToProcess.join(\", \")}\\`));\n }\n\n // Apply --skip-idp filter\n if (skipIdp) {\n if (entitiesToProcess) {\n entitiesToProcess = entitiesToProcess.filter((entity) => entity !== \"_User\");\n } else {\n entitiesToProcess = entities.filter((entity) => entity !== \"_User\");\n }\n }\n\n // Get application info\n const appInfo = await show({ configPath, profile: values.profile });\n const authNamespace = appInfo.auth;\n\n // Initialize operator client (once for all namespaces)\n const accessToken = await loadAccessToken({ profile: values.profile, useProfile: true });\n const workspaceId = await loadWorkspaceId({ profile: values.profile });\n const operatorClient = await initOperatorClient(accessToken);\n\n ${generateIdpUserTruncateFunction(hasIdpUser, idpNamespace)}\n\n // Truncate tables if requested\n if (values.truncate) {\n const answer = values.yes ? \"y\" : await promptConfirmation(\"Are you sure you want to truncate? (y/n): \");\n if (answer !== \"y\") {\n console.log(styleText(\"yellow\", \"Truncate cancelled.\"));\n process.exit(0);\n }\n\n console.log(styleText(\"cyan\", \"Truncating tables...\"));\n\n try {\n if (hasNamespace) {\n await truncate({\n configPath,\n profile: values.profile,\n namespace: values.namespace,\n });\n } else if (hasTypes) {\n const typesToTruncate = entitiesToProcess.filter((t) => t !== \"_User\");\n if (typesToTruncate.length > 0) {\n await truncate({\n configPath,\n profile: values.profile,\n types: typesToTruncate,\n });\n } else {\n console.log(styleText(\"dim\", \"No TailorDB types to truncate (only _User was specified).\"));\n }\n } else {\n await truncate({\n configPath,\n profile: values.profile,\n all: true,\n });\n }\n } catch (error) {\n console.error(styleText(\"red\", \\`Truncate failed: \\${error.message}\\`));\n process.exit(1);\n }\n\n ${generateIdpUserTruncateCall(hasIdpUser)}\n\n console.log(styleText(\"green\", \"Truncate completed.\"));\n }\n\n console.log(styleText(\"cyan\", \"\\\\nStarting seed data generation...\"));\n if (skipIdp) {\n console.log(styleText(\"dim\", \\` Skipping IdP user (_User)\\`));\n }\n\n // Load seed data from JSONL files\n const loadSeedData = (dataDir, typeNames) => {\n const data = {};\n for (const typeName of typeNames) {\n const jsonlPath = join(dataDir, \\`\\${typeName}.jsonl\\`);\n try {\n const content = readFileSync(jsonlPath, \"utf-8\").trim();\n if (content) {\n data[typeName] = content.split(\"\\\\n\").map((line) => JSON.parse(line));\n } else {\n data[typeName] = [];\n }\n } catch (error) {\n if (error.code === \"ENOENT\") {\n data[typeName] = [];\n } else {\n throw error;\n }\n }\n }\n return data;\n };\n\n // Topological sort for dependency order\n const topologicalSort = (types, deps) => {\n const visited = new Set();\n const result = [];\n\n const visit = (type) => {\n if (visited.has(type)) return;\n visited.add(type);\n const typeDeps = deps[type] || [];\n for (const dep of typeDeps) {\n if (types.includes(dep)) {\n visit(dep);\n }\n }\n result.push(type);\n };\n\n for (const type of types) {\n visit(type);\n }\n return result;\n };\n\n // Seed TailorDB types via testExecScript\n const seedViaTestExecScript = async (namespace, typesToSeed, deps) => {\n const dataDir = join(configDir, \"data\");\n const sortedTypes = topologicalSort(typesToSeed, deps);\n const data = loadSeedData(dataDir, sortedTypes);\n\n // Skip if no data\n const typesWithData = sortedTypes.filter((t) => data[t] && data[t].length > 0);\n if (typesWithData.length === 0) {\n console.log(styleText(\"dim\", \\` [\\${namespace}] No data to seed\\`));\n return { success: true, processed: {} };\n }\n\n console.log(styleText(\"cyan\", \\` [\\${namespace}] Seeding \\${typesWithData.length} types via Kysely batch insert...\\`));\n\n // Bundle seed script\n const bundled = await bundleSeedScript(namespace, typesWithData);\n\n // Chunk seed data to fit within gRPC message size limits\n const chunks = chunkSeedData({\n data,\n order: sortedTypes,\n codeByteSize: new TextEncoder().encode(bundled.bundledCode).length,\n });\n\n if (chunks.length === 0) {\n console.log(styleText(\"dim\", \\` [\\${namespace}] No data to seed\\`));\n return { success: true, processed: {} };\n }\n\n if (chunks.length > 1) {\n console.log(styleText(\"dim\", \\` Split into \\${chunks.length} chunks\\`));\n }\n\n const allProcessed = {};\n let hasError = false;\n const allErrors = [];\n\n for (const chunk of chunks) {\n if (chunks.length > 1) {\n console.log(styleText(\"dim\", \\` Chunk \\${chunk.index + 1}/\\${chunk.total}: \\${chunk.order.join(\", \")}\\`));\n }\n\n // Execute seed script for this chunk\n const result = await executeScript({\n client: operatorClient,\n workspaceId,\n name: \\`seed-\\${namespace}.ts\\`,\n code: bundled.bundledCode,\n arg: JSON.stringify({ data: chunk.data, order: chunk.order }),\n invoker: {\n namespace: authNamespace,\n machineUserName,\n },\n });\n\n // Parse result and display logs\n if (result.logs) {\n for (const line of result.logs.split(\"\\\\n\").filter(Boolean)) {\n console.log(styleText(\"dim\", \\` \\${line}\\`));\n }\n }\n\n if (result.success) {\n let parsed;\n try {\n const parsedResult = JSON.parse(result.result || \"{}\");\n parsed = parsedResult && typeof parsedResult === \"object\" ? parsedResult : {};\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(styleText(\"red\", \\` ✗ Failed to parse seed result: \\${message}\\`));\n hasError = true;\n allErrors.push(message);\n continue;\n }\n\n const processed = parsed.processed || {};\n for (const [type, count] of Object.entries(processed)) {\n allProcessed[type] = (allProcessed[type] || 0) + count;\n console.log(styleText(\"green\", \\` ✓ \\${type}: \\${count} rows inserted\\`));\n }\n\n if (!parsed.success) {\n const errors = Array.isArray(parsed.errors) ? parsed.errors : [];\n const errorMessage =\n errors.length > 0 ? errors.join(\"\\\\n \") : \"Seed script reported failure\";\n console.error(styleText(\"red\", \\` ✗ Seed failed:\\\\n \\${errorMessage}\\`));\n hasError = true;\n allErrors.push(errorMessage);\n }\n } else {\n console.error(styleText(\"red\", \\` ✗ Seed failed: \\${result.error}\\`));\n hasError = true;\n allErrors.push(result.error);\n }\n }\n\n if (hasError) {\n return { success: false, error: allErrors.join(\"\\\\n\") };\n }\n return { success: true, processed: allProcessed };\n };\n\n ${generateIdpUserSeedFunction(hasIdpUser, idpNamespace)}\n\n // Main execution\n try {\n let allSuccess = true;\n\n // Determine which namespaces and types to process\n const namespacesToProcess = hasNamespace\n ? [values.namespace]\n : Object.keys(namespaceEntities);\n\n for (const namespace of namespacesToProcess) {\n const nsTypes = namespaceEntities[namespace] || [];\n const nsDeps = namespaceDeps[namespace] || {};\n\n // Filter types if specific types requested\n let typesToSeed = entitiesToProcess\n ? nsTypes.filter((t) => entitiesToProcess.includes(t))\n : nsTypes;\n\n if (typesToSeed.length === 0) continue;\n\n const result = await seedViaTestExecScript(namespace, typesToSeed, nsDeps);\n if (!result.success) {\n allSuccess = false;\n }\n }\n\n ${generateIdpUserSeedCall(hasIdpUser)}\n\n if (allSuccess) {\n console.log(styleText(\"green\", \"\\\\n✓ Seed data generation completed successfully\"));\n } else {\n console.error(styleText(\"red\", \"\\\\n✗ Seed data generation completed with errors\"));\n process.exit(1);\n }\n } catch (error) {\n console.error(styleText(\"red\", \\`\\\\n✗ Seed data generation failed: \\${error.message}\\`));\n process.exit(1);\n }\n\n `;\n}\n\n/**\n * Plugin that generates seed data files with Kysely batch insert and tailor.idp.Client for _User.\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 * @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 files (Kysely batch insert + tailor.idp.Client for _User)\",\n pluginConfig: options,\n\n async onTailorDBReady(ctx: TailorDBReadyContext<SeedPluginOptions>): Promise<GeneratorResult> {\n const files: GeneratorResult[\"files\"] = [];\n const namespaceConfigs: NamespaceConfig[] = [];\n\n for (const ns of ctx.tailordb) {\n const types: string[] = [];\n const dependencies: Record<string, string[]> = {};\n\n for (const [typeName, type] of Object.entries(ns.types)) {\n const source = ns.sourceInfo.get(typeName)!;\n const typeInfo = processSeedTypeInfo(type, ns.namespace);\n const linesDb = processLinesDb(type, source);\n\n types.push(typeInfo.name);\n dependencies[typeInfo.name] = typeInfo.dependencies;\n\n // Generate empty JSONL data file\n files.push({\n path: path.join(ctx.pluginConfig.distPath, typeInfo.dataFile),\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 namespaceConfigs.push({\n namespace: ns.namespace,\n types,\n dependencies,\n });\n }\n\n // Process IdP user if configured\n const idpUser = ctx.auth ? (processIdpUser(ctx.auth) ?? null) : null;\n const hasIdpUser = idpUser !== null;\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\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"data\", `${idpUser.name}.schema.ts`),\n content: generateIdpUserSchemaFile(\n idpUser.schema.usernameField,\n idpUser.schema.userTypeName,\n ),\n });\n }\n\n // Generate exec.mjs (machineUserName can be provided at runtime if not configured)\n const relativeConfigPath = path.relative(ctx.pluginConfig.distPath, ctx.configPath);\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"exec.mjs\"),\n content: generateExecScript(\n ctx.pluginConfig.machineUserName,\n relativeConfigPath,\n namespaceConfigs,\n hasIdpUser,\n idpUser?.idpNamespace ?? null,\n ),\n });\n\n return { files };\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { n as shutdownTelemetry, r as withSpan, t as initTelemetry } from "./telemetry-DuBhnd0X.mjs";
2
+
3
+ export { initTelemetry, shutdownTelemetry };
@@ -34,7 +34,7 @@ async function initTelemetry() {
34
34
  import("@opentelemetry/exporter-trace-otlp-proto"),
35
35
  import("@opentelemetry/resources"),
36
36
  import("@opentelemetry/semantic-conventions"),
37
- import("./package-json-Dd1AnA5F.mjs")
37
+ import("./package-json-DTDAqRRJ.mjs")
38
38
  ]);
39
39
  const version = (await readPackageJson()).version ?? "unknown";
40
40
  _provider = new NodeTracerProvider({
@@ -81,4 +81,4 @@ async function withSpan(name, fn) {
81
81
 
82
82
  //#endregion
83
83
  export { shutdownTelemetry as n, withSpan as r, initTelemetry as t };
84
- //# sourceMappingURL=telemetry-rFq0QdvJ.mjs.map
84
+ //# sourceMappingURL=telemetry-DuBhnd0X.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-DuBhnd0X.mjs","names":[],"sources":["../src/cli/telemetry/config.ts","../src/cli/telemetry/index.ts"],"sourcesContent":["/**\n * Telemetry configuration parsed from standard OpenTelemetry environment variables.\n * Tracing is enabled when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n */\nexport interface TelemetryConfig {\n readonly enabled: boolean;\n readonly endpoint: string;\n}\n\n/**\n * Parse telemetry configuration from standard OpenTelemetry environment variables.\n * Tracing is enabled when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n * @returns Telemetry configuration\n */\nexport function parseTelemetryConfig(): TelemetryConfig {\n const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? \"\";\n const enabled = endpoint.length > 0;\n\n return {\n enabled,\n endpoint,\n };\n}\n","import { trace, SpanStatusCode, type Span } from \"@opentelemetry/api\";\nimport { parseTelemetryConfig, type TelemetryConfig } from \"./config\";\n\nlet _config: TelemetryConfig | undefined;\nlet _initialized = false;\nlet _provider: { register: () => void; shutdown: () => Promise<void> } | undefined;\n\n/**\n * Check whether telemetry is currently enabled.\n * @returns true if telemetry has been initialized and is enabled\n */\nexport function isTelemetryEnabled(): boolean {\n return _config?.enabled ?? false;\n}\n\n/**\n * Initialize telemetry if OTEL_EXPORTER_OTLP_ENDPOINT is set.\n * When disabled, this is a no-op with zero overhead beyond reading env vars.\n * @returns Promise that resolves when initialization completes\n */\nexport async function initTelemetry(): Promise<void> {\n if (_initialized) return;\n _initialized = true;\n\n _config = parseTelemetryConfig();\n if (!_config.enabled) return;\n\n // Dynamic imports - only loaded when tracing is enabled\n const [\n { NodeTracerProvider, BatchSpanProcessor },\n { OTLPTraceExporter },\n { resourceFromAttributes },\n { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION },\n { readPackageJson },\n ] = await Promise.all([\n import(\"@opentelemetry/sdk-trace-node\"),\n import(\"@opentelemetry/exporter-trace-otlp-proto\"),\n import(\"@opentelemetry/resources\"),\n import(\"@opentelemetry/semantic-conventions\"),\n import(\"@/cli/shared/package-json\"),\n ]);\n\n const packageJson = await readPackageJson();\n const version = packageJson.version ?? \"unknown\";\n\n const resource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: \"tailor-sdk\",\n [ATTR_SERVICE_VERSION]: version,\n });\n\n const exporter = new OTLPTraceExporter({\n url: `${_config.endpoint}/v1/traces`,\n });\n\n _provider = new NodeTracerProvider({\n resource,\n spanProcessors: [new BatchSpanProcessor(exporter)],\n });\n\n _provider.register();\n}\n\n/**\n * Shutdown the telemetry provider, flushing all pending spans.\n * Must be called before process exit to ensure traces are exported.\n * @returns Promise that resolves when shutdown completes\n */\nexport async function shutdownTelemetry(): Promise<void> {\n if (!_provider) return;\n await _provider.shutdown();\n}\n\n/**\n * Execute a function within a new span. Records exceptions and sets span status.\n * When no TracerProvider is registered, the OTel API automatically provides\n * noop spans with zero overhead.\n * @param name - Span name\n * @param fn - Function to execute within the span\n * @returns Result of fn\n */\nexport async function withSpan<T>(name: string, fn: (span: Span) => Promise<T>): Promise<T> {\n const tracer = trace.getTracer(\"tailor-sdk\");\n\n return tracer.startActiveSpan(name, async (span) => {\n try {\n const result = await fn(span);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n if (error instanceof Error) {\n span.recordException(error);\n }\n throw error;\n } finally {\n span.end();\n }\n });\n}\n"],"mappings":";;;;;;;;AAcA,SAAgB,uBAAwC;CACtD,MAAM,WAAW,QAAQ,IAAI,+BAA+B;AAG5D,QAAO;EACL,SAHc,SAAS,SAAS;EAIhC;EACD;;;;;AClBH,IAAI;AACJ,IAAI,eAAe;AACnB,IAAI;;;;;;AAeJ,eAAsB,gBAA+B;AACnD,KAAI,aAAc;AAClB,gBAAe;AAEf,WAAU,sBAAsB;AAChC,KAAI,CAAC,QAAQ,QAAS;CAGtB,MAAM,CACJ,EAAE,oBAAoB,sBACtB,EAAE,qBACF,EAAE,0BACF,EAAE,mBAAmB,wBACrB,EAAE,qBACA,MAAM,QAAQ,IAAI;EACpB,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACR,CAAC;CAGF,MAAM,WADc,MAAM,iBAAiB,EACf,WAAW;AAWvC,aAAY,IAAI,mBAAmB;EACjC,UAVe,uBAAuB;IACrC,oBAAoB;IACpB,uBAAuB;GACzB,CAAC;EAQA,gBAAgB,CAAC,IAAI,mBANN,IAAI,kBAAkB,EACrC,KAAK,GAAG,QAAQ,SAAS,aAC1B,CAAC,CAIiD,CAAC;EACnD,CAAC;AAEF,WAAU,UAAU;;;;;;;AAQtB,eAAsB,oBAAmC;AACvD,KAAI,CAAC,UAAW;AAChB,OAAM,UAAU,UAAU;;;;;;;;;;AAW5B,eAAsB,SAAY,MAAc,IAA4C;AAG1F,QAFe,MAAM,UAAU,aAAa,CAE9B,gBAAgB,MAAM,OAAO,SAAS;AAClD,MAAI;GACF,MAAM,SAAS,MAAM,GAAG,KAAK;AAC7B,QAAK,UAAU,EAAE,MAAM,eAAe,IAAI,CAAC;AAC3C,UAAO;WACA,OAAO;AACd,QAAK,UAAU,EAAE,MAAM,eAAe,OAAO,CAAC;AAC9C,OAAI,iBAAiB,MACnB,MAAK,gBAAgB,MAAM;AAE7B,SAAM;YACE;AACR,QAAK,KAAK;;GAEZ"}
@@ -1,5 +1,5 @@
1
1
  /// <reference path="./user-defined.d.ts" />
2
- import { P as ExecutorServiceInput, Pt as ResolverServiceInput, W as AuthConfig, Y as BuiltinIdP, qt as TailorDBServiceInput } from "./types-CblXasFV.mjs";
2
+ import { P as ExecutorServiceInput, Pt as ResolverServiceInput, W as AuthConfig, Y as BuiltinIdP, qt as TailorDBServiceInput } from "./types-QKq1usl7.mjs";
3
3
  import { z } from "zod";
4
4
 
5
5
  //#region src/parser/service/workflow/types.d.ts
@@ -89,8 +89,92 @@ declare const IdPSchema: z.core.$ZodBranded<z.ZodObject<{
89
89
  disablePasswordAuth?: boolean | undefined;
90
90
  }>>>;
91
91
  publishUserEvents: z.ZodOptional<z.ZodBoolean>;
92
+ gqlOperations: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodLiteral<"query">, z.ZodObject<{
93
+ create: z.ZodOptional<z.ZodBoolean>;
94
+ update: z.ZodOptional<z.ZodBoolean>;
95
+ delete: z.ZodOptional<z.ZodBoolean>;
96
+ read: z.ZodOptional<z.ZodBoolean>;
97
+ sendPasswordResetEmail: z.ZodOptional<z.ZodBoolean>;
98
+ }, z.core.$strip>]>, z.ZodTransform<IdPGqlOperations, "query" | {
99
+ create?: boolean | undefined;
100
+ update?: boolean | undefined;
101
+ delete?: boolean | undefined;
102
+ read?: boolean | undefined;
103
+ sendPasswordResetEmail?: boolean | undefined;
104
+ }>>>;
92
105
  }, z.core.$strip>, "IdPConfig", "out">;
93
106
  //#endregion
107
+ //#region src/configure/services/idp/index.d.ts
108
+ /**
109
+ * Configuration for GraphQL operations on IdP users.
110
+ * All operations are enabled by default (undefined or true = enabled, false = disabled).
111
+ */
112
+ interface IdPGqlOperations {
113
+ /** Enable _createUser mutation (default: true) */
114
+ create?: boolean;
115
+ /** Enable _updateUser mutation (default: true) */
116
+ update?: boolean;
117
+ /** Enable _deleteUser mutation (default: true) */
118
+ delete?: boolean;
119
+ /** Enable _users and _user queries (default: true) */
120
+ read?: boolean;
121
+ /** Enable _sendPasswordResetEmail mutation (default: true) */
122
+ sendPasswordResetEmail?: boolean;
123
+ }
124
+ /**
125
+ * Alias for common IdPGqlOperations configurations.
126
+ * - "query": Read-only mode - disables all mutations (create, update, delete, sendPasswordResetEmail)
127
+ */
128
+ type IdPGqlOperationsAliasQuery = "query";
129
+ /**
130
+ * Configuration for GraphQL operations - either an alias string or detailed object.
131
+ */
132
+ type IdPGqlOperationsConfig = IdPGqlOperationsAliasQuery | IdPGqlOperations;
133
+ /**
134
+ * Define an IdP service configuration for the Tailor SDK.
135
+ * @template TClients
136
+ * @param name - IdP service name
137
+ * @param config - IdP configuration
138
+ * @returns Defined IdP service
139
+ */
140
+ declare function defineIdp<const TClients extends string[]>(name: string, config: Omit<IdPInput, "name" | "clients"> & {
141
+ clients: TClients;
142
+ }): {
143
+ readonly name: string;
144
+ readonly provider: (providerName: string, clientName: TClients[number]) => {
145
+ readonly name: string;
146
+ readonly kind: "BuiltInIdP";
147
+ readonly namespace: string;
148
+ readonly clientName: TClients[number];
149
+ };
150
+ readonly authorization: "insecure" | "loggedIn" | {
151
+ cel: string;
152
+ };
153
+ readonly lang?: "en" | "ja" | undefined;
154
+ readonly userAuthPolicy?: {
155
+ useNonEmailIdentifier?: boolean | undefined;
156
+ allowSelfPasswordReset?: boolean | undefined;
157
+ passwordRequireUppercase?: boolean | undefined;
158
+ passwordRequireLowercase?: boolean | undefined;
159
+ passwordRequireNonAlphanumeric?: boolean | undefined;
160
+ passwordRequireNumeric?: boolean | undefined;
161
+ passwordMinLength?: number | undefined;
162
+ passwordMaxLength?: number | undefined;
163
+ allowedEmailDomains?: string[] | undefined;
164
+ allowGoogleOauth?: boolean | undefined;
165
+ disablePasswordAuth?: boolean | undefined;
166
+ } | undefined;
167
+ readonly publishUserEvents?: boolean | undefined;
168
+ readonly gqlOperations?: "query" | {
169
+ create?: boolean | undefined;
170
+ update?: boolean | undefined;
171
+ delete?: boolean | undefined;
172
+ read?: boolean | undefined;
173
+ sendPasswordResetEmail?: boolean | undefined;
174
+ } | undefined;
175
+ readonly clients: TClients;
176
+ } & IdpDefinitionBrand;
177
+ //#endregion
94
178
  //#region src/parser/service/idp/types.d.ts
95
179
  type IdPInput = z.input<typeof IdPSchema>;
96
180
  declare const idpDefinitionBrand: unique symbol;
@@ -154,5 +238,5 @@ interface AppConfig<Auth extends AuthConfig = AuthConfig, Idp extends IdPConfig[
154
238
  inlineSourcemap?: boolean;
155
239
  }
156
240
  //#endregion
157
- export { IdpDefinitionBrand as a, WorkflowServiceConfig as c, IdPInput as i, WorkflowServiceInput as l, IdPConfig as n, StaticWebsiteConfig as o, IdPExternalConfig as r, defineStaticWebSite as s, AppConfig as t };
158
- //# sourceMappingURL=types-CJF3Y1x8.d.mts.map
241
+ export { IdPGqlOperationsAliasQuery as a, StaticWebsiteConfig as c, WorkflowServiceInput as d, IdPGqlOperations as i, defineStaticWebSite as l, IdPConfig as n, IdPGqlOperationsConfig as o, IdPExternalConfig as r, defineIdp as s, AppConfig as t, WorkflowServiceConfig as u };
242
+ //# sourceMappingURL=types-C0o90Cmb.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-ClK_HJ0G.mjs","names":[],"sources":["../src/parser/service/tailordb/types.ts"],"sourcesContent":["import type { RelationType } from \"./relation\";\nimport type {\n DBFieldMetadataSchema,\n RawRelationConfigSchema,\n RawPermissionsSchema,\n TailorDBTypeSchema,\n TailorDBServiceConfig as TailorDBServiceConfigType,\n TailorDBTypeSettingsSchema,\n} from \"./schema\";\nimport type { GqlOperationsConfig } from \"@/configure/services/tailordb\";\nimport type { ValueOperand } from \"@/parser/service/auth/types\";\nimport type { z } from \"zod\";\n\nexport type { RelationType } from \"./relation\";\nexport type { TypeSourceInfo } from \"./type-parser\";\n\n// ========================================\n// Source info type for TailorDB types\n// ========================================\n\n/**\n * Source information for a user-defined TailorDB type.\n */\nexport interface UserDefinedTypeSource {\n /** File path to import from */\n filePath: string;\n /** Export name in the source file */\n exportName: string;\n /** Not present for user-defined types */\n pluginId?: never;\n}\n\n/**\n * Source information for a plugin-generated TailorDB type.\n */\nexport interface PluginGeneratedTypeSource {\n /** Not present for plugin-generated types */\n filePath?: never;\n /** Export name of the generated type */\n exportName: string;\n /** Plugin ID that generated this type */\n pluginId: string;\n /** Plugin import path for code generators */\n pluginImportPath: string;\n /** Original type's file path */\n originalFilePath: string;\n /** Original type's export name */\n originalExportName: string;\n /** Generated type kind for getGeneratedType() API (e.g., \"request\", \"step\") */\n generatedTypeKind?: string;\n /** Plugin config used to generate this type */\n pluginConfig?: unknown;\n /** Namespace where this type was generated */\n namespace?: string;\n}\n\n/**\n * Source information for a TailorDB type.\n * Discriminated union: use `pluginId` to distinguish between user-defined and plugin-generated types.\n */\nexport type TypeSourceInfoEntry = UserDefinedTypeSource | PluginGeneratedTypeSource;\n\n/**\n * Type guard to check if source is plugin-generated\n * @param source - Type source info to check\n * @returns True if source is plugin-generated\n */\nexport function isPluginGeneratedType(\n source: TypeSourceInfoEntry,\n): source is PluginGeneratedTypeSource {\n return source.pluginId !== undefined;\n}\n\nexport type {\n TailorAnyDBField,\n TailorAnyDBType,\n TailorDBField,\n DBFieldMetadata,\n Hook,\n TailorTypePermission,\n TailorTypeGqlPermission,\n GqlOperationsConfig,\n GqlOperations,\n} from \"@/configure/services/tailordb\";\nexport type {\n TailorDBServiceConfigInput,\n TailorDBServiceConfig,\n TailorDBExternalConfig,\n TailorDBServiceInput,\n} from \"./schema\";\n\n/**\n * Parsed and normalized settings for TailorDB type.\n * gqlOperations is normalized from alias to object format.\n * @public\n */\nexport type TailorDBTypeParsedSettings = z.output<typeof TailorDBTypeSettingsSchema>;\n\n/**\n * Migration configuration for TailorDB\n * @public\n */\nexport type TailorDBMigrationConfig = NonNullable<TailorDBServiceConfigType[\"migration\"]>;\n\nexport type TailorDBTypeSchemaOutput = z.output<typeof TailorDBTypeSchema>;\n\nexport type DBFieldMetadataOutput = z.output<typeof DBFieldMetadataSchema>;\nexport type RawRelationConfigOutput = z.output<typeof RawRelationConfigSchema>;\n\nexport type RawPermissions = z.output<typeof RawPermissionsSchema>;\n\nexport type TailorDBFieldOutput = {\n type: string;\n fields?: Record<string, TailorDBFieldOutput>;\n metadata: DBFieldMetadataOutput;\n rawRelation?: RawRelationConfigOutput;\n};\n\nexport interface Script {\n expr: string;\n}\n\nexport interface EnumValue {\n value: string;\n description?: string;\n}\n\ninterface OperatorValidateConfig {\n script: Script;\n errorMessage: string;\n}\n\ninterface OperatorFieldHook {\n create?: Script;\n update?: Script;\n}\n\n/**\n * Raw relation config stored in configure layer, processed in parser layer.\n * This is the serialized form of RelationConfig from schema.ts where\n * the TailorDBType reference is replaced with the type name string.\n */\nexport interface RawRelationConfig {\n type: RelationType;\n toward: {\n type: string;\n as?: string;\n key?: string;\n };\n backward?: string;\n}\n\nexport interface OperatorFieldConfig {\n type: string;\n required?: boolean;\n description?: string;\n allowedValues?: EnumValue[];\n array?: boolean;\n index?: boolean;\n unique?: boolean;\n vector?: boolean;\n foreignKey?: boolean;\n foreignKeyType?: string;\n foreignKeyField?: string;\n rawRelation?: RawRelationConfig;\n validate?: OperatorValidateConfig[];\n hooks?: OperatorFieldHook;\n serial?: {\n start: number;\n maxValue?: number;\n format?: string;\n };\n scale?: number;\n fields?: Record<string, OperatorFieldConfig>;\n}\n\ntype GqlPermissionAction = \"read\" | \"create\" | \"update\" | \"delete\" | \"aggregate\" | \"bulkUpsert\";\n\ntype StandardPermissionOperator = \"eq\" | \"ne\" | \"in\" | \"nin\" | \"hasAny\" | \"nhasAny\";\n\ntype UserOperand = {\n user: string;\n};\n\ntype RecordOperand<Update extends boolean = false> = Update extends true\n ? { oldRecord: string } | { newRecord: string }\n : { record: string };\n\nexport type PermissionOperand<\n Level extends \"record\" | \"gql\" = \"record\" | \"gql\",\n Update extends boolean = boolean,\n> = UserOperand | ValueOperand | (Level extends \"record\" ? RecordOperand<Update> : never);\n\nexport type StandardPermissionCondition<\n Level extends \"record\" | \"gql\" = \"record\" | \"gql\",\n Update extends boolean = boolean,\n> = readonly [\n PermissionOperand<Level, Update>,\n StandardPermissionOperator,\n PermissionOperand<Level, Update>,\n];\n\nexport type StandardActionPermission<\n Level extends \"record\" | \"gql\" = \"record\" | \"gql\",\n Update extends boolean = boolean,\n> = {\n conditions: readonly StandardPermissionCondition<Level, Update>[];\n description?: string;\n permit: \"allow\" | \"deny\";\n};\n\nexport type StandardTailorTypePermission = {\n create: readonly StandardActionPermission<\"record\", false>[];\n read: readonly StandardActionPermission<\"record\", false>[];\n update: readonly StandardActionPermission<\"record\", true>[];\n delete: readonly StandardActionPermission<\"record\", false>[];\n};\n\nexport type StandardGqlPermissionPolicy = {\n conditions: readonly StandardPermissionCondition<\"gql\">[];\n actions: readonly [\"all\"] | readonly GqlPermissionAction[];\n permit: \"allow\" | \"deny\";\n description?: string;\n};\n\nexport type StandardTailorTypeGqlPermission = readonly StandardGqlPermissionPolicy[];\n\nexport interface Permissions {\n record?: StandardTailorTypePermission;\n gql?: StandardTailorTypeGqlPermission;\n}\n\nexport interface TailorDBTypeMetadata {\n name: string;\n description?: string;\n settings?: {\n pluralForm?: string;\n aggregation?: boolean;\n bulkUpsert?: boolean;\n gqlOperations?: GqlOperationsConfig;\n };\n permissions: RawPermissions;\n files: Record<string, string>;\n indexes?: Record<\n string,\n {\n fields: string[];\n unique?: boolean;\n }\n >;\n}\n\n/**\n * Parsed and normalized TailorDB field information\n */\nexport interface ParsedField {\n name: string;\n config: OperatorFieldConfig;\n relation?: {\n targetType: string;\n forwardName: string;\n backwardName: string;\n key: string;\n unique: boolean;\n };\n}\n\n/**\n * Parsed and normalized TailorDB relationship information\n */\nexport interface ParsedRelationship {\n name: string;\n targetType: string;\n targetField: string;\n sourceField: string;\n isArray: boolean;\n description: string;\n}\n\n/**\n * Parsed and normalized TailorDB type information\n */\nexport interface TailorDBType {\n name: string;\n pluralForm: string;\n description?: string;\n fields: Record<string, ParsedField>;\n forwardRelationships: Record<string, ParsedRelationship>;\n backwardRelationships: Record<string, ParsedRelationship>;\n settings: TailorDBTypeParsedSettings;\n permissions: Permissions;\n indexes?: TailorDBTypeMetadata[\"indexes\"];\n files?: TailorDBTypeMetadata[\"files\"];\n}\n"],"mappings":";;;;;;AAmEA,SAAgB,sBACd,QACqC;AACrC,QAAO,OAAO,aAAa"}
1
+ {"version":3,"file":"types-ClK_HJ0G.mjs","names":[],"sources":["../src/parser/service/tailordb/types.ts"],"sourcesContent":["import type { RelationType } from \"./relation\";\nimport type {\n DBFieldMetadataSchema,\n RawRelationConfigSchema,\n RawPermissionsSchema,\n TailorDBTypeSchema,\n TailorDBServiceConfig as TailorDBServiceConfigType,\n TailorDBTypeSettingsSchema,\n} from \"./schema\";\nimport type { GqlOperationsConfig } from \"@/configure/services/tailordb\";\nimport type { ValueOperand } from \"@/parser/service/auth/types\";\nimport type { z } from \"zod\";\n\nexport type { RelationType } from \"./relation\";\nexport type { TypeSourceInfo } from \"./type-parser\";\n\n// ========================================\n// Source info type for TailorDB types\n// ========================================\n\n/**\n * Source information for a user-defined TailorDB type.\n */\nexport interface UserDefinedTypeSource {\n /** File path to import from */\n filePath: string;\n /** Export name in the source file */\n exportName: string;\n /** Not present for user-defined types */\n pluginId?: never;\n}\n\n/**\n * Source information for a plugin-generated TailorDB type.\n */\nexport interface PluginGeneratedTypeSource {\n /** Not present for plugin-generated types */\n filePath?: never;\n /** Export name of the generated type */\n exportName: string;\n /** Plugin ID that generated this type */\n pluginId: string;\n /** Plugin import path for code generators */\n pluginImportPath: string;\n /** Original type's file path */\n originalFilePath: string;\n /** Original type's export name */\n originalExportName: string;\n /** Generated type kind for getGeneratedType() API (e.g., \"request\", \"step\") */\n generatedTypeKind?: string;\n /** Plugin config used to generate this type */\n pluginConfig?: unknown;\n /** Namespace where this type was generated */\n namespace?: string;\n}\n\n/**\n * Source information for a TailorDB type.\n * Discriminated union: use `pluginId` to distinguish between user-defined and plugin-generated types.\n */\nexport type TypeSourceInfoEntry = UserDefinedTypeSource | PluginGeneratedTypeSource;\n\n/**\n * Type guard to check if source is plugin-generated\n * @param source - Type source info to check\n * @returns True if source is plugin-generated\n */\nexport function isPluginGeneratedType(\n source: TypeSourceInfoEntry,\n): source is PluginGeneratedTypeSource {\n return source.pluginId !== undefined;\n}\n\nexport type {\n TailorAnyDBField,\n TailorAnyDBType,\n TailorDBField,\n DBFieldMetadata,\n Hook,\n TailorTypePermission,\n TailorTypeGqlPermission,\n GqlOperationsConfig,\n GqlOperations,\n} from \"@/configure/services/tailordb\";\nexport type {\n TailorDBServiceConfigInput,\n TailorDBServiceConfig,\n TailorDBExternalConfig,\n TailorDBServiceInput,\n} from \"./schema\";\n\n/**\n * Parsed and normalized settings for TailorDB type.\n * gqlOperations is normalized from alias to object format.\n * @public\n */\nexport type TailorDBTypeParsedSettings = z.output<typeof TailorDBTypeSettingsSchema>;\n\n/**\n * Migration configuration for TailorDB\n * @public\n */\nexport type TailorDBMigrationConfig = NonNullable<TailorDBServiceConfigType[\"migration\"]>;\n\nexport type TailorDBTypeSchemaOutput = z.output<typeof TailorDBTypeSchema>;\n\nexport type DBFieldMetadataOutput = z.output<typeof DBFieldMetadataSchema>;\nexport type RawRelationConfigOutput = z.output<typeof RawRelationConfigSchema>;\n\nexport type RawPermissions = z.output<typeof RawPermissionsSchema>;\n\nexport type TailorDBFieldOutput = {\n type: string;\n fields?: Record<string, TailorDBFieldOutput>;\n metadata: DBFieldMetadataOutput;\n rawRelation?: RawRelationConfigOutput;\n};\n\nexport interface Script {\n expr: string;\n}\n\nexport interface EnumValue {\n value: string;\n description?: string;\n}\n\ninterface OperatorValidateConfig {\n script: Script;\n errorMessage: string;\n}\n\ninterface OperatorFieldHook {\n create?: Script;\n update?: Script;\n}\n\n/**\n * Raw relation config stored in configure layer, processed in parser layer.\n * This is the serialized form of RelationConfig from schema.ts where\n * the TailorDBType reference is replaced with the type name string.\n */\nexport interface RawRelationConfig {\n type: RelationType;\n toward: {\n type: string;\n as?: string;\n key?: string;\n };\n backward?: string;\n}\n\nexport interface OperatorFieldConfig {\n type: string;\n required?: boolean;\n description?: string;\n allowedValues?: EnumValue[];\n array?: boolean;\n index?: boolean;\n unique?: boolean;\n vector?: boolean;\n foreignKey?: boolean;\n foreignKeyType?: string;\n foreignKeyField?: string;\n rawRelation?: RawRelationConfig;\n validate?: OperatorValidateConfig[];\n hooks?: OperatorFieldHook;\n serial?: {\n start: number;\n maxValue?: number;\n format?: string;\n };\n scale?: number;\n fields?: Record<string, OperatorFieldConfig>;\n}\n\ntype GqlPermissionAction = \"read\" | \"create\" | \"update\" | \"delete\" | \"aggregate\" | \"bulkUpsert\";\n\ntype StandardPermissionOperator = \"eq\" | \"ne\" | \"in\" | \"nin\" | \"hasAny\" | \"nhasAny\";\n\ntype UserOperand = {\n user: string;\n};\n\ntype RecordOperand<Update extends boolean = false> = Update extends true\n ? { oldRecord: string } | { newRecord: string }\n : { record: string };\n\nexport type PermissionOperand<\n Level extends \"record\" | \"gql\" = \"record\" | \"gql\",\n Update extends boolean = boolean,\n> = UserOperand | ValueOperand | (Level extends \"record\" ? RecordOperand<Update> : never);\n\nexport type StandardPermissionCondition<\n Level extends \"record\" | \"gql\" = \"record\" | \"gql\",\n Update extends boolean = boolean,\n> = readonly [\n PermissionOperand<Level, Update>,\n StandardPermissionOperator,\n PermissionOperand<Level, Update>,\n];\n\nexport type StandardActionPermission<\n Level extends \"record\" | \"gql\" = \"record\" | \"gql\",\n Update extends boolean = boolean,\n> = {\n conditions: readonly StandardPermissionCondition<Level, Update>[];\n description?: string;\n permit: \"allow\" | \"deny\";\n};\n\nexport type StandardTailorTypePermission = {\n create: readonly StandardActionPermission<\"record\", false>[];\n read: readonly StandardActionPermission<\"record\", false>[];\n update: readonly StandardActionPermission<\"record\", true>[];\n delete: readonly StandardActionPermission<\"record\", false>[];\n};\n\nexport type StandardGqlPermissionPolicy = {\n conditions: readonly StandardPermissionCondition<\"gql\">[];\n actions: readonly [\"all\"] | readonly GqlPermissionAction[];\n permit: \"allow\" | \"deny\";\n description?: string;\n};\n\nexport type StandardTailorTypeGqlPermission = readonly StandardGqlPermissionPolicy[];\n\nexport interface Permissions {\n record?: StandardTailorTypePermission;\n gql?: StandardTailorTypeGqlPermission;\n}\n\nexport interface TailorDBTypeMetadata {\n name: string;\n description?: string;\n settings?: {\n pluralForm?: string;\n aggregation?: boolean;\n bulkUpsert?: boolean;\n gqlOperations?: GqlOperationsConfig;\n publishEvents?: boolean;\n };\n permissions: RawPermissions;\n files: Record<string, string>;\n indexes?: Record<\n string,\n {\n fields: string[];\n unique?: boolean;\n }\n >;\n}\n\n/**\n * Parsed and normalized TailorDB field information\n */\nexport interface ParsedField {\n name: string;\n config: OperatorFieldConfig;\n relation?: {\n targetType: string;\n forwardName: string;\n backwardName: string;\n key: string;\n unique: boolean;\n };\n}\n\n/**\n * Parsed and normalized TailorDB relationship information\n */\nexport interface ParsedRelationship {\n name: string;\n targetType: string;\n targetField: string;\n sourceField: string;\n isArray: boolean;\n description: string;\n}\n\n/**\n * Parsed and normalized TailorDB type information\n */\nexport interface TailorDBType {\n name: string;\n pluralForm: string;\n description?: string;\n fields: Record<string, ParsedField>;\n forwardRelationships: Record<string, ParsedRelationship>;\n backwardRelationships: Record<string, ParsedRelationship>;\n settings: TailorDBTypeParsedSettings;\n permissions: Permissions;\n indexes?: TailorDBTypeMetadata[\"indexes\"];\n files?: TailorDBTypeMetadata[\"files\"];\n}\n"],"mappings":";;;;;;AAmEA,SAAgB,sBACd,QACqC;AACrC,QAAO,OAAO,aAAa"}