@autonoma-ai/sdk 0.1.11 → 0.1.12

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.
@@ -84,13 +84,34 @@ interface HandlerConfig {
84
84
  allowProduction?: boolean;
85
85
  /**
86
86
  * Auth callback — called after entity creation during `up`.
87
- * Receives the first User record from refs (or null if no User model exists).
87
+ * Receives the first User record from refs (or null if no User model exists)
88
+ * and a context object with scopeValue and refs.
88
89
  * Must return auth credentials for the test runner.
89
90
  */
90
- auth: (user: Record<string, unknown> | null) => Promise<AuthResult> | AuthResult;
91
+ auth: (user: Record<string, unknown> | null, context: AuthContext) => Promise<AuthResult> | AuthResult;
92
+ /**
93
+ * Optional hook called before teardown in `down`.
94
+ * Use this to clean up data created outside the SDK (e.g., external service records).
95
+ */
96
+ beforeDown?: (context: HookContext) => Promise<void> | void;
97
+ /**
98
+ * Optional hook called after entity creation and auth in `up`.
99
+ * Can modify the auth result before it is returned to the caller.
100
+ */
101
+ afterUp?: (context: HookContext, authResult: AuthResult) => Promise<AuthResult> | AuthResult;
91
102
  /** SDK identity metadata. Server and ORM adapters populate this. */
92
103
  sdk?: Partial<SdkInfo>;
93
104
  }
105
+ interface AuthContext {
106
+ /** The detected scope value (e.g. organization ID) or testRunId fallback. */
107
+ scopeValue: string;
108
+ /** All created entity refs, keyed by model name. */
109
+ refs: Record<string, Record<string, unknown>[]>;
110
+ }
111
+ interface HookContext {
112
+ scenarioName: string;
113
+ refs: Record<string, Record<string, unknown>[]>;
114
+ }
94
115
  interface AuthCookie {
95
116
  name: string;
96
117
  value: string;
@@ -145,4 +166,4 @@ declare function topoSort(nodes: string[], edges: FKEdge[]): TopoSortResult;
145
166
  */
146
167
  declare function findDeferrableEdge(cycle: string[], edges: FKEdge[]): FKEdge | null;
147
168
 
148
- export { type AuthCookie as A, type CreateContext as C, type DiscoverResponse as D, type FKEdge as F, type HandlerConfig as H, type ModelInfo as M, type ResolvedEntitySpec as R, type SchemaInfo as S, type TopoSortResult as T, type UpResponse as U, type HandlerRequest as a, type HandlerResponse as b, type SQLExecutor as c, type ScenarioDefinition as d, type AuthResult as e, type DownResponse as f, type FieldInfo as g, type SchemaRelation as h, type SdkInfo as i, findDeferrableEdge as j, topoSort as t };
169
+ export { type AuthContext as A, type CreateContext as C, type DiscoverResponse as D, type FKEdge as F, type HandlerConfig as H, type ModelInfo as M, type ResolvedEntitySpec as R, type SchemaInfo as S, type TopoSortResult as T, type UpResponse as U, type HandlerRequest as a, type HandlerResponse as b, type SQLExecutor as c, type ScenarioDefinition as d, type AuthCookie as e, type AuthResult as f, type DownResponse as g, type FieldInfo as h, type HookContext as i, type SchemaRelation as j, type SdkInfo as k, findDeferrableEdge as l, topoSort as t };
package/dist/graph.d.ts CHANGED
@@ -1 +1 @@
1
- export { F as FKEdge, T as TopoSortResult, j as findDeferrableEdge, t as topoSort } from './graph-DY4OdpZ4.js';
1
+ export { F as FKEdge, T as TopoSortResult, l as findDeferrableEdge, t as topoSort } from './graph-mTRfWyfN.js';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { H as HandlerConfig, a as HandlerRequest, b as HandlerResponse, S as SchemaInfo, c as SQLExecutor, d as ScenarioDefinition, R as ResolvedEntitySpec, C as CreateContext, M as ModelInfo } from './graph-DY4OdpZ4.js';
2
- export { A as AuthCookie, e as AuthResult, D as DiscoverResponse, f as DownResponse, F as FKEdge, g as FieldInfo, h as SchemaRelation, i as SdkInfo, U as UpResponse, j as findDeferrableEdge, t as topoSort } from './graph-DY4OdpZ4.js';
1
+ import { H as HandlerConfig, a as HandlerRequest, b as HandlerResponse, S as SchemaInfo, c as SQLExecutor, d as ScenarioDefinition, R as ResolvedEntitySpec, C as CreateContext, M as ModelInfo } from './graph-mTRfWyfN.js';
2
+ export { A as AuthContext, e as AuthCookie, f as AuthResult, D as DiscoverResponse, g as DownResponse, F as FKEdge, h as FieldInfo, i as HookContext, j as SchemaRelation, k as SdkInfo, U as UpResponse, l as findDeferrableEdge, t as topoSort } from './graph-mTRfWyfN.js';
3
3
 
4
4
  declare const PROTOCOL_VERSION: string;
5
5
  declare function handleRequest(config: HandlerConfig, req: HandlerRequest): Promise<HandlerResponse>;
package/dist/index.js CHANGED
@@ -534,7 +534,8 @@ async function createEntities(executor, dialect, tableMap, columnMaps, spec, _co
534
534
  const colMap = columnMaps.get(model) ?? /* @__PURE__ */ new Map();
535
535
  const enumTypeMap = enumTypeMaps.get(model) ?? /* @__PURE__ */ new Map();
536
536
  const modelInfo = schemaModels.find((m) => m.name === model);
537
- const pkField = modelInfo?.fields.find((f) => f.isId);
537
+ const idFields = modelInfo?.fields.filter((f) => f.isId) ?? [];
538
+ const pkField = idFields.find((f) => f.name.toLowerCase() === "id") ?? idFields[0];
538
539
  const pkFieldName = pkField?.name ?? "id";
539
540
  const pkFieldType = pkField?.type ?? "String";
540
541
  if (entitySpec.batch && entitySpec.fields.length > 0) {
@@ -742,13 +743,50 @@ async function teardown(executor, dialect, tableMap, columnMaps, schema, scopeVa
742
743
  }
743
744
  }
744
745
  }
745
- const reversed = [...sorted].reverse();
746
- for (const model of reversed) {
747
- if (model === scopeRootModel) continue;
748
- await deleteModel(tx, dialect, tableMap, columnMaps, model, scopeValue, scopeFieldByModel, refs, schema);
749
- }
746
+ const components = [];
747
+ const nodeToComp = /* @__PURE__ */ new Map();
750
748
  for (const cycle of cycles) {
751
- for (const model of cycle) {
749
+ const idx = components.length;
750
+ components.push(cycle);
751
+ for (const node of cycle) nodeToComp.set(node, idx);
752
+ }
753
+ for (const node of sorted) {
754
+ nodeToComp.set(node, components.length);
755
+ components.push([node]);
756
+ }
757
+ const condAdj = /* @__PURE__ */ new Map();
758
+ const condInDeg = /* @__PURE__ */ new Map();
759
+ for (let i = 0; i < components.length; i++) {
760
+ condAdj.set(i, /* @__PURE__ */ new Set());
761
+ condInDeg.set(i, 0);
762
+ }
763
+ for (const edge of schema.edges) {
764
+ if (edge.from === edge.to) continue;
765
+ const fc = nodeToComp.get(edge.from);
766
+ const tc = nodeToComp.get(edge.to);
767
+ if (fc !== void 0 && tc !== void 0 && fc !== tc && !condAdj.get(tc).has(fc)) {
768
+ condAdj.get(tc).add(fc);
769
+ condInDeg.set(fc, (condInDeg.get(fc) ?? 0) + 1);
770
+ }
771
+ }
772
+ const condQueue = [];
773
+ for (const [idx, deg] of condInDeg) {
774
+ if (deg === 0) condQueue.push(idx);
775
+ }
776
+ const condOrder = [];
777
+ while (condQueue.length > 0) {
778
+ condQueue.sort();
779
+ const idx = condQueue.shift();
780
+ condOrder.push(idx);
781
+ for (const neighbor of condAdj.get(idx)) {
782
+ const nd = (condInDeg.get(neighbor) ?? 1) - 1;
783
+ condInDeg.set(neighbor, nd);
784
+ if (nd === 0) condQueue.push(neighbor);
785
+ }
786
+ }
787
+ for (const compIdx of [...condOrder].reverse()) {
788
+ for (const model of components[compIdx]) {
789
+ if (model === scopeRootModel) continue;
752
790
  await deleteModel(tx, dialect, tableMap, columnMaps, model, scopeValue, scopeFieldByModel, refs, schema);
753
791
  }
754
792
  }
@@ -757,7 +795,8 @@ async function teardown(executor, dialect, tableMap, columnMaps, schema, scopeVa
757
795
  const colMap = columnMaps.get(scopeRootModel) ?? /* @__PURE__ */ new Map();
758
796
  if (dbTable) {
759
797
  const rootModelInfo = schema.models.find((m) => m.name === scopeRootModel);
760
- const rootPkFieldName = rootModelInfo?.fields.find((f) => f.isId)?.name ?? "id";
798
+ const rootIdFields = rootModelInfo?.fields.filter((f) => f.isId) ?? [];
799
+ const rootPkFieldName = (rootIdFields.find((f) => f.name.toLowerCase() === "id") ?? rootIdFields[0])?.name ?? "id";
761
800
  const idCol = colMap.get(rootPkFieldName) ?? rootPkFieldName;
762
801
  await tx.query(
763
802
  `DELETE FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(idCol)} = ${dialect.param(1)}`,
@@ -772,7 +811,8 @@ async function deleteModel(tx, dialect, tableMap, columnMaps, model, scopeValue,
772
811
  if (!dbTable) return;
773
812
  const colMap = columnMaps.get(model) ?? /* @__PURE__ */ new Map();
774
813
  const modelInfo = schema.models.find((m) => m.name === model);
775
- const pkFieldName = modelInfo?.fields.find((f) => f.isId)?.name ?? "id";
814
+ const idFields = modelInfo?.fields.filter((f) => f.isId) ?? [];
815
+ const pkFieldName = (idFields.find((f) => f.name.toLowerCase() === "id") ?? idFields[0])?.name ?? "id";
776
816
  const scopeFK = scopeFieldByModel.get(model);
777
817
  if (scopeFK) {
778
818
  const dbCol = colMap.get(scopeFK) ?? scopeFK;
@@ -885,7 +925,8 @@ async function handleUp(config, body) {
885
925
  batch.push(tree.ops[i]);
886
926
  }
887
927
  const modelInfo = schema.models.find((m) => m.name === model);
888
- const pkField = modelInfo?.fields.find((f) => f.isId);
928
+ const idFields = modelInfo?.fields.filter((f) => f.isId) ?? [];
929
+ const pkField = idFields.find((f) => f.name.toLowerCase() === "id") ?? idFields[0];
889
930
  const pkFieldName = pkField?.name ?? "id";
890
931
  const resolvedFields = batch.map((b) => {
891
932
  const fields = { ...b.fields };
@@ -942,13 +983,18 @@ async function handleUp(config, body) {
942
983
  );
943
984
  }
944
985
  const deferredModelInfo = schema.models.find((m) => m.name === deferred.model);
945
- const deferredPkFieldName = deferredModelInfo?.fields.find((f) => f.isId)?.name ?? "id";
986
+ const deferredIdFields = deferredModelInfo?.fields.filter((f) => f.isId) ?? [];
987
+ const deferredPkFieldName = (deferredIdFields.find((f) => f.name.toLowerCase() === "id") ?? deferredIdFields[0])?.name ?? "id";
946
988
  await updateEntity(tx, dialect, tableMap, columnMaps, deferred.model, String(realTargetId), { [deferred.field]: realRefId }, enumTypeMaps, deferredPkFieldName);
947
989
  }
948
990
  });
949
991
  const scopeValue = detectScopeValue(refs, schema.scopeField) ?? testRunId;
950
992
  const firstUser = findFirstUser(refs);
951
- const auth = await config.auth(firstUser);
993
+ let auth = await config.auth(firstUser, { scopeValue, refs });
994
+ if (config.afterUp) {
995
+ const hookCtx = { scenarioName: scopeValue, refs };
996
+ auth = await config.afterUp(hookCtx, auth);
997
+ }
952
998
  const refsToken = signRefs(
953
999
  { refs, testRunId: scopeValue, environment: "" },
954
1000
  config.signingSecret
@@ -967,6 +1013,10 @@ async function handleDown(config, body) {
967
1013
  }
968
1014
  const { schema, tableMap, columnMaps } = await getIntrospection(config);
969
1015
  const dialect = getDialect(config.dialect);
1016
+ if (config.beforeDown) {
1017
+ const hookCtx = { scenarioName: payload.testRunId, refs: payload.refs ?? {} };
1018
+ await config.beforeDown(hookCtx);
1019
+ }
970
1020
  await teardown(config.executor, dialect, tableMap, columnMaps, schema, payload.testRunId, payload.refs);
971
1021
  return { status: 200, body: { ...buildSdkMeta(config), ok: true } };
972
1022
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hmac.ts","../src/refs.ts","../src/tree.ts","../src/errors.ts","../src/generated/sql-queries.ts","../src/dialect.ts","../src/introspect.ts","../src/create.ts","../src/teardown.ts","../src/handler.ts","../src/fingerprint.ts","../src/check.ts"],"sourcesContent":["import { createHmac, timingSafeEqual } from 'node:crypto'\n\nexport function signBody(body: string, secret: string): string {\n return createHmac('sha256', secret).update(body).digest('hex')\n}\n\nexport function verifySignature(\n body: string,\n signature: string,\n secret: string,\n): boolean {\n const expected = signBody(body, secret)\n if (expected.length !== signature.length) return false\n return timingSafeEqual(Buffer.from(expected), Buffer.from(signature))\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto'\n\ninterface RefsPayload {\n refs: Record<string, Record<string, unknown>[]>\n testRunId: string\n environment: string\n}\n\n/**\n * Sign refs into a JWT-like token (header.payload.signature).\n * Uses HMAC-SHA256 — not a full JWT library to avoid dependencies.\n */\nexport function signRefs(payload: RefsPayload, secret: string): string {\n const header = base64url({ alg: 'HS256', typ: 'REFS' })\n const body = base64url(payload)\n const signature = hmac(`${header}.${body}`, secret)\n return `${header}.${body}.${signature}`\n}\n\n/**\n * Verify and decode a refs token. Returns the payload or throws.\n */\nexport function verifyRefs(\n token: string,\n secret: string,\n): RefsPayload {\n const parts = token.split('.')\n if (parts.length !== 3) throw new Error('malformed token')\n\n const [header, body, signature] = parts\n const expected = hmac(`${header}.${body}`, secret)\n\n const expectedBuf = Buffer.from(expected)\n const signatureBuf = Buffer.from(signature!)\n if (expectedBuf.length !== signatureBuf.length || !timingSafeEqual(expectedBuf, signatureBuf)) {\n throw new Error('signature mismatch')\n }\n\n return JSON.parse(Buffer.from(body!, 'base64url').toString())\n}\n\nfunction base64url(obj: unknown): string {\n return Buffer.from(JSON.stringify(obj, (_key, value) =>\n typeof value === 'bigint' ? value.toString() : value\n )).toString('base64url')\n}\n\nfunction hmac(data: string, secret: string): string {\n return createHmac('sha256', secret).update(data).digest('base64url')\n}\n","import type { SchemaInfo, SchemaRelation } from './types'\n\nconst RESERVED_KEYS = new Set(['_alias', '_ref'])\n\n/** A create operation produced by the tree resolver */\nexport interface CreateOp {\n model: string\n fields: Record<string, unknown>\n tempId: string\n batch: boolean\n}\n\n/**\n * A deferred FK update — emitted when a _ref points to a node that hasn't\n * been created yet (circular dependency). Resolved after all creates.\n */\nexport interface DeferredUpdate {\n /** Temp ID of the record that needs to be updated */\n targetTempId: string\n /** Model name of the record to update */\n model: string\n /** Field on the record that holds the deferred FK */\n field: string\n /** Alias that will resolve to the FK value once created */\n refAlias: string\n}\n\n/** Result of resolving a tree scenario */\nexport interface ResolvedTree {\n ops: CreateOp[]\n deferredUpdates: DeferredUpdate[]\n aliases: Map<string, string>\n}\n\n/** A resolved reference to another node's id */\nexport interface RefNode {\n _ref: string\n}\n\n/**\n * Resolve a nested scenario tree into an ordered list of create operations.\n *\n * Walks depth-first. Parent-child FKs are wired automatically.\n * Handles both directions:\n * - FK on child (Application.organizationId → Organization): set child FK to parent ID\n * - FK on parent (Member.userId → User): create child first, set parent FK to child ID\n *\n * Circular FK cycles (e.g. Application.mainBranchId ↔ Branch.applicationId) are handled\n * transparently: the nullable FK is omitted on the first create and emitted as a\n * DeferredUpdate to be applied via UPDATE after all records exist.\n */\nexport function resolveTree(\n create: Record<string, Record<string, unknown>[]>,\n schema: SchemaInfo,\n): ResolvedTree {\n const relationByParentField = new Map<string, SchemaRelation>()\n for (const rel of schema.relations) {\n relationByParentField.set(`${rel.parentModel}.${rel.parentField}`, rel)\n }\n\n // Determine FK direction for each relation:\n // Is childField on the parent model or the child model?\n const fkOnParent = new Set<string>() // key: \"parentModel.parentField\"\n for (const rel of schema.relations) {\n const edge = schema.edges.find(\n (e) => e.localField === rel.childField && (e.from === rel.parentModel || e.from === rel.childModel),\n )\n if (edge && edge.from === rel.parentModel) {\n // FK column is on the parent model → create child first, then set parent FK\n fkOnParent.add(`${rel.parentModel}.${rel.parentField}`)\n }\n }\n\n const aliases = new Map<string, string>()\n const ops: CreateOp[] = []\n const deferredUpdates: DeferredUpdate[] = []\n let tempCounter = 0\n\n function makeTempId(model: string): string {\n return `__temp_${model}_${tempCounter++}`\n }\n\n function walkNode(\n modelName: string,\n node: Record<string, unknown>,\n parentTempId: string | null,\n parentRelation: SchemaRelation | null,\n parentFkOnParent: boolean,\n ): string {\n const fields: Record<string, unknown> = {}\n const preChildren: Array<{ relation: SchemaRelation; value: unknown; fkOnParent: boolean }> = []\n const postChildren: Array<{ relation: SchemaRelation; value: unknown; fkOnParent: boolean }> = []\n const alias = node._alias as string | undefined\n const tempId = makeTempId(modelName)\n\n for (const [key, value] of Object.entries(node)) {\n if (RESERVED_KEYS.has(key)) continue\n\n // Look up relation by exact key, then try fallbacks:\n // 1. Model name prefix: Test.steps → Test.testSteps (Prisma abbreviated names)\n // 2. Child model name: Organization.Application → Organization.applications\n // (scenarios using PascalCase model names as relation keys)\n const exactKey = `${modelName}.${key}`\n const prefixedKey = `${modelName}.${modelName.charAt(0).toLowerCase()}${modelName.slice(1)}${key.charAt(0).toUpperCase()}${key.slice(1)}`\n let relation = relationByParentField.get(exactKey) ?? relationByParentField.get(prefixedKey) ?? undefined\n let matchedKey = relationByParentField.has(exactKey) ? exactKey : prefixedKey\n if (!relation) {\n // Fallback: match by child model name (PascalCase keys like Application, Tag)\n for (const [relKey, rel] of relationByParentField) {\n if (relKey.startsWith(`${modelName}.`) && rel.childModel.toLowerCase() === key.toLowerCase()) {\n relation = rel\n matchedKey = relKey\n break\n }\n }\n }\n if (relation) {\n const isOnParent = fkOnParent.has(matchedKey)\n if (isOnParent) {\n // FK is on this model → need to create the child BEFORE this node\n preChildren.push({ relation, value, fkOnParent: true })\n } else {\n // FK is on the child → create child AFTER this node (normal)\n postChildren.push({ relation, value, fkOnParent: false })\n }\n continue\n }\n\n if (value && typeof value === 'object' && '_ref' in value) {\n const refAlias = (value as RefNode)._ref\n const refTempId = aliases.get(refAlias)\n if (!refTempId) {\n // Alias not created yet — defer this FK as an UPDATE after all creates.\n // This handles circular FK cycles (e.g. Application.mainBranchId → Branch\n // where Branch.applicationId → Application).\n deferredUpdates.push({ targetTempId: tempId, model: modelName, field: key, refAlias })\n continue\n }\n fields[key] = refTempId\n continue\n }\n\n fields[key] = value\n }\n\n // Wire FK to parent (if this node is a child and FK is on the child)\n if (parentRelation && parentTempId && !parentFkOnParent) {\n fields[parentRelation.childField] = parentTempId\n }\n\n // Process pre-children: these need to be created BEFORE this node\n // because this node's FK points to them\n for (const { relation, value } of preChildren) {\n if (Array.isArray(value)) {\n for (const item of value) {\n const childTempId = walkNode(relation.childModel, item as Record<string, unknown>, tempId, relation, true)\n // Set this node's FK to point to the created child\n fields[relation.childField] = childTempId\n }\n }\n }\n\n // Create this node\n ops.push({ model: modelName, fields, tempId, batch: false })\n if (alias) aliases.set(alias, tempId)\n\n // Process post-children: normal case, FK is on the child\n for (const { relation, value } of postChildren) {\n if (Array.isArray(value)) {\n for (const item of value) {\n walkNode(relation.childModel, item as Record<string, unknown>, tempId, relation, false)\n }\n }\n }\n\n return tempId\n }\n\n for (const [modelName, nodes] of Object.entries(create)) {\n for (const node of nodes) {\n walkNode(modelName, node, null, null, false)\n }\n }\n\n return { ops, deferredUpdates, aliases }\n}\n","export class AutonomaError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly status: number,\n ) {\n super(message)\n this.name = 'AutonomaError'\n }\n}\n\nexport const Errors = {\n unknownAction(action: string) {\n return new AutonomaError(\n `Unknown action: ${action}`,\n 'UNKNOWN_ACTION',\n 400,\n )\n },\n unknownEnvironment(name: string) {\n return new AutonomaError(\n `Unknown environment: ${name}`,\n 'UNKNOWN_ENVIRONMENT',\n 400,\n )\n },\n invalidSignature() {\n return new AutonomaError(\n 'Invalid HMAC signature',\n 'INVALID_SIGNATURE',\n 401,\n )\n },\n invalidRefsToken(reason: string) {\n return new AutonomaError(\n `Invalid refs token: ${reason}`,\n 'INVALID_REFS_TOKEN',\n 403,\n )\n },\n productionBlocked() {\n return new AutonomaError(\n 'Environment factory is disabled in production',\n 'PRODUCTION_BLOCKED',\n 404,\n )\n },\n invalidBody(reason: string) {\n return new AutonomaError(\n `Invalid request body: ${reason}`,\n 'INVALID_BODY',\n 400,\n )\n },\n} as const\n","// AUTO-GENERATED by protocol/sql/codegen.ts — do not edit\n\nexport const POSTGRES_COLUMNS = `SELECT\n table_name,\n column_name,\n data_type,\n udt_name,\n is_nullable,\n column_default\nFROM information_schema.columns\nWHERE table_schema = '{{schema}}'\nORDER BY table_name, ordinal_position`\n\nexport const POSTGRES_ENUMS = `SELECT t.typname AS enum_name, e.enumlabel AS enum_value\nFROM pg_type t\nJOIN pg_enum e ON t.oid = e.enumtypid\nJOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\nORDER BY t.typname, e.enumsortorder`\n\nexport const POSTGRES_FOREIGN_KEYS = `SELECT\n kcu.table_name AS from_table,\n kcu.column_name AS from_column,\n ccu.table_name AS to_table,\n ccu.column_name AS to_column,\n c.is_nullable\nFROM information_schema.table_constraints tc\nJOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\nJOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.table_schema = ccu.table_schema\nLEFT JOIN information_schema.columns c\n ON c.table_schema = kcu.table_schema\n AND c.table_name = kcu.table_name\n AND c.column_name = kcu.column_name\nWHERE tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_schema = '{{schema}}'\nORDER BY kcu.table_name, kcu.ordinal_position`\n\nexport const POSTGRES_PRIMARY_KEYS = `SELECT\n tc.table_name,\n kcu.column_name\nFROM information_schema.table_constraints tc\nJOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\nWHERE tc.constraint_type = 'PRIMARY KEY'\n AND tc.table_schema = '{{schema}}'\nORDER BY tc.table_name, kcu.ordinal_position`\n\nexport const POSTGRES_TABLES = `SELECT table_name\nFROM information_schema.tables\nWHERE table_schema = '{{schema}}'\n AND table_type = 'BASE TABLE'\nORDER BY table_name`\n\nexport const MYSQL_COLUMNS = `SELECT\n table_name,\n column_name,\n data_type,\n column_type AS udt_name,\n is_nullable,\n column_default\nFROM information_schema.columns\nWHERE table_schema = '{{schema}}'\nORDER BY table_name, ordinal_position`\n\nexport const MYSQL_ENUMS = `SELECT NULL AS enum_name, NULL AS enum_value FROM DUAL WHERE 1 = 0`\n\nexport const MYSQL_FOREIGN_KEYS = `SELECT\n kcu.table_name AS from_table,\n kcu.column_name AS from_column,\n kcu.referenced_table_name AS to_table,\n kcu.referenced_column_name AS to_column,\n c.is_nullable\nFROM information_schema.key_column_usage kcu\nJOIN information_schema.columns c\n ON c.table_schema = kcu.table_schema\n AND c.table_name = kcu.table_name\n AND c.column_name = kcu.column_name\nWHERE kcu.referenced_table_name IS NOT NULL\n AND kcu.table_schema = '{{schema}}'\nORDER BY kcu.table_name, kcu.ordinal_position`\n\nexport const MYSQL_PRIMARY_KEYS = `SELECT\n tc.table_name,\n kcu.column_name\nFROM information_schema.table_constraints tc\nJOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\nWHERE tc.constraint_type = 'PRIMARY KEY'\n AND tc.table_schema = '{{schema}}'\nORDER BY tc.table_name, kcu.ordinal_position`\n\nexport const MYSQL_TABLES = `SELECT table_name\nFROM information_schema.tables\nWHERE table_schema = '{{schema}}'\n AND table_type = 'BASE TABLE'\nORDER BY table_name`\n","/** Database dialect abstraction — generates dialect-specific SQL strings. */\n\nimport {\n POSTGRES_TABLES,\n POSTGRES_COLUMNS,\n POSTGRES_PRIMARY_KEYS,\n POSTGRES_FOREIGN_KEYS,\n POSTGRES_ENUMS,\n MYSQL_TABLES,\n MYSQL_COLUMNS,\n MYSQL_PRIMARY_KEYS,\n MYSQL_FOREIGN_KEYS,\n MYSQL_ENUMS,\n} from './generated/sql-queries'\n\nexport interface Dialect {\n readonly name: 'postgres' | 'mysql' | 'sqlite'\n /** Parameter placeholder for index (1-based). Postgres: $1, MySQL/SQLite: ? */\n param(index: number): string\n /** Quote an identifier. Postgres: \"name\", MySQL: `name` */\n quoteId(name: string): string\n /** Whether INSERT ... RETURNING is supported */\n readonly supportsReturning: boolean\n\n /** SQL to list all base tables in a schema/database */\n tablesSQL(schema: string): string\n /** SQL to list all columns for all tables in a schema/database */\n columnsSQL(schema: string): string\n /** SQL to list primary key columns */\n primaryKeysSQL(schema: string): string\n /** SQL to list foreign key relationships */\n foreignKeysSQL(schema: string): string\n /** SQL to list enum types and their values */\n enumsSQL(schema: string): string\n}\n\nconst replaceSchema = (template: string, schema: string) =>\n template.replace('{{schema}}', schema)\n\nexport const postgres: Dialect = {\n name: 'postgres',\n param: (i) => `$${i}`,\n quoteId: (name) => `\"${name}\"`,\n supportsReturning: true,\n\n tablesSQL: (schema) => replaceSchema(POSTGRES_TABLES, schema),\n columnsSQL: (schema) => replaceSchema(POSTGRES_COLUMNS, schema),\n primaryKeysSQL: (schema) => replaceSchema(POSTGRES_PRIMARY_KEYS, schema),\n foreignKeysSQL: (schema) => replaceSchema(POSTGRES_FOREIGN_KEYS, schema),\n enumsSQL: () => POSTGRES_ENUMS,\n}\n\nexport const mysql: Dialect = {\n name: 'mysql',\n param: () => '?',\n quoteId: (name) => `\\`${name}\\``,\n supportsReturning: false,\n\n tablesSQL: (schema) => replaceSchema(MYSQL_TABLES, schema),\n columnsSQL: (schema) => replaceSchema(MYSQL_COLUMNS, schema),\n primaryKeysSQL: (schema) => replaceSchema(MYSQL_PRIMARY_KEYS, schema),\n foreignKeysSQL: (schema) => replaceSchema(MYSQL_FOREIGN_KEYS, schema),\n enumsSQL: () => MYSQL_ENUMS,\n}\n\nexport function getDialect(name: 'postgres' | 'mysql' | 'sqlite' = 'postgres'): Dialect {\n switch (name) {\n case 'postgres':\n return postgres\n case 'mysql':\n return mysql\n default:\n throw new Error(`Dialect \"${name}\" is not yet supported. Currently only \"postgres\" and \"mysql\" are available.`)\n }\n}\n","import type { SQLExecutor, SchemaInfo, SchemaRelation, ModelInfo, FieldInfo, FKEdge } from './types'\nimport type { Dialect } from './dialect'\n\n/** Internal result including name mapping tables */\nexport interface IntrospectionResult {\n schema: SchemaInfo\n /** model name → DB table name */\n tableMap: Map<string, string>\n /** model name → (field name → DB column name) */\n columnMaps: Map<string, Map<string, string>>\n /** model name → (field name → Postgres enum type name). Only populated for Postgres. */\n enumTypeMaps: Map<string, Map<string, string>>\n}\n\ninterface TableRow { table_name: string }\ninterface ColumnRow {\n table_name: string\n column_name: string\n data_type: string\n udt_name: string\n is_nullable: string\n column_default: string | null\n}\ninterface PKRow { table_name: string; column_name: string }\ninterface FKRow {\n from_table: string\n from_column: string\n to_table: string\n to_column: string\n is_nullable: string\n}\ninterface EnumRow { enum_name: string; enum_value: string }\n\n/**\n * Introspect a database via information_schema to build SchemaInfo.\n *\n * Auto-maps DB names (snake_case) to model names (PascalCase) and\n * field names (camelCase). Override with `tableNameMap`.\n */\nexport async function introspectDatabase(\n executor: SQLExecutor,\n dialect: Dialect,\n config: {\n scopeField: string\n schema?: string\n tableNameMap?: Record<string, string>\n excludeTables?: string[]\n },\n): Promise<IntrospectionResult> {\n const dbSchema = config.schema ?? (dialect.name === 'mysql' ? undefined : 'public')\n if (!dbSchema) {\n throw new Error('MySQL requires a schema (database name). Pass it via config.schema or HandlerConfig.dbSchema.')\n }\n const excludeSet = new Set(config.excludeTables ?? ['_prisma_migrations'])\n\n // Run all introspection queries in parallel.\n // Normalize row keys to lowercase — MySQL's information_schema can return\n // column names in uppercase (TABLE_NAME vs table_name).\n const [tableRows, columnRows, pkRows, fkRows, enumRows] = await Promise.all([\n executor.query<TableRow>(dialect.tablesSQL(dbSchema)).then(normalizeKeys),\n executor.query<ColumnRow>(dialect.columnsSQL(dbSchema)).then(normalizeKeys),\n executor.query<PKRow>(dialect.primaryKeysSQL(dbSchema)).then(normalizeKeys),\n executor.query<FKRow>(dialect.foreignKeysSQL(dbSchema)).then(normalizeKeys),\n executor.query<EnumRow>(dialect.enumsSQL(dbSchema)).then(normalizeKeys),\n ])\n\n // Build enum lookup: name → values[]\n // For Postgres: from pg_type/pg_enum rows\n // For MySQL: extracted from column_type in the column rows below\n const enumValues = new Map<string, string[]>()\n for (const row of enumRows) {\n if (!row.enum_name) continue\n if (!enumValues.has(row.enum_name)) enumValues.set(row.enum_name, [])\n enumValues.get(row.enum_name)!.push(row.enum_value)\n }\n\n // For MySQL, parse inline enums from column_type (udt_name alias)\n // e.g. \"enum('WEB','ANDROID','IOS')\" → ['WEB','ANDROID','IOS']\n if (dialect.name === 'mysql') {\n for (const col of columnRows) {\n const parsed = parseMySQLEnum(col.udt_name)\n if (parsed) {\n const enumKey = `${col.table_name}.${col.column_name}`\n enumValues.set(enumKey, parsed)\n }\n }\n }\n\n // Build PK lookup: table_name → Set<column_name>\n const pksByTable = new Map<string, Set<string>>()\n for (const row of pkRows) {\n if (!pksByTable.has(row.table_name)) pksByTable.set(row.table_name, new Set())\n pksByTable.get(row.table_name)!.add(row.column_name)\n }\n\n // Build table name mapping\n const userMap = config.tableNameMap ?? {}\n const tableMap = new Map<string, string>()\n const reverseTableMap = new Map<string, string>()\n\n // First, register user-provided mappings\n for (const [model, dbTable] of Object.entries(userMap)) {\n tableMap.set(model, dbTable)\n reverseTableMap.set(dbTable, model)\n }\n\n // Then auto-map remaining tables\n const dbTables = tableRows\n .map((r) => r.table_name)\n .filter((t) => !excludeSet.has(t))\n\n for (const dbTable of dbTables) {\n if (reverseTableMap.has(dbTable)) continue\n const modelName = snakeToPascal(dbTable)\n tableMap.set(modelName, dbTable)\n reverseTableMap.set(dbTable, modelName)\n }\n\n // Build column maps and model info\n const models: ModelInfo[] = []\n const columnMaps = new Map<string, Map<string, string>>()\n const enumTypeMaps = new Map<string, Map<string, string>>()\n\n // Group columns by table\n const columnsByTable = new Map<string, ColumnRow[]>()\n for (const row of columnRows) {\n if (!columnsByTable.has(row.table_name)) columnsByTable.set(row.table_name, [])\n columnsByTable.get(row.table_name)!.push(row)\n }\n\n for (const [modelName, dbTable] of tableMap) {\n const cols = columnsByTable.get(dbTable) ?? []\n const pks = pksByTable.get(dbTable) ?? new Set<string>()\n const colMap = new Map<string, string>()\n const fields: FieldInfo[] = []\n\n for (const col of cols) {\n const fieldName = snakeToCamel(col.column_name)\n colMap.set(fieldName, col.column_name)\n\n // Check for enum values\n let enumVals: string[] | undefined\n if (dialect.name === 'mysql') {\n enumVals = enumValues.get(`${col.table_name}.${col.column_name}`)\n } else {\n enumVals = enumValues.get(col.udt_name)\n }\n\n const type = enumVals\n ? `enum(${enumVals.join(',')})`\n : mapDataType(col.data_type, col.udt_name, dialect.name)\n\n // Track Postgres types that need explicit parameter casting.\n // Prisma's $queryRawUnsafe sends string params as explicit text type,\n // preventing Postgres auto-cast for enums, jsonb, and timestamps.\n if (dialect.name === 'postgres') {\n if (enumVals) {\n if (!enumTypeMaps.has(modelName)) enumTypeMaps.set(modelName, new Map())\n enumTypeMaps.get(modelName)!.set(fieldName, col.udt_name)\n } else if (col.data_type === 'jsonb' || col.udt_name === 'jsonb' || col.data_type === 'json' || col.udt_name === 'json') {\n if (!enumTypeMaps.has(modelName)) enumTypeMaps.set(modelName, new Map())\n const jsonType = (col.data_type === 'json' || col.udt_name === 'json') ? 'json' : 'jsonb'\n enumTypeMaps.get(modelName)!.set(fieldName, jsonType)\n } else if (col.data_type.includes('timestamp') || col.udt_name === 'timestamptz' || col.udt_name === 'timestamp') {\n if (!enumTypeMaps.has(modelName)) enumTypeMaps.set(modelName, new Map())\n enumTypeMaps.get(modelName)!.set(fieldName, col.udt_name)\n }\n }\n\n fields.push({\n name: fieldName,\n type,\n isRequired: col.is_nullable === 'NO',\n isId: pks.has(col.column_name),\n hasDefault: col.column_default !== null,\n })\n }\n\n columnMaps.set(modelName, colMap)\n models.push({ name: modelName, tableName: dbTable, fields })\n }\n\n // Build FK edges\n const edges: FKEdge[] = []\n for (const fk of fkRows) {\n const fromModel = reverseTableMap.get(fk.from_table)\n const toModel = reverseTableMap.get(fk.to_table)\n if (!fromModel || !toModel) continue\n\n const fromColMap = columnMaps.get(fromModel)\n const toColMap = columnMaps.get(toModel)\n const localField = fromColMap ? reverseGet(fromColMap, fk.from_column) ?? fk.from_column : fk.from_column\n const foreignField = toColMap ? reverseGet(toColMap, fk.to_column) ?? fk.to_column : fk.to_column\n\n edges.push({\n from: fromModel,\n to: toModel,\n localField,\n foreignField,\n nullable: fk.is_nullable === 'YES',\n })\n }\n\n // Build relations from FK edges.\n // For each edge (from→to), generate two relations:\n // 1. Parent-side: on the \"to\" model, a field pointing to \"from\" model (e.g., Organization.members)\n // 2. Child-side: on the \"from\" model, a field pointing to \"to\" model (e.g., Member.organization)\n const relations: SchemaRelation[] = []\n for (const edge of edges) {\n // Detect one-to-one: if the FK column is the sole PK of the child table,\n // the relationship is one-to-one (e.g., WebApplicationData.applicationId is\n // both PK and FK → Application has singular webApplicationData, not plural).\n const fromDbTable = tableMap.get(edge.from)!\n const fromColMap = columnMaps.get(edge.from) ?? new Map<string, string>()\n const fkDbCol = fromColMap.get(edge.localField) ?? edge.localField\n const fromPks = pksByTable.get(fromDbTable)\n const isOneToOne = fromPks !== undefined && fromPks.size === 1 && fromPks.has(fkDbCol)\n\n // Parent-side: \"to\" model has a collection/reference to \"from\" model\n relations.push({\n parentModel: edge.to,\n childModel: edge.from,\n parentField: isOneToOne ? lowerFirst(edge.from) : pluralCamelCase(edge.from),\n childField: edge.localField,\n })\n\n // Child-side: \"from\" model has a singular reference to \"to\" model (FK is on this side)\n relations.push({\n parentModel: edge.from,\n childModel: edge.to,\n parentField: lowerFirst(edge.to),\n childField: edge.localField,\n })\n }\n\n return {\n schema: { models, edges, relations, scopeField: config.scopeField },\n tableMap,\n columnMaps,\n enumTypeMaps,\n }\n}\n\n// --- Name mapping utilities ---\n\nfunction snakeToPascal(str: string): string {\n return str\n .split('_')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n .join('')\n}\n\nfunction snakeToCamel(str: string): string {\n const pascal = snakeToPascal(str)\n return pascal.charAt(0).toLowerCase() + pascal.slice(1)\n}\n\n/**\n * Parse MySQL inline enum definition: \"enum('a','b','c')\" → ['a','b','c']\n */\nfunction parseMySQLEnum(columnType: string): string[] | null {\n if (!columnType) return null\n const match = columnType.match(/^enum\\((.+)\\)$/i)\n if (!match) return null\n return match[1]!\n .split(',')\n .map((v) => v.trim().replace(/^'|'$/g, ''))\n}\n\nfunction mapDataType(dataType: string, udtName: string, dialectName: string): string {\n const dt = dataType.toLowerCase()\n\n // MySQL tinyint(1) is conventionally Boolean — check column_type (udtName) before generic tinyint mapping.\n // data_type from information_schema is just \"tinyint\"; the display width lives in udt_name (column_type).\n if (dialectName === 'mysql' && dt === 'tinyint' && udtName.toLowerCase().startsWith('tinyint(1)')) return 'Boolean'\n\n // Integer types\n if (dt === 'integer' || dt === 'smallint' || dt === 'bigint' || dt === 'int' || dt === 'mediumint' || dt === 'tinyint') return 'Int'\n\n // Float types\n if (dt === 'numeric' || dt === 'real' || dt === 'double precision' || dt === 'float' || dt === 'double' || dt === 'decimal') return 'Float'\n\n // Boolean (Postgres native boolean type, or tinyint(1) when data_type includes display width)\n if (dt === 'boolean' || dt === 'tinyint(1)') return 'Boolean'\n\n // String types\n if (dt === 'text' || dt === 'character varying' || dt === 'character' || dt === 'varchar' || dt === 'char'\n || dt === 'mediumtext' || dt === 'longtext' || dt === 'tinytext') return 'String'\n\n // DateTime types\n if (dt === 'timestamp with time zone' || dt === 'timestamp without time zone'\n || dt === 'date' || dt === 'time' || dt === 'datetime' || dt === 'timestamp') return 'DateTime'\n\n // JSON types\n if (dt === 'json' || dt === 'jsonb') return 'Json'\n\n // UUID / binary\n if (dt === 'uuid') return 'String'\n if (dt === 'bytea' || dt === 'blob' || dt === 'mediumblob' || dt === 'longblob' || dt === 'tinyblob' || dt === 'binary' || dt === 'varbinary') return 'Bytes'\n\n // Postgres user-defined (enums handled by caller)\n if (dt === 'user-defined' && dialectName === 'postgres') return udtName\n\n // MySQL enum is handled before this function is called\n if (dt === 'enum' || dt === 'set') return udtName\n\n return dataType\n}\n\nfunction lowerFirst(str: string): string {\n return str.charAt(0).toLowerCase() + str.slice(1)\n}\n\n/**\n * Convert a PascalCase model name to a camelCase plural field name.\n * e.g., \"Member\" → \"members\", \"Application\" → \"applications\", \"ApiKey\" → \"apiKeys\"\n */\nfunction pluralCamelCase(modelName: string): string {\n const camel = lowerFirst(modelName)\n return pluralize(camel)\n}\n\nfunction pluralize(str: string): string {\n if (str.endsWith('s') || str.endsWith('x') || str.endsWith('z') || str.endsWith('ch') || str.endsWith('sh')) {\n return str + 'es'\n }\n if (str.endsWith('y') && str.length > 1 && !isVowel(str.charAt(str.length - 2))) {\n return str.slice(0, -1) + 'ies'\n }\n return str + 's'\n}\n\nfunction isVowel(ch: string): boolean {\n return 'aeiou'.includes(ch.toLowerCase())\n}\n\n/**\n * Lowercase all keys in each row — handles MySQL information_schema returning\n * uppercase column names (TABLE_NAME, COLUMN_NAME, etc.)\n */\nfunction normalizeKeys<T>(rows: T[]): T[] {\n return rows.map((row) => {\n if (!row || typeof row !== 'object') return row\n const normalized: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(row as Record<string, unknown>)) {\n normalized[key.toLowerCase()] = val\n }\n return normalized as T\n })\n}\n\n/** Reverse lookup: find the key whose value matches `dbName` */\nfunction reverseGet(map: Map<string, string>, dbName: string): string | null {\n for (const [key, val] of map) {\n if (val === dbName) return key\n }\n return null\n}\n","import { randomUUID } from 'node:crypto'\nimport type { SQLExecutor, ResolvedEntitySpec, CreateContext, ModelInfo } from './types'\nimport type { Dialect } from './dialect'\n\n/**\n * Create entities via raw SQL INSERT.\n *\n * Entities arrive pre-sorted by FK order (handler does topo-sort via tree.ts).\n * Each model in `spec` is inserted sequentially; within a model, batch mode\n * uses a single multi-row INSERT while normal mode inserts one row at a time.\n *\n * For dialects with RETURNING (Postgres): INSERT ... RETURNING *\n * For dialects without (MySQL): INSERT then SELECT via LAST_INSERT_ID()\n */\nexport async function createEntities(\n executor: SQLExecutor,\n dialect: Dialect,\n tableMap: Map<string, string>,\n columnMaps: Map<string, Map<string, string>>,\n spec: Record<string, ResolvedEntitySpec>,\n _context: CreateContext,\n enumTypeMaps: Map<string, Map<string, string>> = new Map(),\n schemaModels: ModelInfo[] = [],\n): Promise<Record<string, Record<string, unknown>[]>> {\n const results: Record<string, Record<string, unknown>[]> = {}\n\n for (const [model, entitySpec] of Object.entries(spec)) {\n const dbTable = tableMap.get(model)\n if (!dbTable) throw new Error(`Unknown model \"${model}\". Not found in database tables.`)\n const colMap = columnMaps.get(model) ?? new Map<string, string>()\n const enumTypeMap = enumTypeMaps.get(model) ?? new Map<string, string>()\n\n // Bug 4: find actual PK field name from schema\n const modelInfo = schemaModels.find((m) => m.name === model)\n const pkField = modelInfo?.fields.find((f) => f.isId)\n const pkFieldName = pkField?.name ?? 'id'\n const pkFieldType = pkField?.type ?? 'String'\n\n if (entitySpec.batch && entitySpec.fields.length > 0) {\n results[model] = await insertBatch(executor, dialect, dbTable, colMap, enumTypeMap, entitySpec.fields, pkFieldName, pkFieldType)\n } else {\n const created: Record<string, unknown>[] = []\n for (const fields of entitySpec.fields) {\n const [record] = await insertOne(executor, dialect, dbTable, colMap, enumTypeMap, fields, pkFieldName, pkFieldType)\n if (record) created.push(record)\n }\n results[model] = created\n }\n }\n\n return results\n}\n\n/**\n * Update a single record by primary key. Used for circular FK backfill.\n */\nexport async function updateEntity(\n executor: SQLExecutor,\n dialect: Dialect,\n tableMap: Map<string, string>,\n columnMaps: Map<string, Map<string, string>>,\n model: string,\n id: string,\n fields: Record<string, unknown>,\n enumTypeMaps: Map<string, Map<string, string>> = new Map(),\n pkFieldName: string = 'id',\n): Promise<void> {\n const dbTable = tableMap.get(model)\n if (!dbTable) throw new Error(`Unknown model \"${model}\" for update.`)\n const colMap = columnMaps.get(model) ?? new Map<string, string>()\n const enumTypeMap = enumTypeMaps.get(model) ?? new Map<string, string>()\n\n const setClauses: string[] = []\n const params: unknown[] = []\n let paramIdx = 1\n\n for (const [fieldName, value] of Object.entries(fields)) {\n const dbCol = colMap.get(fieldName) ?? fieldName\n setClauses.push(`${dialect.quoteId(dbCol)} = ${castParam(dialect, paramIdx, enumTypeMap, fieldName)}`)\n params.push(serializeValue(value, dialect))\n paramIdx++\n }\n\n const idCol = colMap.get(pkFieldName) ?? pkFieldName\n params.push(id)\n\n const sql = `UPDATE ${dialect.quoteId(dbTable)} SET ${setClauses.join(', ')} WHERE ${dialect.quoteId(idCol)} = ${dialect.param(paramIdx)}`\n await executor.query(sql, params)\n}\n\n// --- Internal helpers ---\n\nasync function insertOne(\n executor: SQLExecutor,\n dialect: Dialect,\n dbTable: string,\n colMap: Map<string, string>,\n enumTypeMap: Map<string, string>,\n fields: Record<string, unknown>,\n pkFieldName: string = 'id',\n pkFieldType: string = 'String',\n): Promise<Record<string, unknown>[]> {\n // Generate a client-side ID when none is provided and the PK type is String.\n // Int/BigInt PKs use DB auto-increment, so we skip UUID generation for those.\n if (pkFieldName && fields[pkFieldName] === undefined && pkFieldType === 'String') {\n fields = { ...fields, [pkFieldName]: randomUUID() }\n }\n\n const entries = Object.entries(fields)\n\n if (entries.length === 0) {\n const sql = `INSERT INTO ${dialect.quoteId(dbTable)} DEFAULT VALUES RETURNING *`\n return mapRowsBack(await executor.query(sql), colMap)\n }\n\n const dbCols: string[] = []\n const params: unknown[] = []\n const placeholders: string[] = []\n let paramIdx = 1\n\n for (const [fieldName, value] of entries) {\n const dbCol = colMap.get(fieldName) ?? fieldName\n dbCols.push(dialect.quoteId(dbCol))\n placeholders.push(castParam(dialect, paramIdx, enumTypeMap, fieldName))\n params.push(serializeValue(value, dialect))\n paramIdx++\n }\n\n const colList = dbCols.join(', ')\n const valList = placeholders.join(', ')\n\n if (dialect.supportsReturning) {\n const sql = `INSERT INTO ${dialect.quoteId(dbTable)} (${colList}) VALUES (${valList}) RETURNING *`\n return mapRowsBack(await executor.query(sql, params), colMap)\n }\n\n // MySQL: INSERT then SELECT back by the ID we set\n await executor.query(\n `INSERT INTO ${dialect.quoteId(dbTable)} (${colList}) VALUES (${valList})`,\n params,\n )\n\n const idCol = colMap.get(pkFieldName) ?? pkFieldName\n const id = fields[pkFieldName]\n\n return mapRowsBack(\n await executor.query(\n `SELECT * FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(idCol)} = ${dialect.param(1)}`,\n [id],\n ),\n colMap,\n )\n}\n\nasync function insertBatch(\n executor: SQLExecutor,\n dialect: Dialect,\n dbTable: string,\n colMap: Map<string, string>,\n enumTypeMap: Map<string, string>,\n fieldsArr: Record<string, unknown>[],\n pkFieldName: string = 'id',\n pkFieldType: string = 'String',\n): Promise<Record<string, unknown>[]> {\n if (fieldsArr.length === 0) return []\n\n // Generate client-side IDs for batch records when the PK type is String.\n // Int/BigInt PKs use DB auto-increment.\n if (pkFieldName && pkFieldType === 'String') {\n fieldsArr = fieldsArr.map((fields) => {\n if (fields[pkFieldName] === undefined) {\n return { ...fields, [pkFieldName]: randomUUID() }\n }\n return fields\n })\n }\n\n // Compute the union of keys across all rows in deterministic (sorted) order.\n const fieldNameSet = new Set<string>()\n for (const fields of fieldsArr) {\n for (const key of Object.keys(fields)) {\n fieldNameSet.add(key)\n }\n }\n const fieldNames = [...fieldNameSet].sort()\n\n // If no fields at all, fall back to individual DEFAULT VALUES inserts.\n if (fieldNames.length === 0) {\n const allResults: Record<string, unknown>[] = []\n for (const fields of fieldsArr) {\n const [record] = await insertOne(executor, dialect, dbTable, colMap, enumTypeMap, fields)\n if (record) allResults.push(record)\n }\n return allResults\n }\n\n const dbCols = fieldNames.map((f) => dialect.quoteId(colMap.get(f) ?? f))\n const colList = dbCols.join(', ')\n\n // Postgres has a max of 32,767 bind variables per statement.\n // Chunk large batches to stay within this limit.\n const MAX_PARAMS = 32_000\n const chunkSize = Math.max(1, Math.floor(MAX_PARAMS / fieldNames.length))\n const allResults: Record<string, unknown>[] = []\n\n for (let offset = 0; offset < fieldsArr.length; offset += chunkSize) {\n const chunk = fieldsArr.slice(offset, offset + chunkSize)\n const params: unknown[] = []\n const valueTuples: string[] = []\n let paramIdx = 1\n\n for (const fields of chunk) {\n const placeholders: string[] = []\n for (const fieldName of fieldNames) {\n placeholders.push(castParam(dialect, paramIdx, enumTypeMap, fieldName))\n params.push(serializeValue(fields[fieldName], dialect))\n paramIdx++\n }\n valueTuples.push(`(${placeholders.join(', ')})`)\n }\n\n const valList = valueTuples.join(', ')\n\n if (dialect.supportsReturning) {\n const sql = `INSERT INTO ${dialect.quoteId(dbTable)} (${colList}) VALUES ${valList} RETURNING *`\n allResults.push(...mapRowsBack(await executor.query(sql, params), colMap))\n } else {\n await executor.query(\n `INSERT INTO ${dialect.quoteId(dbTable)} (${colList}) VALUES ${valList}`,\n params,\n )\n }\n }\n\n return allResults\n}\n\n/**\n * Map DB column names back to camelCase field names in returned rows.\n */\nfunction mapRowsBack(\n rows: Record<string, unknown>[],\n colMap: Map<string, string>,\n): Record<string, unknown>[] {\n if (colMap.size === 0) return rows\n\n const reverse = new Map<string, string>()\n for (const [fieldName, dbCol] of colMap) {\n reverse.set(dbCol, fieldName)\n }\n\n return rows.map((row) => {\n const mapped: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(row)) {\n const fieldName = reverse.get(key) ?? key\n mapped[fieldName] = value\n }\n return mapped\n })\n}\n\n\n/**\n * Build a parameter placeholder with an optional Postgres enum cast.\n * e.g. `$1::\"ApplicationArchitecture\"` for enum fields, or just `$1` otherwise.\n */\nfunction castParam(\n dialect: Dialect,\n paramIdx: number,\n enumTypeMap: Map<string, string>,\n fieldName: string,\n): string {\n const placeholder = dialect.param(paramIdx)\n if (dialect.name === 'postgres') {\n const enumType = enumTypeMap.get(fieldName)\n if (enumType) return `${placeholder}::${dialect.quoteId(enumType)}`\n }\n return placeholder\n}\n\n/** Pre-compiled regex for MySQL datetime detection (avoids re-compilation per call). */\nconst MYSQL_DATETIME_RE = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/\n\n/**\n * Serialize a JS value for SQL insertion.\n * Handles MySQL-specific quirks:\n * - Objects/arrays → JSON.stringify (MySQL requires JSON strings, not objects)\n * - ISO 8601 datetime strings → MySQL DATETIME format\n */\nfunction serializeValue(value: unknown, dialect: Dialect): unknown {\n if (value === null || value === undefined) return null\n\n // JSON: stringify objects/dicts for JSON/JSONB columns.\n // Arrays are returned as native arrays for Postgres ARRAY columns.\n if (typeof value === 'object' && !(value instanceof Date)) {\n if (Array.isArray(value)) return value\n return JSON.stringify(value)\n }\n\n // DateTime: MySQL doesn't accept ISO 8601 with 'T' and 'Z'\n if (typeof value === 'string' && dialect.name === 'mysql') {\n if (MYSQL_DATETIME_RE.test(value)) {\n return value.replace('T', ' ').replace('Z', '').replace(/\\.\\d+$/, '')\n }\n }\n\n return value\n}\n","import type { SQLExecutor, SchemaInfo } from './types'\nimport type { Dialect } from './dialect'\nimport { topoSort, findDeferrableEdge } from './graph'\n\n/**\n * Tear down all data scoped to a value, in reverse topological order.\n *\n * Strategy:\n * 1. Find the scope root model (e.g. Organization) from FK edges\n * 2. Any model with a FK pointing to the scope root is \"scoped\"\n * 3. Delete scoped models by their FK = scopeValue\n * 4. Delete non-scoped models by their record IDs from refs\n * 5. Delete the scope root entity last by id = scopeValue\n */\nexport async function teardown(\n executor: SQLExecutor,\n dialect: Dialect,\n tableMap: Map<string, string>,\n columnMaps: Map<string, Map<string, string>>,\n schema: SchemaInfo,\n scopeValue: string,\n refs?: Record<string, Record<string, unknown>[]>,\n): Promise<void> {\n // Find scope root: the model that the scopeField FK points TO\n let scopeRootModel: string | null = null\n for (const edge of schema.edges) {\n if (edge.localField.toLowerCase() === schema.scopeField.toLowerCase() && edge.to !== edge.from) {\n scopeRootModel = edge.to\n break\n }\n }\n\n // Build map: model → FK field name that points to the scope root\n const scopeFieldByModel = new Map<string, string>()\n if (scopeRootModel) {\n for (const edge of schema.edges) {\n if (edge.to === scopeRootModel && edge.from !== scopeRootModel) {\n scopeFieldByModel.set(edge.from, edge.localField)\n }\n }\n }\n\n const modelNames = schema.models.map((m) => m.name)\n const { sorted, cycles } = topoSort(modelNames, schema.edges)\n\n await executor.transaction(async (tx) => {\n // Break cycles by nullifying deferrable FKs\n for (const cycle of cycles) {\n const edge = findDeferrableEdge(cycle, schema.edges)\n if (edge) {\n const scopeFK = scopeFieldByModel.get(edge.from)\n if (scopeFK) {\n const dbTable = tableMap.get(edge.from)\n const colMap = columnMaps.get(edge.from) ?? new Map<string, string>()\n if (dbTable) {\n const dbFKCol = colMap.get(edge.localField) ?? edge.localField\n const dbScopeCol = colMap.get(scopeFK) ?? scopeFK\n await tx.query(\n `UPDATE ${dialect.quoteId(dbTable)} SET ${dialect.quoteId(dbFKCol)} = NULL WHERE ${dialect.quoteId(dbScopeCol)} = ${dialect.param(1)}`,\n [scopeValue],\n )\n }\n }\n }\n }\n\n // Delete non-cycle nodes in reverse topo order first (dependents before cycle nodes)\n const reversed = [...sorted].reverse()\n for (const model of reversed) {\n if (model === scopeRootModel) continue // deleted last\n await deleteModel(tx, dialect, tableMap, columnMaps, model, scopeValue, scopeFieldByModel, refs, schema)\n }\n\n // Delete cycle nodes after their non-cycle dependents are gone\n for (const cycle of cycles) {\n for (const model of cycle) {\n await deleteModel(tx, dialect, tableMap, columnMaps, model, scopeValue, scopeFieldByModel, refs, schema)\n }\n }\n\n // Delete the scope root entity last\n if (scopeRootModel) {\n const dbTable = tableMap.get(scopeRootModel)\n const colMap = columnMaps.get(scopeRootModel) ?? new Map<string, string>()\n if (dbTable) {\n const rootModelInfo = schema.models.find((m) => m.name === scopeRootModel)\n const rootPkFieldName = rootModelInfo?.fields.find((f) => f.isId)?.name ?? 'id'\n const idCol = colMap.get(rootPkFieldName) ?? rootPkFieldName\n await tx.query(\n `DELETE FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(idCol)} = ${dialect.param(1)}`,\n [scopeValue],\n )\n }\n }\n })\n}\n\nasync function deleteModel(\n tx: SQLExecutor,\n dialect: Dialect,\n tableMap: Map<string, string>,\n columnMaps: Map<string, Map<string, string>>,\n model: string,\n scopeValue: string,\n scopeFieldByModel: Map<string, string>,\n refs: Record<string, Record<string, unknown>[]> | undefined,\n schema: SchemaInfo,\n): Promise<void> {\n const dbTable = tableMap.get(model)\n if (!dbTable) return\n const colMap = columnMaps.get(model) ?? new Map<string, string>()\n\n // Find actual PK field name from schema\n const modelInfo = schema.models.find((m) => m.name === model)\n const pkFieldName = modelInfo?.fields.find((f) => f.isId)?.name ?? 'id'\n\n const scopeFK = scopeFieldByModel.get(model)\n if (scopeFK) {\n // Has FK to scope root → delete by that FK\n const dbCol = colMap.get(scopeFK) ?? scopeFK\n await tx.query(\n `DELETE FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(dbCol)} = ${dialect.param(1)}`,\n [scopeValue],\n )\n } else if (refs?.[model]) {\n // No FK to scope root, but we created records → delete by IDs\n const ids = refs[model]\n .map((r) => r[pkFieldName])\n .filter((id): id is string | number => id != null)\n if (ids.length > 0) {\n const idCol = colMap.get(pkFieldName) ?? pkFieldName\n const placeholders = ids.map((_, i) => dialect.param(i + 1)).join(', ')\n await tx.query(\n `DELETE FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(idCol)} IN (${placeholders})`,\n ids,\n )\n }\n }\n}\n","import type {\n HandlerConfig,\n HandlerRequest,\n HandlerResponse,\n ResolvedEntitySpec,\n SdkInfo,\n} from './types'\nimport { verifySignature } from './hmac'\nimport { signRefs, verifyRefs } from './refs'\nimport { resolveTree } from './tree'\nimport { AutonomaError, Errors } from './errors'\nimport { getDialect } from './dialect'\nimport { introspectDatabase, type IntrospectionResult } from './introspect'\nimport { createEntities, updateEntity } from './create'\nimport { teardown } from './teardown'\n\n/** Cache introspection results per config to avoid re-querying on every request */\nconst introspectionCache = new WeakMap<HandlerConfig, IntrospectionResult>()\n\nasync function getIntrospection(config: HandlerConfig): Promise<IntrospectionResult> {\n let cached = introspectionCache.get(config)\n if (cached) return cached\n\n const dialect = getDialect(config.dialect)\n cached = await introspectDatabase(config.executor, dialect, {\n scopeField: config.scopeField,\n schema: config.dbSchema,\n tableNameMap: config.tableNameMap,\n excludeTables: config.excludeTables,\n })\n introspectionCache.set(config, cached)\n return cached\n}\n\ndeclare const __PROTOCOL_VERSION__: string\nexport const PROTOCOL_VERSION = __PROTOCOL_VERSION__\n\nfunction buildSdkMeta(config: HandlerConfig): { version: string; sdk: SdkInfo } {\n return {\n version: PROTOCOL_VERSION,\n sdk: {\n language: 'typescript',\n orm: config.sdk?.orm ?? 'unknown',\n server: config.sdk?.server ?? 'unknown',\n },\n }\n}\n\nexport async function handleRequest(\n config: HandlerConfig,\n req: HandlerRequest,\n): Promise<HandlerResponse> {\n try {\n if (config.sharedSecret === config.signingSecret) {\n throw new AutonomaError(\n 'sharedSecret and signingSecret must be different. The shared secret is known by Autonoma; the signing secret must be private.',\n 'SAME_SECRETS',\n 500,\n )\n }\n\n if (!config.allowProduction && process.env.NODE_ENV === 'production') {\n throw Errors.productionBlocked()\n }\n\n const signature = req.headers['x-signature'] ?? req.headers['X-Signature'] ?? ''\n if (!verifySignature(req.body, signature, config.sharedSecret)) {\n throw Errors.invalidSignature()\n }\n\n let body: Record<string, unknown>\n try {\n body = JSON.parse(req.body)\n } catch {\n throw Errors.invalidBody('invalid JSON')\n }\n\n const action = body.action as string\n if (!action) throw Errors.invalidBody('missing action')\n\n switch (action) {\n case 'discover':\n return await handleDiscover(config)\n case 'up':\n return await handleUp(config, body)\n case 'down':\n return await handleDown(config, body)\n default:\n throw Errors.unknownAction(action)\n }\n } catch (err) {\n if (err instanceof AutonomaError) {\n return { status: err.status, body: { error: err.message, code: err.code } }\n }\n const message = err instanceof Error ? err.message : 'Internal error'\n return { status: 500, body: { error: message, code: 'INTERNAL_ERROR' } }\n }\n}\n\nasync function handleDiscover(config: HandlerConfig): Promise<HandlerResponse> {\n const { schema } = await getIntrospection(config)\n return { status: 200, body: { ...buildSdkMeta(config), schema } }\n}\n\nasync function handleUp(\n config: HandlerConfig,\n body: Record<string, unknown>,\n): Promise<HandlerResponse> {\n const create = body.create as Record<string, Record<string, unknown>[]> | undefined\n if (!create) throw Errors.invalidBody('missing \"create\" in request body')\n\n const testRunId = (body.testRunId as string) ?? crypto.randomUUID()\n const { schema, tableMap, columnMaps, enumTypeMaps } = await getIntrospection(config)\n const dialect = getDialect(config.dialect)\n\n const tree = resolveTree(create, schema)\n const refs: Record<string, Record<string, unknown>[]> = {}\n const idMap = new Map<string, string | number>()\n\n await config.executor.transaction(async (tx) => {\n let i = 0\n while (i < tree.ops.length) {\n const op = tree.ops[i]!\n const model = op.model\n\n // Collect consecutive ops for the same model with same batch flag\n const batch: typeof tree.ops = [op]\n while (i + 1 < tree.ops.length && tree.ops[i + 1]!.model === model && tree.ops[i + 1]!.batch === op.batch) {\n i++\n batch.push(tree.ops[i]!)\n }\n\n // Replace temp IDs with real IDs in all fields\n const modelInfo = schema.models.find((m) => m.name === model)\n const pkField = modelInfo?.fields.find((f) => f.isId)\n const pkFieldName = pkField?.name ?? 'id'\n const resolvedFields = batch.map((b) => {\n const fields = { ...b.fields }\n for (const [key, value] of Object.entries(fields)) {\n if (typeof value === 'string' && value.startsWith('__temp_')) {\n const realId = idMap.get(value)\n if (realId) fields[key] = realId\n }\n }\n // Inject scope field if applicable\n const scopeEdge = schema.edges.find(\n (e) => e.from === model && e.localField.replace(/_/g, '').toLowerCase() === schema.scopeField.replace(/_/g, '').toLowerCase() && e.from !== e.to,\n )\n if (scopeEdge && !(scopeEdge.localField in fields)) {\n const scopeVal = detectScopeValue(refs, schema.scopeField)\n if (scopeVal) fields[scopeEdge.localField] = scopeVal\n }\n // Auto-populate required fields without DB defaults (e.g. Prisma's @updatedAt)\n if (modelInfo) {\n for (const field of modelInfo.fields) {\n if (field.isRequired && !field.hasDefault && !field.isId && !(field.name in fields)) {\n if (field.type === 'DateTime') {\n fields[field.name] = new Date()\n }\n }\n }\n }\n return fields\n })\n\n const spec: Record<string, ResolvedEntitySpec> = {\n [model]: { count: resolvedFields.length, fields: resolvedFields, batch: op.batch },\n }\n\n const context = { testRunId, refs }\n const created = await createEntities(tx, dialect, tableMap, columnMaps, spec, context, enumTypeMaps, schema.models)\n const records = created[model] ?? []\n\n if (!refs[model]) refs[model] = []\n refs[model].push(...records)\n\n for (let j = 0; j < batch.length; j++) {\n const record = records[j]\n if (record) {\n const recordId = record[pkFieldName]\n if (recordId != null) {\n idMap.set(batch[j]!.tempId, recordId as string | number)\n }\n }\n }\n\n i++\n }\n\n // Resolve deferred FK updates (circular dependency cycles)\n for (const deferred of tree.deferredUpdates) {\n const realTargetId = idMap.get(deferred.targetTempId)\n const refTempId = tree.aliases.get(deferred.refAlias)\n const realRefId = refTempId ? idMap.get(refTempId) : undefined\n\n if (!realTargetId || !realRefId) {\n throw new Error(\n `_ref \"${deferred.refAlias}\" could not be resolved. Ensure the referenced node has _alias defined in the scenario.`,\n )\n }\n\n const deferredModelInfo = schema.models.find((m) => m.name === deferred.model)\n const deferredPkFieldName = deferredModelInfo?.fields.find((f) => f.isId)?.name ?? 'id'\n await updateEntity(tx, dialect, tableMap, columnMaps, deferred.model, String(realTargetId), { [deferred.field]: realRefId }, enumTypeMaps, deferredPkFieldName)\n }\n })\n\n const scopeValue = detectScopeValue(refs, schema.scopeField) ?? testRunId\n\n const firstUser = findFirstUser(refs)\n const auth = await config.auth(firstUser)\n\n const refsToken = signRefs(\n { refs, testRunId: scopeValue, environment: '' },\n config.signingSecret,\n )\n\n return { status: 200, body: { ...buildSdkMeta(config), auth, refs, refsToken } }\n}\n\nasync function handleDown(\n config: HandlerConfig,\n body: Record<string, unknown>,\n): Promise<HandlerResponse> {\n const refsToken = body.refsToken as string\n if (!refsToken) throw Errors.invalidBody('missing refsToken')\n\n let payload: ReturnType<typeof verifyRefs>\n try {\n payload = verifyRefs(refsToken, config.signingSecret)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'invalid token'\n throw Errors.invalidRefsToken(message)\n }\n\n const { schema, tableMap, columnMaps } = await getIntrospection(config)\n const dialect = getDialect(config.dialect)\n\n await teardown(config.executor, dialect, tableMap, columnMaps, schema, payload.testRunId, payload.refs)\n\n return { status: 200, body: { ...buildSdkMeta(config), ok: true } }\n}\n\nfunction findFirstUser(\n refs: Record<string, Record<string, unknown>[]>,\n): Record<string, unknown> | null {\n for (const [model, records] of Object.entries(refs)) {\n const normalized = model.toLowerCase()\n if ((normalized === 'user' || normalized === 'users') && records.length > 0) {\n return records[0]!\n }\n }\n return null\n}\n\nfunction detectScopeValue(\n refs: Record<string, Record<string, unknown>[]>,\n scopeField: string,\n): string | null {\n const scopeNormalized = scopeField.replace(/_/g, '').toLowerCase()\n for (const records of Object.values(refs)) {\n for (const record of records) {\n for (const [key, value] of Object.entries(record)) {\n if (key.replace(/_/g, '').toLowerCase() === scopeNormalized && typeof value === 'string') {\n return value\n }\n }\n }\n }\n return null\n}\n","import { createHash } from 'node:crypto'\n\n/**\n * Compute a stable 16-char hex fingerprint of a scenario definition.\n * Uses sha256 of the JSON-serialized spec with sorted keys.\n */\nexport function fingerprint(value: unknown): string {\n const json = JSON.stringify(value, sortReplacer)\n return createHash('sha256').update(json).digest('hex').slice(0, 16)\n}\n\n/**\n * JSON replacer that sorts object keys for deterministic serialization.\n */\nfunction sortReplacer(_key: string, value: unknown): unknown {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return Object.keys(value as Record<string, unknown>)\n .sort()\n .reduce(\n (sorted, k) => {\n sorted[k] = (value as Record<string, unknown>)[k]\n return sorted\n },\n {} as Record<string, unknown>,\n )\n }\n return value\n}\n","import type {\n SQLExecutor,\n ScenarioDefinition,\n HandlerConfig,\n} from './types'\nimport { handleRequest } from './handler'\nimport { signBody } from './hmac'\n\nexport interface CheckResult {\n valid: boolean\n phase: 'up' | 'down' | 'ok'\n errors: CheckError[]\n timing?: { upMs: number; downMs: number }\n}\n\nexport interface CheckError {\n phase: 'up' | 'down'\n message: string\n fix?: string\n}\n\n/**\n * Dry-run a scenario against a real database.\n * Runs the full up → down cycle and returns structured errors.\n */\nexport async function checkScenario(\n executor: SQLExecutor,\n scenario: ScenarioDefinition,\n options?: {\n scopeField: string\n dialect?: HandlerConfig['dialect']\n dbSchema?: string\n tableNameMap?: Record<string, string>\n sharedSecret?: string\n signingSecret?: string\n auth?: HandlerConfig['auth']\n },\n): Promise<CheckResult> {\n const sharedSecret = options?.sharedSecret ?? 'autonoma-check-shared'\n const signingSecret = options?.signingSecret ?? 'autonoma-check-signing'\n\n const config: HandlerConfig = {\n executor,\n scopeField: options?.scopeField ?? 'organizationId',\n dialect: options?.dialect,\n dbSchema: options?.dbSchema,\n tableNameMap: options?.tableNameMap,\n sharedSecret,\n signingSecret,\n auth: options?.auth ?? (async () => ({ headers: { Authorization: 'Bearer check-token' } })),\n }\n\n // Up\n const upBody = JSON.stringify({ action: 'up', create: scenario.create })\n const upReq = {\n body: upBody,\n headers: { 'x-signature': signBody(upBody, sharedSecret) },\n }\n\n const t0 = performance.now()\n const upRes = await handleRequest(config, upReq)\n const upMs = Math.round(performance.now() - t0)\n\n if (upRes.status !== 200) {\n const errorMsg = (upRes.body as Record<string, string>).error ?? 'Unknown error'\n return {\n valid: false,\n phase: 'up',\n errors: [{ phase: 'up', message: errorMsg, fix: suggestFix(errorMsg) }],\n timing: { upMs, downMs: 0 },\n }\n }\n\n // Down\n const refsToken = (upRes.body as Record<string, string>).refsToken\n const downBody = JSON.stringify({ action: 'down', refsToken })\n const downReq = {\n body: downBody,\n headers: { 'x-signature': signBody(downBody, sharedSecret) },\n }\n\n const t1 = performance.now()\n const downRes = await handleRequest(config, downReq)\n const downMs = Math.round(performance.now() - t1)\n\n if (downRes.status !== 200) {\n const errorMsg = (downRes.body as Record<string, string>).error ?? 'Unknown error'\n return {\n valid: false,\n phase: 'down',\n errors: [{ phase: 'down', message: errorMsg }],\n timing: { upMs, downMs },\n }\n }\n\n return { valid: true, phase: 'ok', errors: [], timing: { upMs, downMs } }\n}\n\n/**\n * Check multiple scenarios sequentially.\n */\nexport async function checkAllScenarios(\n executor: SQLExecutor,\n scenarios: ScenarioDefinition[],\n options?: {\n scopeField: string\n dialect?: HandlerConfig['dialect']\n dbSchema?: string\n tableNameMap?: Record<string, string>\n sharedSecret?: string\n signingSecret?: string\n auth?: HandlerConfig['auth']\n },\n): Promise<CheckResult[]> {\n const results: CheckResult[] = []\n for (const scenario of scenarios) {\n results.push(await checkScenario(executor, scenario, options))\n }\n return results\n}\n\nfunction suggestFix(errorMsg: string): string {\n if (errorMsg.includes('Unique constraint failed') || errorMsg.includes('unique constraint')) {\n const match = errorMsg.match(/fields: \\(`(.+?)`\\)/) ?? errorMsg.match(/constraint \"(.+?)\"/)\n if (match) return `Unique constraint on (${match[1]}). Ensure field values are unique across instances.`\n return 'Unique constraint violation. Make field values unique across instances.'\n }\n if (errorMsg.includes('Foreign key constraint') || errorMsg.includes('foreign key')) {\n return 'A referenced record does not exist. Check that parent entities are nested correctly.'\n }\n if (errorMsg.includes('null value in column') || errorMsg.includes('must not be null')) {\n return 'A required field is null. Add it to the node with a value.'\n }\n return ''\n}\n"],"mappings":"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","names":["createHmac","timingSafeEqual","allResults"]}
1
+ {"version":3,"sources":["../src/hmac.ts","../src/refs.ts","../src/tree.ts","../src/errors.ts","../src/generated/sql-queries.ts","../src/dialect.ts","../src/introspect.ts","../src/create.ts","../src/teardown.ts","../src/handler.ts","../src/fingerprint.ts","../src/check.ts"],"sourcesContent":["import { createHmac, timingSafeEqual } from 'node:crypto'\n\nexport function signBody(body: string, secret: string): string {\n return createHmac('sha256', secret).update(body).digest('hex')\n}\n\nexport function verifySignature(\n body: string,\n signature: string,\n secret: string,\n): boolean {\n const expected = signBody(body, secret)\n if (expected.length !== signature.length) return false\n return timingSafeEqual(Buffer.from(expected), Buffer.from(signature))\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto'\n\ninterface RefsPayload {\n refs: Record<string, Record<string, unknown>[]>\n testRunId: string\n environment: string\n}\n\n/**\n * Sign refs into a JWT-like token (header.payload.signature).\n * Uses HMAC-SHA256 — not a full JWT library to avoid dependencies.\n */\nexport function signRefs(payload: RefsPayload, secret: string): string {\n const header = base64url({ alg: 'HS256', typ: 'REFS' })\n const body = base64url(payload)\n const signature = hmac(`${header}.${body}`, secret)\n return `${header}.${body}.${signature}`\n}\n\n/**\n * Verify and decode a refs token. Returns the payload or throws.\n */\nexport function verifyRefs(\n token: string,\n secret: string,\n): RefsPayload {\n const parts = token.split('.')\n if (parts.length !== 3) throw new Error('malformed token')\n\n const [header, body, signature] = parts\n const expected = hmac(`${header}.${body}`, secret)\n\n const expectedBuf = Buffer.from(expected)\n const signatureBuf = Buffer.from(signature!)\n if (expectedBuf.length !== signatureBuf.length || !timingSafeEqual(expectedBuf, signatureBuf)) {\n throw new Error('signature mismatch')\n }\n\n return JSON.parse(Buffer.from(body!, 'base64url').toString())\n}\n\nfunction base64url(obj: unknown): string {\n return Buffer.from(JSON.stringify(obj, (_key, value) =>\n typeof value === 'bigint' ? value.toString() : value\n )).toString('base64url')\n}\n\nfunction hmac(data: string, secret: string): string {\n return createHmac('sha256', secret).update(data).digest('base64url')\n}\n","import type { SchemaInfo, SchemaRelation } from './types'\n\nconst RESERVED_KEYS = new Set(['_alias', '_ref'])\n\n/** A create operation produced by the tree resolver */\nexport interface CreateOp {\n model: string\n fields: Record<string, unknown>\n tempId: string\n batch: boolean\n}\n\n/**\n * A deferred FK update — emitted when a _ref points to a node that hasn't\n * been created yet (circular dependency). Resolved after all creates.\n */\nexport interface DeferredUpdate {\n /** Temp ID of the record that needs to be updated */\n targetTempId: string\n /** Model name of the record to update */\n model: string\n /** Field on the record that holds the deferred FK */\n field: string\n /** Alias that will resolve to the FK value once created */\n refAlias: string\n}\n\n/** Result of resolving a tree scenario */\nexport interface ResolvedTree {\n ops: CreateOp[]\n deferredUpdates: DeferredUpdate[]\n aliases: Map<string, string>\n}\n\n/** A resolved reference to another node's id */\nexport interface RefNode {\n _ref: string\n}\n\n/**\n * Resolve a nested scenario tree into an ordered list of create operations.\n *\n * Walks depth-first. Parent-child FKs are wired automatically.\n * Handles both directions:\n * - FK on child (Application.organizationId → Organization): set child FK to parent ID\n * - FK on parent (Member.userId → User): create child first, set parent FK to child ID\n *\n * Circular FK cycles (e.g. Application.mainBranchId ↔ Branch.applicationId) are handled\n * transparently: the nullable FK is omitted on the first create and emitted as a\n * DeferredUpdate to be applied via UPDATE after all records exist.\n */\nexport function resolveTree(\n create: Record<string, Record<string, unknown>[]>,\n schema: SchemaInfo,\n): ResolvedTree {\n const relationByParentField = new Map<string, SchemaRelation>()\n for (const rel of schema.relations) {\n relationByParentField.set(`${rel.parentModel}.${rel.parentField}`, rel)\n }\n\n // Determine FK direction for each relation:\n // Is childField on the parent model or the child model?\n const fkOnParent = new Set<string>() // key: \"parentModel.parentField\"\n for (const rel of schema.relations) {\n const edge = schema.edges.find(\n (e) => e.localField === rel.childField && (e.from === rel.parentModel || e.from === rel.childModel),\n )\n if (edge && edge.from === rel.parentModel) {\n // FK column is on the parent model → create child first, then set parent FK\n fkOnParent.add(`${rel.parentModel}.${rel.parentField}`)\n }\n }\n\n const aliases = new Map<string, string>()\n const ops: CreateOp[] = []\n const deferredUpdates: DeferredUpdate[] = []\n let tempCounter = 0\n\n function makeTempId(model: string): string {\n return `__temp_${model}_${tempCounter++}`\n }\n\n function walkNode(\n modelName: string,\n node: Record<string, unknown>,\n parentTempId: string | null,\n parentRelation: SchemaRelation | null,\n parentFkOnParent: boolean,\n ): string {\n const fields: Record<string, unknown> = {}\n const preChildren: Array<{ relation: SchemaRelation; value: unknown; fkOnParent: boolean }> = []\n const postChildren: Array<{ relation: SchemaRelation; value: unknown; fkOnParent: boolean }> = []\n const alias = node._alias as string | undefined\n const tempId = makeTempId(modelName)\n\n for (const [key, value] of Object.entries(node)) {\n if (RESERVED_KEYS.has(key)) continue\n\n // Look up relation by exact key, then try fallbacks:\n // 1. Model name prefix: Test.steps → Test.testSteps (Prisma abbreviated names)\n // 2. Child model name: Organization.Application → Organization.applications\n // (scenarios using PascalCase model names as relation keys)\n const exactKey = `${modelName}.${key}`\n const prefixedKey = `${modelName}.${modelName.charAt(0).toLowerCase()}${modelName.slice(1)}${key.charAt(0).toUpperCase()}${key.slice(1)}`\n let relation = relationByParentField.get(exactKey) ?? relationByParentField.get(prefixedKey) ?? undefined\n let matchedKey = relationByParentField.has(exactKey) ? exactKey : prefixedKey\n if (!relation) {\n // Fallback: match by child model name (PascalCase keys like Application, Tag)\n for (const [relKey, rel] of relationByParentField) {\n if (relKey.startsWith(`${modelName}.`) && rel.childModel.toLowerCase() === key.toLowerCase()) {\n relation = rel\n matchedKey = relKey\n break\n }\n }\n }\n if (relation) {\n const isOnParent = fkOnParent.has(matchedKey)\n if (isOnParent) {\n // FK is on this model → need to create the child BEFORE this node\n preChildren.push({ relation, value, fkOnParent: true })\n } else {\n // FK is on the child → create child AFTER this node (normal)\n postChildren.push({ relation, value, fkOnParent: false })\n }\n continue\n }\n\n if (value && typeof value === 'object' && '_ref' in value) {\n const refAlias = (value as RefNode)._ref\n const refTempId = aliases.get(refAlias)\n if (!refTempId) {\n // Alias not created yet — defer this FK as an UPDATE after all creates.\n // This handles circular FK cycles (e.g. Application.mainBranchId → Branch\n // where Branch.applicationId → Application).\n deferredUpdates.push({ targetTempId: tempId, model: modelName, field: key, refAlias })\n continue\n }\n fields[key] = refTempId\n continue\n }\n\n fields[key] = value\n }\n\n // Wire FK to parent (if this node is a child and FK is on the child)\n if (parentRelation && parentTempId && !parentFkOnParent) {\n fields[parentRelation.childField] = parentTempId\n }\n\n // Process pre-children: these need to be created BEFORE this node\n // because this node's FK points to them\n for (const { relation, value } of preChildren) {\n if (Array.isArray(value)) {\n for (const item of value) {\n const childTempId = walkNode(relation.childModel, item as Record<string, unknown>, tempId, relation, true)\n // Set this node's FK to point to the created child\n fields[relation.childField] = childTempId\n }\n }\n }\n\n // Create this node\n ops.push({ model: modelName, fields, tempId, batch: false })\n if (alias) aliases.set(alias, tempId)\n\n // Process post-children: normal case, FK is on the child\n for (const { relation, value } of postChildren) {\n if (Array.isArray(value)) {\n for (const item of value) {\n walkNode(relation.childModel, item as Record<string, unknown>, tempId, relation, false)\n }\n }\n }\n\n return tempId\n }\n\n for (const [modelName, nodes] of Object.entries(create)) {\n for (const node of nodes) {\n walkNode(modelName, node, null, null, false)\n }\n }\n\n return { ops, deferredUpdates, aliases }\n}\n","export class AutonomaError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly status: number,\n ) {\n super(message)\n this.name = 'AutonomaError'\n }\n}\n\nexport const Errors = {\n unknownAction(action: string) {\n return new AutonomaError(\n `Unknown action: ${action}`,\n 'UNKNOWN_ACTION',\n 400,\n )\n },\n unknownEnvironment(name: string) {\n return new AutonomaError(\n `Unknown environment: ${name}`,\n 'UNKNOWN_ENVIRONMENT',\n 400,\n )\n },\n invalidSignature() {\n return new AutonomaError(\n 'Invalid HMAC signature',\n 'INVALID_SIGNATURE',\n 401,\n )\n },\n invalidRefsToken(reason: string) {\n return new AutonomaError(\n `Invalid refs token: ${reason}`,\n 'INVALID_REFS_TOKEN',\n 403,\n )\n },\n productionBlocked() {\n return new AutonomaError(\n 'Environment factory is disabled in production',\n 'PRODUCTION_BLOCKED',\n 404,\n )\n },\n invalidBody(reason: string) {\n return new AutonomaError(\n `Invalid request body: ${reason}`,\n 'INVALID_BODY',\n 400,\n )\n },\n} as const\n","// AUTO-GENERATED by protocol/sql/codegen.ts — do not edit\n\nexport const POSTGRES_COLUMNS = `SELECT\n table_name,\n column_name,\n data_type,\n udt_name,\n is_nullable,\n column_default\nFROM information_schema.columns\nWHERE table_schema = '{{schema}}'\nORDER BY table_name, ordinal_position`\n\nexport const POSTGRES_ENUMS = `SELECT t.typname AS enum_name, e.enumlabel AS enum_value\nFROM pg_type t\nJOIN pg_enum e ON t.oid = e.enumtypid\nJOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\nORDER BY t.typname, e.enumsortorder`\n\nexport const POSTGRES_FOREIGN_KEYS = `SELECT\n kcu.table_name AS from_table,\n kcu.column_name AS from_column,\n ccu.table_name AS to_table,\n ccu.column_name AS to_column,\n c.is_nullable\nFROM information_schema.table_constraints tc\nJOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\nJOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.table_schema = ccu.table_schema\nLEFT JOIN information_schema.columns c\n ON c.table_schema = kcu.table_schema\n AND c.table_name = kcu.table_name\n AND c.column_name = kcu.column_name\nWHERE tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_schema = '{{schema}}'\nORDER BY kcu.table_name, kcu.ordinal_position`\n\nexport const POSTGRES_PRIMARY_KEYS = `SELECT\n tc.table_name,\n kcu.column_name\nFROM information_schema.table_constraints tc\nJOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\nWHERE tc.constraint_type = 'PRIMARY KEY'\n AND tc.table_schema = '{{schema}}'\nORDER BY tc.table_name, kcu.ordinal_position`\n\nexport const POSTGRES_TABLES = `SELECT table_name\nFROM information_schema.tables\nWHERE table_schema = '{{schema}}'\n AND table_type = 'BASE TABLE'\nORDER BY table_name`\n\nexport const MYSQL_COLUMNS = `SELECT\n table_name,\n column_name,\n data_type,\n column_type AS udt_name,\n is_nullable,\n column_default\nFROM information_schema.columns\nWHERE table_schema = '{{schema}}'\nORDER BY table_name, ordinal_position`\n\nexport const MYSQL_ENUMS = `SELECT NULL AS enum_name, NULL AS enum_value FROM DUAL WHERE 1 = 0`\n\nexport const MYSQL_FOREIGN_KEYS = `SELECT\n kcu.table_name AS from_table,\n kcu.column_name AS from_column,\n kcu.referenced_table_name AS to_table,\n kcu.referenced_column_name AS to_column,\n c.is_nullable\nFROM information_schema.key_column_usage kcu\nJOIN information_schema.columns c\n ON c.table_schema = kcu.table_schema\n AND c.table_name = kcu.table_name\n AND c.column_name = kcu.column_name\nWHERE kcu.referenced_table_name IS NOT NULL\n AND kcu.table_schema = '{{schema}}'\nORDER BY kcu.table_name, kcu.ordinal_position`\n\nexport const MYSQL_PRIMARY_KEYS = `SELECT\n tc.table_name,\n kcu.column_name\nFROM information_schema.table_constraints tc\nJOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\nWHERE tc.constraint_type = 'PRIMARY KEY'\n AND tc.table_schema = '{{schema}}'\nORDER BY tc.table_name, kcu.ordinal_position`\n\nexport const MYSQL_TABLES = `SELECT table_name\nFROM information_schema.tables\nWHERE table_schema = '{{schema}}'\n AND table_type = 'BASE TABLE'\nORDER BY table_name`\n","/** Database dialect abstraction — generates dialect-specific SQL strings. */\n\nimport {\n POSTGRES_TABLES,\n POSTGRES_COLUMNS,\n POSTGRES_PRIMARY_KEYS,\n POSTGRES_FOREIGN_KEYS,\n POSTGRES_ENUMS,\n MYSQL_TABLES,\n MYSQL_COLUMNS,\n MYSQL_PRIMARY_KEYS,\n MYSQL_FOREIGN_KEYS,\n MYSQL_ENUMS,\n} from './generated/sql-queries'\n\nexport interface Dialect {\n readonly name: 'postgres' | 'mysql' | 'sqlite'\n /** Parameter placeholder for index (1-based). Postgres: $1, MySQL/SQLite: ? */\n param(index: number): string\n /** Quote an identifier. Postgres: \"name\", MySQL: `name` */\n quoteId(name: string): string\n /** Whether INSERT ... RETURNING is supported */\n readonly supportsReturning: boolean\n\n /** SQL to list all base tables in a schema/database */\n tablesSQL(schema: string): string\n /** SQL to list all columns for all tables in a schema/database */\n columnsSQL(schema: string): string\n /** SQL to list primary key columns */\n primaryKeysSQL(schema: string): string\n /** SQL to list foreign key relationships */\n foreignKeysSQL(schema: string): string\n /** SQL to list enum types and their values */\n enumsSQL(schema: string): string\n}\n\nconst replaceSchema = (template: string, schema: string) =>\n template.replace('{{schema}}', schema)\n\nexport const postgres: Dialect = {\n name: 'postgres',\n param: (i) => `$${i}`,\n quoteId: (name) => `\"${name}\"`,\n supportsReturning: true,\n\n tablesSQL: (schema) => replaceSchema(POSTGRES_TABLES, schema),\n columnsSQL: (schema) => replaceSchema(POSTGRES_COLUMNS, schema),\n primaryKeysSQL: (schema) => replaceSchema(POSTGRES_PRIMARY_KEYS, schema),\n foreignKeysSQL: (schema) => replaceSchema(POSTGRES_FOREIGN_KEYS, schema),\n enumsSQL: () => POSTGRES_ENUMS,\n}\n\nexport const mysql: Dialect = {\n name: 'mysql',\n param: () => '?',\n quoteId: (name) => `\\`${name}\\``,\n supportsReturning: false,\n\n tablesSQL: (schema) => replaceSchema(MYSQL_TABLES, schema),\n columnsSQL: (schema) => replaceSchema(MYSQL_COLUMNS, schema),\n primaryKeysSQL: (schema) => replaceSchema(MYSQL_PRIMARY_KEYS, schema),\n foreignKeysSQL: (schema) => replaceSchema(MYSQL_FOREIGN_KEYS, schema),\n enumsSQL: () => MYSQL_ENUMS,\n}\n\nexport function getDialect(name: 'postgres' | 'mysql' | 'sqlite' = 'postgres'): Dialect {\n switch (name) {\n case 'postgres':\n return postgres\n case 'mysql':\n return mysql\n default:\n throw new Error(`Dialect \"${name}\" is not yet supported. Currently only \"postgres\" and \"mysql\" are available.`)\n }\n}\n","import type { SQLExecutor, SchemaInfo, SchemaRelation, ModelInfo, FieldInfo, FKEdge } from './types'\nimport type { Dialect } from './dialect'\n\n/** Internal result including name mapping tables */\nexport interface IntrospectionResult {\n schema: SchemaInfo\n /** model name → DB table name */\n tableMap: Map<string, string>\n /** model name → (field name → DB column name) */\n columnMaps: Map<string, Map<string, string>>\n /** model name → (field name → Postgres enum type name). Only populated for Postgres. */\n enumTypeMaps: Map<string, Map<string, string>>\n}\n\ninterface TableRow { table_name: string }\ninterface ColumnRow {\n table_name: string\n column_name: string\n data_type: string\n udt_name: string\n is_nullable: string\n column_default: string | null\n}\ninterface PKRow { table_name: string; column_name: string }\ninterface FKRow {\n from_table: string\n from_column: string\n to_table: string\n to_column: string\n is_nullable: string\n}\ninterface EnumRow { enum_name: string; enum_value: string }\n\n/**\n * Introspect a database via information_schema to build SchemaInfo.\n *\n * Auto-maps DB names (snake_case) to model names (PascalCase) and\n * field names (camelCase). Override with `tableNameMap`.\n */\nexport async function introspectDatabase(\n executor: SQLExecutor,\n dialect: Dialect,\n config: {\n scopeField: string\n schema?: string\n tableNameMap?: Record<string, string>\n excludeTables?: string[]\n },\n): Promise<IntrospectionResult> {\n const dbSchema = config.schema ?? (dialect.name === 'mysql' ? undefined : 'public')\n if (!dbSchema) {\n throw new Error('MySQL requires a schema (database name). Pass it via config.schema or HandlerConfig.dbSchema.')\n }\n const excludeSet = new Set(config.excludeTables ?? ['_prisma_migrations'])\n\n // Run all introspection queries in parallel.\n // Normalize row keys to lowercase — MySQL's information_schema can return\n // column names in uppercase (TABLE_NAME vs table_name).\n const [tableRows, columnRows, pkRows, fkRows, enumRows] = await Promise.all([\n executor.query<TableRow>(dialect.tablesSQL(dbSchema)).then(normalizeKeys),\n executor.query<ColumnRow>(dialect.columnsSQL(dbSchema)).then(normalizeKeys),\n executor.query<PKRow>(dialect.primaryKeysSQL(dbSchema)).then(normalizeKeys),\n executor.query<FKRow>(dialect.foreignKeysSQL(dbSchema)).then(normalizeKeys),\n executor.query<EnumRow>(dialect.enumsSQL(dbSchema)).then(normalizeKeys),\n ])\n\n // Build enum lookup: name → values[]\n // For Postgres: from pg_type/pg_enum rows\n // For MySQL: extracted from column_type in the column rows below\n const enumValues = new Map<string, string[]>()\n for (const row of enumRows) {\n if (!row.enum_name) continue\n if (!enumValues.has(row.enum_name)) enumValues.set(row.enum_name, [])\n enumValues.get(row.enum_name)!.push(row.enum_value)\n }\n\n // For MySQL, parse inline enums from column_type (udt_name alias)\n // e.g. \"enum('WEB','ANDROID','IOS')\" → ['WEB','ANDROID','IOS']\n if (dialect.name === 'mysql') {\n for (const col of columnRows) {\n const parsed = parseMySQLEnum(col.udt_name)\n if (parsed) {\n const enumKey = `${col.table_name}.${col.column_name}`\n enumValues.set(enumKey, parsed)\n }\n }\n }\n\n // Build PK lookup: table_name → Set<column_name>\n const pksByTable = new Map<string, Set<string>>()\n for (const row of pkRows) {\n if (!pksByTable.has(row.table_name)) pksByTable.set(row.table_name, new Set())\n pksByTable.get(row.table_name)!.add(row.column_name)\n }\n\n // Build table name mapping\n const userMap = config.tableNameMap ?? {}\n const tableMap = new Map<string, string>()\n const reverseTableMap = new Map<string, string>()\n\n // First, register user-provided mappings\n for (const [model, dbTable] of Object.entries(userMap)) {\n tableMap.set(model, dbTable)\n reverseTableMap.set(dbTable, model)\n }\n\n // Then auto-map remaining tables\n const dbTables = tableRows\n .map((r) => r.table_name)\n .filter((t) => !excludeSet.has(t))\n\n for (const dbTable of dbTables) {\n if (reverseTableMap.has(dbTable)) continue\n const modelName = snakeToPascal(dbTable)\n tableMap.set(modelName, dbTable)\n reverseTableMap.set(dbTable, modelName)\n }\n\n // Build column maps and model info\n const models: ModelInfo[] = []\n const columnMaps = new Map<string, Map<string, string>>()\n const enumTypeMaps = new Map<string, Map<string, string>>()\n\n // Group columns by table\n const columnsByTable = new Map<string, ColumnRow[]>()\n for (const row of columnRows) {\n if (!columnsByTable.has(row.table_name)) columnsByTable.set(row.table_name, [])\n columnsByTable.get(row.table_name)!.push(row)\n }\n\n for (const [modelName, dbTable] of tableMap) {\n const cols = columnsByTable.get(dbTable) ?? []\n const pks = pksByTable.get(dbTable) ?? new Set<string>()\n const colMap = new Map<string, string>()\n const fields: FieldInfo[] = []\n\n for (const col of cols) {\n const fieldName = snakeToCamel(col.column_name)\n colMap.set(fieldName, col.column_name)\n\n // Check for enum values\n let enumVals: string[] | undefined\n if (dialect.name === 'mysql') {\n enumVals = enumValues.get(`${col.table_name}.${col.column_name}`)\n } else {\n enumVals = enumValues.get(col.udt_name)\n }\n\n const type = enumVals\n ? `enum(${enumVals.join(',')})`\n : mapDataType(col.data_type, col.udt_name, dialect.name)\n\n // Track Postgres types that need explicit parameter casting.\n // Prisma's $queryRawUnsafe sends string params as explicit text type,\n // preventing Postgres auto-cast for enums, jsonb, and timestamps.\n if (dialect.name === 'postgres') {\n if (enumVals) {\n if (!enumTypeMaps.has(modelName)) enumTypeMaps.set(modelName, new Map())\n enumTypeMaps.get(modelName)!.set(fieldName, col.udt_name)\n } else if (col.data_type === 'jsonb' || col.udt_name === 'jsonb' || col.data_type === 'json' || col.udt_name === 'json') {\n if (!enumTypeMaps.has(modelName)) enumTypeMaps.set(modelName, new Map())\n const jsonType = (col.data_type === 'json' || col.udt_name === 'json') ? 'json' : 'jsonb'\n enumTypeMaps.get(modelName)!.set(fieldName, jsonType)\n } else if (col.data_type.includes('timestamp') || col.udt_name === 'timestamptz' || col.udt_name === 'timestamp') {\n if (!enumTypeMaps.has(modelName)) enumTypeMaps.set(modelName, new Map())\n enumTypeMaps.get(modelName)!.set(fieldName, col.udt_name)\n }\n }\n\n fields.push({\n name: fieldName,\n type,\n isRequired: col.is_nullable === 'NO',\n isId: pks.has(col.column_name),\n hasDefault: col.column_default !== null,\n })\n }\n\n columnMaps.set(modelName, colMap)\n models.push({ name: modelName, tableName: dbTable, fields })\n }\n\n // Build FK edges\n const edges: FKEdge[] = []\n for (const fk of fkRows) {\n const fromModel = reverseTableMap.get(fk.from_table)\n const toModel = reverseTableMap.get(fk.to_table)\n if (!fromModel || !toModel) continue\n\n const fromColMap = columnMaps.get(fromModel)\n const toColMap = columnMaps.get(toModel)\n const localField = fromColMap ? reverseGet(fromColMap, fk.from_column) ?? fk.from_column : fk.from_column\n const foreignField = toColMap ? reverseGet(toColMap, fk.to_column) ?? fk.to_column : fk.to_column\n\n edges.push({\n from: fromModel,\n to: toModel,\n localField,\n foreignField,\n nullable: fk.is_nullable === 'YES',\n })\n }\n\n // Build relations from FK edges.\n // For each edge (from→to), generate two relations:\n // 1. Parent-side: on the \"to\" model, a field pointing to \"from\" model (e.g., Organization.members)\n // 2. Child-side: on the \"from\" model, a field pointing to \"to\" model (e.g., Member.organization)\n const relations: SchemaRelation[] = []\n for (const edge of edges) {\n // Detect one-to-one: if the FK column is the sole PK of the child table,\n // the relationship is one-to-one (e.g., WebApplicationData.applicationId is\n // both PK and FK → Application has singular webApplicationData, not plural).\n const fromDbTable = tableMap.get(edge.from)!\n const fromColMap = columnMaps.get(edge.from) ?? new Map<string, string>()\n const fkDbCol = fromColMap.get(edge.localField) ?? edge.localField\n const fromPks = pksByTable.get(fromDbTable)\n const isOneToOne = fromPks !== undefined && fromPks.size === 1 && fromPks.has(fkDbCol)\n\n // Parent-side: \"to\" model has a collection/reference to \"from\" model\n relations.push({\n parentModel: edge.to,\n childModel: edge.from,\n parentField: isOneToOne ? lowerFirst(edge.from) : pluralCamelCase(edge.from),\n childField: edge.localField,\n })\n\n // Child-side: \"from\" model has a singular reference to \"to\" model (FK is on this side)\n relations.push({\n parentModel: edge.from,\n childModel: edge.to,\n parentField: lowerFirst(edge.to),\n childField: edge.localField,\n })\n }\n\n return {\n schema: { models, edges, relations, scopeField: config.scopeField },\n tableMap,\n columnMaps,\n enumTypeMaps,\n }\n}\n\n// --- Name mapping utilities ---\n\nfunction snakeToPascal(str: string): string {\n return str\n .split('_')\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n .join('')\n}\n\nfunction snakeToCamel(str: string): string {\n const pascal = snakeToPascal(str)\n return pascal.charAt(0).toLowerCase() + pascal.slice(1)\n}\n\n/**\n * Parse MySQL inline enum definition: \"enum('a','b','c')\" → ['a','b','c']\n */\nfunction parseMySQLEnum(columnType: string): string[] | null {\n if (!columnType) return null\n const match = columnType.match(/^enum\\((.+)\\)$/i)\n if (!match) return null\n return match[1]!\n .split(',')\n .map((v) => v.trim().replace(/^'|'$/g, ''))\n}\n\nfunction mapDataType(dataType: string, udtName: string, dialectName: string): string {\n const dt = dataType.toLowerCase()\n\n // MySQL tinyint(1) is conventionally Boolean — check column_type (udtName) before generic tinyint mapping.\n // data_type from information_schema is just \"tinyint\"; the display width lives in udt_name (column_type).\n if (dialectName === 'mysql' && dt === 'tinyint' && udtName.toLowerCase().startsWith('tinyint(1)')) return 'Boolean'\n\n // Integer types\n if (dt === 'integer' || dt === 'smallint' || dt === 'bigint' || dt === 'int' || dt === 'mediumint' || dt === 'tinyint') return 'Int'\n\n // Float types\n if (dt === 'numeric' || dt === 'real' || dt === 'double precision' || dt === 'float' || dt === 'double' || dt === 'decimal') return 'Float'\n\n // Boolean (Postgres native boolean type, or tinyint(1) when data_type includes display width)\n if (dt === 'boolean' || dt === 'tinyint(1)') return 'Boolean'\n\n // String types\n if (dt === 'text' || dt === 'character varying' || dt === 'character' || dt === 'varchar' || dt === 'char'\n || dt === 'mediumtext' || dt === 'longtext' || dt === 'tinytext') return 'String'\n\n // DateTime types\n if (dt === 'timestamp with time zone' || dt === 'timestamp without time zone'\n || dt === 'date' || dt === 'time' || dt === 'datetime' || dt === 'timestamp') return 'DateTime'\n\n // JSON types\n if (dt === 'json' || dt === 'jsonb') return 'Json'\n\n // UUID / binary\n if (dt === 'uuid') return 'String'\n if (dt === 'bytea' || dt === 'blob' || dt === 'mediumblob' || dt === 'longblob' || dt === 'tinyblob' || dt === 'binary' || dt === 'varbinary') return 'Bytes'\n\n // Postgres user-defined (enums handled by caller)\n if (dt === 'user-defined' && dialectName === 'postgres') return udtName\n\n // MySQL enum is handled before this function is called\n if (dt === 'enum' || dt === 'set') return udtName\n\n return dataType\n}\n\nfunction lowerFirst(str: string): string {\n return str.charAt(0).toLowerCase() + str.slice(1)\n}\n\n/**\n * Convert a PascalCase model name to a camelCase plural field name.\n * e.g., \"Member\" → \"members\", \"Application\" → \"applications\", \"ApiKey\" → \"apiKeys\"\n */\nfunction pluralCamelCase(modelName: string): string {\n const camel = lowerFirst(modelName)\n return pluralize(camel)\n}\n\nfunction pluralize(str: string): string {\n if (str.endsWith('s') || str.endsWith('x') || str.endsWith('z') || str.endsWith('ch') || str.endsWith('sh')) {\n return str + 'es'\n }\n if (str.endsWith('y') && str.length > 1 && !isVowel(str.charAt(str.length - 2))) {\n return str.slice(0, -1) + 'ies'\n }\n return str + 's'\n}\n\nfunction isVowel(ch: string): boolean {\n return 'aeiou'.includes(ch.toLowerCase())\n}\n\n/**\n * Lowercase all keys in each row — handles MySQL information_schema returning\n * uppercase column names (TABLE_NAME, COLUMN_NAME, etc.)\n */\nfunction normalizeKeys<T>(rows: T[]): T[] {\n return rows.map((row) => {\n if (!row || typeof row !== 'object') return row\n const normalized: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(row as Record<string, unknown>)) {\n normalized[key.toLowerCase()] = val\n }\n return normalized as T\n })\n}\n\n/** Reverse lookup: find the key whose value matches `dbName` */\nfunction reverseGet(map: Map<string, string>, dbName: string): string | null {\n for (const [key, val] of map) {\n if (val === dbName) return key\n }\n return null\n}\n","import { randomUUID } from 'node:crypto'\nimport type { SQLExecutor, ResolvedEntitySpec, CreateContext, ModelInfo } from './types'\nimport type { Dialect } from './dialect'\n\n/**\n * Create entities via raw SQL INSERT.\n *\n * Entities arrive pre-sorted by FK order (handler does topo-sort via tree.ts).\n * Each model in `spec` is inserted sequentially; within a model, batch mode\n * uses a single multi-row INSERT while normal mode inserts one row at a time.\n *\n * For dialects with RETURNING (Postgres): INSERT ... RETURNING *\n * For dialects without (MySQL): INSERT then SELECT via LAST_INSERT_ID()\n */\nexport async function createEntities(\n executor: SQLExecutor,\n dialect: Dialect,\n tableMap: Map<string, string>,\n columnMaps: Map<string, Map<string, string>>,\n spec: Record<string, ResolvedEntitySpec>,\n _context: CreateContext,\n enumTypeMaps: Map<string, Map<string, string>> = new Map(),\n schemaModels: ModelInfo[] = [],\n): Promise<Record<string, Record<string, unknown>[]>> {\n const results: Record<string, Record<string, unknown>[]> = {}\n\n for (const [model, entitySpec] of Object.entries(spec)) {\n const dbTable = tableMap.get(model)\n if (!dbTable) throw new Error(`Unknown model \"${model}\". Not found in database tables.`)\n const colMap = columnMaps.get(model) ?? new Map<string, string>()\n const enumTypeMap = enumTypeMaps.get(model) ?? new Map<string, string>()\n\n // Bug 4: find actual PK field name from schema\n const modelInfo = schemaModels.find((m) => m.name === model)\n const idFields = modelInfo?.fields.filter((f) => f.isId) ?? []\n const pkField = idFields.find((f) => f.name.toLowerCase() === 'id') ?? idFields[0]\n const pkFieldName = pkField?.name ?? 'id'\n const pkFieldType = pkField?.type ?? 'String'\n\n if (entitySpec.batch && entitySpec.fields.length > 0) {\n results[model] = await insertBatch(executor, dialect, dbTable, colMap, enumTypeMap, entitySpec.fields, pkFieldName, pkFieldType)\n } else {\n const created: Record<string, unknown>[] = []\n for (const fields of entitySpec.fields) {\n const [record] = await insertOne(executor, dialect, dbTable, colMap, enumTypeMap, fields, pkFieldName, pkFieldType)\n if (record) created.push(record)\n }\n results[model] = created\n }\n }\n\n return results\n}\n\n/**\n * Update a single record by primary key. Used for circular FK backfill.\n */\nexport async function updateEntity(\n executor: SQLExecutor,\n dialect: Dialect,\n tableMap: Map<string, string>,\n columnMaps: Map<string, Map<string, string>>,\n model: string,\n id: string,\n fields: Record<string, unknown>,\n enumTypeMaps: Map<string, Map<string, string>> = new Map(),\n pkFieldName: string = 'id',\n): Promise<void> {\n const dbTable = tableMap.get(model)\n if (!dbTable) throw new Error(`Unknown model \"${model}\" for update.`)\n const colMap = columnMaps.get(model) ?? new Map<string, string>()\n const enumTypeMap = enumTypeMaps.get(model) ?? new Map<string, string>()\n\n const setClauses: string[] = []\n const params: unknown[] = []\n let paramIdx = 1\n\n for (const [fieldName, value] of Object.entries(fields)) {\n const dbCol = colMap.get(fieldName) ?? fieldName\n setClauses.push(`${dialect.quoteId(dbCol)} = ${castParam(dialect, paramIdx, enumTypeMap, fieldName)}`)\n params.push(serializeValue(value, dialect))\n paramIdx++\n }\n\n const idCol = colMap.get(pkFieldName) ?? pkFieldName\n params.push(id)\n\n const sql = `UPDATE ${dialect.quoteId(dbTable)} SET ${setClauses.join(', ')} WHERE ${dialect.quoteId(idCol)} = ${dialect.param(paramIdx)}`\n await executor.query(sql, params)\n}\n\n// --- Internal helpers ---\n\nasync function insertOne(\n executor: SQLExecutor,\n dialect: Dialect,\n dbTable: string,\n colMap: Map<string, string>,\n enumTypeMap: Map<string, string>,\n fields: Record<string, unknown>,\n pkFieldName: string = 'id',\n pkFieldType: string = 'String',\n): Promise<Record<string, unknown>[]> {\n // Generate a client-side ID when none is provided and the PK type is String.\n // Int/BigInt PKs use DB auto-increment, so we skip UUID generation for those.\n if (pkFieldName && fields[pkFieldName] === undefined && pkFieldType === 'String') {\n fields = { ...fields, [pkFieldName]: randomUUID() }\n }\n\n const entries = Object.entries(fields)\n\n if (entries.length === 0) {\n const sql = `INSERT INTO ${dialect.quoteId(dbTable)} DEFAULT VALUES RETURNING *`\n return mapRowsBack(await executor.query(sql), colMap)\n }\n\n const dbCols: string[] = []\n const params: unknown[] = []\n const placeholders: string[] = []\n let paramIdx = 1\n\n for (const [fieldName, value] of entries) {\n const dbCol = colMap.get(fieldName) ?? fieldName\n dbCols.push(dialect.quoteId(dbCol))\n placeholders.push(castParam(dialect, paramIdx, enumTypeMap, fieldName))\n params.push(serializeValue(value, dialect))\n paramIdx++\n }\n\n const colList = dbCols.join(', ')\n const valList = placeholders.join(', ')\n\n if (dialect.supportsReturning) {\n const sql = `INSERT INTO ${dialect.quoteId(dbTable)} (${colList}) VALUES (${valList}) RETURNING *`\n return mapRowsBack(await executor.query(sql, params), colMap)\n }\n\n // MySQL: INSERT then SELECT back by the ID we set\n await executor.query(\n `INSERT INTO ${dialect.quoteId(dbTable)} (${colList}) VALUES (${valList})`,\n params,\n )\n\n const idCol = colMap.get(pkFieldName) ?? pkFieldName\n const id = fields[pkFieldName]\n\n return mapRowsBack(\n await executor.query(\n `SELECT * FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(idCol)} = ${dialect.param(1)}`,\n [id],\n ),\n colMap,\n )\n}\n\nasync function insertBatch(\n executor: SQLExecutor,\n dialect: Dialect,\n dbTable: string,\n colMap: Map<string, string>,\n enumTypeMap: Map<string, string>,\n fieldsArr: Record<string, unknown>[],\n pkFieldName: string = 'id',\n pkFieldType: string = 'String',\n): Promise<Record<string, unknown>[]> {\n if (fieldsArr.length === 0) return []\n\n // Generate client-side IDs for batch records when the PK type is String.\n // Int/BigInt PKs use DB auto-increment.\n if (pkFieldName && pkFieldType === 'String') {\n fieldsArr = fieldsArr.map((fields) => {\n if (fields[pkFieldName] === undefined) {\n return { ...fields, [pkFieldName]: randomUUID() }\n }\n return fields\n })\n }\n\n // Compute the union of keys across all rows in deterministic (sorted) order.\n const fieldNameSet = new Set<string>()\n for (const fields of fieldsArr) {\n for (const key of Object.keys(fields)) {\n fieldNameSet.add(key)\n }\n }\n const fieldNames = [...fieldNameSet].sort()\n\n // If no fields at all, fall back to individual DEFAULT VALUES inserts.\n if (fieldNames.length === 0) {\n const allResults: Record<string, unknown>[] = []\n for (const fields of fieldsArr) {\n const [record] = await insertOne(executor, dialect, dbTable, colMap, enumTypeMap, fields)\n if (record) allResults.push(record)\n }\n return allResults\n }\n\n const dbCols = fieldNames.map((f) => dialect.quoteId(colMap.get(f) ?? f))\n const colList = dbCols.join(', ')\n\n // Postgres has a max of 32,767 bind variables per statement.\n // Chunk large batches to stay within this limit.\n const MAX_PARAMS = 32_000\n const chunkSize = Math.max(1, Math.floor(MAX_PARAMS / fieldNames.length))\n const allResults: Record<string, unknown>[] = []\n\n for (let offset = 0; offset < fieldsArr.length; offset += chunkSize) {\n const chunk = fieldsArr.slice(offset, offset + chunkSize)\n const params: unknown[] = []\n const valueTuples: string[] = []\n let paramIdx = 1\n\n for (const fields of chunk) {\n const placeholders: string[] = []\n for (const fieldName of fieldNames) {\n placeholders.push(castParam(dialect, paramIdx, enumTypeMap, fieldName))\n params.push(serializeValue(fields[fieldName], dialect))\n paramIdx++\n }\n valueTuples.push(`(${placeholders.join(', ')})`)\n }\n\n const valList = valueTuples.join(', ')\n\n if (dialect.supportsReturning) {\n const sql = `INSERT INTO ${dialect.quoteId(dbTable)} (${colList}) VALUES ${valList} RETURNING *`\n allResults.push(...mapRowsBack(await executor.query(sql, params), colMap))\n } else {\n await executor.query(\n `INSERT INTO ${dialect.quoteId(dbTable)} (${colList}) VALUES ${valList}`,\n params,\n )\n }\n }\n\n return allResults\n}\n\n/**\n * Map DB column names back to camelCase field names in returned rows.\n */\nfunction mapRowsBack(\n rows: Record<string, unknown>[],\n colMap: Map<string, string>,\n): Record<string, unknown>[] {\n if (colMap.size === 0) return rows\n\n const reverse = new Map<string, string>()\n for (const [fieldName, dbCol] of colMap) {\n reverse.set(dbCol, fieldName)\n }\n\n return rows.map((row) => {\n const mapped: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(row)) {\n const fieldName = reverse.get(key) ?? key\n mapped[fieldName] = value\n }\n return mapped\n })\n}\n\n\n/**\n * Build a parameter placeholder with an optional Postgres enum cast.\n * e.g. `$1::\"ApplicationArchitecture\"` for enum fields, or just `$1` otherwise.\n */\nfunction castParam(\n dialect: Dialect,\n paramIdx: number,\n enumTypeMap: Map<string, string>,\n fieldName: string,\n): string {\n const placeholder = dialect.param(paramIdx)\n if (dialect.name === 'postgres') {\n const enumType = enumTypeMap.get(fieldName)\n if (enumType) return `${placeholder}::${dialect.quoteId(enumType)}`\n }\n return placeholder\n}\n\n/** Pre-compiled regex for MySQL datetime detection (avoids re-compilation per call). */\nconst MYSQL_DATETIME_RE = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/\n\n/**\n * Serialize a JS value for SQL insertion.\n * Handles MySQL-specific quirks:\n * - Objects/arrays → JSON.stringify (MySQL requires JSON strings, not objects)\n * - ISO 8601 datetime strings → MySQL DATETIME format\n */\nfunction serializeValue(value: unknown, dialect: Dialect): unknown {\n if (value === null || value === undefined) return null\n\n // JSON: stringify objects/dicts for JSON/JSONB columns.\n // Arrays are returned as native arrays for Postgres ARRAY columns.\n if (typeof value === 'object' && !(value instanceof Date)) {\n if (Array.isArray(value)) return value\n return JSON.stringify(value)\n }\n\n // DateTime: MySQL doesn't accept ISO 8601 with 'T' and 'Z'\n if (typeof value === 'string' && dialect.name === 'mysql') {\n if (MYSQL_DATETIME_RE.test(value)) {\n return value.replace('T', ' ').replace('Z', '').replace(/\\.\\d+$/, '')\n }\n }\n\n return value\n}\n","import type { SQLExecutor, SchemaInfo } from './types'\nimport type { Dialect } from './dialect'\nimport { topoSort, findDeferrableEdge } from './graph'\n\n/**\n * Tear down all data scoped to a value, in reverse topological order.\n *\n * Strategy:\n * 1. Find the scope root model (e.g. Organization) from FK edges\n * 2. Any model with a FK pointing to the scope root is \"scoped\"\n * 3. Delete scoped models by their FK = scopeValue\n * 4. Delete non-scoped models by their record IDs from refs\n * 5. Delete the scope root entity last by id = scopeValue\n */\nexport async function teardown(\n executor: SQLExecutor,\n dialect: Dialect,\n tableMap: Map<string, string>,\n columnMaps: Map<string, Map<string, string>>,\n schema: SchemaInfo,\n scopeValue: string,\n refs?: Record<string, Record<string, unknown>[]>,\n): Promise<void> {\n // Find scope root: the model that the scopeField FK points TO\n let scopeRootModel: string | null = null\n for (const edge of schema.edges) {\n if (edge.localField.toLowerCase() === schema.scopeField.toLowerCase() && edge.to !== edge.from) {\n scopeRootModel = edge.to\n break\n }\n }\n\n // Build map: model → FK field name that points to the scope root\n const scopeFieldByModel = new Map<string, string>()\n if (scopeRootModel) {\n for (const edge of schema.edges) {\n if (edge.to === scopeRootModel && edge.from !== scopeRootModel) {\n scopeFieldByModel.set(edge.from, edge.localField)\n }\n }\n }\n\n const modelNames = schema.models.map((m) => m.name)\n const { sorted, cycles } = topoSort(modelNames, schema.edges)\n\n await executor.transaction(async (tx) => {\n // Break cycles by nullifying deferrable FKs\n for (const cycle of cycles) {\n const edge = findDeferrableEdge(cycle, schema.edges)\n if (edge) {\n const scopeFK = scopeFieldByModel.get(edge.from)\n if (scopeFK) {\n const dbTable = tableMap.get(edge.from)\n const colMap = columnMaps.get(edge.from) ?? new Map<string, string>()\n if (dbTable) {\n const dbFKCol = colMap.get(edge.localField) ?? edge.localField\n const dbScopeCol = colMap.get(scopeFK) ?? scopeFK\n await tx.query(\n `UPDATE ${dialect.quoteId(dbTable)} SET ${dialect.quoteId(dbFKCol)} = NULL WHERE ${dialect.quoteId(dbScopeCol)} = ${dialect.param(1)}`,\n [scopeValue],\n )\n }\n }\n }\n }\n\n // Build condensation graph: each SCC is a super-node, each sorted node\n // is its own node. Topo-sort the condensation DAG and delete in reverse\n // order so that dependents of cycles are deleted before the cycle itself.\n const components: string[][] = []\n const nodeToComp = new Map<string, number>()\n\n for (const cycle of cycles) {\n const idx = components.length\n components.push(cycle)\n for (const node of cycle) nodeToComp.set(node, idx)\n }\n for (const node of sorted) {\n nodeToComp.set(node, components.length)\n components.push([node])\n }\n\n // Build condensation DAG edges (dependency → dependent)\n const condAdj = new Map<number, Set<number>>()\n const condInDeg = new Map<number, number>()\n for (let i = 0; i < components.length; i++) {\n condAdj.set(i, new Set())\n condInDeg.set(i, 0)\n }\n for (const edge of schema.edges) {\n if (edge.from === edge.to) continue\n const fc = nodeToComp.get(edge.from)\n const tc = nodeToComp.get(edge.to)\n if (fc !== undefined && tc !== undefined && fc !== tc && !condAdj.get(tc)!.has(fc)) {\n condAdj.get(tc)!.add(fc)\n condInDeg.set(fc, (condInDeg.get(fc) ?? 0) + 1)\n }\n }\n\n // Kahn's algorithm on the condensation DAG\n const condQueue: number[] = []\n for (const [idx, deg] of condInDeg) {\n if (deg === 0) condQueue.push(idx)\n }\n const condOrder: number[] = []\n while (condQueue.length > 0) {\n condQueue.sort()\n const idx = condQueue.shift()!\n condOrder.push(idx)\n for (const neighbor of condAdj.get(idx)!) {\n const nd = (condInDeg.get(neighbor) ?? 1) - 1\n condInDeg.set(neighbor, nd)\n if (nd === 0) condQueue.push(neighbor)\n }\n }\n\n // Delete in reverse condensation order (dependents first)\n for (const compIdx of [...condOrder].reverse()) {\n for (const model of components[compIdx]) {\n if (model === scopeRootModel) continue\n await deleteModel(tx, dialect, tableMap, columnMaps, model, scopeValue, scopeFieldByModel, refs, schema)\n }\n }\n\n // Delete the scope root entity last\n if (scopeRootModel) {\n const dbTable = tableMap.get(scopeRootModel)\n const colMap = columnMaps.get(scopeRootModel) ?? new Map<string, string>()\n if (dbTable) {\n const rootModelInfo = schema.models.find((m) => m.name === scopeRootModel)\n const rootIdFields = rootModelInfo?.fields.filter((f) => f.isId) ?? []\n const rootPkFieldName = (rootIdFields.find((f) => f.name.toLowerCase() === 'id') ?? rootIdFields[0])?.name ?? 'id'\n const idCol = colMap.get(rootPkFieldName) ?? rootPkFieldName\n await tx.query(\n `DELETE FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(idCol)} = ${dialect.param(1)}`,\n [scopeValue],\n )\n }\n }\n })\n}\n\nasync function deleteModel(\n tx: SQLExecutor,\n dialect: Dialect,\n tableMap: Map<string, string>,\n columnMaps: Map<string, Map<string, string>>,\n model: string,\n scopeValue: string,\n scopeFieldByModel: Map<string, string>,\n refs: Record<string, Record<string, unknown>[]> | undefined,\n schema: SchemaInfo,\n): Promise<void> {\n const dbTable = tableMap.get(model)\n if (!dbTable) return\n const colMap = columnMaps.get(model) ?? new Map<string, string>()\n\n // Find actual PK field name from schema\n const modelInfo = schema.models.find((m) => m.name === model)\n const idFields = modelInfo?.fields.filter((f) => f.isId) ?? []\n const pkFieldName = (idFields.find((f) => f.name.toLowerCase() === 'id') ?? idFields[0])?.name ?? 'id'\n\n const scopeFK = scopeFieldByModel.get(model)\n if (scopeFK) {\n // Has FK to scope root → delete by that FK\n const dbCol = colMap.get(scopeFK) ?? scopeFK\n await tx.query(\n `DELETE FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(dbCol)} = ${dialect.param(1)}`,\n [scopeValue],\n )\n } else if (refs?.[model]) {\n // No FK to scope root, but we created records → delete by IDs\n const ids = refs[model]\n .map((r) => r[pkFieldName])\n .filter((id): id is string | number => id != null)\n if (ids.length > 0) {\n const idCol = colMap.get(pkFieldName) ?? pkFieldName\n const placeholders = ids.map((_, i) => dialect.param(i + 1)).join(', ')\n await tx.query(\n `DELETE FROM ${dialect.quoteId(dbTable)} WHERE ${dialect.quoteId(idCol)} IN (${placeholders})`,\n ids,\n )\n }\n }\n}\n","import type {\n AuthResult,\n HandlerConfig,\n HandlerRequest,\n HandlerResponse,\n HookContext,\n ResolvedEntitySpec,\n SdkInfo,\n} from './types'\nimport { verifySignature } from './hmac'\nimport { signRefs, verifyRefs } from './refs'\nimport { resolveTree } from './tree'\nimport { AutonomaError, Errors } from './errors'\nimport { getDialect } from './dialect'\nimport { introspectDatabase, type IntrospectionResult } from './introspect'\nimport { createEntities, updateEntity } from './create'\nimport { teardown } from './teardown'\n\n/** Cache introspection results per config to avoid re-querying on every request */\nconst introspectionCache = new WeakMap<HandlerConfig, IntrospectionResult>()\n\nasync function getIntrospection(config: HandlerConfig): Promise<IntrospectionResult> {\n let cached = introspectionCache.get(config)\n if (cached) return cached\n\n const dialect = getDialect(config.dialect)\n cached = await introspectDatabase(config.executor, dialect, {\n scopeField: config.scopeField,\n schema: config.dbSchema,\n tableNameMap: config.tableNameMap,\n excludeTables: config.excludeTables,\n })\n introspectionCache.set(config, cached)\n return cached\n}\n\ndeclare const __PROTOCOL_VERSION__: string\nexport const PROTOCOL_VERSION = __PROTOCOL_VERSION__\n\nfunction buildSdkMeta(config: HandlerConfig): { version: string; sdk: SdkInfo } {\n return {\n version: PROTOCOL_VERSION,\n sdk: {\n language: 'typescript',\n orm: config.sdk?.orm ?? 'unknown',\n server: config.sdk?.server ?? 'unknown',\n },\n }\n}\n\nexport async function handleRequest(\n config: HandlerConfig,\n req: HandlerRequest,\n): Promise<HandlerResponse> {\n try {\n if (config.sharedSecret === config.signingSecret) {\n throw new AutonomaError(\n 'sharedSecret and signingSecret must be different. The shared secret is known by Autonoma; the signing secret must be private.',\n 'SAME_SECRETS',\n 500,\n )\n }\n\n if (!config.allowProduction && process.env.NODE_ENV === 'production') {\n throw Errors.productionBlocked()\n }\n\n const signature = req.headers['x-signature'] ?? req.headers['X-Signature'] ?? ''\n if (!verifySignature(req.body, signature, config.sharedSecret)) {\n throw Errors.invalidSignature()\n }\n\n let body: Record<string, unknown>\n try {\n body = JSON.parse(req.body)\n } catch {\n throw Errors.invalidBody('invalid JSON')\n }\n\n const action = body.action as string\n if (!action) throw Errors.invalidBody('missing action')\n\n switch (action) {\n case 'discover':\n return await handleDiscover(config)\n case 'up':\n return await handleUp(config, body)\n case 'down':\n return await handleDown(config, body)\n default:\n throw Errors.unknownAction(action)\n }\n } catch (err) {\n if (err instanceof AutonomaError) {\n return { status: err.status, body: { error: err.message, code: err.code } }\n }\n const message = err instanceof Error ? err.message : 'Internal error'\n return { status: 500, body: { error: message, code: 'INTERNAL_ERROR' } }\n }\n}\n\nasync function handleDiscover(config: HandlerConfig): Promise<HandlerResponse> {\n const { schema } = await getIntrospection(config)\n return { status: 200, body: { ...buildSdkMeta(config), schema } }\n}\n\nasync function handleUp(\n config: HandlerConfig,\n body: Record<string, unknown>,\n): Promise<HandlerResponse> {\n const create = body.create as Record<string, Record<string, unknown>[]> | undefined\n if (!create) throw Errors.invalidBody('missing \"create\" in request body')\n\n const testRunId = (body.testRunId as string) ?? crypto.randomUUID()\n const { schema, tableMap, columnMaps, enumTypeMaps } = await getIntrospection(config)\n const dialect = getDialect(config.dialect)\n\n const tree = resolveTree(create, schema)\n const refs: Record<string, Record<string, unknown>[]> = {}\n const idMap = new Map<string, string | number>()\n\n await config.executor.transaction(async (tx) => {\n let i = 0\n while (i < tree.ops.length) {\n const op = tree.ops[i]!\n const model = op.model\n\n // Collect consecutive ops for the same model with same batch flag\n const batch: typeof tree.ops = [op]\n while (i + 1 < tree.ops.length && tree.ops[i + 1]!.model === model && tree.ops[i + 1]!.batch === op.batch) {\n i++\n batch.push(tree.ops[i]!)\n }\n\n // Replace temp IDs with real IDs in all fields\n const modelInfo = schema.models.find((m) => m.name === model)\n const idFields = modelInfo?.fields.filter((f) => f.isId) ?? []\n const pkField = idFields.find((f) => f.name.toLowerCase() === 'id') ?? idFields[0]\n const pkFieldName = pkField?.name ?? 'id'\n const resolvedFields = batch.map((b) => {\n const fields = { ...b.fields }\n for (const [key, value] of Object.entries(fields)) {\n if (typeof value === 'string' && value.startsWith('__temp_')) {\n const realId = idMap.get(value)\n if (realId) fields[key] = realId\n }\n }\n // Inject scope field if applicable\n const scopeEdge = schema.edges.find(\n (e) => e.from === model && e.localField.replace(/_/g, '').toLowerCase() === schema.scopeField.replace(/_/g, '').toLowerCase() && e.from !== e.to,\n )\n if (scopeEdge && !(scopeEdge.localField in fields)) {\n const scopeVal = detectScopeValue(refs, schema.scopeField)\n if (scopeVal) fields[scopeEdge.localField] = scopeVal\n }\n // Auto-populate required fields without DB defaults (e.g. Prisma's @updatedAt)\n if (modelInfo) {\n for (const field of modelInfo.fields) {\n if (field.isRequired && !field.hasDefault && !field.isId && !(field.name in fields)) {\n if (field.type === 'DateTime') {\n fields[field.name] = new Date()\n }\n }\n }\n }\n return fields\n })\n\n const spec: Record<string, ResolvedEntitySpec> = {\n [model]: { count: resolvedFields.length, fields: resolvedFields, batch: op.batch },\n }\n\n const context = { testRunId, refs }\n const created = await createEntities(tx, dialect, tableMap, columnMaps, spec, context, enumTypeMaps, schema.models)\n const records = created[model] ?? []\n\n if (!refs[model]) refs[model] = []\n refs[model].push(...records)\n\n for (let j = 0; j < batch.length; j++) {\n const record = records[j]\n if (record) {\n const recordId = record[pkFieldName]\n if (recordId != null) {\n idMap.set(batch[j]!.tempId, recordId as string | number)\n }\n }\n }\n\n i++\n }\n\n // Resolve deferred FK updates (circular dependency cycles)\n for (const deferred of tree.deferredUpdates) {\n const realTargetId = idMap.get(deferred.targetTempId)\n const refTempId = tree.aliases.get(deferred.refAlias)\n const realRefId = refTempId ? idMap.get(refTempId) : undefined\n\n if (!realTargetId || !realRefId) {\n throw new Error(\n `_ref \"${deferred.refAlias}\" could not be resolved. Ensure the referenced node has _alias defined in the scenario.`,\n )\n }\n\n const deferredModelInfo = schema.models.find((m) => m.name === deferred.model)\n const deferredIdFields = deferredModelInfo?.fields.filter((f) => f.isId) ?? []\n const deferredPkFieldName = (deferredIdFields.find((f) => f.name.toLowerCase() === 'id') ?? deferredIdFields[0])?.name ?? 'id'\n await updateEntity(tx, dialect, tableMap, columnMaps, deferred.model, String(realTargetId), { [deferred.field]: realRefId }, enumTypeMaps, deferredPkFieldName)\n }\n })\n\n const scopeValue = detectScopeValue(refs, schema.scopeField) ?? testRunId\n\n const firstUser = findFirstUser(refs)\n let auth: AuthResult = await config.auth(firstUser, { scopeValue, refs })\n\n if (config.afterUp) {\n const hookCtx: HookContext = { scenarioName: scopeValue, refs }\n auth = await config.afterUp(hookCtx, auth)\n }\n\n const refsToken = signRefs(\n { refs, testRunId: scopeValue, environment: '' },\n config.signingSecret,\n )\n\n return { status: 200, body: { ...buildSdkMeta(config), auth, refs, refsToken } }\n}\n\nasync function handleDown(\n config: HandlerConfig,\n body: Record<string, unknown>,\n): Promise<HandlerResponse> {\n const refsToken = body.refsToken as string\n if (!refsToken) throw Errors.invalidBody('missing refsToken')\n\n let payload: ReturnType<typeof verifyRefs>\n try {\n payload = verifyRefs(refsToken, config.signingSecret)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'invalid token'\n throw Errors.invalidRefsToken(message)\n }\n\n const { schema, tableMap, columnMaps } = await getIntrospection(config)\n const dialect = getDialect(config.dialect)\n\n if (config.beforeDown) {\n const hookCtx: HookContext = { scenarioName: payload.testRunId, refs: payload.refs ?? {} }\n await config.beforeDown(hookCtx)\n }\n\n await teardown(config.executor, dialect, tableMap, columnMaps, schema, payload.testRunId, payload.refs)\n\n return { status: 200, body: { ...buildSdkMeta(config), ok: true } }\n}\n\nfunction findFirstUser(\n refs: Record<string, Record<string, unknown>[]>,\n): Record<string, unknown> | null {\n for (const [model, records] of Object.entries(refs)) {\n const normalized = model.toLowerCase()\n if ((normalized === 'user' || normalized === 'users') && records.length > 0) {\n return records[0]!\n }\n }\n return null\n}\n\nfunction detectScopeValue(\n refs: Record<string, Record<string, unknown>[]>,\n scopeField: string,\n): string | null {\n const scopeNormalized = scopeField.replace(/_/g, '').toLowerCase()\n for (const records of Object.values(refs)) {\n for (const record of records) {\n for (const [key, value] of Object.entries(record)) {\n if (key.replace(/_/g, '').toLowerCase() === scopeNormalized && typeof value === 'string') {\n return value\n }\n }\n }\n }\n return null\n}\n","import { createHash } from 'node:crypto'\n\n/**\n * Compute a stable 16-char hex fingerprint of a scenario definition.\n * Uses sha256 of the JSON-serialized spec with sorted keys.\n */\nexport function fingerprint(value: unknown): string {\n const json = JSON.stringify(value, sortReplacer)\n return createHash('sha256').update(json).digest('hex').slice(0, 16)\n}\n\n/**\n * JSON replacer that sorts object keys for deterministic serialization.\n */\nfunction sortReplacer(_key: string, value: unknown): unknown {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return Object.keys(value as Record<string, unknown>)\n .sort()\n .reduce(\n (sorted, k) => {\n sorted[k] = (value as Record<string, unknown>)[k]\n return sorted\n },\n {} as Record<string, unknown>,\n )\n }\n return value\n}\n","import type {\n SQLExecutor,\n ScenarioDefinition,\n HandlerConfig,\n} from './types'\nimport { handleRequest } from './handler'\nimport { signBody } from './hmac'\n\nexport interface CheckResult {\n valid: boolean\n phase: 'up' | 'down' | 'ok'\n errors: CheckError[]\n timing?: { upMs: number; downMs: number }\n}\n\nexport interface CheckError {\n phase: 'up' | 'down'\n message: string\n fix?: string\n}\n\n/**\n * Dry-run a scenario against a real database.\n * Runs the full up → down cycle and returns structured errors.\n */\nexport async function checkScenario(\n executor: SQLExecutor,\n scenario: ScenarioDefinition,\n options?: {\n scopeField: string\n dialect?: HandlerConfig['dialect']\n dbSchema?: string\n tableNameMap?: Record<string, string>\n sharedSecret?: string\n signingSecret?: string\n auth?: HandlerConfig['auth']\n },\n): Promise<CheckResult> {\n const sharedSecret = options?.sharedSecret ?? 'autonoma-check-shared'\n const signingSecret = options?.signingSecret ?? 'autonoma-check-signing'\n\n const config: HandlerConfig = {\n executor,\n scopeField: options?.scopeField ?? 'organizationId',\n dialect: options?.dialect,\n dbSchema: options?.dbSchema,\n tableNameMap: options?.tableNameMap,\n sharedSecret,\n signingSecret,\n auth: options?.auth ?? (async () => ({ headers: { Authorization: 'Bearer check-token' } })),\n }\n\n // Up\n const upBody = JSON.stringify({ action: 'up', create: scenario.create })\n const upReq = {\n body: upBody,\n headers: { 'x-signature': signBody(upBody, sharedSecret) },\n }\n\n const t0 = performance.now()\n const upRes = await handleRequest(config, upReq)\n const upMs = Math.round(performance.now() - t0)\n\n if (upRes.status !== 200) {\n const errorMsg = (upRes.body as Record<string, string>).error ?? 'Unknown error'\n return {\n valid: false,\n phase: 'up',\n errors: [{ phase: 'up', message: errorMsg, fix: suggestFix(errorMsg) }],\n timing: { upMs, downMs: 0 },\n }\n }\n\n // Down\n const refsToken = (upRes.body as Record<string, string>).refsToken\n const downBody = JSON.stringify({ action: 'down', refsToken })\n const downReq = {\n body: downBody,\n headers: { 'x-signature': signBody(downBody, sharedSecret) },\n }\n\n const t1 = performance.now()\n const downRes = await handleRequest(config, downReq)\n const downMs = Math.round(performance.now() - t1)\n\n if (downRes.status !== 200) {\n const errorMsg = (downRes.body as Record<string, string>).error ?? 'Unknown error'\n return {\n valid: false,\n phase: 'down',\n errors: [{ phase: 'down', message: errorMsg }],\n timing: { upMs, downMs },\n }\n }\n\n return { valid: true, phase: 'ok', errors: [], timing: { upMs, downMs } }\n}\n\n/**\n * Check multiple scenarios sequentially.\n */\nexport async function checkAllScenarios(\n executor: SQLExecutor,\n scenarios: ScenarioDefinition[],\n options?: {\n scopeField: string\n dialect?: HandlerConfig['dialect']\n dbSchema?: string\n tableNameMap?: Record<string, string>\n sharedSecret?: string\n signingSecret?: string\n auth?: HandlerConfig['auth']\n },\n): Promise<CheckResult[]> {\n const results: CheckResult[] = []\n for (const scenario of scenarios) {\n results.push(await checkScenario(executor, scenario, options))\n }\n return results\n}\n\nfunction suggestFix(errorMsg: string): string {\n if (errorMsg.includes('Unique constraint failed') || errorMsg.includes('unique constraint')) {\n const match = errorMsg.match(/fields: \\(`(.+?)`\\)/) ?? errorMsg.match(/constraint \"(.+?)\"/)\n if (match) return `Unique constraint on (${match[1]}). Ensure field values are unique across instances.`\n return 'Unique constraint violation. Make field values unique across instances.'\n }\n if (errorMsg.includes('Foreign key constraint') || errorMsg.includes('foreign key')) {\n return 'A referenced record does not exist. Check that parent entities are nested correctly.'\n }\n if (errorMsg.includes('null value in column') || errorMsg.includes('must not be null')) {\n return 'A required field is null. Add it to the node with a value.'\n }\n return ''\n}\n"],"mappings":"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","names":["createHmac","timingSafeEqual","allResults"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autonoma-ai/sdk",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Autonoma Environment Factory SDK — protocol layer",
5
5
  "type": "module",
6
6
  "exports": {