@autonoma-ai/sdk 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -95,7 +95,7 @@ function convertDMMFToSchema(dmmf, scopeField) {
95
95
  });
96
96
  }
97
97
  }
98
- models.push({ name: model.name, fields });
98
+ models.push({ name: model.name, tableName: model.dbName ?? model.name, fields });
99
99
  }
100
100
  return { models, edges, relations: [], scopeField };
101
101
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport type { SchemaInfo } from './types'\n\nconst HELP = `\nautonoma — Autonoma SDK CLI\n\nCommands:\n autonoma schema convert <dmmf.json> Convert Prisma DMMF to autonoma schema\n\nOptions:\n --scope-field <name> Scope field name (default: \"testRunId\")\n --pretty Pretty-print output\n -o, --output <path> Write output to file instead of stdout\n -h, --help Show this help\n`.trim()\n\nasync function main() {\n const args = process.argv.slice(2)\n\n if (args.length === 0 || args.includes('-h') || args.includes('--help')) {\n console.log(HELP)\n process.exit(0)\n }\n\n const command = args[0]\n\n switch (command) {\n case 'schema':\n return await cmdSchema(args.slice(1))\n default:\n console.error(`Unknown command: ${command}`)\n console.log(HELP)\n process.exit(1)\n }\n}\n\n// ── schema convert ────────────────────────────────────────────────────────\n\nasync function cmdSchema(args: string[]) {\n const subcommand = args[0]\n\n if (subcommand !== 'convert') {\n console.error('Usage: autonoma schema convert <dmmf.json> --scope-field <name>')\n process.exit(1)\n }\n\n const flags = parseFlags(args.slice(1))\n const positional = flags._positional\n\n if (positional.length < 1) {\n console.error('Usage: autonoma schema convert <dmmf.json> --scope-field <name>')\n process.exit(1)\n }\n\n const dmmfPath = resolve(positional[0]!)\n const scopeField = (flags['--scope-field'] as string) ?? 'testRunId'\n const dmmf = await readJSON<DMMFInput>(dmmfPath)\n\n const schema = convertDMMFToSchema(dmmf, scopeField)\n\n const json = JSON.stringify(schema, null, 2)\n\n if (flags['-o'] || flags['--output']) {\n const outPath = resolve((flags['-o'] ?? flags['--output']) as string)\n await writeFile(outPath, json + '\\n')\n console.error(`Schema written to ${outPath}`)\n console.error(` ${schema.models.length} models, ${schema.edges.length} FK edges, scopeField: \"${scopeField}\"`)\n } else {\n console.log(json)\n }\n}\n\n// ── DMMF conversion ───────────────────────────────────────────────────────\n\ninterface DMMFInput {\n models: Record<string, DMMFModel> | DMMFModel[]\n datamodel?: { models: DMMFModel[] }\n}\n\ninterface DMMFModel {\n name: string\n fields: DMMFField[]\n}\n\ninterface DMMFField {\n name: string\n type: string\n kind: string\n isRequired: boolean\n isId: boolean\n hasDefaultValue: boolean\n relationFromFields?: string[]\n relationToFields?: string[]\n}\n\nfunction convertDMMFToSchema(dmmf: DMMFInput, scopeField: string): SchemaInfo {\n let dmmfModels: DMMFModel[]\n\n if (dmmf.datamodel?.models) {\n dmmfModels = dmmf.datamodel.models\n } else if (Array.isArray(dmmf.models)) {\n dmmfModels = dmmf.models\n } else {\n dmmfModels = Object.entries(dmmf.models).map(\n ([name, model]) => ({ ...model, name }),\n )\n }\n\n const models: SchemaInfo['models'] = []\n const edges: SchemaInfo['edges'] = []\n\n for (const model of dmmfModels) {\n const fields: SchemaInfo['models'][number]['fields'] = []\n\n for (const field of model.fields) {\n if (field.kind === 'object') {\n if (field.relationFromFields?.length) {\n edges.push({\n from: model.name,\n to: field.type,\n localField: field.relationFromFields[0]!,\n foreignField: field.relationToFields?.[0] ?? 'id',\n nullable: !field.isRequired,\n })\n }\n continue\n }\n\n if (field.kind === 'scalar' || field.kind === 'enum') {\n fields.push({\n name: field.name,\n type: field.type,\n isRequired: field.isRequired,\n isId: field.isId,\n hasDefault: field.hasDefaultValue,\n })\n }\n }\n\n models.push({ name: model.name, fields })\n }\n\n return { models, edges, relations: [], scopeField }\n}\n\n// ── Utilities ─────────────────────────────────────────────────────────────\n\nasync function readJSON<T>(path: string): Promise<T> {\n try {\n const content = await readFile(path, 'utf-8')\n return JSON.parse(content) as T\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n console.error(`File not found: ${path}`)\n } else if (err instanceof SyntaxError) {\n console.error(`Invalid JSON in ${path}: ${err.message}`)\n } else {\n console.error(`Error reading ${path}: ${err}`)\n }\n process.exit(1)\n }\n}\n\ninterface ParsedFlags {\n [key: string]: string | boolean | string[]\n _positional: string[]\n}\n\nfunction parseFlags(args: string[]): ParsedFlags {\n const result: ParsedFlags = { _positional: [] }\n let i = 0\n while (i < args.length) {\n const arg = args[i]!\n if (arg.startsWith('-')) {\n const next = args[i + 1]\n if (next && !next.startsWith('-')) {\n result[arg] = next\n i += 2\n } else {\n result[arg] = true\n i++\n }\n } else {\n result._positional.push(arg)\n i++\n }\n }\n return result\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err instanceof Error ? err.message : err)\n process.exit(1)\n})\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport type { SchemaInfo } from './types'\n\nconst HELP = `\nautonoma — Autonoma SDK CLI\n\nCommands:\n autonoma schema convert <dmmf.json> Convert Prisma DMMF to autonoma schema\n\nOptions:\n --scope-field <name> Scope field name (default: \"testRunId\")\n --pretty Pretty-print output\n -o, --output <path> Write output to file instead of stdout\n -h, --help Show this help\n`.trim()\n\nasync function main() {\n const args = process.argv.slice(2)\n\n if (args.length === 0 || args.includes('-h') || args.includes('--help')) {\n console.log(HELP)\n process.exit(0)\n }\n\n const command = args[0]\n\n switch (command) {\n case 'schema':\n return await cmdSchema(args.slice(1))\n default:\n console.error(`Unknown command: ${command}`)\n console.log(HELP)\n process.exit(1)\n }\n}\n\n// ── schema convert ────────────────────────────────────────────────────────\n\nasync function cmdSchema(args: string[]) {\n const subcommand = args[0]\n\n if (subcommand !== 'convert') {\n console.error('Usage: autonoma schema convert <dmmf.json> --scope-field <name>')\n process.exit(1)\n }\n\n const flags = parseFlags(args.slice(1))\n const positional = flags._positional\n\n if (positional.length < 1) {\n console.error('Usage: autonoma schema convert <dmmf.json> --scope-field <name>')\n process.exit(1)\n }\n\n const dmmfPath = resolve(positional[0]!)\n const scopeField = (flags['--scope-field'] as string) ?? 'testRunId'\n const dmmf = await readJSON<DMMFInput>(dmmfPath)\n\n const schema = convertDMMFToSchema(dmmf, scopeField)\n\n const json = JSON.stringify(schema, null, 2)\n\n if (flags['-o'] || flags['--output']) {\n const outPath = resolve((flags['-o'] ?? flags['--output']) as string)\n await writeFile(outPath, json + '\\n')\n console.error(`Schema written to ${outPath}`)\n console.error(` ${schema.models.length} models, ${schema.edges.length} FK edges, scopeField: \"${scopeField}\"`)\n } else {\n console.log(json)\n }\n}\n\n// ── DMMF conversion ───────────────────────────────────────────────────────\n\ninterface DMMFInput {\n models: Record<string, DMMFModel> | DMMFModel[]\n datamodel?: { models: DMMFModel[] }\n}\n\ninterface DMMFModel {\n name: string\n dbName?: string | null\n fields: DMMFField[]\n}\n\ninterface DMMFField {\n name: string\n type: string\n kind: string\n isRequired: boolean\n isId: boolean\n hasDefaultValue: boolean\n relationFromFields?: string[]\n relationToFields?: string[]\n}\n\nfunction convertDMMFToSchema(dmmf: DMMFInput, scopeField: string): SchemaInfo {\n let dmmfModels: DMMFModel[]\n\n if (dmmf.datamodel?.models) {\n dmmfModels = dmmf.datamodel.models\n } else if (Array.isArray(dmmf.models)) {\n dmmfModels = dmmf.models\n } else {\n dmmfModels = Object.entries(dmmf.models).map(\n ([name, model]) => ({ ...model, name }),\n )\n }\n\n const models: SchemaInfo['models'] = []\n const edges: SchemaInfo['edges'] = []\n\n for (const model of dmmfModels) {\n const fields: SchemaInfo['models'][number]['fields'] = []\n\n for (const field of model.fields) {\n if (field.kind === 'object') {\n if (field.relationFromFields?.length) {\n edges.push({\n from: model.name,\n to: field.type,\n localField: field.relationFromFields[0]!,\n foreignField: field.relationToFields?.[0] ?? 'id',\n nullable: !field.isRequired,\n })\n }\n continue\n }\n\n if (field.kind === 'scalar' || field.kind === 'enum') {\n fields.push({\n name: field.name,\n type: field.type,\n isRequired: field.isRequired,\n isId: field.isId,\n hasDefault: field.hasDefaultValue,\n })\n }\n }\n\n models.push({ name: model.name, tableName: model.dbName ?? model.name, fields })\n }\n\n return { models, edges, relations: [], scopeField }\n}\n\n// ── Utilities ─────────────────────────────────────────────────────────────\n\nasync function readJSON<T>(path: string): Promise<T> {\n try {\n const content = await readFile(path, 'utf-8')\n return JSON.parse(content) as T\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n console.error(`File not found: ${path}`)\n } else if (err instanceof SyntaxError) {\n console.error(`Invalid JSON in ${path}: ${err.message}`)\n } else {\n console.error(`Error reading ${path}: ${err}`)\n }\n process.exit(1)\n }\n}\n\ninterface ParsedFlags {\n [key: string]: string | boolean | string[]\n _positional: string[]\n}\n\nfunction parseFlags(args: string[]): ParsedFlags {\n const result: ParsedFlags = { _positional: [] }\n let i = 0\n while (i < args.length) {\n const arg = args[i]!\n if (arg.startsWith('-')) {\n const next = args[i + 1]\n if (next && !next.startsWith('-')) {\n result[arg] = next\n i += 2\n } else {\n result[arg] = true\n i++\n }\n } else {\n result._positional.push(arg)\n i++\n }\n }\n return result\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err instanceof Error ? err.message : err)\n process.exit(1)\n})\n"],"mappings":"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","names":[]}
@@ -1,17 +1,13 @@
1
- /** ORM adapter interfaceimplemented by @autonoma-ai/sdk-prisma, @autonoma-ai/sdk-drizzle, etc. */
2
- interface OrmAdapter {
3
- /** Return schema metadata for discover (models, fields, relationships) */
4
- getSchema(): SchemaInfo;
5
- /** Create entities from a resolved spec, return created records keyed by model */
6
- createEntities(spec: Record<string, ResolvedEntitySpec>, context: CreateContext): Promise<Record<string, Record<string, unknown>[]>>;
7
- /** Delete all data scoped to a value. Refs are provided for targeted cleanup of un-scoped models. */
8
- teardown(scopeValue: string, refs?: Record<string, Record<string, unknown>[]>): Promise<void>;
1
+ /** Minimal SQL executorwrap your DB connection (pg Pool, Prisma, Drizzle, etc.) into this. */
2
+ interface SQLExecutor {
3
+ /** Execute a SQL query with parameterized values. Returns rows as plain objects. */
4
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
9
5
  /**
10
- * Update a single record by ID. Used to backfill nullable FKs in circular
11
- * dependency cycles (e.g. Application.mainBranchId after Branch is created).
12
- * Optional only required when circular FK relationships exist in the schema.
6
+ * Execute a block within a transaction.
7
+ * The callback receives an executor scoped to the transaction.
8
+ * If the callback throws, the transaction is rolled back.
13
9
  */
14
- updateEntity?(model: string, id: string, fields: Record<string, unknown>): Promise<void>;
10
+ transaction<T>(fn: (tx: SQLExecutor) => Promise<T>): Promise<T>;
15
11
  }
16
12
  interface SchemaInfo {
17
13
  models: ModelInfo[];
@@ -28,6 +24,7 @@ interface SchemaRelation {
28
24
  }
29
25
  interface ModelInfo {
30
26
  name: string;
27
+ tableName: string;
31
28
  fields: FieldInfo[];
32
29
  }
33
30
  interface FieldInfo {
@@ -58,18 +55,56 @@ interface ScenarioDefinition {
58
55
  /** Nested tree: model name → array of node objects with nested children */
59
56
  create: Record<string, Record<string, unknown>[]>;
60
57
  }
58
+ interface SdkInfo {
59
+ language: string;
60
+ orm: string;
61
+ server: string;
62
+ }
61
63
  interface HandlerConfig {
62
- adapter: OrmAdapter;
64
+ /** SQL executor wrapping your database connection */
65
+ executor: SQLExecutor;
66
+ /** Scope field name (camelCase), e.g., 'organizationId' */
67
+ scopeField: string;
68
+ /** Database dialect. Defaults to 'postgres'. */
69
+ dialect?: 'postgres' | 'mysql' | 'sqlite';
70
+ /** DB schema name. Defaults to 'public' for Postgres. */
71
+ dbSchema?: string;
72
+ /**
73
+ * Map scenario model names to DB table names.
74
+ * Keys are model names (PascalCase), values are DB table names.
75
+ * If omitted, auto-detected from information_schema with PascalCase inference.
76
+ */
77
+ tableNameMap?: Record<string, string>;
78
+ /** Tables to exclude from introspection. Defaults to ['_prisma_migrations']. */
79
+ excludeTables?: string[];
63
80
  /** Shared secret — known by both you and Autonoma. Used to verify HMAC signatures on incoming requests. */
64
81
  sharedSecret: string;
65
82
  /** Internal secret — only you know this. Used to sign the refs JWT token. Autonoma never sees it. */
66
83
  signingSecret: string;
67
84
  allowProduction?: boolean;
68
- auth?: (user: Record<string, unknown>) => Promise<AuthResult> | AuthResult;
85
+ /**
86
+ * Auth callback — called after entity creation during `up`.
87
+ * Receives the first User record from refs (or null if no User model exists).
88
+ * Must return auth credentials for the test runner.
89
+ */
90
+ auth: (user: Record<string, unknown> | null) => Promise<AuthResult> | AuthResult;
91
+ /** SDK identity metadata. Server and ORM adapters populate this. */
92
+ sdk?: Partial<SdkInfo>;
93
+ }
94
+ interface AuthCookie {
95
+ name: string;
96
+ value: string;
97
+ httpOnly?: boolean;
98
+ sameSite?: 'strict' | 'lax' | 'none';
99
+ path?: string;
100
+ domain?: string;
101
+ secure?: boolean;
102
+ maxAge?: number;
69
103
  }
70
104
  interface AuthResult {
71
- token: string;
72
- [key: string]: unknown;
105
+ cookies?: AuthCookie[];
106
+ headers?: Record<string, string>;
107
+ credentials?: Record<string, string>;
73
108
  }
74
109
  interface HandlerRequest {
75
110
  body: string;
@@ -110,4 +145,4 @@ declare function topoSort(nodes: string[], edges: FKEdge[]): TopoSortResult;
110
145
  */
111
146
  declare function findDeferrableEdge(cycle: string[], edges: FKEdge[]): FKEdge | null;
112
147
 
113
- export { type AuthResult as A, type CreateContext as C, type DiscoverResponse as D, type FKEdge as F, type HandlerConfig as H, type ModelInfo as M, type OrmAdapter as O, 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 ScenarioDefinition as c, type DownResponse as d, type FieldInfo as e, type SchemaRelation as f, findDeferrableEdge as g, topoSort as t };
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 };
package/dist/graph.d.ts CHANGED
@@ -1 +1 @@
1
- export { F as FKEdge, T as TopoSortResult, g as findDeferrableEdge, t as topoSort } from './graph-DmvFK17b.js';
1
+ export { F as FKEdge, T as TopoSortResult, j as findDeferrableEdge, t as topoSort } from './graph-DY4OdpZ4.js';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { H as HandlerConfig, a as HandlerRequest, b as HandlerResponse, S as SchemaInfo, O as OrmAdapter, c as ScenarioDefinition } from './graph-DmvFK17b.js';
2
- export { A as AuthResult, C as CreateContext, D as DiscoverResponse, d as DownResponse, F as FKEdge, e as FieldInfo, M as ModelInfo, R as ResolvedEntitySpec, f as SchemaRelation, U as UpResponse, g as findDeferrableEdge, t as topoSort } from './graph-DmvFK17b.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 } from './graph-DY4OdpZ4.js';
2
+ export { A as AuthCookie, e as AuthResult, D as DiscoverResponse, f as DownResponse, F as FKEdge, g as FieldInfo, M as ModelInfo, h as SchemaRelation, i as SdkInfo, U as UpResponse, j as findDeferrableEdge, t as topoSort } from './graph-DY4OdpZ4.js';
3
3
 
4
+ declare const PROTOCOL_VERSION = "1.0";
4
5
  declare function handleRequest(config: HandlerConfig, req: HandlerRequest): Promise<HandlerResponse>;
5
6
 
6
7
  declare function signBody(body: string, secret: string): string;
@@ -99,7 +100,11 @@ interface CheckError {
99
100
  * Dry-run a scenario against a real database.
100
101
  * Runs the full up → down cycle and returns structured errors.
101
102
  */
102
- declare function checkScenario(adapter: OrmAdapter, scenario: ScenarioDefinition, options?: {
103
+ declare function checkScenario(executor: SQLExecutor, scenario: ScenarioDefinition, options?: {
104
+ scopeField: string;
105
+ dialect?: HandlerConfig['dialect'];
106
+ dbSchema?: string;
107
+ tableNameMap?: Record<string, string>;
103
108
  sharedSecret?: string;
104
109
  signingSecret?: string;
105
110
  auth?: HandlerConfig['auth'];
@@ -107,10 +112,83 @@ declare function checkScenario(adapter: OrmAdapter, scenario: ScenarioDefinition
107
112
  /**
108
113
  * Check multiple scenarios sequentially.
109
114
  */
110
- declare function checkAllScenarios(adapter: OrmAdapter, scenarios: ScenarioDefinition[], options?: {
115
+ declare function checkAllScenarios(executor: SQLExecutor, scenarios: ScenarioDefinition[], options?: {
116
+ scopeField: string;
117
+ dialect?: HandlerConfig['dialect'];
118
+ dbSchema?: string;
119
+ tableNameMap?: Record<string, string>;
111
120
  sharedSecret?: string;
112
121
  signingSecret?: string;
113
122
  auth?: HandlerConfig['auth'];
114
123
  }): Promise<CheckResult[]>;
115
124
 
116
- export { type CheckError, type CheckResult, type CreateOp, HandlerConfig, HandlerRequest, HandlerResponse, OrmAdapter, type RefNode, type ResolvedTree, ScenarioDefinition, SchemaInfo, type TemplateContext, checkAllScenarios, checkScenario, fingerprint, handleRequest, resolveTemplate, resolveTree, signBody, signRefs, verifyRefs, verifySignature };
125
+ /** Database dialect abstraction generates dialect-specific SQL strings. */
126
+ interface Dialect {
127
+ readonly name: 'postgres' | 'mysql' | 'sqlite';
128
+ /** Parameter placeholder for index (1-based). Postgres: $1, MySQL/SQLite: ? */
129
+ param(index: number): string;
130
+ /** Quote an identifier. Postgres: "name", MySQL: `name` */
131
+ quoteId(name: string): string;
132
+ /** Whether INSERT ... RETURNING is supported */
133
+ readonly supportsReturning: boolean;
134
+ /** SQL to list all base tables in a schema/database */
135
+ tablesSQL(schema: string): string;
136
+ /** SQL to list all columns for all tables in a schema/database */
137
+ columnsSQL(schema: string): string;
138
+ /** SQL to list primary key columns */
139
+ primaryKeysSQL(schema: string): string;
140
+ /** SQL to list foreign key relationships */
141
+ foreignKeysSQL(schema: string): string;
142
+ /** SQL to list enum types and their values */
143
+ enumsSQL(schema: string): string;
144
+ }
145
+ declare function getDialect(name?: 'postgres' | 'mysql' | 'sqlite'): Dialect;
146
+
147
+ /** Internal result including name mapping tables */
148
+ interface IntrospectionResult {
149
+ schema: SchemaInfo;
150
+ /** model name → DB table name */
151
+ tableMap: Map<string, string>;
152
+ /** model name → (field name → DB column name) */
153
+ columnMaps: Map<string, Map<string, string>>;
154
+ /** model name → (field name → Postgres enum type name). Only populated for Postgres. */
155
+ enumTypeMaps: Map<string, Map<string, string>>;
156
+ }
157
+ /**
158
+ * Introspect a database via information_schema to build SchemaInfo.
159
+ *
160
+ * Auto-maps DB names (snake_case) to model names (PascalCase) and
161
+ * field names (camelCase). Override with `tableNameMap`.
162
+ */
163
+ declare function introspectDatabase(executor: SQLExecutor, dialect: Dialect, config: {
164
+ scopeField: string;
165
+ schema?: string;
166
+ tableNameMap?: Record<string, string>;
167
+ excludeTables?: string[];
168
+ }): Promise<IntrospectionResult>;
169
+
170
+ /**
171
+ * Create entities via raw SQL INSERT.
172
+ *
173
+ * Entities arrive pre-sorted by FK order (handler does topo-sort via tree.ts).
174
+ * Each model in `spec` is inserted sequentially; within a model, batch mode
175
+ * uses a single multi-row INSERT while normal mode inserts one row at a time.
176
+ *
177
+ * For dialects with RETURNING (Postgres): INSERT ... RETURNING *
178
+ * For dialects without (MySQL): INSERT then SELECT via LAST_INSERT_ID()
179
+ */
180
+ declare function createEntities(executor: SQLExecutor, dialect: Dialect, tableMap: Map<string, string>, columnMaps: Map<string, Map<string, string>>, spec: Record<string, ResolvedEntitySpec>, _context: CreateContext, enumTypeMaps?: Map<string, Map<string, string>>): Promise<Record<string, Record<string, unknown>[]>>;
181
+
182
+ /**
183
+ * Tear down all data scoped to a value, in reverse topological order.
184
+ *
185
+ * Strategy:
186
+ * 1. Find the scope root model (e.g. Organization) from FK edges
187
+ * 2. Any model with a FK pointing to the scope root is "scoped"
188
+ * 3. Delete scoped models by their FK = scopeValue
189
+ * 4. Delete non-scoped models by their record IDs from refs
190
+ * 5. Delete the scope root entity last by id = scopeValue
191
+ */
192
+ declare function teardown(executor: SQLExecutor, dialect: Dialect, tableMap: Map<string, string>, columnMaps: Map<string, Map<string, string>>, schema: SchemaInfo, scopeValue: string, refs?: Record<string, Record<string, unknown>[]>): Promise<void>;
193
+
194
+ export { type CheckError, type CheckResult, CreateContext, type CreateOp, type Dialect, HandlerConfig, HandlerRequest, HandlerResponse, type IntrospectionResult, PROTOCOL_VERSION, type RefNode, ResolvedEntitySpec, type ResolvedTree, SQLExecutor, ScenarioDefinition, SchemaInfo, type TemplateContext, checkAllScenarios, checkScenario, createEntities, fingerprint, getDialect, handleRequest, introspectDatabase, resolveTemplate, resolveTree, signBody, signRefs, teardown, verifyRefs, verifySignature };