@danceroutine/tango-orm 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -49,7 +49,7 @@ export const TodoModel = Model({
49
49
  schema: TodoReadSchema.extend({
50
50
  id: t.primaryKey(z.number().int()),
51
51
  title: z.string(),
52
- completed: t.default(z.coerce.boolean(), 'false'),
52
+ completed: t.field(z.coerce.boolean()).defaultValue('false').build(),
53
53
  }),
54
54
  });
55
55
 
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { PostgresAdapter } from "./PostgresAdapter-C9a1XJRx.js";
2
2
  import { SqliteAdapter } from "./SqliteAdapter-Dp6VRXmz.js";
3
3
  import { AdapterRegistry, connectDB, connection_exports, getDefaultAdapterRegistry } from "./connection-CVvycXus.js";
4
- import { QBuilder, QueryCompiler, QuerySet, query_exports } from "./query-wnl4h2o7.js";
5
- import { ModelManager, TangoRuntime, getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from "./registerModelObjects-emX7Hja9.js";
6
- import { manager_exports } from "./manager-D6tU8xTO.js";
7
- import { runtime_exports } from "./runtime-7U5_XDad.js";
4
+ import { ModelManager, TangoRuntime, getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from "./registerModelObjects-vsX6GzCN.js";
5
+ import { QBuilder, QueryCompiler, QuerySet, query_exports } from "./query-BKt2nKIt.js";
6
+ import { manager_exports } from "./manager-CKUy1CIt.js";
7
+ import { runtime_exports } from "./runtime-BUpil272.js";
8
8
  import { UnitOfWork, transaction_exports } from "./transaction-DooTMuAl.js";
9
9
 
10
10
  export { AdapterRegistry, ModelManager, PostgresAdapter, QBuilder as Q, QBuilder, QueryCompiler, QuerySet, SqliteAdapter, TangoRuntime, UnitOfWork, connectDB, connection_exports as connection, getDefaultAdapterRegistry, getTangoRuntime, initializeTangoRuntime, manager_exports as manager, query_exports as query, resetTangoRuntime, runtime_exports as runtime, transaction_exports as transaction };
@@ -1,4 +1,4 @@
1
- import type { ModelWriteHooks } from '@danceroutine/tango-schema';
1
+ import { type ModelWriteHooks } from '@danceroutine/tango-schema';
2
2
  import type { TableMeta } from '../query/domain/index';
3
3
  import type { QuerySet } from '../query/index';
4
4
  import type { TangoRuntime } from '../runtime/TangoRuntime';
@@ -10,6 +10,7 @@ type FieldLike = {
10
10
  };
11
11
  type ModelLike<T extends Record<string, unknown>> = {
12
12
  metadata: {
13
+ key?: string;
13
14
  name: string;
14
15
  table: string;
15
16
  fields: FieldLike[];
@@ -25,11 +26,13 @@ type ModelLike<T extends Record<string, unknown>> = {
25
26
  export declare class ModelManager<T extends Record<string, unknown>> implements ManagerLike<T> {
26
27
  static readonly BRAND: "tango.orm.model_manager";
27
28
  readonly __tangoBrand: typeof ModelManager.BRAND;
28
- readonly meta: TableMeta;
29
29
  private readonly queryExecutor;
30
30
  private readonly mutationCompiler;
31
31
  private readonly model;
32
+ private readonly client;
33
+ private readonly dialect;
32
34
  constructor(model: ModelLike<T>, runtime: TangoRuntime);
35
+ get meta(): TableMeta;
33
36
  /**
34
37
  * Narrow an unknown value to `ModelManager`.
35
38
  */
@@ -1,8 +1,8 @@
1
1
  import "../PostgresAdapter-C9a1XJRx.js";
2
2
  import "../SqliteAdapter-Dp6VRXmz.js";
3
3
  import "../connection-CVvycXus.js";
4
- import "../query-wnl4h2o7.js";
5
- import { ModelManager, registerModelObjects } from "../registerModelObjects-emX7Hja9.js";
6
- import "../manager-D6tU8xTO.js";
4
+ import { ModelManager, registerModelObjects } from "../registerModelObjects-vsX6GzCN.js";
5
+ import "../query-BKt2nKIt.js";
6
+ import "../manager-CKUy1CIt.js";
7
7
 
8
8
  export { ModelManager, registerModelObjects };
@@ -1,5 +1,5 @@
1
1
  import { __export } from "./chunk-DLY2FNSh.js";
2
- import { ModelManager, registerModelObjects } from "./registerModelObjects-emX7Hja9.js";
2
+ import { ModelManager, registerModelObjects } from "./registerModelObjects-vsX6GzCN.js";
3
3
 
4
4
  //#region src/manager/index.ts
5
5
  var manager_exports = {};
@@ -10,4 +10,4 @@ __export(manager_exports, {
10
10
 
11
11
  //#endregion
12
12
  export { manager_exports };
13
- //# sourceMappingURL=manager-D6tU8xTO.js.map
13
+ //# sourceMappingURL=manager-CKUy1CIt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"manager-D6tU8xTO.js","names":[],"sources":["../src/manager/index.ts"],"sourcesContent":["/**\n * Domain boundary barrel: centralizes manager-first ORM APIs.\n */\nexport type { ManagerLike } from './ManagerLike';\nexport { ModelManager } from './ModelManager';\nexport { registerModelObjects } from './registerModelObjects';\n"],"mappings":""}
1
+ {"version":3,"file":"manager-CKUy1CIt.js","names":[],"sources":["../src/manager/index.ts"],"sourcesContent":["/**\n * Domain boundary barrel: centralizes manager-first ORM APIs.\n */\nexport type { ManagerLike } from './ManagerLike';\nexport { ModelManager } from './ModelManager';\nexport { registerModelObjects } from './registerModelObjects';\n"],"mappings":""}
@@ -23,11 +23,19 @@ export interface QueryExecutor<T> {
23
23
  params: readonly unknown[];
24
24
  }): Promise<T[]>;
25
25
  }
26
+ type QueryShapeFunction<TInput, TOutput> = (row: TInput) => TOutput;
27
+ type QueryShapeParser<TInput, TOutput> = {
28
+ parse: (row: TInput) => TOutput;
29
+ };
30
+ type QueryShape<TInput> = QueryShapeFunction<TInput, unknown> | QueryShapeParser<TInput, unknown>;
31
+ type QueryShapeOutput<TInput, TShape> = TShape extends QueryShapeFunction<TInput, infer TOutput> ? TOutput : TShape extends QueryShapeParser<TInput, infer TOutput> ? TOutput : never;
32
+ type ProjectedResult<TModel extends Record<string, unknown>, TKeys extends readonly (keyof TModel)[]> = number extends TKeys['length'] ? TModel : [TKeys[number]] extends [never] ? TModel : Pick<TModel, TKeys[number]>;
26
33
  /**
27
34
  * Django-inspired query builder for constructing and executing database queries.
28
35
  * Provides a fluent API for filtering, ordering, pagination, and eager loading.
29
36
  *
30
- * @template T - The model type being queried
37
+ * @template TModel - The full model row type used for query composition
38
+ * @template TResult - The fetched row shape returned by execution methods
31
39
  *
32
40
  * @example
33
41
  * ```typescript
@@ -40,66 +48,80 @@ export interface QueryExecutor<T> {
40
48
  * .fetch();
41
49
  * ```
42
50
  */
43
- export declare class QuerySet<T extends Record<string, unknown>> {
51
+ export declare class QuerySet<TModel extends Record<string, unknown>, TResult extends Record<string, unknown> = TModel> {
44
52
  private executor;
45
53
  private state;
46
54
  static readonly BRAND: "tango.orm.query_set";
47
55
  readonly __tangoBrand: typeof QuerySet.BRAND;
48
- constructor(executor: QueryExecutor<T>, state?: QuerySetState<T>);
56
+ constructor(executor: QueryExecutor<TModel>, state?: QuerySetState<TModel>);
49
57
  /**
50
58
  * Narrow an unknown value to `QuerySet`.
51
59
  */
52
- static isQuerySet<T extends Record<string, unknown>>(value: unknown): value is QuerySet<T>;
60
+ static isQuerySet<TModel extends Record<string, unknown>, TResult extends Record<string, unknown> = TModel>(value: unknown): value is QuerySet<TModel, TResult>;
53
61
  /**
54
62
  * Add a filter expression to the query.
55
63
  *
56
64
  * Multiple `filter()` calls are composed with `AND`.
57
65
  */
58
- filter(q: FilterInput<T> | QNode<T>): QuerySet<T>;
66
+ filter(q: FilterInput<TModel> | QNode<TModel>): QuerySet<TModel, TResult>;
59
67
  /**
60
68
  * Add an exclusion expression to the query.
61
69
  *
62
70
  * Exclusions are translated to `NOT (...)` predicates.
63
71
  */
64
- exclude(q: FilterInput<T> | QNode<T>): QuerySet<T>;
72
+ exclude(q: FilterInput<TModel> | QNode<TModel>): QuerySet<TModel, TResult>;
65
73
  /**
66
74
  * Apply ordering tokens such as `'name'` or `'-createdAt'`.
67
75
  */
68
- orderBy(...tokens: OrderToken<T>[]): QuerySet<T>;
76
+ orderBy(...tokens: OrderToken<TModel>[]): QuerySet<TModel, TResult>;
69
77
  /**
70
78
  * Limit the maximum number of rows returned.
71
79
  */
72
- limit(n: number): QuerySet<T>;
80
+ limit(n: number): QuerySet<TModel, TResult>;
73
81
  /**
74
82
  * Skip the first `n` rows.
75
83
  */
76
- offset(n: number): QuerySet<T>;
84
+ offset(n: number): QuerySet<TModel, TResult>;
77
85
  /**
78
- * Restrict selected columns.
86
+ * Restrict selected columns and narrow the fetched row type when the
87
+ * selected keys are known precisely at the call site.
88
+ *
89
+ * Empty selections reset back to the full model row, and repeated
90
+ * `select(...)` calls replace the previous projection rather than
91
+ * intersecting it.
79
92
  */
80
- select(cols: (keyof T)[]): QuerySet<T>;
93
+ select<const TKeys extends readonly (keyof TModel)[]>(cols: TKeys): QuerySet<TModel, ProjectedResult<TModel, TKeys>>;
94
+ select(cols: readonly (keyof TModel)[]): QuerySet<TModel, TModel>;
81
95
  /**
82
96
  * Request SQL joins for related data when supported by relation metadata.
83
97
  */
84
- selectRelated(...rels: string[]): QuerySet<T>;
98
+ selectRelated(...rels: string[]): QuerySet<TModel, TResult>;
85
99
  /**
86
100
  * Register relation names for prefetch behavior.
87
101
  *
88
102
  * Prefetch orchestration is adapter-specific.
89
103
  */
90
- prefetchRelated(...rels: string[]): QuerySet<T>;
104
+ prefetchRelated(...rels: string[]): QuerySet<TModel, TResult>;
91
105
  /**
92
106
  * Execute the query and optionally shape each row.
107
+ *
108
+ * When the queryset has been narrowed by `select(...)`, rows passed to the
109
+ * shaping callback or parser use that narrowed fetched-row type.
93
110
  */
94
- fetch<Out = T>(shape?: ((r: T) => Out) | {
95
- parse: (r: T) => Out;
96
- }): Promise<QueryResult<Out>>;
111
+ fetch(): Promise<QueryResult<TResult>>;
112
+ fetch<Out>(shape: QueryShapeFunction<TResult, Out>): Promise<QueryResult<Out>>;
113
+ fetch<Out>(shape: QueryShapeParser<TResult, Out>): Promise<QueryResult<Out>>;
114
+ fetch<TShape extends QueryShape<TResult> | undefined>(shape: TShape): Promise<QueryResult<TResult | QueryShapeOutput<TResult, NonNullable<TShape>>>>;
97
115
  /**
98
116
  * Execute the query and return the first row, or `null`.
117
+ *
118
+ * As with `fetch(...)`, parser and function overloads receive the current
119
+ * fetched-row type after any `select(...)` projection narrowing.
99
120
  */
100
- fetchOne<Out = T>(shape?: ((r: T) => Out) | {
101
- parse: (r: T) => Out;
102
- }): Promise<Out | null>;
121
+ fetchOne(): Promise<TResult | null>;
122
+ fetchOne<Out>(shape: QueryShapeFunction<TResult, Out>): Promise<Out | null>;
123
+ fetchOne<Out>(shape: QueryShapeParser<TResult, Out>): Promise<Out | null>;
124
+ fetchOne<TShape extends QueryShape<TResult> | undefined>(shape: TShape): Promise<TResult | QueryShapeOutput<TResult, NonNullable<TShape>> | null>;
103
125
  /**
104
126
  * Execute a `COUNT(*)` query for the current filtered state.
105
127
  */
@@ -113,3 +135,4 @@ export declare class QuerySet<T extends Record<string, unknown>> {
113
135
  private normalizeSqliteBoolean;
114
136
  private normalizeBooleanColumns;
115
137
  }
138
+ export {};
@@ -2,4 +2,5 @@ export declare const InternalRelationKind: {
2
2
  readonly HAS_MANY: "hasMany";
3
3
  readonly BELONGS_TO: "belongsTo";
4
4
  readonly HAS_ONE: "hasOne";
5
+ readonly MANY_TO_MANY: "manyToMany";
5
6
  };
@@ -1,3 +1,3 @@
1
- import { QBuilder, QueryCompiler, QuerySet, compiler_exports, domain_exports } from "../query-wnl4h2o7.js";
1
+ import { QBuilder, QueryCompiler, QuerySet, compiler_exports, domain_exports } from "../query-BKt2nKIt.js";
2
2
 
3
3
  export { QBuilder as Q, QBuilder, QueryCompiler, QuerySet, compiler_exports as compiler, domain_exports as domain };
@@ -559,13 +559,10 @@ var QuerySet = class QuerySet {
559
559
  offset: n
560
560
  });
561
561
  }
562
- /**
563
- * Restrict selected columns.
564
- */
565
562
  select(cols) {
566
563
  return new QuerySet(this.executor, {
567
564
  ...this.state,
568
- select: cols
565
+ select: [...cols]
569
566
  });
570
567
  }
571
568
  /**
@@ -588,26 +585,21 @@ var QuerySet = class QuerySet {
588
585
  prefetchRelated: rels
589
586
  });
590
587
  }
591
- /**
592
- * Execute the query and optionally shape each row.
593
- */
594
588
  async fetch(shape) {
595
589
  const compiler = new QueryCompiler(this.executor.meta, this.executor.dialect);
596
590
  const compiled = compiler.compile(this.state);
597
591
  const rows = await this.executor.run(compiled);
598
592
  const normalizedRows = this.normalizeRowsForSchemaParsing(rows, shape);
599
- const results = !shape ? normalizedRows : typeof shape === "function" ? normalizedRows.map(shape) : normalizedRows.map((r) => shape.parse(r));
593
+ const projectedRows = normalizedRows;
594
+ const results = !shape ? projectedRows : typeof shape === "function" ? projectedRows.map(shape) : projectedRows.map((r) => shape.parse(r));
600
595
  return {
601
596
  results,
602
597
  nextCursor: null
603
598
  };
604
599
  }
605
- /**
606
- * Execute the query and return the first row, or `null`.
607
- */
608
600
  async fetchOne(shape) {
609
601
  const limited = this.limit(1);
610
- const result = await limited.fetch(shape);
602
+ const result = !shape ? await limited.fetch() : typeof shape === "function" ? await limited.fetch(shape) : await limited.fetch(shape);
611
603
  return result.results[0] ?? null;
612
604
  }
613
605
  /**
@@ -668,4 +660,4 @@ __export(query_exports, {
668
660
 
669
661
  //#endregion
670
662
  export { OrmSqlSafetyAdapter, QBuilder, QueryCompiler, QuerySet, compiler_exports, domain_exports, query_exports };
671
- //# sourceMappingURL=query-wnl4h2o7.js.map
663
+ //# sourceMappingURL=query-BKt2nKIt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-BKt2nKIt.js","names":["engine: SqlSafetyEngine","plan: SqlValidationPlan","meta: TableMeta","relationNames: readonly string[]","validatedMeta: ValidatedTableMeta","meta: ValidatedTableMeta","relationName: string","relations: TableMeta['relations']","rawKey: string","field: string","meta: TableMeta","dialect: Dialect","value: unknown","state: QuerySetState<T>","whereParts: string[]","params: unknown[]","node: QNode<T>","paramIndex: number","filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>","where: FilterInput<T>","nodes: QNode<T>[]","col: string","lookup: LookupType","filterKeys: Set<string>","value: unknown","node: FilterInput<T> | QNode<T>","input: FilterInput<T> | QNode<T>","executor: QueryExecutor<TModel>","state: QuerySetState<TModel>","value: unknown","q: FilterInput<TModel> | QNode<TModel>","wrapped: QNode<TModel>","n: number","cols: readonly (keyof TModel)[]","shape?: QueryShapeFunction<TResult, Out> | QueryShapeParser<TResult, Out>","results: Array<TResult | Out>","rows: TModel[]","row: TModel","columns: readonly string[]","normalized: TModel | null"],"sources":["../src/query/domain/internal/InternalDialect.ts","../src/query/domain/internal/InternalQNodeType.ts","../src/query/domain/internal/InternalLookupType.ts","../src/validation/OrmSqlSafetyAdapter.ts","../src/query/compiler/QueryCompiler.ts","../src/query/compiler/index.ts","../src/query/domain/index.ts","../src/query/domain/internal/InternalDirection.ts","../src/query/QBuilder.ts","../src/query/QuerySet.ts","../src/query/index.ts"],"sourcesContent":["export const InternalDialect = {\n POSTGRES: 'postgres',\n SQLITE: 'sqlite',\n} as const;\n","export const InternalQNodeType = {\n ATOM: 'atom',\n AND: 'and',\n OR: 'or',\n NOT: 'not',\n} as const;\n","export const InternalLookupType = {\n EXACT: 'exact',\n LT: 'lt',\n LTE: 'lte',\n GT: 'gt',\n GTE: 'gte',\n IN: 'in',\n ISNULL: 'isnull',\n CONTAINS: 'contains',\n ICONTAINS: 'icontains',\n STARTSWITH: 'startswith',\n ISTARTSWITH: 'istartswith',\n ENDSWITH: 'endswith',\n IENDSWITH: 'iendswith',\n} as const;\n","import { SqlSafetyEngine, type SqlIdentifierRequest } from '@danceroutine/tango-core';\nimport type { LookupType } from '../query/domain/LookupType';\nimport type { TableMeta } from '../query/domain/TableMeta';\nimport { InternalLookupType } from '../query/domain/internal/InternalLookupType';\nimport type {\n SQLValidationEngine,\n ValidatedDeleteSqlPlan,\n ValidatedFilterDescriptor,\n ValidatedInsertSqlPlan,\n ValidatedRelationMeta,\n ValidatedTableMeta,\n ValidatedSelectSqlPlan,\n ValidatedSqlPlan,\n ValidatedUpdateSqlPlan,\n} from './SQLValidationEngine';\nimport type {\n DeleteSqlValidationPlan,\n InsertSqlValidationPlan,\n SelectSqlValidationPlan,\n SqlValidationPlan,\n UpdateSqlValidationPlan,\n} from './SqlValidationPlan';\n\nconst ALLOWED_LOOKUPS = Object.values(InternalLookupType) as readonly string[];\n\n/**\n * ORM-local adapter that translates query validation plans into the\n * shared Tango SQL safety engine.\n */\nexport class OrmSqlSafetyAdapter implements SQLValidationEngine {\n static readonly BRAND = 'tango.orm.orm_sql_safety_adapter' as const;\n readonly __tangoBrand: typeof OrmSqlSafetyAdapter.BRAND = OrmSqlSafetyAdapter.BRAND;\n\n constructor(private readonly engine: SqlSafetyEngine = new SqlSafetyEngine()) {}\n\n validate(plan: SelectSqlValidationPlan): ValidatedSelectSqlPlan;\n validate(plan: InsertSqlValidationPlan): ValidatedInsertSqlPlan;\n validate(plan: UpdateSqlValidationPlan): ValidatedUpdateSqlPlan;\n validate(plan: DeleteSqlValidationPlan): ValidatedDeleteSqlPlan;\n validate(plan: SqlValidationPlan): ValidatedSqlPlan {\n switch (plan.kind) {\n case 'select': {\n const meta = this.validateTableMeta(plan.meta, plan.relationNames ?? []);\n return {\n kind: 'select',\n meta,\n selectFields: Object.fromEntries(\n (plan.selectFields ?? []).map((field) => [\n field,\n `${meta.table}.${this.resolveColumn(meta, field)}`,\n ])\n ),\n filterKeys: Object.fromEntries(\n (plan.filterKeys ?? []).map((rawKey) => [rawKey, this.validateFilterKey(meta, rawKey)])\n ),\n orderFields: Object.fromEntries(\n (plan.orderFields ?? []).map((field) => [\n field,\n `${meta.table}.${this.resolveColumn(meta, field)}`,\n ])\n ),\n relations: Object.fromEntries(\n (plan.relationNames ?? []).map((relationName) => [\n relationName,\n this.resolveRelation(meta, relationName),\n ])\n ),\n };\n }\n case 'insert': {\n const meta = this.validateTableMeta(plan.meta);\n return {\n kind: 'insert',\n meta,\n writeKeys: plan.writeKeys.map((key) => this.resolveColumn(meta, key)),\n };\n }\n case 'update': {\n const meta = this.validateTableMeta(plan.meta);\n return {\n kind: 'update',\n meta,\n writeKeys: plan.writeKeys.map((key) => this.resolveColumn(meta, key)),\n };\n }\n case 'delete': {\n return {\n kind: 'delete',\n meta: this.validateTableMeta(plan.meta),\n };\n }\n }\n }\n\n private validateTableMeta(meta: TableMeta, relationNames: readonly string[] = []): ValidatedTableMeta {\n const columnNames = Object.keys(meta.columns);\n const validated = this.engine.validate({\n identifiers: [\n { key: 'table', role: 'table', value: meta.table },\n { key: 'pk', role: 'primaryKey', value: meta.pk, allowlist: columnNames },\n ...columnNames.map<SqlIdentifierRequest>((column) => ({\n key: `column:${column}`,\n role: 'column',\n value: column,\n })),\n ],\n });\n\n const validatedMeta: ValidatedTableMeta = {\n table: validated.identifiers.table!.value,\n pk: validated.identifiers.pk!.value,\n columns: Object.fromEntries(\n columnNames.map((column) => [validated.identifiers[`column:${column}`]!.value, meta.columns[column]!])\n ),\n };\n\n if (!(validatedMeta.pk in validatedMeta.columns)) {\n throw new Error(`Unknown column '${validatedMeta.pk}' for table '${validatedMeta.table}'.`);\n }\n\n if (relationNames.length > 0) {\n validatedMeta.relations = Object.fromEntries(\n relationNames.map((relationName) => [\n relationName,\n this.validateRelationMeta(validatedMeta, relationName, meta.relations),\n ])\n );\n }\n\n return validatedMeta;\n }\n\n private validateRelationMeta(\n meta: ValidatedTableMeta,\n relationName: string,\n relations: TableMeta['relations']\n ): ValidatedRelationMeta {\n const relation = relations?.[relationName];\n if (!relation) {\n throw new Error(`Unknown relation '${relationName}' for table '${meta.table}'.`);\n }\n\n const validated = this.engine.validate({\n identifiers: [\n { key: 'table', role: 'relationTable', value: relation.table },\n { key: 'alias', role: 'alias', value: relation.alias },\n { key: 'targetPk', role: 'relationTargetPrimaryKey', value: relation.targetPk },\n ...(relation.foreignKey\n ? [{ key: 'foreignKey', role: 'relationForeignKey' as const, value: relation.foreignKey }]\n : []),\n ],\n });\n\n return {\n ...relation,\n table: validated.identifiers.table!.value,\n alias: validated.identifiers.alias!.value,\n targetPk: validated.identifiers.targetPk!.value,\n localKey: relation.localKey ? this.resolveColumn(meta, relation.localKey) : undefined,\n foreignKey: relation.foreignKey ? validated.identifiers.foreignKey!.value : undefined,\n };\n }\n\n private validateFilterKey(meta: ValidatedTableMeta, rawKey: string): ValidatedFilterDescriptor {\n const segments = rawKey.split('__');\n if (segments.length > 2) {\n throw new Error(`Invalid SQL lookup key: '${rawKey}'.`);\n }\n\n const field = segments[0]!;\n const lookup = (segments[1] ?? InternalLookupType.EXACT) as LookupType;\n const validated = this.engine.validate({\n lookupTokens: [{ key: rawKey, lookup, allowed: ALLOWED_LOOKUPS }],\n });\n\n return {\n rawKey,\n field,\n lookup: validated.lookupTokens[rawKey]!.lookup as LookupType,\n qualifiedColumn: `${meta.table}.${this.resolveColumn(meta, field)}`,\n };\n }\n\n private resolveColumn(meta: ValidatedTableMeta, field: string): string {\n if (!(field in meta.columns)) {\n throw new Error(`Unknown column '${field}' for table '${meta.table}'.`);\n }\n\n return field;\n }\n\n private resolveRelation(meta: ValidatedTableMeta, relationName: string): ValidatedRelationMeta {\n const relation = meta.relations?.[relationName];\n if (!relation) {\n throw new Error(`Unknown relation '${relationName}' for table '${meta.table}'.`);\n }\n\n if (relation.kind === 'belongsTo' && !relation.localKey) {\n throw new Error(`Relation '${relationName}' for table '${meta.table}' requires a local key.`);\n }\n\n return relation;\n }\n}\n","import type { LookupType } from '../domain/LookupType';\nimport type { QuerySetState } from '../domain/QuerySetState';\nimport type { TableMeta } from '../domain/TableMeta';\nimport type { QNode } from '../domain/QNode';\nimport type { CompiledQuery } from '../domain/CompiledQuery';\nimport type { WhereClause } from '../domain/WhereClause';\nimport type { FilterInput } from '../domain/FilterInput';\nimport type { Dialect } from '../domain/Dialect';\nimport { InternalDialect } from '../domain/internal/InternalDialect';\nimport { InternalQNodeType } from '../domain/internal/InternalQNodeType';\nimport { InternalLookupType } from '../domain/internal/InternalLookupType';\nimport { OrmSqlSafetyAdapter } from '../../validation';\n\n// The adapter is stateless, so a shared module instance keeps compiler construction cheap.\nconst sqlSafetyAdapter = new OrmSqlSafetyAdapter();\n\n/**\n * Compiles immutable `QuerySet` state into parameterized SQL.\n *\n * The compiler is intentionally stateless with respect to execution and only\n * produces SQL + params artifacts that can be executed by a `DBClient`.\n */\nexport class QueryCompiler {\n static readonly BRAND = 'tango.orm.query_compiler' as const;\n readonly __tangoBrand: typeof QueryCompiler.BRAND = QueryCompiler.BRAND;\n\n /**\n * Build a compiler for the given repository metadata and SQL dialect.\n */\n constructor(\n private meta: TableMeta,\n private dialect: Dialect = InternalDialect.POSTGRES\n ) {}\n\n /**\n * Narrow an unknown value to `QueryCompiler`.\n */\n static isQueryCompiler(value: unknown): value is QueryCompiler {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === QueryCompiler.BRAND\n );\n }\n\n /**\n * Compile a query state tree into a SQL statement and bound parameters.\n */\n compile<T>(state: QuerySetState<T>): CompiledQuery {\n const knownRelationNames = (state.selectRelated ?? []).filter(\n (relationName) => this.meta.relations?.[relationName] !== undefined\n );\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'select',\n meta: this.meta,\n selectFields: state.select?.map(String),\n filterKeys: this.collectStateFilterKeys(state),\n orderFields: state.order?.map((order) => String(order.by)),\n relationNames: knownRelationNames,\n });\n const table = validatedPlan.meta.table;\n const whereParts: string[] = [];\n const params: unknown[] = [];\n\n if (state.q) {\n const result = this.compileQNode(state.q, params.length + 1, validatedPlan.filterKeys);\n if (result.sql) {\n whereParts.push(result.sql);\n params.push(...result.params);\n }\n }\n\n state.excludes?.forEach((exclude) => {\n const result = this.compileQNode(\n { kind: InternalQNodeType.NOT, node: exclude },\n params.length + 1,\n validatedPlan.filterKeys\n );\n if (result.sql) {\n whereParts.push(result.sql);\n params.push(...result.params);\n }\n });\n\n const select = state.select?.length\n ? state.select.map((field) => validatedPlan.selectFields[String(field)]!).join(', ')\n : `${table}.*`;\n\n const joins = knownRelationNames\n .map((rel) => {\n const relation = validatedPlan.relations[rel];\n if (!relation || relation.kind !== 'belongsTo') {\n return '';\n }\n return `LEFT JOIN ${relation.table} ${relation.alias} ON ${relation.alias}.${relation.targetPk} = ${table}.${relation.localKey!}`;\n })\n .filter(Boolean)\n .join(' ');\n\n const whereSQL = whereParts.length ? ` WHERE ${whereParts.join(' AND ')}` : '';\n const orderSQL = ` ORDER BY ${\n state.order?.length\n ? state.order\n .map((order) => `${validatedPlan.orderFields[String(order.by)]!} ${order.dir.toUpperCase()}`)\n .join(', ')\n : `${table}.${validatedPlan.meta.pk} ASC`\n }`;\n const limitSQL = state.limit ? ` LIMIT ${state.limit}` : '';\n const offsetSQL = state.offset ? ` OFFSET ${state.offset}` : '';\n const sql = `SELECT ${select} FROM ${table}${joins ? ` ${joins}` : ''}${whereSQL}${orderSQL}${limitSQL}${offsetSQL}`;\n\n return { sql, params };\n }\n\n private compileQNode<T>(\n node: QNode<T>,\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n switch (node.kind) {\n case InternalQNodeType.ATOM:\n return this.compileAtom(node.where || {}, paramIndex, filterKeys);\n case InternalQNodeType.AND:\n return this.compileAnd(node.nodes || [], paramIndex, filterKeys);\n case InternalQNodeType.OR:\n return this.compileOr(node.nodes || [], paramIndex, filterKeys);\n case InternalQNodeType.NOT:\n return this.compileNot(node.node!, paramIndex, filterKeys);\n default:\n return { sql: '', params: [] };\n }\n }\n\n private compileAtom<T>(\n where: FilterInput<T>,\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n const entries = Object.entries(where).filter(([, value]) => value !== undefined);\n\n const { parts, params } = entries.reduce<{ parts: string[]; params: unknown[] }>(\n (accumulator, [key, value]) => {\n const descriptor = filterKeys[String(key)]!;\n const idx = paramIndex + accumulator.params.length;\n const clause = this.lookupToSQL(descriptor.qualifiedColumn, descriptor.lookup, value, idx);\n accumulator.parts.push(clause.sql);\n accumulator.params.push(...clause.params);\n return accumulator;\n },\n { parts: [], params: [] }\n );\n\n return {\n sql: parts.length ? `(${parts.join(' AND ')})` : '',\n params,\n };\n }\n\n private compileAnd<T>(\n nodes: QNode<T>[],\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n const { parts, params } = nodes.reduce<{ parts: string[]; params: unknown[] }>(\n (accumulator, node) => {\n const result = this.compileQNode(node, paramIndex + accumulator.params.length, filterKeys);\n if (result.sql) {\n accumulator.parts.push(result.sql);\n accumulator.params.push(...result.params);\n }\n return accumulator;\n },\n { parts: [], params: [] }\n );\n\n return {\n sql: parts.length ? `(${parts.join(' AND ')})` : '',\n params,\n };\n }\n\n private compileOr<T>(\n nodes: QNode<T>[],\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n const { parts, params } = nodes.reduce<{ parts: string[]; params: unknown[] }>(\n (accumulator, node) => {\n const result = this.compileQNode(node, paramIndex + accumulator.params.length, filterKeys);\n if (result.sql) {\n accumulator.parts.push(result.sql);\n accumulator.params.push(...result.params);\n }\n return accumulator;\n },\n { parts: [], params: [] }\n );\n\n return {\n sql: parts.length ? `(${parts.join(' OR ')})` : '',\n params,\n };\n }\n\n private compileNot<T>(\n node: QNode<T>,\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n const result = this.compileQNode(node, paramIndex, filterKeys);\n if (!result.sql) {\n return { sql: '', params: [] };\n }\n\n return {\n sql: `(NOT ${result.sql})`,\n params: result.params,\n };\n }\n\n private lookupToSQL(col: string, lookup: LookupType, value: unknown, paramIndex: number): WhereClause {\n const placeholder = this.dialect === InternalDialect.POSTGRES ? `$${paramIndex}` : '?';\n const normalized = this.normalizeParam(value);\n\n switch (lookup) {\n case InternalLookupType.EXACT:\n if (value === null) {\n return { sql: `${col} IS NULL`, params: [] };\n }\n return { sql: `${col} = ${placeholder}`, params: [normalized] };\n case InternalLookupType.LT:\n return { sql: `${col} < ${placeholder}`, params: [normalized] };\n case InternalLookupType.LTE:\n return { sql: `${col} <= ${placeholder}`, params: [normalized] };\n case InternalLookupType.GT:\n return { sql: `${col} > ${placeholder}`, params: [normalized] };\n case InternalLookupType.GTE:\n return { sql: `${col} >= ${placeholder}`, params: [normalized] };\n case InternalLookupType.IN: {\n const entries = (Array.isArray(value) ? value : [value]).map((entry) => this.normalizeParam(entry));\n if (entries.length === 0) {\n return { sql: '1=0', params: [] };\n }\n const placeholders =\n this.dialect === InternalDialect.POSTGRES\n ? entries.map((_, index) => `$${paramIndex + index}`).join(', ')\n : entries.map(() => '?').join(', ');\n return { sql: `${col} IN (${placeholders})`, params: entries };\n }\n case InternalLookupType.ISNULL:\n return { sql: value ? `${col} IS NULL` : `${col} IS NOT NULL`, params: [] };\n case InternalLookupType.CONTAINS:\n return { sql: `${col} LIKE ${placeholder}`, params: [`%${value}%`] };\n case InternalLookupType.ICONTAINS: {\n const lowerCol = this.dialect === InternalDialect.POSTGRES ? `LOWER(${col})` : `${col}`;\n return { sql: `${lowerCol} LIKE ${placeholder}`, params: [`%${String(value).toLowerCase()}%`] };\n }\n case InternalLookupType.STARTSWITH:\n return { sql: `${col} LIKE ${placeholder}`, params: [`${value}%`] };\n case InternalLookupType.ISTARTSWITH: {\n const lowerCol = this.dialect === InternalDialect.POSTGRES ? `LOWER(${col})` : `${col}`;\n return { sql: `${lowerCol} LIKE ${placeholder}`, params: [`${String(value).toLowerCase()}%`] };\n }\n case InternalLookupType.ENDSWITH:\n return { sql: `${col} LIKE ${placeholder}`, params: [`%${value}`] };\n case InternalLookupType.IENDSWITH: {\n const lowerCol = this.dialect === InternalDialect.POSTGRES ? `LOWER(${col})` : `${col}`;\n return { sql: `${lowerCol} LIKE ${placeholder}`, params: [`%${String(value).toLowerCase()}`] };\n }\n default:\n throw new Error(`Unknown lookup: ${lookup}`);\n }\n }\n\n private normalizeParam(value: unknown): unknown {\n if (this.dialect === InternalDialect.SQLITE && typeof value === 'boolean') {\n return value ? 1 : 0;\n }\n return value;\n }\n\n private collectStateFilterKeys<T>(state: QuerySetState<T>): string[] {\n const filterKeys = new Set<string>();\n if (state.q) {\n this.collectNodeFilterKeys(state.q, filterKeys);\n }\n\n state.excludes?.forEach((exclude) => this.collectNodeFilterKeys(exclude, filterKeys));\n return [...filterKeys];\n }\n\n private collectNodeFilterKeys<T>(node: QNode<T>, filterKeys: Set<string>): void {\n Object.keys(node.where ?? {}).forEach((key) => filterKeys.add(key));\n node.nodes?.forEach((child) => this.collectNodeFilterKeys(child, filterKeys));\n if (node.node) {\n this.collectNodeFilterKeys(node.node, filterKeys);\n }\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { QueryCompiler } from './QueryCompiler';\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport type { CompiledQuery } from './CompiledQuery';\nexport type { Dialect } from './Dialect';\nexport type { Direction } from './Direction';\nexport type { FilterInput } from './FilterInput';\nexport type { FilterKey } from './FilterKey';\nexport type { FilterValue } from './FilterValue';\nexport type { LookupType } from './LookupType';\nexport type { OrderSpec } from './OrderSpec';\nexport type { OrderToken } from './OrderToken';\nexport type { QNode } from './QNode';\nexport type { QueryResult } from './QueryResult';\nexport type { QuerySetState } from './QuerySetState';\nexport type { RelationMeta } from './RelationMeta';\nexport type { TableMeta } from './TableMeta';\nexport type { WhereClause } from './WhereClause';\n","export const InternalDirection = {\n ASC: 'asc',\n DESC: 'desc',\n} as const;\n","import type { QNode } from './domain/QNode';\nimport type { FilterInput } from './domain/FilterInput';\nimport { InternalQNodeType } from './domain/internal/InternalQNodeType';\n\n/**\n * Static builder for composing boolean query expressions.\n *\n * This mirrors Django's `Q(...)` composition patterns and is intended\n * for ergonomic construction of nested `AND`/`OR`/`NOT` trees.\n */\nexport class QBuilder {\n static readonly BRAND = 'tango.orm.q_builder' as const;\n readonly __tangoBrand: typeof QBuilder.BRAND = QBuilder.BRAND;\n\n /**\n * Narrow an unknown value to `QBuilder`.\n */\n static isQBuilder(value: unknown): value is QBuilder {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === QBuilder.BRAND\n );\n }\n\n /**\n * Combine multiple filter fragments using logical `AND`.\n */\n static and<T>(...nodes: Array<FilterInput<T> | QNode<T>>): QNode<T> {\n return {\n kind: InternalQNodeType.AND,\n nodes: nodes.map(QBuilder.wrapNode),\n };\n }\n\n /**\n * Combine multiple filter fragments using logical `OR`.\n */\n static or<T>(...nodes: Array<FilterInput<T> | QNode<T>>): QNode<T> {\n return {\n kind: InternalQNodeType.OR,\n nodes: nodes.map(QBuilder.wrapNode),\n };\n }\n\n /**\n * Negate a filter fragment using logical `NOT`.\n */\n static not<T>(node: FilterInput<T> | QNode<T>): QNode<T> {\n return {\n kind: InternalQNodeType.NOT,\n node: QBuilder.wrapNode(node),\n };\n }\n\n private static wrapNode<T>(input: FilterInput<T> | QNode<T>): QNode<T> {\n if ((input as QNode<T>).kind) {\n return input as QNode<T>;\n }\n return {\n kind: InternalQNodeType.ATOM,\n where: input as FilterInput<T>,\n };\n }\n}\n","import type { DBClient } from '../connection/clients/DBClient';\nimport type { Dialect } from './domain/Dialect';\nimport type { QuerySetState } from './domain/QuerySetState';\nimport type { TableMeta } from './domain/TableMeta';\nimport type { QNode } from './domain/QNode';\nimport type { QueryResult } from './domain/QueryResult';\nimport type { OrderToken } from './domain/OrderToken';\nimport type { FilterInput } from './domain/FilterInput';\nimport { InternalQNodeType } from './domain/internal/InternalQNodeType';\nimport { InternalDirection } from './domain/internal/InternalDirection';\nimport { InternalDialect } from './domain/internal/InternalDialect';\nimport { QBuilder as Q } from './QBuilder';\nimport { QueryCompiler } from './compiler';\n\n/**\n * Query execution seam consumed by `QuerySet`.\n *\n * Application code usually reaches this through `Model.objects` or testing\n * fixtures rather than implementing it directly.\n *\n * @template T - The model type\n */\nexport interface QueryExecutor<T> {\n meta: TableMeta;\n client: DBClient;\n dialect: Dialect;\n run(compiled: { sql: string; params: readonly unknown[] }): Promise<T[]>;\n}\n\ntype QueryShapeFunction<TInput, TOutput> = (row: TInput) => TOutput;\n\ntype QueryShapeParser<TInput, TOutput> = {\n parse: (row: TInput) => TOutput;\n};\n\ntype QueryShape<TInput> = QueryShapeFunction<TInput, unknown> | QueryShapeParser<TInput, unknown>;\n\ntype QueryShapeOutput<TInput, TShape> =\n TShape extends QueryShapeFunction<TInput, infer TOutput>\n ? TOutput\n : TShape extends QueryShapeParser<TInput, infer TOutput>\n ? TOutput\n : never;\n\ntype ProjectedResult<\n TModel extends Record<string, unknown>,\n TKeys extends readonly (keyof TModel)[],\n> = number extends TKeys['length'] ? TModel : [TKeys[number]] extends [never] ? TModel : Pick<TModel, TKeys[number]>;\n\n/**\n * Django-inspired query builder for constructing and executing database queries.\n * Provides a fluent API for filtering, ordering, pagination, and eager loading.\n *\n * @template TModel - The full model row type used for query composition\n * @template TResult - The fetched row shape returned by execution methods\n *\n * @example\n * ```typescript\n * const users = await TodoModel.objects\n * .query()\n * .filter({ active: true })\n * .filter(Q.or({ role: 'admin' }, { role: 'moderator' }))\n * .orderBy('-createdAt')\n * .limit(10)\n * .fetch();\n * ```\n */\nexport class QuerySet<TModel extends Record<string, unknown>, TResult extends Record<string, unknown> = TModel> {\n static readonly BRAND = 'tango.orm.query_set' as const;\n readonly __tangoBrand: typeof QuerySet.BRAND = QuerySet.BRAND;\n\n constructor(\n private executor: QueryExecutor<TModel>,\n private state: QuerySetState<TModel> = {}\n ) {}\n\n /**\n * Narrow an unknown value to `QuerySet`.\n */\n static isQuerySet<TModel extends Record<string, unknown>, TResult extends Record<string, unknown> = TModel>(\n value: unknown\n ): value is QuerySet<TModel, TResult> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === QuerySet.BRAND\n );\n }\n\n /**\n * Add a filter expression to the query.\n *\n * Multiple `filter()` calls are composed with `AND`.\n */\n filter(q: FilterInput<TModel> | QNode<TModel>): QuerySet<TModel, TResult> {\n const wrapped: QNode<TModel> = (q as QNode<TModel>).kind\n ? (q as QNode<TModel>)\n : { kind: InternalQNodeType.ATOM, where: q as FilterInput<TModel> };\n const merged = this.state.q ? Q.and(this.state.q, wrapped) : wrapped;\n return new QuerySet(this.executor, { ...this.state, q: merged });\n }\n\n /**\n * Add an exclusion expression to the query.\n *\n * Exclusions are translated to `NOT (...)` predicates.\n */\n exclude(q: FilterInput<TModel> | QNode<TModel>): QuerySet<TModel, TResult> {\n const wrapped: QNode<TModel> = (q as QNode<TModel>).kind\n ? (q as QNode<TModel>)\n : { kind: InternalQNodeType.ATOM, where: q as FilterInput<TModel> };\n const excludes = [...(this.state.excludes ?? []), wrapped];\n return new QuerySet(this.executor, { ...this.state, excludes });\n }\n\n /**\n * Apply ordering tokens such as `'name'` or `'-createdAt'`.\n */\n orderBy(...tokens: OrderToken<TModel>[]): QuerySet<TModel, TResult> {\n const order = tokens.map((t) => {\n const str = String(t);\n if (str.startsWith('-')) {\n return { by: str.slice(1) as keyof TModel, dir: InternalDirection.DESC };\n }\n return { by: t as keyof TModel, dir: InternalDirection.ASC };\n });\n return new QuerySet(this.executor, { ...this.state, order });\n }\n\n /**\n * Limit the maximum number of rows returned.\n */\n limit(n: number): QuerySet<TModel, TResult> {\n return new QuerySet(this.executor, { ...this.state, limit: n });\n }\n\n /**\n * Skip the first `n` rows.\n */\n offset(n: number): QuerySet<TModel, TResult> {\n return new QuerySet(this.executor, { ...this.state, offset: n });\n }\n\n /**\n * Restrict selected columns and narrow the fetched row type when the\n * selected keys are known precisely at the call site.\n *\n * Empty selections reset back to the full model row, and repeated\n * `select(...)` calls replace the previous projection rather than\n * intersecting it.\n */\n select<const TKeys extends readonly (keyof TModel)[]>(\n cols: TKeys\n ): QuerySet<TModel, ProjectedResult<TModel, TKeys>>;\n select(cols: readonly (keyof TModel)[]): QuerySet<TModel, TModel>;\n select(cols: readonly (keyof TModel)[]): QuerySet<TModel, TModel> {\n return new QuerySet(this.executor, { ...this.state, select: [...cols] as (keyof TModel)[] });\n }\n\n /**\n * Request SQL joins for related data when supported by relation metadata.\n */\n selectRelated(...rels: string[]): QuerySet<TModel, TResult> {\n return new QuerySet(this.executor, { ...this.state, selectRelated: rels });\n }\n\n /**\n * Register relation names for prefetch behavior.\n *\n * Prefetch orchestration is adapter-specific.\n */\n prefetchRelated(...rels: string[]): QuerySet<TModel, TResult> {\n return new QuerySet(this.executor, { ...this.state, prefetchRelated: rels });\n }\n\n /**\n * Execute the query and optionally shape each row.\n *\n * When the queryset has been narrowed by `select(...)`, rows passed to the\n * shaping callback or parser use that narrowed fetched-row type.\n */\n async fetch(): Promise<QueryResult<TResult>>;\n async fetch<Out>(shape: QueryShapeFunction<TResult, Out>): Promise<QueryResult<Out>>;\n async fetch<Out>(shape: QueryShapeParser<TResult, Out>): Promise<QueryResult<Out>>;\n async fetch<TShape extends QueryShape<TResult> | undefined>(\n shape: TShape\n ): Promise<QueryResult<TResult | QueryShapeOutput<TResult, NonNullable<TShape>>>>;\n async fetch<Out>(\n shape?: QueryShapeFunction<TResult, Out> | QueryShapeParser<TResult, Out>\n ): Promise<QueryResult<TResult | Out>> {\n const compiler = new QueryCompiler(this.executor.meta, this.executor.dialect);\n const compiled = compiler.compile(this.state);\n const rows = await this.executor.run(compiled);\n const normalizedRows = this.normalizeRowsForSchemaParsing(rows, shape);\n const projectedRows = normalizedRows as unknown as TResult[];\n\n const results: Array<TResult | Out> = !shape\n ? projectedRows\n : typeof shape === 'function'\n ? projectedRows.map(shape)\n : projectedRows.map((r) => shape.parse(r));\n\n return {\n results,\n nextCursor: null,\n };\n }\n\n /**\n * Execute the query and return the first row, or `null`.\n *\n * As with `fetch(...)`, parser and function overloads receive the current\n * fetched-row type after any `select(...)` projection narrowing.\n */\n async fetchOne(): Promise<TResult | null>;\n async fetchOne<Out>(shape: QueryShapeFunction<TResult, Out>): Promise<Out | null>;\n async fetchOne<Out>(shape: QueryShapeParser<TResult, Out>): Promise<Out | null>;\n async fetchOne<TShape extends QueryShape<TResult> | undefined>(\n shape: TShape\n ): Promise<TResult | QueryShapeOutput<TResult, NonNullable<TShape>> | null>;\n async fetchOne<Out>(\n shape?: QueryShapeFunction<TResult, Out> | QueryShapeParser<TResult, Out>\n ): Promise<TResult | Out | null> {\n const limited = this.limit(1);\n const result = !shape\n ? await limited.fetch()\n : typeof shape === 'function'\n ? await limited.fetch(shape)\n : await limited.fetch(shape);\n return result.results[0] ?? null;\n }\n\n /**\n * Execute a `COUNT(*)` query for the current filtered state.\n */\n async count(): Promise<number> {\n const compiler = new QueryCompiler(this.executor.meta, this.executor.dialect);\n const compiled = compiler.compile(this.state);\n const countQuery = `SELECT COUNT(*) as count FROM (${compiled.sql}) AS tango_count_subquery`;\n const rows = await this.executor.client.query<{ count: number }>(countQuery, compiled.params);\n return Number(rows.rows[0]?.count ?? 0);\n }\n\n /**\n * Return whether at least one row matches the current query state.\n */\n async exists(): Promise<boolean> {\n const count = await this.count();\n return count > 0;\n }\n\n private normalizeRowsForSchemaParsing<Out>(\n rows: TModel[],\n shape?: QueryShapeFunction<TResult, Out> | QueryShapeParser<TResult, Out>\n ): TModel[] {\n if (!shape || typeof shape === 'function' || this.executor.dialect !== InternalDialect.SQLITE) {\n return rows;\n }\n\n const booleanColumns = Object.entries(this.executor.meta.columns)\n .filter(([, value]) => this.isBooleanColumnType(value))\n .map(([column]) => column);\n\n if (booleanColumns.length === 0) {\n return rows;\n }\n\n return rows.map((row) => this.normalizeBooleanColumns(row, booleanColumns));\n }\n\n private isBooleanColumnType(value: unknown): boolean {\n return typeof value === 'string' && ['bool', 'boolean'].includes(value.trim().toLowerCase());\n }\n\n private normalizeSqliteBoolean(value: unknown): unknown {\n if (value === 0 || value === '0') {\n return false;\n }\n if (value === 1 || value === '1') {\n return true;\n }\n return value;\n }\n\n private normalizeBooleanColumns(row: TModel, columns: readonly string[]): TModel {\n let normalized: TModel | null = null;\n\n for (const column of columns) {\n const current = (row as Record<string, unknown>)[column];\n const next = this.normalizeSqliteBoolean(current);\n if (next === current) {\n continue;\n }\n if (!normalized) {\n normalized = { ...row };\n }\n (normalized as Record<string, unknown>)[column] = next;\n }\n\n return normalized ?? row;\n }\n}\n","/**\n * Domain boundary barrel: exposes namespaced exports for Django-style drill-down\n * imports and curated flat exports for TS-native ergonomics.\n */\n\nexport * as compiler from './compiler/index';\nexport * as domain from './domain/index';\n\nexport type * from './domain/index';\nexport type { TableMeta } from './domain/index';\nexport { QuerySet } from './QuerySet';\nexport type { QueryExecutor } from './QuerySet';\nexport { QBuilder, QBuilder as Q } from './QBuilder';\nexport { QueryCompiler } from './compiler/index';\n"],"mappings":"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"}
@@ -1,9 +1,18 @@
1
1
  import { connectDB } from "./connection-CVvycXus.js";
2
- import { OrmSqlSafetyAdapter, QuerySet } from "./query-wnl4h2o7.js";
2
+ import { OrmSqlSafetyAdapter, QuerySet } from "./query-BKt2nKIt.js";
3
3
  import { NotFoundError } from "@danceroutine/tango-core";
4
- import { registerModelAugmentor } from "@danceroutine/tango-schema";
4
+ import { ModelRegistry, registerModelAugmentor } from "@danceroutine/tango-schema";
5
5
  import { loadConfig, loadConfigFromProjectRoot } from "@danceroutine/tango-config";
6
6
 
7
+ //#region src/query/domain/internal/InternalRelationKind.ts
8
+ const InternalRelationKind = {
9
+ HAS_MANY: "hasMany",
10
+ BELONGS_TO: "belongsTo",
11
+ HAS_ONE: "hasOne",
12
+ MANY_TO_MANY: "manyToMany"
13
+ };
14
+
15
+ //#endregion
7
16
  //#region src/manager/internal/MutationCompiler.ts
8
17
  var MutationCompiler = class {
9
18
  constructor(dialect) {
@@ -82,26 +91,31 @@ const sqlSafetyAdapter = new OrmSqlSafetyAdapter();
82
91
  var ModelManager = class ModelManager {
83
92
  static BRAND = "tango.orm.model_manager";
84
93
  __tangoBrand = ModelManager.BRAND;
85
- meta;
86
94
  queryExecutor;
87
95
  mutationCompiler;
88
96
  model;
97
+ client;
98
+ dialect;
89
99
  constructor(model, runtime) {
90
100
  this.model = model;
91
- this.meta = ModelManager.createTableMeta(model);
92
- const client = new RuntimeBoundClient(runtime);
93
- const dialect = runtime.getDialect();
94
- this.mutationCompiler = new MutationCompiler(dialect);
101
+ this.client = new RuntimeBoundClient(runtime);
102
+ this.dialect = runtime.getDialect();
103
+ this.mutationCompiler = new MutationCompiler(this.dialect);
95
104
  this.queryExecutor = {
96
- meta: this.meta,
97
- client,
98
- dialect,
105
+ get meta() {
106
+ return ModelManager.createTableMeta(model);
107
+ },
108
+ client: this.client,
109
+ dialect: this.dialect,
99
110
  run: async (compiled) => {
100
- const result = await client.query(compiled.sql, compiled.params);
111
+ const result = await this.client.query(compiled.sql, compiled.params);
101
112
  return result.rows;
102
113
  }
103
114
  };
104
115
  }
116
+ get meta() {
117
+ return ModelManager.createTableMeta(this.model);
118
+ }
105
119
  /**
106
120
  * Narrow an unknown value to `ModelManager`.
107
121
  */
@@ -116,11 +130,30 @@ var ModelManager = class ModelManager {
116
130
  pk: pkField.name,
117
131
  columns: Object.fromEntries(model.metadata.fields.map((field) => [field.name, field.type]))
118
132
  };
119
- return sqlSafetyAdapter.validate({
133
+ if (model.metadata.key) {
134
+ const owner = ModelRegistry.getOwner(model);
135
+ const relations = owner.getResolvedRelationGraph().byModel.get(model.metadata.key);
136
+ if (relations && relations.size > 0) rawMeta.relations = Object.fromEntries(Array.from(relations.entries()).filter(([, relation]) => relation.kind !== InternalRelationKind.MANY_TO_MANY).map(([name, relation]) => {
137
+ const isForwardReference = relation.kind === InternalRelationKind.BELONGS_TO;
138
+ const sourceKey = isForwardReference ? relation.localFieldName : relation.targetFieldName;
139
+ const targetKey = isForwardReference ? relation.targetFieldName : relation.localFieldName;
140
+ return [name, {
141
+ kind: relation.kind,
142
+ table: owner.getByKey(relation.targetModelKey).metadata.table,
143
+ targetPk: targetKey,
144
+ localKey: sourceKey,
145
+ foreignKey: relation.localFieldName,
146
+ alias: relation.alias
147
+ }];
148
+ }));
149
+ }
150
+ const validatedMeta = sqlSafetyAdapter.validate({
120
151
  kind: "insert",
121
152
  meta: rawMeta,
122
153
  writeKeys: Object.keys(rawMeta.columns)
123
154
  }).meta;
155
+ if (rawMeta.relations) validatedMeta.relations = rawMeta.relations;
156
+ return validatedMeta;
124
157
  }
125
158
  query() {
126
159
  return new QuerySet(this.queryExecutor, {});
@@ -351,4 +384,4 @@ function registerModelObjects() {
351
384
 
352
385
  //#endregion
353
386
  export { ModelManager, TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime };
354
- //# sourceMappingURL=registerModelObjects-emX7Hja9.js.map
387
+ //# sourceMappingURL=registerModelObjects-vsX6GzCN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerModelObjects-vsX6GzCN.js","names":["dialect: Dialect","plan: ValidatedInsertSqlPlan","values: readonly unknown[]","plan: ValidatedUpdateSqlPlan","id: unknown","plan: ValidatedDeleteSqlPlan","valueRows: ReadonlyArray<ReadonlyArray<unknown>>","count: number","index: number","runtime: TangoRuntime","sql: string","params?: readonly unknown[]","model: ModelLike<T>","runtime: TangoRuntime","value: unknown","rawMeta: TableMeta","id: T[keyof T]","input: Partial<T>","patch: Partial<T>","inputs: Partial<T>[]","batchPrepared: Partial<T>[]","data: Partial<T>","current: T","loadLoadedConfig: () => LoadedConfig","value: unknown","defaultRuntime: TangoRuntime | null","fromFile: () => unknown","model: SchemaModel<TSchema>"],"sources":["../src/query/domain/internal/InternalRelationKind.ts","../src/manager/internal/MutationCompiler.ts","../src/manager/internal/RuntimeBoundClient.ts","../src/manager/ModelManager.ts","../src/runtime/TangoRuntime.ts","../src/runtime/defaultRuntime.ts","../src/manager/registerModelObjects.ts"],"sourcesContent":["export const InternalRelationKind = {\n HAS_MANY: 'hasMany',\n BELONGS_TO: 'belongsTo',\n HAS_ONE: 'hasOne',\n MANY_TO_MANY: 'manyToMany',\n} as const;\n","import type { CompiledQuery, Dialect } from '../../query/domain/index';\nimport type {\n ValidatedDeleteSqlPlan,\n ValidatedInsertSqlPlan,\n ValidatedUpdateSqlPlan,\n} from '../../validation/SQLValidationEngine';\n\n/**\n * Internal compiler for manager-owned INSERT/UPDATE/DELETE statements.\n */\nexport class MutationCompiler {\n constructor(private readonly dialect: Dialect) {}\n\n compileInsert(plan: ValidatedInsertSqlPlan, values: readonly unknown[]): CompiledQuery {\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES (${this.buildValuePlaceholders(plan.writeKeys.length)}) RETURNING *`,\n params: values,\n };\n }\n\n compileUpdate(plan: ValidatedUpdateSqlPlan, values: readonly unknown[], id: unknown): CompiledQuery {\n const sets = plan.writeKeys.map((key, index) => `${key} = ${this.placeholder(index + 1)}`).join(', ');\n const whereParam = this.placeholder(plan.writeKeys.length + 1);\n\n return {\n sql: `UPDATE ${plan.meta.table} SET ${sets} WHERE ${plan.meta.pk} = ${whereParam} RETURNING *`,\n params: [...values, id],\n };\n }\n\n compileDelete(plan: ValidatedDeleteSqlPlan, id: unknown): CompiledQuery {\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${plan.meta.pk} = ${this.placeholder(1)}`,\n params: [id],\n };\n }\n\n compileBulkInsert(plan: ValidatedInsertSqlPlan, valueRows: ReadonlyArray<ReadonlyArray<unknown>>): CompiledQuery {\n const columnCount = plan.writeKeys.length;\n const placeholders = valueRows\n .map((_row, rowIndex) => {\n const offset = rowIndex * columnCount;\n return `(${plan.writeKeys.map((_, colIndex) => this.placeholder(offset + colIndex + 1)).join(', ')})`;\n })\n .join(', ');\n\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders} RETURNING *`,\n params: valueRows.flat(),\n };\n }\n\n private buildValuePlaceholders(count: number): string {\n return Array.from({ length: count }, (_value, index) => this.placeholder(index + 1)).join(', ');\n }\n\n private placeholder(index: number): string {\n return this.dialect === 'postgres' ? `$${index}` : '?';\n }\n}\n","import type { DBClient } from '../../connection/index';\nimport type { TangoRuntime } from '../../runtime/index';\n\n/**\n * DB client proxy that resolves the real Tango runtime client lazily.\n */\nexport class RuntimeBoundClient implements DBClient {\n constructor(private readonly runtime: TangoRuntime) {}\n\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const client = await this.runtime.getClient();\n return client.query<T>(sql, params);\n }\n\n async begin(): Promise<void> {\n const client = await this.runtime.getClient();\n await client.begin();\n }\n\n async commit(): Promise<void> {\n const client = await this.runtime.getClient();\n await client.commit();\n }\n\n async rollback(): Promise<void> {\n const client = await this.runtime.getClient();\n await client.rollback();\n }\n\n async close(): Promise<void> {\n const client = await this.runtime.getClient();\n await client.close();\n }\n}\n","import { NotFoundError } from '@danceroutine/tango-core';\nimport { ModelRegistry, type ModelWriteHooks } from '@danceroutine/tango-schema';\nimport type { FilterInput, RelationMeta, TableMeta } from '../query/domain/index';\nimport { InternalRelationKind } from '../query/domain/internal/InternalRelationKind';\nimport type { QuerySet } from '../query/index';\nimport { QuerySet as QuerySetClass } from '../query/index';\nimport type { Dialect, QueryExecutor } from '../query/index';\nimport type { TangoRuntime } from '../runtime/TangoRuntime';\nimport { OrmSqlSafetyAdapter } from '../validation';\nimport type { ManagerLike } from './ManagerLike';\nimport { MutationCompiler } from './internal/MutationCompiler';\nimport { RuntimeBoundClient } from './internal/RuntimeBoundClient';\n\nconst sqlSafetyAdapter = new OrmSqlSafetyAdapter();\n\ntype FieldLike = {\n name: string;\n type: string;\n primaryKey?: boolean;\n};\n\ntype ModelLike<T extends Record<string, unknown>> = {\n metadata: {\n key?: string;\n name: string;\n table: string;\n fields: FieldLike[];\n };\n schema: {\n parse(input: unknown): T;\n };\n hooks?: ModelWriteHooks<T>;\n};\n\n/**\n * Model-backed data access API exposed as `Model.objects`.\n */\nexport class ModelManager<T extends Record<string, unknown>> implements ManagerLike<T> {\n static readonly BRAND = 'tango.orm.model_manager' as const;\n readonly __tangoBrand: typeof ModelManager.BRAND = ModelManager.BRAND;\n private readonly queryExecutor: QueryExecutor<T>;\n private readonly mutationCompiler: MutationCompiler;\n private readonly model: ModelLike<T>;\n private readonly client: RuntimeBoundClient;\n private readonly dialect: Dialect;\n\n constructor(model: ModelLike<T>, runtime: TangoRuntime) {\n this.model = model;\n this.client = new RuntimeBoundClient(runtime);\n this.dialect = runtime.getDialect() as Dialect;\n this.mutationCompiler = new MutationCompiler(this.dialect);\n this.queryExecutor = {\n get meta() {\n return ModelManager.createTableMeta(model);\n },\n client: this.client,\n dialect: this.dialect,\n run: async (compiled) => {\n const result = await this.client.query<T>(compiled.sql, compiled.params);\n return result.rows;\n },\n };\n }\n\n get meta(): TableMeta {\n return ModelManager.createTableMeta(this.model);\n }\n\n /**\n * Narrow an unknown value to `ModelManager`.\n */\n static isModelManager<T extends Record<string, unknown>>(value: unknown): value is ModelManager<T> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === ModelManager.BRAND\n );\n }\n\n private static createTableMeta<T extends Record<string, unknown>>(model: ModelLike<T>): TableMeta {\n const pkField = model.metadata.fields.find((field) => field.primaryKey);\n if (!pkField) {\n throw new Error(`Model '${model.metadata.name}' cannot attach a manager without a primary key field.`);\n }\n\n const rawMeta: TableMeta = {\n table: model.metadata.table,\n pk: pkField.name,\n columns: Object.fromEntries(model.metadata.fields.map((field) => [field.name, field.type])),\n };\n\n if (model.metadata.key) {\n const owner = ModelRegistry.getOwner(model as never);\n const relations = owner.getResolvedRelationGraph().byModel.get(model.metadata.key);\n if (relations && relations.size > 0) {\n rawMeta.relations = Object.fromEntries(\n Array.from(relations.entries())\n .filter(([, relation]) => relation.kind !== InternalRelationKind.MANY_TO_MANY)\n .map(([name, relation]) => {\n const isForwardReference = relation.kind === InternalRelationKind.BELONGS_TO;\n const sourceKey = isForwardReference ? relation.localFieldName : relation.targetFieldName;\n const targetKey = isForwardReference ? relation.targetFieldName : relation.localFieldName;\n\n return [\n name,\n {\n kind: relation.kind as RelationMeta['kind'],\n table: owner.getByKey(relation.targetModelKey)!.metadata.table,\n targetPk: targetKey!,\n localKey: sourceKey,\n foreignKey: relation.localFieldName,\n alias: relation.alias,\n },\n ];\n })\n );\n }\n }\n\n const validatedMeta = sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: rawMeta,\n writeKeys: Object.keys(rawMeta.columns),\n }).meta;\n\n if (rawMeta.relations) {\n validatedMeta.relations = rawMeta.relations;\n }\n\n return validatedMeta;\n }\n\n query(): QuerySet<T> {\n return new QuerySetClass<T>(this.queryExecutor, {});\n }\n\n async findById(id: T[keyof T]): Promise<T | null> {\n const filter = { [this.meta.pk]: id } as unknown as FilterInput<T>;\n return this.query().filter(filter).fetchOne();\n }\n\n async getOrThrow(id: T[keyof T]): Promise<T> {\n const result = await this.findById(id);\n if (!result) {\n throw new NotFoundError(`${this.model.metadata.name} with ${this.meta.pk}=${String(id)} not found`);\n }\n return result;\n }\n\n async create(input: Partial<T>): Promise<T> {\n const prepared = await this.runBeforeCreate(input);\n const preparedKeys = Object.keys(prepared);\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot create ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const compiled = this.mutationCompiler.compileInsert(\n validatedPlan,\n preparedKeys.map((key) => prepared[key as keyof T])\n );\n const result = await this.queryExecutor.client.query<T>(compiled.sql, compiled.params);\n const created = result.rows[0]!;\n await this.model.hooks?.afterCreate?.({\n record: created,\n model: this.model,\n manager: this,\n });\n return created;\n }\n\n async update(id: T[keyof T], patch: Partial<T>): Promise<T> {\n const current = await this.getOrThrow(id);\n const prepared = await this.runBeforeUpdate(id, patch, current);\n const preparedKeys = Object.keys(prepared);\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot update ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'update',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const compiled = this.mutationCompiler.compileUpdate(\n validatedPlan,\n preparedKeys.map((key) => prepared[key as keyof T]),\n id\n );\n const result = await this.queryExecutor.client.query<T>(compiled.sql, compiled.params);\n const updated = result.rows[0]!;\n await this.model.hooks?.afterUpdate?.({\n id,\n patch: prepared,\n previous: current,\n record: updated,\n model: this.model,\n manager: this,\n });\n return updated;\n }\n\n async delete(id: T[keyof T]): Promise<void> {\n const current = await this.getOrThrow(id);\n await this.model.hooks?.beforeDelete?.({\n id,\n current,\n model: this.model,\n manager: this,\n });\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'delete',\n meta: this.meta,\n });\n const compiled = this.mutationCompiler.compileDelete(validatedPlan, id);\n await this.queryExecutor.client.query(compiled.sql, compiled.params);\n await this.model.hooks?.afterDelete?.({\n id,\n previous: current,\n model: this.model,\n manager: this,\n });\n }\n\n async bulkCreate(inputs: Partial<T>[]): Promise<T[]> {\n if (inputs.length === 0) {\n return [];\n }\n\n const perRowPrepared = await Promise.all(inputs.map((input) => this.runBeforeCreate(input)));\n const batchPrepared: Partial<T>[] =\n (await this.model.hooks?.beforeBulkCreate?.({\n rows: perRowPrepared,\n model: this.model,\n manager: this,\n })) ?? perRowPrepared;\n const preparedKeys = Object.keys(batchPrepared[0] ?? {});\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot create ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const valueRows = batchPrepared.map((input) => preparedKeys.map((key) => input[key as keyof T]));\n const compiled = this.mutationCompiler.compileBulkInsert(validatedPlan, valueRows);\n const result = await this.queryExecutor.client.query<T>(compiled.sql, compiled.params);\n await Promise.all(\n result.rows.map((record) =>\n this.model.hooks?.afterCreate?.({\n record,\n model: this.model,\n manager: this,\n })\n )\n );\n await this.model.hooks?.afterBulkCreate?.({\n records: result.rows,\n model: this.model,\n manager: this,\n });\n return result.rows;\n }\n\n private async runBeforeCreate(data: Partial<T>): Promise<Partial<T>> {\n return (\n (await this.model.hooks?.beforeCreate?.({\n data,\n model: this.model,\n manager: this,\n })) ?? data\n );\n }\n\n private async runBeforeUpdate(id: T[keyof T], patch: Partial<T>, current: T): Promise<Partial<T>> {\n return (\n (await this.model.hooks?.beforeUpdate?.({\n id,\n patch,\n current,\n model: this.model,\n manager: this,\n })) ?? patch\n );\n }\n}\n","import type { LoadedConfig } from '@danceroutine/tango-config';\nimport type { DBClient } from '../connection/index';\nimport { connectDB } from '../connection/index';\nimport type { Dialect } from '../query/domain/index';\n\n/**\n * Framework-owned database runtime that resolves Tango config and lazily\n * creates the shared DB client used by manager-backed models.\n */\nexport class TangoRuntime {\n static readonly BRAND = 'tango.orm.runtime' as const;\n readonly __tangoBrand: typeof TangoRuntime.BRAND = TangoRuntime.BRAND;\n private readonly loadedConfig: LoadedConfig;\n private clientPromise: Promise<DBClient> | null = null;\n\n constructor(loadLoadedConfig: () => LoadedConfig) {\n this.loadedConfig = loadLoadedConfig();\n }\n\n /**\n * Narrow an unknown value to `TangoRuntime`.\n */\n static isTangoRuntime(value: unknown): value is TangoRuntime {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === TangoRuntime.BRAND\n );\n }\n\n /**\n * Return the loaded Tango config snapshot for the active environment.\n */\n getConfig(): LoadedConfig {\n return this.loadedConfig;\n }\n\n /**\n * Return the configured SQL dialect for the current runtime.\n */\n getDialect(): Dialect {\n return this.loadedConfig.current.db.adapter;\n }\n\n /**\n * Return the shared DB client, creating it once on first access.\n */\n async getClient(): Promise<DBClient> {\n if (!this.clientPromise) {\n const db = this.loadedConfig.current.db;\n this.clientPromise = connectDB({\n adapter: db.adapter,\n url: db.url,\n host: db.host,\n port: db.port,\n database: db.database,\n user: db.user,\n password: db.password,\n filename: db.filename,\n maxConnections: db.maxConnections,\n });\n }\n\n return this.clientPromise;\n }\n\n /**\n * Close and clear the cached DB client so tests can start fresh.\n */\n async reset(): Promise<void> {\n if (!this.clientPromise) {\n return;\n }\n\n const client = await this.clientPromise;\n this.clientPromise = null;\n await client.close();\n }\n}\n","import { loadConfig, loadConfigFromProjectRoot } from '@danceroutine/tango-config';\nimport { TangoRuntime } from './TangoRuntime';\n\nlet defaultRuntime: TangoRuntime | null = null;\n\n/**\n * Initialize the process-default Tango runtime from a Tango config loader.\n */\nexport function initializeTangoRuntime(fromFile: () => unknown): TangoRuntime {\n defaultRuntime = new TangoRuntime(() => loadConfig(fromFile));\n return defaultRuntime;\n}\n\n/**\n * Return the process-default Tango runtime, lazily loading Tango config on first access.\n */\nexport function getTangoRuntime(): TangoRuntime {\n if (!defaultRuntime) {\n defaultRuntime = new TangoRuntime(() => loadConfigFromProjectRoot());\n }\n\n return defaultRuntime;\n}\n\n/**\n * Reset the process-default Tango runtime and release any cached client.\n */\nexport async function resetTangoRuntime(): Promise<void> {\n if (!defaultRuntime) {\n return;\n }\n\n const runtime = defaultRuntime;\n defaultRuntime = null;\n await runtime.reset();\n}\n","import type { z } from 'zod';\nimport type { Model as SchemaModel, PersistedModelOutput } from '@danceroutine/tango-schema/domain';\nimport { registerModelAugmentor } from '@danceroutine/tango-schema';\nimport { ModelManager } from './ModelManager';\nimport type { TangoRuntime } from '../runtime/TangoRuntime';\nimport { getTangoRuntime } from '../runtime/defaultRuntime';\n\nconst managerCache = new WeakMap<object, { runtime: TangoRuntime; manager: ModelManager<Record<string, unknown>> }>();\nlet hasRegisteredModelObjects = false;\n\ntype AugmentableSchemaModel<TSchema extends z.ZodObject<z.ZodRawShape>> = {\n metadata: {\n key?: string;\n name: string;\n table: string;\n fields: Array<{ name: string; type: string; primaryKey?: boolean }>;\n };\n schema: {\n parse(input: unknown): PersistedModelOutput<TSchema>;\n };\n hooks?: SchemaModel<TSchema>['hooks'];\n};\n\nfunction defineObjectsProperty<TSchema extends z.ZodObject<z.ZodRawShape>>(model: SchemaModel<TSchema>): void {\n Object.defineProperty(model, 'objects', {\n configurable: true,\n enumerable: true,\n get() {\n const runtime = getTangoRuntime();\n const cached = managerCache.get(model);\n if (cached && cached.runtime === runtime) {\n return cached.manager;\n }\n\n const manager = new ModelManager<PersistedModelOutput<TSchema>>(\n model as unknown as AugmentableSchemaModel<TSchema>,\n runtime\n );\n managerCache.set(model, {\n runtime,\n manager: manager as ModelManager<Record<string, unknown>>,\n });\n return manager;\n },\n });\n}\n\n/**\n * Install the schema model augmentor that exposes `Model.objects`.\n * This registration is idempotent so multiple Tango entrypoints can safely call it.\n */\nexport function registerModelObjects(): void {\n if (hasRegisteredModelObjects) {\n return;\n }\n\n registerModelAugmentor(defineObjectsProperty);\n hasRegisteredModelObjects = true;\n}\n"],"mappings":"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"}
@@ -1,11 +1,12 @@
1
1
  import type { z } from 'zod';
2
2
  import type { ModelManager } from '../manager/ModelManager';
3
+ import type { PersistedModelOutput } from '@danceroutine/tango-schema/domain';
3
4
  /**
4
5
  * Domain boundary barrel: centralizes Tango runtime ownership APIs.
5
6
  */
6
7
  declare global {
7
8
  interface TangoSchemaModelAugmentations<TSchema extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>> {
8
- readonly objects: ModelManager<z.output<TSchema>>;
9
+ readonly objects: ModelManager<PersistedModelOutput<TSchema>>;
9
10
  }
10
11
  }
11
12
  export { registerModelObjects } from '../manager/registerModelObjects';
@@ -1,8 +1,8 @@
1
1
  import "../PostgresAdapter-C9a1XJRx.js";
2
2
  import "../SqliteAdapter-Dp6VRXmz.js";
3
3
  import "../connection-CVvycXus.js";
4
- import "../query-wnl4h2o7.js";
5
- import { TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime } from "../registerModelObjects-emX7Hja9.js";
6
- import "../runtime-7U5_XDad.js";
4
+ import { TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime } from "../registerModelObjects-vsX6GzCN.js";
5
+ import "../query-BKt2nKIt.js";
6
+ import "../runtime-BUpil272.js";
7
7
 
8
8
  export { TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime };
@@ -1,5 +1,5 @@
1
1
  import { __export } from "./chunk-DLY2FNSh.js";
2
- import { TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime } from "./registerModelObjects-emX7Hja9.js";
2
+ import { TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime } from "./registerModelObjects-vsX6GzCN.js";
3
3
 
4
4
  //#region src/runtime/index.ts
5
5
  var runtime_exports = {};
@@ -14,4 +14,4 @@ registerModelObjects();
14
14
 
15
15
  //#endregion
16
16
  export { runtime_exports };
17
- //# sourceMappingURL=runtime-7U5_XDad.js.map
17
+ //# sourceMappingURL=runtime-BUpil272.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-BUpil272.js","names":[],"sources":["../src/runtime/index.ts"],"sourcesContent":["import type { z } from 'zod';\nimport type { ModelManager } from '../manager/ModelManager';\nimport type { PersistedModelOutput } from '@danceroutine/tango-schema/domain';\nimport { registerModelObjects } from '../manager/registerModelObjects';\n\n/**\n * Domain boundary barrel: centralizes Tango runtime ownership APIs.\n */\n\ndeclare global {\n interface TangoSchemaModelAugmentations<TSchema extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>> {\n readonly objects: ModelManager<PersistedModelOutput<TSchema>>;\n }\n}\n\nregisterModelObjects();\n\nexport { registerModelObjects } from '../manager/registerModelObjects';\nexport { TangoRuntime } from './TangoRuntime';\nexport { getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from './defaultRuntime';\n"],"mappings":";;;;;;;;;;;;AAeA,sBAAsB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danceroutine/tango-orm",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "Model-first querying, runtime-managed database access, and transactions for Tango",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,9 +49,9 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "zod": "^4.0.0",
52
- "@danceroutine/tango-config": "1.1.2",
53
- "@danceroutine/tango-core": "1.1.2",
54
- "@danceroutine/tango-schema": "1.1.2"
52
+ "@danceroutine/tango-config": "1.2.0",
53
+ "@danceroutine/tango-core": "1.2.0",
54
+ "@danceroutine/tango-schema": "1.2.0"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "pg": "^8.13.1",
@@ -74,8 +74,8 @@
74
74
  "tsdown": "^0.4.0",
75
75
  "typescript": "^5.6.3",
76
76
  "vitest": "^4.0.6",
77
- "@danceroutine/tango-testing": "1.1.2",
78
- "@danceroutine/tango-migrations": "1.1.2"
77
+ "@danceroutine/tango-migrations": "1.2.0",
78
+ "@danceroutine/tango-testing": "1.2.0"
79
79
  },
80
80
  "scripts": {
81
81
  "build": "tsdown",
@@ -1 +0,0 @@
1
- {"version":3,"file":"query-wnl4h2o7.js","names":["engine: SqlSafetyEngine","plan: SqlValidationPlan","meta: TableMeta","relationNames: readonly string[]","validatedMeta: ValidatedTableMeta","meta: ValidatedTableMeta","relationName: string","relations: TableMeta['relations']","rawKey: string","field: string","meta: TableMeta","dialect: Dialect","value: unknown","state: QuerySetState<T>","whereParts: string[]","params: unknown[]","node: QNode<T>","paramIndex: number","filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>","where: FilterInput<T>","nodes: QNode<T>[]","col: string","lookup: LookupType","filterKeys: Set<string>","value: unknown","node: FilterInput<T> | QNode<T>","input: FilterInput<T> | QNode<T>","executor: QueryExecutor<T>","state: QuerySetState<T>","value: unknown","q: FilterInput<T> | QNode<T>","wrapped: QNode<T>","n: number","cols: (keyof T)[]","shape?: ((r: T) => Out) | { parse: (r: T) => Out }","results: Out[]","rows: T[]","row: T","columns: readonly string[]","normalized: T | null"],"sources":["../src/query/domain/internal/InternalDialect.ts","../src/query/domain/internal/InternalQNodeType.ts","../src/query/domain/internal/InternalLookupType.ts","../src/validation/OrmSqlSafetyAdapter.ts","../src/query/compiler/QueryCompiler.ts","../src/query/compiler/index.ts","../src/query/domain/index.ts","../src/query/domain/internal/InternalDirection.ts","../src/query/QBuilder.ts","../src/query/QuerySet.ts","../src/query/index.ts"],"sourcesContent":["export const InternalDialect = {\n POSTGRES: 'postgres',\n SQLITE: 'sqlite',\n} as const;\n","export const InternalQNodeType = {\n ATOM: 'atom',\n AND: 'and',\n OR: 'or',\n NOT: 'not',\n} as const;\n","export const InternalLookupType = {\n EXACT: 'exact',\n LT: 'lt',\n LTE: 'lte',\n GT: 'gt',\n GTE: 'gte',\n IN: 'in',\n ISNULL: 'isnull',\n CONTAINS: 'contains',\n ICONTAINS: 'icontains',\n STARTSWITH: 'startswith',\n ISTARTSWITH: 'istartswith',\n ENDSWITH: 'endswith',\n IENDSWITH: 'iendswith',\n} as const;\n","import { SqlSafetyEngine, type SqlIdentifierRequest } from '@danceroutine/tango-core';\nimport type { LookupType } from '../query/domain/LookupType';\nimport type { TableMeta } from '../query/domain/TableMeta';\nimport { InternalLookupType } from '../query/domain/internal/InternalLookupType';\nimport type {\n SQLValidationEngine,\n ValidatedDeleteSqlPlan,\n ValidatedFilterDescriptor,\n ValidatedInsertSqlPlan,\n ValidatedRelationMeta,\n ValidatedTableMeta,\n ValidatedSelectSqlPlan,\n ValidatedSqlPlan,\n ValidatedUpdateSqlPlan,\n} from './SQLValidationEngine';\nimport type {\n DeleteSqlValidationPlan,\n InsertSqlValidationPlan,\n SelectSqlValidationPlan,\n SqlValidationPlan,\n UpdateSqlValidationPlan,\n} from './SqlValidationPlan';\n\nconst ALLOWED_LOOKUPS = Object.values(InternalLookupType) as readonly string[];\n\n/**\n * ORM-local adapter that translates query validation plans into the\n * shared Tango SQL safety engine.\n */\nexport class OrmSqlSafetyAdapter implements SQLValidationEngine {\n static readonly BRAND = 'tango.orm.orm_sql_safety_adapter' as const;\n readonly __tangoBrand: typeof OrmSqlSafetyAdapter.BRAND = OrmSqlSafetyAdapter.BRAND;\n\n constructor(private readonly engine: SqlSafetyEngine = new SqlSafetyEngine()) {}\n\n validate(plan: SelectSqlValidationPlan): ValidatedSelectSqlPlan;\n validate(plan: InsertSqlValidationPlan): ValidatedInsertSqlPlan;\n validate(plan: UpdateSqlValidationPlan): ValidatedUpdateSqlPlan;\n validate(plan: DeleteSqlValidationPlan): ValidatedDeleteSqlPlan;\n validate(plan: SqlValidationPlan): ValidatedSqlPlan {\n switch (plan.kind) {\n case 'select': {\n const meta = this.validateTableMeta(plan.meta, plan.relationNames ?? []);\n return {\n kind: 'select',\n meta,\n selectFields: Object.fromEntries(\n (plan.selectFields ?? []).map((field) => [\n field,\n `${meta.table}.${this.resolveColumn(meta, field)}`,\n ])\n ),\n filterKeys: Object.fromEntries(\n (plan.filterKeys ?? []).map((rawKey) => [rawKey, this.validateFilterKey(meta, rawKey)])\n ),\n orderFields: Object.fromEntries(\n (plan.orderFields ?? []).map((field) => [\n field,\n `${meta.table}.${this.resolveColumn(meta, field)}`,\n ])\n ),\n relations: Object.fromEntries(\n (plan.relationNames ?? []).map((relationName) => [\n relationName,\n this.resolveRelation(meta, relationName),\n ])\n ),\n };\n }\n case 'insert': {\n const meta = this.validateTableMeta(plan.meta);\n return {\n kind: 'insert',\n meta,\n writeKeys: plan.writeKeys.map((key) => this.resolveColumn(meta, key)),\n };\n }\n case 'update': {\n const meta = this.validateTableMeta(plan.meta);\n return {\n kind: 'update',\n meta,\n writeKeys: plan.writeKeys.map((key) => this.resolveColumn(meta, key)),\n };\n }\n case 'delete': {\n return {\n kind: 'delete',\n meta: this.validateTableMeta(plan.meta),\n };\n }\n }\n }\n\n private validateTableMeta(meta: TableMeta, relationNames: readonly string[] = []): ValidatedTableMeta {\n const columnNames = Object.keys(meta.columns);\n const validated = this.engine.validate({\n identifiers: [\n { key: 'table', role: 'table', value: meta.table },\n { key: 'pk', role: 'primaryKey', value: meta.pk, allowlist: columnNames },\n ...columnNames.map<SqlIdentifierRequest>((column) => ({\n key: `column:${column}`,\n role: 'column',\n value: column,\n })),\n ],\n });\n\n const validatedMeta: ValidatedTableMeta = {\n table: validated.identifiers.table!.value,\n pk: validated.identifiers.pk!.value,\n columns: Object.fromEntries(\n columnNames.map((column) => [validated.identifiers[`column:${column}`]!.value, meta.columns[column]!])\n ),\n };\n\n if (!(validatedMeta.pk in validatedMeta.columns)) {\n throw new Error(`Unknown column '${validatedMeta.pk}' for table '${validatedMeta.table}'.`);\n }\n\n if (relationNames.length > 0) {\n validatedMeta.relations = Object.fromEntries(\n relationNames.map((relationName) => [\n relationName,\n this.validateRelationMeta(validatedMeta, relationName, meta.relations),\n ])\n );\n }\n\n return validatedMeta;\n }\n\n private validateRelationMeta(\n meta: ValidatedTableMeta,\n relationName: string,\n relations: TableMeta['relations']\n ): ValidatedRelationMeta {\n const relation = relations?.[relationName];\n if (!relation) {\n throw new Error(`Unknown relation '${relationName}' for table '${meta.table}'.`);\n }\n\n const validated = this.engine.validate({\n identifiers: [\n { key: 'table', role: 'relationTable', value: relation.table },\n { key: 'alias', role: 'alias', value: relation.alias },\n { key: 'targetPk', role: 'relationTargetPrimaryKey', value: relation.targetPk },\n ...(relation.foreignKey\n ? [{ key: 'foreignKey', role: 'relationForeignKey' as const, value: relation.foreignKey }]\n : []),\n ],\n });\n\n return {\n ...relation,\n table: validated.identifiers.table!.value,\n alias: validated.identifiers.alias!.value,\n targetPk: validated.identifiers.targetPk!.value,\n localKey: relation.localKey ? this.resolveColumn(meta, relation.localKey) : undefined,\n foreignKey: relation.foreignKey ? validated.identifiers.foreignKey!.value : undefined,\n };\n }\n\n private validateFilterKey(meta: ValidatedTableMeta, rawKey: string): ValidatedFilterDescriptor {\n const segments = rawKey.split('__');\n if (segments.length > 2) {\n throw new Error(`Invalid SQL lookup key: '${rawKey}'.`);\n }\n\n const field = segments[0]!;\n const lookup = (segments[1] ?? InternalLookupType.EXACT) as LookupType;\n const validated = this.engine.validate({\n lookupTokens: [{ key: rawKey, lookup, allowed: ALLOWED_LOOKUPS }],\n });\n\n return {\n rawKey,\n field,\n lookup: validated.lookupTokens[rawKey]!.lookup as LookupType,\n qualifiedColumn: `${meta.table}.${this.resolveColumn(meta, field)}`,\n };\n }\n\n private resolveColumn(meta: ValidatedTableMeta, field: string): string {\n if (!(field in meta.columns)) {\n throw new Error(`Unknown column '${field}' for table '${meta.table}'.`);\n }\n\n return field;\n }\n\n private resolveRelation(meta: ValidatedTableMeta, relationName: string): ValidatedRelationMeta {\n const relation = meta.relations?.[relationName];\n if (!relation) {\n throw new Error(`Unknown relation '${relationName}' for table '${meta.table}'.`);\n }\n\n if (relation.kind === 'belongsTo' && !relation.localKey) {\n throw new Error(`Relation '${relationName}' for table '${meta.table}' requires a local key.`);\n }\n\n return relation;\n }\n}\n","import type { LookupType } from '../domain/LookupType';\nimport type { QuerySetState } from '../domain/QuerySetState';\nimport type { TableMeta } from '../domain/TableMeta';\nimport type { QNode } from '../domain/QNode';\nimport type { CompiledQuery } from '../domain/CompiledQuery';\nimport type { WhereClause } from '../domain/WhereClause';\nimport type { FilterInput } from '../domain/FilterInput';\nimport type { Dialect } from '../domain/Dialect';\nimport { InternalDialect } from '../domain/internal/InternalDialect';\nimport { InternalQNodeType } from '../domain/internal/InternalQNodeType';\nimport { InternalLookupType } from '../domain/internal/InternalLookupType';\nimport { OrmSqlSafetyAdapter } from '../../validation';\n\n// The adapter is stateless, so a shared module instance keeps compiler construction cheap.\nconst sqlSafetyAdapter = new OrmSqlSafetyAdapter();\n\n/**\n * Compiles immutable `QuerySet` state into parameterized SQL.\n *\n * The compiler is intentionally stateless with respect to execution and only\n * produces SQL + params artifacts that can be executed by a `DBClient`.\n */\nexport class QueryCompiler {\n static readonly BRAND = 'tango.orm.query_compiler' as const;\n readonly __tangoBrand: typeof QueryCompiler.BRAND = QueryCompiler.BRAND;\n\n /**\n * Build a compiler for the given repository metadata and SQL dialect.\n */\n constructor(\n private meta: TableMeta,\n private dialect: Dialect = InternalDialect.POSTGRES\n ) {}\n\n /**\n * Narrow an unknown value to `QueryCompiler`.\n */\n static isQueryCompiler(value: unknown): value is QueryCompiler {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === QueryCompiler.BRAND\n );\n }\n\n /**\n * Compile a query state tree into a SQL statement and bound parameters.\n */\n compile<T>(state: QuerySetState<T>): CompiledQuery {\n const knownRelationNames = (state.selectRelated ?? []).filter(\n (relationName) => this.meta.relations?.[relationName] !== undefined\n );\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'select',\n meta: this.meta,\n selectFields: state.select?.map(String),\n filterKeys: this.collectStateFilterKeys(state),\n orderFields: state.order?.map((order) => String(order.by)),\n relationNames: knownRelationNames,\n });\n const table = validatedPlan.meta.table;\n const whereParts: string[] = [];\n const params: unknown[] = [];\n\n if (state.q) {\n const result = this.compileQNode(state.q, params.length + 1, validatedPlan.filterKeys);\n if (result.sql) {\n whereParts.push(result.sql);\n params.push(...result.params);\n }\n }\n\n state.excludes?.forEach((exclude) => {\n const result = this.compileQNode(\n { kind: InternalQNodeType.NOT, node: exclude },\n params.length + 1,\n validatedPlan.filterKeys\n );\n if (result.sql) {\n whereParts.push(result.sql);\n params.push(...result.params);\n }\n });\n\n const select = state.select?.length\n ? state.select.map((field) => validatedPlan.selectFields[String(field)]!).join(', ')\n : `${table}.*`;\n\n const joins = knownRelationNames\n .map((rel) => {\n const relation = validatedPlan.relations[rel];\n if (!relation || relation.kind !== 'belongsTo') {\n return '';\n }\n return `LEFT JOIN ${relation.table} ${relation.alias} ON ${relation.alias}.${relation.targetPk} = ${table}.${relation.localKey!}`;\n })\n .filter(Boolean)\n .join(' ');\n\n const whereSQL = whereParts.length ? ` WHERE ${whereParts.join(' AND ')}` : '';\n const orderSQL = ` ORDER BY ${\n state.order?.length\n ? state.order\n .map((order) => `${validatedPlan.orderFields[String(order.by)]!} ${order.dir.toUpperCase()}`)\n .join(', ')\n : `${table}.${validatedPlan.meta.pk} ASC`\n }`;\n const limitSQL = state.limit ? ` LIMIT ${state.limit}` : '';\n const offsetSQL = state.offset ? ` OFFSET ${state.offset}` : '';\n const sql = `SELECT ${select} FROM ${table}${joins ? ` ${joins}` : ''}${whereSQL}${orderSQL}${limitSQL}${offsetSQL}`;\n\n return { sql, params };\n }\n\n private compileQNode<T>(\n node: QNode<T>,\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n switch (node.kind) {\n case InternalQNodeType.ATOM:\n return this.compileAtom(node.where || {}, paramIndex, filterKeys);\n case InternalQNodeType.AND:\n return this.compileAnd(node.nodes || [], paramIndex, filterKeys);\n case InternalQNodeType.OR:\n return this.compileOr(node.nodes || [], paramIndex, filterKeys);\n case InternalQNodeType.NOT:\n return this.compileNot(node.node!, paramIndex, filterKeys);\n default:\n return { sql: '', params: [] };\n }\n }\n\n private compileAtom<T>(\n where: FilterInput<T>,\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n const entries = Object.entries(where).filter(([, value]) => value !== undefined);\n\n const { parts, params } = entries.reduce<{ parts: string[]; params: unknown[] }>(\n (accumulator, [key, value]) => {\n const descriptor = filterKeys[String(key)]!;\n const idx = paramIndex + accumulator.params.length;\n const clause = this.lookupToSQL(descriptor.qualifiedColumn, descriptor.lookup, value, idx);\n accumulator.parts.push(clause.sql);\n accumulator.params.push(...clause.params);\n return accumulator;\n },\n { parts: [], params: [] }\n );\n\n return {\n sql: parts.length ? `(${parts.join(' AND ')})` : '',\n params,\n };\n }\n\n private compileAnd<T>(\n nodes: QNode<T>[],\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n const { parts, params } = nodes.reduce<{ parts: string[]; params: unknown[] }>(\n (accumulator, node) => {\n const result = this.compileQNode(node, paramIndex + accumulator.params.length, filterKeys);\n if (result.sql) {\n accumulator.parts.push(result.sql);\n accumulator.params.push(...result.params);\n }\n return accumulator;\n },\n { parts: [], params: [] }\n );\n\n return {\n sql: parts.length ? `(${parts.join(' AND ')})` : '',\n params,\n };\n }\n\n private compileOr<T>(\n nodes: QNode<T>[],\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n const { parts, params } = nodes.reduce<{ parts: string[]; params: unknown[] }>(\n (accumulator, node) => {\n const result = this.compileQNode(node, paramIndex + accumulator.params.length, filterKeys);\n if (result.sql) {\n accumulator.parts.push(result.sql);\n accumulator.params.push(...result.params);\n }\n return accumulator;\n },\n { parts: [], params: [] }\n );\n\n return {\n sql: parts.length ? `(${parts.join(' OR ')})` : '',\n params,\n };\n }\n\n private compileNot<T>(\n node: QNode<T>,\n paramIndex: number,\n filterKeys: Record<string, { lookup: LookupType; qualifiedColumn: string }>\n ): WhereClause {\n const result = this.compileQNode(node, paramIndex, filterKeys);\n if (!result.sql) {\n return { sql: '', params: [] };\n }\n\n return {\n sql: `(NOT ${result.sql})`,\n params: result.params,\n };\n }\n\n private lookupToSQL(col: string, lookup: LookupType, value: unknown, paramIndex: number): WhereClause {\n const placeholder = this.dialect === InternalDialect.POSTGRES ? `$${paramIndex}` : '?';\n const normalized = this.normalizeParam(value);\n\n switch (lookup) {\n case InternalLookupType.EXACT:\n if (value === null) {\n return { sql: `${col} IS NULL`, params: [] };\n }\n return { sql: `${col} = ${placeholder}`, params: [normalized] };\n case InternalLookupType.LT:\n return { sql: `${col} < ${placeholder}`, params: [normalized] };\n case InternalLookupType.LTE:\n return { sql: `${col} <= ${placeholder}`, params: [normalized] };\n case InternalLookupType.GT:\n return { sql: `${col} > ${placeholder}`, params: [normalized] };\n case InternalLookupType.GTE:\n return { sql: `${col} >= ${placeholder}`, params: [normalized] };\n case InternalLookupType.IN: {\n const entries = (Array.isArray(value) ? value : [value]).map((entry) => this.normalizeParam(entry));\n if (entries.length === 0) {\n return { sql: '1=0', params: [] };\n }\n const placeholders =\n this.dialect === InternalDialect.POSTGRES\n ? entries.map((_, index) => `$${paramIndex + index}`).join(', ')\n : entries.map(() => '?').join(', ');\n return { sql: `${col} IN (${placeholders})`, params: entries };\n }\n case InternalLookupType.ISNULL:\n return { sql: value ? `${col} IS NULL` : `${col} IS NOT NULL`, params: [] };\n case InternalLookupType.CONTAINS:\n return { sql: `${col} LIKE ${placeholder}`, params: [`%${value}%`] };\n case InternalLookupType.ICONTAINS: {\n const lowerCol = this.dialect === InternalDialect.POSTGRES ? `LOWER(${col})` : `${col}`;\n return { sql: `${lowerCol} LIKE ${placeholder}`, params: [`%${String(value).toLowerCase()}%`] };\n }\n case InternalLookupType.STARTSWITH:\n return { sql: `${col} LIKE ${placeholder}`, params: [`${value}%`] };\n case InternalLookupType.ISTARTSWITH: {\n const lowerCol = this.dialect === InternalDialect.POSTGRES ? `LOWER(${col})` : `${col}`;\n return { sql: `${lowerCol} LIKE ${placeholder}`, params: [`${String(value).toLowerCase()}%`] };\n }\n case InternalLookupType.ENDSWITH:\n return { sql: `${col} LIKE ${placeholder}`, params: [`%${value}`] };\n case InternalLookupType.IENDSWITH: {\n const lowerCol = this.dialect === InternalDialect.POSTGRES ? `LOWER(${col})` : `${col}`;\n return { sql: `${lowerCol} LIKE ${placeholder}`, params: [`%${String(value).toLowerCase()}`] };\n }\n default:\n throw new Error(`Unknown lookup: ${lookup}`);\n }\n }\n\n private normalizeParam(value: unknown): unknown {\n if (this.dialect === InternalDialect.SQLITE && typeof value === 'boolean') {\n return value ? 1 : 0;\n }\n return value;\n }\n\n private collectStateFilterKeys<T>(state: QuerySetState<T>): string[] {\n const filterKeys = new Set<string>();\n if (state.q) {\n this.collectNodeFilterKeys(state.q, filterKeys);\n }\n\n state.excludes?.forEach((exclude) => this.collectNodeFilterKeys(exclude, filterKeys));\n return [...filterKeys];\n }\n\n private collectNodeFilterKeys<T>(node: QNode<T>, filterKeys: Set<string>): void {\n Object.keys(node.where ?? {}).forEach((key) => filterKeys.add(key));\n node.nodes?.forEach((child) => this.collectNodeFilterKeys(child, filterKeys));\n if (node.node) {\n this.collectNodeFilterKeys(node.node, filterKeys);\n }\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { QueryCompiler } from './QueryCompiler';\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport type { CompiledQuery } from './CompiledQuery';\nexport type { Dialect } from './Dialect';\nexport type { Direction } from './Direction';\nexport type { FilterInput } from './FilterInput';\nexport type { FilterKey } from './FilterKey';\nexport type { FilterValue } from './FilterValue';\nexport type { LookupType } from './LookupType';\nexport type { OrderSpec } from './OrderSpec';\nexport type { OrderToken } from './OrderToken';\nexport type { QNode } from './QNode';\nexport type { QueryResult } from './QueryResult';\nexport type { QuerySetState } from './QuerySetState';\nexport type { RelationMeta } from './RelationMeta';\nexport type { TableMeta } from './TableMeta';\nexport type { WhereClause } from './WhereClause';\n","export const InternalDirection = {\n ASC: 'asc',\n DESC: 'desc',\n} as const;\n","import type { QNode } from './domain/QNode';\nimport type { FilterInput } from './domain/FilterInput';\nimport { InternalQNodeType } from './domain/internal/InternalQNodeType';\n\n/**\n * Static builder for composing boolean query expressions.\n *\n * This mirrors Django's `Q(...)` composition patterns and is intended\n * for ergonomic construction of nested `AND`/`OR`/`NOT` trees.\n */\nexport class QBuilder {\n static readonly BRAND = 'tango.orm.q_builder' as const;\n readonly __tangoBrand: typeof QBuilder.BRAND = QBuilder.BRAND;\n\n /**\n * Narrow an unknown value to `QBuilder`.\n */\n static isQBuilder(value: unknown): value is QBuilder {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === QBuilder.BRAND\n );\n }\n\n /**\n * Combine multiple filter fragments using logical `AND`.\n */\n static and<T>(...nodes: Array<FilterInput<T> | QNode<T>>): QNode<T> {\n return {\n kind: InternalQNodeType.AND,\n nodes: nodes.map(QBuilder.wrapNode),\n };\n }\n\n /**\n * Combine multiple filter fragments using logical `OR`.\n */\n static or<T>(...nodes: Array<FilterInput<T> | QNode<T>>): QNode<T> {\n return {\n kind: InternalQNodeType.OR,\n nodes: nodes.map(QBuilder.wrapNode),\n };\n }\n\n /**\n * Negate a filter fragment using logical `NOT`.\n */\n static not<T>(node: FilterInput<T> | QNode<T>): QNode<T> {\n return {\n kind: InternalQNodeType.NOT,\n node: QBuilder.wrapNode(node),\n };\n }\n\n private static wrapNode<T>(input: FilterInput<T> | QNode<T>): QNode<T> {\n if ((input as QNode<T>).kind) {\n return input as QNode<T>;\n }\n return {\n kind: InternalQNodeType.ATOM,\n where: input as FilterInput<T>,\n };\n }\n}\n","import type { DBClient } from '../connection/clients/DBClient';\nimport type { Dialect } from './domain/Dialect';\nimport type { QuerySetState } from './domain/QuerySetState';\nimport type { TableMeta } from './domain/TableMeta';\nimport type { QNode } from './domain/QNode';\nimport type { QueryResult } from './domain/QueryResult';\nimport type { OrderToken } from './domain/OrderToken';\nimport type { FilterInput } from './domain/FilterInput';\nimport { InternalQNodeType } from './domain/internal/InternalQNodeType';\nimport { InternalDirection } from './domain/internal/InternalDirection';\nimport { InternalDialect } from './domain/internal/InternalDialect';\nimport { QBuilder as Q } from './QBuilder';\nimport { QueryCompiler } from './compiler';\n\n/**\n * Query execution seam consumed by `QuerySet`.\n *\n * Application code usually reaches this through `Model.objects` or testing\n * fixtures rather than implementing it directly.\n *\n * @template T - The model type\n */\nexport interface QueryExecutor<T> {\n meta: TableMeta;\n client: DBClient;\n dialect: Dialect;\n run(compiled: { sql: string; params: readonly unknown[] }): Promise<T[]>;\n}\n\n/**\n * Django-inspired query builder for constructing and executing database queries.\n * Provides a fluent API for filtering, ordering, pagination, and eager loading.\n *\n * @template T - The model type being queried\n *\n * @example\n * ```typescript\n * const users = await TodoModel.objects\n * .query()\n * .filter({ active: true })\n * .filter(Q.or({ role: 'admin' }, { role: 'moderator' }))\n * .orderBy('-createdAt')\n * .limit(10)\n * .fetch();\n * ```\n */\nexport class QuerySet<T extends Record<string, unknown>> {\n static readonly BRAND = 'tango.orm.query_set' as const;\n readonly __tangoBrand: typeof QuerySet.BRAND = QuerySet.BRAND;\n\n constructor(\n private executor: QueryExecutor<T>,\n private state: QuerySetState<T> = {}\n ) {}\n\n /**\n * Narrow an unknown value to `QuerySet`.\n */\n static isQuerySet<T extends Record<string, unknown>>(value: unknown): value is QuerySet<T> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === QuerySet.BRAND\n );\n }\n\n /**\n * Add a filter expression to the query.\n *\n * Multiple `filter()` calls are composed with `AND`.\n */\n filter(q: FilterInput<T> | QNode<T>): QuerySet<T> {\n const wrapped: QNode<T> = (q as QNode<T>).kind\n ? (q as QNode<T>)\n : { kind: InternalQNodeType.ATOM, where: q as FilterInput<T> };\n const merged = this.state.q ? Q.and(this.state.q, wrapped) : wrapped;\n return new QuerySet(this.executor, { ...this.state, q: merged });\n }\n\n /**\n * Add an exclusion expression to the query.\n *\n * Exclusions are translated to `NOT (...)` predicates.\n */\n exclude(q: FilterInput<T> | QNode<T>): QuerySet<T> {\n const wrapped: QNode<T> = (q as QNode<T>).kind\n ? (q as QNode<T>)\n : { kind: InternalQNodeType.ATOM, where: q as FilterInput<T> };\n const excludes = [...(this.state.excludes ?? []), wrapped];\n return new QuerySet(this.executor, { ...this.state, excludes });\n }\n\n /**\n * Apply ordering tokens such as `'name'` or `'-createdAt'`.\n */\n orderBy(...tokens: OrderToken<T>[]): QuerySet<T> {\n const order = tokens.map((t) => {\n const str = String(t);\n if (str.startsWith('-')) {\n return { by: str.slice(1) as keyof T, dir: InternalDirection.DESC };\n }\n return { by: t as keyof T, dir: InternalDirection.ASC };\n });\n return new QuerySet(this.executor, { ...this.state, order });\n }\n\n /**\n * Limit the maximum number of rows returned.\n */\n limit(n: number): QuerySet<T> {\n return new QuerySet(this.executor, { ...this.state, limit: n });\n }\n\n /**\n * Skip the first `n` rows.\n */\n offset(n: number): QuerySet<T> {\n return new QuerySet(this.executor, { ...this.state, offset: n });\n }\n\n /**\n * Restrict selected columns.\n */\n select(cols: (keyof T)[]): QuerySet<T> {\n return new QuerySet(this.executor, { ...this.state, select: cols });\n }\n\n /**\n * Request SQL joins for related data when supported by relation metadata.\n */\n selectRelated(...rels: string[]): QuerySet<T> {\n return new QuerySet(this.executor, { ...this.state, selectRelated: rels });\n }\n\n /**\n * Register relation names for prefetch behavior.\n *\n * Prefetch orchestration is adapter-specific.\n */\n prefetchRelated(...rels: string[]): QuerySet<T> {\n return new QuerySet(this.executor, { ...this.state, prefetchRelated: rels });\n }\n\n /**\n * Execute the query and optionally shape each row.\n */\n async fetch<Out = T>(shape?: ((r: T) => Out) | { parse: (r: T) => Out }): Promise<QueryResult<Out>> {\n const compiler = new QueryCompiler(this.executor.meta, this.executor.dialect);\n const compiled = compiler.compile(this.state);\n const rows = await this.executor.run(compiled);\n const normalizedRows = this.normalizeRowsForSchemaParsing(rows, shape);\n\n const results: Out[] = !shape\n ? (normalizedRows as unknown as Out[])\n : typeof shape === 'function'\n ? normalizedRows.map(shape)\n : normalizedRows.map((r) => shape.parse(r));\n\n return {\n results,\n nextCursor: null,\n };\n }\n\n /**\n * Execute the query and return the first row, or `null`.\n */\n async fetchOne<Out = T>(shape?: ((r: T) => Out) | { parse: (r: T) => Out }): Promise<Out | null> {\n const limited = this.limit(1);\n const result = await limited.fetch(shape);\n return result.results[0] ?? null;\n }\n\n /**\n * Execute a `COUNT(*)` query for the current filtered state.\n */\n async count(): Promise<number> {\n const compiler = new QueryCompiler(this.executor.meta, this.executor.dialect);\n const compiled = compiler.compile(this.state);\n const countQuery = `SELECT COUNT(*) as count FROM (${compiled.sql}) AS tango_count_subquery`;\n const rows = await this.executor.client.query<{ count: number }>(countQuery, compiled.params);\n return Number(rows.rows[0]?.count ?? 0);\n }\n\n /**\n * Return whether at least one row matches the current query state.\n */\n async exists(): Promise<boolean> {\n const count = await this.count();\n return count > 0;\n }\n\n private normalizeRowsForSchemaParsing<Out>(rows: T[], shape?: ((r: T) => Out) | { parse: (r: T) => Out }): T[] {\n if (!shape || typeof shape === 'function' || this.executor.dialect !== InternalDialect.SQLITE) {\n return rows;\n }\n\n const booleanColumns = Object.entries(this.executor.meta.columns)\n .filter(([, value]) => this.isBooleanColumnType(value))\n .map(([column]) => column);\n\n if (booleanColumns.length === 0) {\n return rows;\n }\n\n return rows.map((row) => this.normalizeBooleanColumns(row, booleanColumns));\n }\n\n private isBooleanColumnType(value: unknown): boolean {\n return typeof value === 'string' && ['bool', 'boolean'].includes(value.trim().toLowerCase());\n }\n\n private normalizeSqliteBoolean(value: unknown): unknown {\n if (value === 0 || value === '0') {\n return false;\n }\n if (value === 1 || value === '1') {\n return true;\n }\n return value;\n }\n\n private normalizeBooleanColumns(row: T, columns: readonly string[]): T {\n let normalized: T | null = null;\n\n for (const column of columns) {\n const current = (row as Record<string, unknown>)[column];\n const next = this.normalizeSqliteBoolean(current);\n if (next === current) {\n continue;\n }\n if (!normalized) {\n normalized = { ...row };\n }\n (normalized as Record<string, unknown>)[column] = next;\n }\n\n return normalized ?? row;\n }\n}\n","/**\n * Domain boundary barrel: exposes namespaced exports for Django-style drill-down\n * imports and curated flat exports for TS-native ergonomics.\n */\n\nexport * as compiler from './compiler/index';\nexport * as domain from './domain/index';\n\nexport type * from './domain/index';\nexport type { TableMeta } from './domain/index';\nexport { QuerySet } from './QuerySet';\nexport type { QueryExecutor } from './QuerySet';\nexport { QBuilder, QBuilder as Q } from './QBuilder';\nexport { QueryCompiler } from './compiler/index';\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registerModelObjects-emX7Hja9.js","names":["dialect: Dialect","plan: ValidatedInsertSqlPlan","values: readonly unknown[]","plan: ValidatedUpdateSqlPlan","id: unknown","plan: ValidatedDeleteSqlPlan","valueRows: ReadonlyArray<ReadonlyArray<unknown>>","count: number","index: number","runtime: TangoRuntime","sql: string","params?: readonly unknown[]","model: ModelLike<T>","runtime: TangoRuntime","value: unknown","rawMeta: TableMeta","id: T[keyof T]","input: Partial<T>","patch: Partial<T>","inputs: Partial<T>[]","batchPrepared: Partial<T>[]","data: Partial<T>","current: T","loadLoadedConfig: () => LoadedConfig","value: unknown","defaultRuntime: TangoRuntime | null","fromFile: () => unknown","model: SchemaModel<TSchema>"],"sources":["../src/manager/internal/MutationCompiler.ts","../src/manager/internal/RuntimeBoundClient.ts","../src/manager/ModelManager.ts","../src/runtime/TangoRuntime.ts","../src/runtime/defaultRuntime.ts","../src/manager/registerModelObjects.ts"],"sourcesContent":["import type { CompiledQuery, Dialect } from '../../query/domain/index';\nimport type {\n ValidatedDeleteSqlPlan,\n ValidatedInsertSqlPlan,\n ValidatedUpdateSqlPlan,\n} from '../../validation/SQLValidationEngine';\n\n/**\n * Internal compiler for manager-owned INSERT/UPDATE/DELETE statements.\n */\nexport class MutationCompiler {\n constructor(private readonly dialect: Dialect) {}\n\n compileInsert(plan: ValidatedInsertSqlPlan, values: readonly unknown[]): CompiledQuery {\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES (${this.buildValuePlaceholders(plan.writeKeys.length)}) RETURNING *`,\n params: values,\n };\n }\n\n compileUpdate(plan: ValidatedUpdateSqlPlan, values: readonly unknown[], id: unknown): CompiledQuery {\n const sets = plan.writeKeys.map((key, index) => `${key} = ${this.placeholder(index + 1)}`).join(', ');\n const whereParam = this.placeholder(plan.writeKeys.length + 1);\n\n return {\n sql: `UPDATE ${plan.meta.table} SET ${sets} WHERE ${plan.meta.pk} = ${whereParam} RETURNING *`,\n params: [...values, id],\n };\n }\n\n compileDelete(plan: ValidatedDeleteSqlPlan, id: unknown): CompiledQuery {\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${plan.meta.pk} = ${this.placeholder(1)}`,\n params: [id],\n };\n }\n\n compileBulkInsert(plan: ValidatedInsertSqlPlan, valueRows: ReadonlyArray<ReadonlyArray<unknown>>): CompiledQuery {\n const columnCount = plan.writeKeys.length;\n const placeholders = valueRows\n .map((_row, rowIndex) => {\n const offset = rowIndex * columnCount;\n return `(${plan.writeKeys.map((_, colIndex) => this.placeholder(offset + colIndex + 1)).join(', ')})`;\n })\n .join(', ');\n\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders} RETURNING *`,\n params: valueRows.flat(),\n };\n }\n\n private buildValuePlaceholders(count: number): string {\n return Array.from({ length: count }, (_value, index) => this.placeholder(index + 1)).join(', ');\n }\n\n private placeholder(index: number): string {\n return this.dialect === 'postgres' ? `$${index}` : '?';\n }\n}\n","import type { DBClient } from '../../connection/index';\nimport type { TangoRuntime } from '../../runtime/index';\n\n/**\n * DB client proxy that resolves the real Tango runtime client lazily.\n */\nexport class RuntimeBoundClient implements DBClient {\n constructor(private readonly runtime: TangoRuntime) {}\n\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const client = await this.runtime.getClient();\n return client.query<T>(sql, params);\n }\n\n async begin(): Promise<void> {\n const client = await this.runtime.getClient();\n await client.begin();\n }\n\n async commit(): Promise<void> {\n const client = await this.runtime.getClient();\n await client.commit();\n }\n\n async rollback(): Promise<void> {\n const client = await this.runtime.getClient();\n await client.rollback();\n }\n\n async close(): Promise<void> {\n const client = await this.runtime.getClient();\n await client.close();\n }\n}\n","import { NotFoundError } from '@danceroutine/tango-core';\nimport type { ModelWriteHooks } from '@danceroutine/tango-schema';\nimport type { FilterInput, TableMeta } from '../query/domain/index';\nimport type { QuerySet } from '../query/index';\nimport { QuerySet as QuerySetClass } from '../query/index';\nimport type { Dialect, QueryExecutor } from '../query/index';\nimport type { TangoRuntime } from '../runtime/TangoRuntime';\nimport { OrmSqlSafetyAdapter } from '../validation';\nimport type { ManagerLike } from './ManagerLike';\nimport { MutationCompiler } from './internal/MutationCompiler';\nimport { RuntimeBoundClient } from './internal/RuntimeBoundClient';\n\nconst sqlSafetyAdapter = new OrmSqlSafetyAdapter();\n\ntype FieldLike = {\n name: string;\n type: string;\n primaryKey?: boolean;\n};\n\ntype ModelLike<T extends Record<string, unknown>> = {\n metadata: {\n name: string;\n table: string;\n fields: FieldLike[];\n };\n schema: {\n parse(input: unknown): T;\n };\n hooks?: ModelWriteHooks<T>;\n};\n\n/**\n * Model-backed data access API exposed as `Model.objects`.\n */\nexport class ModelManager<T extends Record<string, unknown>> implements ManagerLike<T> {\n static readonly BRAND = 'tango.orm.model_manager' as const;\n readonly __tangoBrand: typeof ModelManager.BRAND = ModelManager.BRAND;\n readonly meta: TableMeta;\n private readonly queryExecutor: QueryExecutor<T>;\n private readonly mutationCompiler: MutationCompiler;\n private readonly model: ModelLike<T>;\n\n constructor(model: ModelLike<T>, runtime: TangoRuntime) {\n this.model = model;\n this.meta = ModelManager.createTableMeta(model);\n const client = new RuntimeBoundClient(runtime);\n const dialect = runtime.getDialect() as Dialect;\n this.mutationCompiler = new MutationCompiler(dialect);\n this.queryExecutor = {\n meta: this.meta,\n client,\n dialect,\n run: async (compiled) => {\n const result = await client.query<T>(compiled.sql, compiled.params);\n return result.rows;\n },\n };\n }\n\n /**\n * Narrow an unknown value to `ModelManager`.\n */\n static isModelManager<T extends Record<string, unknown>>(value: unknown): value is ModelManager<T> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === ModelManager.BRAND\n );\n }\n\n private static createTableMeta<T extends Record<string, unknown>>(model: ModelLike<T>): TableMeta {\n const pkField = model.metadata.fields.find((field) => field.primaryKey);\n if (!pkField) {\n throw new Error(`Model '${model.metadata.name}' cannot attach a manager without a primary key field.`);\n }\n\n const rawMeta: TableMeta = {\n table: model.metadata.table,\n pk: pkField.name,\n columns: Object.fromEntries(model.metadata.fields.map((field) => [field.name, field.type])),\n };\n\n return sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: rawMeta,\n writeKeys: Object.keys(rawMeta.columns),\n }).meta;\n }\n\n query(): QuerySet<T> {\n return new QuerySetClass<T>(this.queryExecutor, {});\n }\n\n async findById(id: T[keyof T]): Promise<T | null> {\n const filter = { [this.meta.pk]: id } as unknown as FilterInput<T>;\n return this.query().filter(filter).fetchOne();\n }\n\n async getOrThrow(id: T[keyof T]): Promise<T> {\n const result = await this.findById(id);\n if (!result) {\n throw new NotFoundError(`${this.model.metadata.name} with ${this.meta.pk}=${String(id)} not found`);\n }\n return result;\n }\n\n async create(input: Partial<T>): Promise<T> {\n const prepared = await this.runBeforeCreate(input);\n const preparedKeys = Object.keys(prepared);\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot create ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const compiled = this.mutationCompiler.compileInsert(\n validatedPlan,\n preparedKeys.map((key) => prepared[key as keyof T])\n );\n const result = await this.queryExecutor.client.query<T>(compiled.sql, compiled.params);\n const created = result.rows[0]!;\n await this.model.hooks?.afterCreate?.({\n record: created,\n model: this.model,\n manager: this,\n });\n return created;\n }\n\n async update(id: T[keyof T], patch: Partial<T>): Promise<T> {\n const current = await this.getOrThrow(id);\n const prepared = await this.runBeforeUpdate(id, patch, current);\n const preparedKeys = Object.keys(prepared);\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot update ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'update',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const compiled = this.mutationCompiler.compileUpdate(\n validatedPlan,\n preparedKeys.map((key) => prepared[key as keyof T]),\n id\n );\n const result = await this.queryExecutor.client.query<T>(compiled.sql, compiled.params);\n const updated = result.rows[0]!;\n await this.model.hooks?.afterUpdate?.({\n id,\n patch: prepared,\n previous: current,\n record: updated,\n model: this.model,\n manager: this,\n });\n return updated;\n }\n\n async delete(id: T[keyof T]): Promise<void> {\n const current = await this.getOrThrow(id);\n await this.model.hooks?.beforeDelete?.({\n id,\n current,\n model: this.model,\n manager: this,\n });\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'delete',\n meta: this.meta,\n });\n const compiled = this.mutationCompiler.compileDelete(validatedPlan, id);\n await this.queryExecutor.client.query(compiled.sql, compiled.params);\n await this.model.hooks?.afterDelete?.({\n id,\n previous: current,\n model: this.model,\n manager: this,\n });\n }\n\n async bulkCreate(inputs: Partial<T>[]): Promise<T[]> {\n if (inputs.length === 0) {\n return [];\n }\n\n const perRowPrepared = await Promise.all(inputs.map((input) => this.runBeforeCreate(input)));\n const batchPrepared: Partial<T>[] =\n (await this.model.hooks?.beforeBulkCreate?.({\n rows: perRowPrepared,\n model: this.model,\n manager: this,\n })) ?? perRowPrepared;\n const preparedKeys = Object.keys(batchPrepared[0] ?? {});\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot create ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const valueRows = batchPrepared.map((input) => preparedKeys.map((key) => input[key as keyof T]));\n const compiled = this.mutationCompiler.compileBulkInsert(validatedPlan, valueRows);\n const result = await this.queryExecutor.client.query<T>(compiled.sql, compiled.params);\n await Promise.all(\n result.rows.map((record) =>\n this.model.hooks?.afterCreate?.({\n record,\n model: this.model,\n manager: this,\n })\n )\n );\n await this.model.hooks?.afterBulkCreate?.({\n records: result.rows,\n model: this.model,\n manager: this,\n });\n return result.rows;\n }\n\n private async runBeforeCreate(data: Partial<T>): Promise<Partial<T>> {\n return (\n (await this.model.hooks?.beforeCreate?.({\n data,\n model: this.model,\n manager: this,\n })) ?? data\n );\n }\n\n private async runBeforeUpdate(id: T[keyof T], patch: Partial<T>, current: T): Promise<Partial<T>> {\n return (\n (await this.model.hooks?.beforeUpdate?.({\n id,\n patch,\n current,\n model: this.model,\n manager: this,\n })) ?? patch\n );\n }\n}\n","import type { LoadedConfig } from '@danceroutine/tango-config';\nimport type { DBClient } from '../connection/index';\nimport { connectDB } from '../connection/index';\nimport type { Dialect } from '../query/domain/index';\n\n/**\n * Framework-owned database runtime that resolves Tango config and lazily\n * creates the shared DB client used by manager-backed models.\n */\nexport class TangoRuntime {\n static readonly BRAND = 'tango.orm.runtime' as const;\n readonly __tangoBrand: typeof TangoRuntime.BRAND = TangoRuntime.BRAND;\n private readonly loadedConfig: LoadedConfig;\n private clientPromise: Promise<DBClient> | null = null;\n\n constructor(loadLoadedConfig: () => LoadedConfig) {\n this.loadedConfig = loadLoadedConfig();\n }\n\n /**\n * Narrow an unknown value to `TangoRuntime`.\n */\n static isTangoRuntime(value: unknown): value is TangoRuntime {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === TangoRuntime.BRAND\n );\n }\n\n /**\n * Return the loaded Tango config snapshot for the active environment.\n */\n getConfig(): LoadedConfig {\n return this.loadedConfig;\n }\n\n /**\n * Return the configured SQL dialect for the current runtime.\n */\n getDialect(): Dialect {\n return this.loadedConfig.current.db.adapter;\n }\n\n /**\n * Return the shared DB client, creating it once on first access.\n */\n async getClient(): Promise<DBClient> {\n if (!this.clientPromise) {\n const db = this.loadedConfig.current.db;\n this.clientPromise = connectDB({\n adapter: db.adapter,\n url: db.url,\n host: db.host,\n port: db.port,\n database: db.database,\n user: db.user,\n password: db.password,\n filename: db.filename,\n maxConnections: db.maxConnections,\n });\n }\n\n return this.clientPromise;\n }\n\n /**\n * Close and clear the cached DB client so tests can start fresh.\n */\n async reset(): Promise<void> {\n if (!this.clientPromise) {\n return;\n }\n\n const client = await this.clientPromise;\n this.clientPromise = null;\n await client.close();\n }\n}\n","import { loadConfig, loadConfigFromProjectRoot } from '@danceroutine/tango-config';\nimport { TangoRuntime } from './TangoRuntime';\n\nlet defaultRuntime: TangoRuntime | null = null;\n\n/**\n * Initialize the process-default Tango runtime from a Tango config loader.\n */\nexport function initializeTangoRuntime(fromFile: () => unknown): TangoRuntime {\n defaultRuntime = new TangoRuntime(() => loadConfig(fromFile));\n return defaultRuntime;\n}\n\n/**\n * Return the process-default Tango runtime, lazily loading Tango config on first access.\n */\nexport function getTangoRuntime(): TangoRuntime {\n if (!defaultRuntime) {\n defaultRuntime = new TangoRuntime(() => loadConfigFromProjectRoot());\n }\n\n return defaultRuntime;\n}\n\n/**\n * Reset the process-default Tango runtime and release any cached client.\n */\nexport async function resetTangoRuntime(): Promise<void> {\n if (!defaultRuntime) {\n return;\n }\n\n const runtime = defaultRuntime;\n defaultRuntime = null;\n await runtime.reset();\n}\n","import type { z } from 'zod';\nimport type { Model as SchemaModel } from '@danceroutine/tango-schema/domain';\nimport { registerModelAugmentor } from '@danceroutine/tango-schema';\nimport { ModelManager } from './ModelManager';\nimport type { TangoRuntime } from '../runtime/TangoRuntime';\nimport { getTangoRuntime } from '../runtime/defaultRuntime';\n\nconst managerCache = new WeakMap<object, { runtime: TangoRuntime; manager: ModelManager<Record<string, unknown>> }>();\nlet hasRegisteredModelObjects = false;\n\nfunction defineObjectsProperty<TSchema extends z.ZodObject<z.ZodRawShape>>(model: SchemaModel<TSchema>): void {\n Object.defineProperty(model, 'objects', {\n configurable: true,\n enumerable: true,\n get() {\n const runtime = getTangoRuntime();\n const cached = managerCache.get(model);\n if (cached && cached.runtime === runtime) {\n return cached.manager;\n }\n\n const manager = new ModelManager<z.output<TSchema>>(model, runtime);\n managerCache.set(model, {\n runtime,\n manager: manager as ModelManager<Record<string, unknown>>,\n });\n return manager;\n },\n });\n}\n\n/**\n * Install the schema model augmentor that exposes `Model.objects`.\n * This registration is idempotent so multiple Tango entrypoints can safely call it.\n */\nexport function registerModelObjects(): void {\n if (hasRegisteredModelObjects) {\n return;\n }\n\n registerModelAugmentor(defineObjectsProperty);\n hasRegisteredModelObjects = true;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime-7U5_XDad.js","names":[],"sources":["../src/runtime/index.ts"],"sourcesContent":["import type { z } from 'zod';\nimport type { ModelManager } from '../manager/ModelManager';\nimport { registerModelObjects } from '../manager/registerModelObjects';\n\n/**\n * Domain boundary barrel: centralizes Tango runtime ownership APIs.\n */\n\ndeclare global {\n interface TangoSchemaModelAugmentations<TSchema extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>> {\n readonly objects: ModelManager<z.output<TSchema>>;\n }\n}\n\nregisterModelObjects();\n\nexport { registerModelObjects } from '../manager/registerModelObjects';\nexport { TangoRuntime } from './TangoRuntime';\nexport { getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from './defaultRuntime';\n"],"mappings":";;;;;;;;;;;;AAcA,sBAAsB"}