@danceroutine/tango-orm 0.1.0 → 1.0.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/LICENSE +21 -0
- package/README.md +104 -0
- package/dist/{PostgresAdapter-_X36-mLL.js → PostgresAdapter-C9a1XJRx.js} +31 -7
- package/dist/PostgresAdapter-C9a1XJRx.js.map +1 -0
- package/dist/PostgresAdapter-CBc1u8eT.js +3 -0
- package/dist/SqliteAdapter-BJKNxCvS.js +3 -0
- package/dist/SqliteAdapter-Dp6VRXmz.js +118 -0
- package/dist/SqliteAdapter-Dp6VRXmz.js.map +1 -0
- package/dist/connection/adapters/Adapter.d.ts +9 -0
- package/dist/connection/adapters/AdapterRegistry.d.ts +28 -1
- package/dist/connection/adapters/dialects/PostgresAdapter.d.ts +10 -1
- package/dist/connection/adapters/dialects/SqliteAdapter.d.ts +11 -1
- package/dist/connection/clients/DBClient.d.ts +8 -0
- package/dist/connection/clients/dialects/PostgresClient.d.ts +22 -1
- package/dist/connection/clients/dialects/SqliteClient.d.ts +26 -1
- package/dist/connection/index.js +3 -3
- package/dist/{connection-DytAsjC9.js → connection-CVvycXus.js} +21 -6
- package/dist/connection-CVvycXus.js.map +1 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +9 -8
- package/dist/manager/ManagerLike.d.ts +15 -0
- package/dist/manager/ModelManager.d.ts +48 -0
- package/dist/manager/index.d.ts +6 -0
- package/dist/manager/index.js +8 -0
- package/dist/manager/internal/MutationCompiler.d.ts +15 -0
- package/dist/manager/internal/RuntimeBoundClient.d.ts +16 -0
- package/dist/manager/registerModelObjects.d.ts +5 -0
- package/dist/manager-D6tU8xTO.js +13 -0
- package/dist/manager-D6tU8xTO.js.map +1 -0
- package/dist/query/QBuilder.d.ts +18 -0
- package/dist/query/QuerySet.d.ts +60 -9
- package/dist/query/compiler/QueryCompiler.d.ts +19 -2
- package/dist/query/domain/{RepositoryMeta.d.ts → TableMeta.d.ts} +1 -1
- package/dist/query/domain/index.d.ts +1 -1
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +1 -2
- package/dist/query-wnl4h2o7.js +671 -0
- package/dist/query-wnl4h2o7.js.map +1 -0
- package/dist/registerModelObjects-emX7Hja9.js +354 -0
- package/dist/registerModelObjects-emX7Hja9.js.map +1 -0
- package/dist/runtime/TangoRuntime.d.ts +34 -0
- package/dist/runtime/defaultRuntime.d.ts +13 -0
- package/dist/runtime/index.d.ts +13 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime-7U5_XDad.js +17 -0
- package/dist/runtime-7U5_XDad.js.map +1 -0
- package/dist/transaction/UnitOfWork.d.ts +21 -3
- package/dist/transaction/index.js +1 -1
- package/dist/{transaction-DIGJnp19.js → transaction-DooTMuAl.js} +29 -11
- package/dist/transaction-DooTMuAl.js.map +1 -0
- package/dist/validation/OrmSqlSafetyAdapter.d.ts +22 -0
- package/dist/validation/SQLValidationEngine.d.ts +51 -0
- package/dist/validation/SqlValidationPlan.d.ts +42 -0
- package/dist/validation/index.d.ts +3 -0
- package/package.json +81 -74
- package/dist/PostgresAdapter-DCF8T4vh.js +0 -3
- package/dist/PostgresAdapter-_X36-mLL.js.map +0 -1
- package/dist/QuerySet-BzR5QzGi.js +0 -411
- package/dist/QuerySet-BzR5QzGi.js.map +0 -1
- package/dist/SqliteAdapter-CBnxCznk.js +0 -3
- package/dist/SqliteAdapter-J03fEjmr.js +0 -70
- package/dist/SqliteAdapter-J03fEjmr.js.map +0 -1
- package/dist/connection/clients/DBClient.js +0 -1
- package/dist/connection/clients/dialects/PostgresClient.js +0 -32
- package/dist/connection/clients/dialects/SqliteClient.js +0 -44
- package/dist/connection-DytAsjC9.js.map +0 -1
- package/dist/query/QuerySet.js +0 -108
- package/dist/query/compiler/QueryCompiler.js +0 -183
- package/dist/query/domain/CompiledQuery.js +0 -1
- package/dist/query/domain/WhereClause.js +0 -1
- package/dist/query-CQbvLeuh.js +0 -21
- package/dist/query-CQbvLeuh.js.map +0 -1
- package/dist/repository/Repository.d.ts +0 -40
- package/dist/repository/Repository.js +0 -100
- package/dist/repository/index.d.ts +0 -4
- package/dist/repository/index.js +0 -4
- package/dist/repository-DaRvsfjs.js +0 -78
- package/dist/repository-DaRvsfjs.js.map +0 -1
- package/dist/transaction-DIGJnp19.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { connectDB } from "./connection-CVvycXus.js";
|
|
2
|
+
import { OrmSqlSafetyAdapter, QuerySet } from "./query-wnl4h2o7.js";
|
|
3
|
+
import { NotFoundError } from "@danceroutine/tango-core";
|
|
4
|
+
import { registerModelAugmentor } from "@danceroutine/tango-schema";
|
|
5
|
+
import { loadConfig, loadConfigFromProjectRoot } from "@danceroutine/tango-config";
|
|
6
|
+
|
|
7
|
+
//#region src/manager/internal/MutationCompiler.ts
|
|
8
|
+
var MutationCompiler = class {
|
|
9
|
+
constructor(dialect) {
|
|
10
|
+
this.dialect = dialect;
|
|
11
|
+
}
|
|
12
|
+
compileInsert(plan, values) {
|
|
13
|
+
return {
|
|
14
|
+
sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(", ")}) VALUES (${this.buildValuePlaceholders(plan.writeKeys.length)}) RETURNING *`,
|
|
15
|
+
params: values
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
compileUpdate(plan, values, id) {
|
|
19
|
+
const sets = plan.writeKeys.map((key, index) => `${key} = ${this.placeholder(index + 1)}`).join(", ");
|
|
20
|
+
const whereParam = this.placeholder(plan.writeKeys.length + 1);
|
|
21
|
+
return {
|
|
22
|
+
sql: `UPDATE ${plan.meta.table} SET ${sets} WHERE ${plan.meta.pk} = ${whereParam} RETURNING *`,
|
|
23
|
+
params: [...values, id]
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
compileDelete(plan, id) {
|
|
27
|
+
return {
|
|
28
|
+
sql: `DELETE FROM ${plan.meta.table} WHERE ${plan.meta.pk} = ${this.placeholder(1)}`,
|
|
29
|
+
params: [id]
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
compileBulkInsert(plan, valueRows) {
|
|
33
|
+
const columnCount = plan.writeKeys.length;
|
|
34
|
+
const placeholders = valueRows.map((_row, rowIndex) => {
|
|
35
|
+
const offset = rowIndex * columnCount;
|
|
36
|
+
return `(${plan.writeKeys.map((_, colIndex) => this.placeholder(offset + colIndex + 1)).join(", ")})`;
|
|
37
|
+
}).join(", ");
|
|
38
|
+
return {
|
|
39
|
+
sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(", ")}) VALUES ${placeholders} RETURNING *`,
|
|
40
|
+
params: valueRows.flat()
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
buildValuePlaceholders(count) {
|
|
44
|
+
return Array.from({ length: count }, (_value, index) => this.placeholder(index + 1)).join(", ");
|
|
45
|
+
}
|
|
46
|
+
placeholder(index) {
|
|
47
|
+
return this.dialect === "postgres" ? `$${index}` : "?";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/manager/internal/RuntimeBoundClient.ts
|
|
53
|
+
var RuntimeBoundClient = class {
|
|
54
|
+
constructor(runtime) {
|
|
55
|
+
this.runtime = runtime;
|
|
56
|
+
}
|
|
57
|
+
async query(sql, params) {
|
|
58
|
+
const client = await this.runtime.getClient();
|
|
59
|
+
return client.query(sql, params);
|
|
60
|
+
}
|
|
61
|
+
async begin() {
|
|
62
|
+
const client = await this.runtime.getClient();
|
|
63
|
+
await client.begin();
|
|
64
|
+
}
|
|
65
|
+
async commit() {
|
|
66
|
+
const client = await this.runtime.getClient();
|
|
67
|
+
await client.commit();
|
|
68
|
+
}
|
|
69
|
+
async rollback() {
|
|
70
|
+
const client = await this.runtime.getClient();
|
|
71
|
+
await client.rollback();
|
|
72
|
+
}
|
|
73
|
+
async close() {
|
|
74
|
+
const client = await this.runtime.getClient();
|
|
75
|
+
await client.close();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/manager/ModelManager.ts
|
|
81
|
+
const sqlSafetyAdapter = new OrmSqlSafetyAdapter();
|
|
82
|
+
var ModelManager = class ModelManager {
|
|
83
|
+
static BRAND = "tango.orm.model_manager";
|
|
84
|
+
__tangoBrand = ModelManager.BRAND;
|
|
85
|
+
meta;
|
|
86
|
+
queryExecutor;
|
|
87
|
+
mutationCompiler;
|
|
88
|
+
model;
|
|
89
|
+
constructor(model, runtime) {
|
|
90
|
+
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);
|
|
95
|
+
this.queryExecutor = {
|
|
96
|
+
meta: this.meta,
|
|
97
|
+
client,
|
|
98
|
+
dialect,
|
|
99
|
+
run: async (compiled) => {
|
|
100
|
+
const result = await client.query(compiled.sql, compiled.params);
|
|
101
|
+
return result.rows;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Narrow an unknown value to `ModelManager`.
|
|
107
|
+
*/
|
|
108
|
+
static isModelManager(value) {
|
|
109
|
+
return typeof value === "object" && value !== null && value.__tangoBrand === ModelManager.BRAND;
|
|
110
|
+
}
|
|
111
|
+
static createTableMeta(model) {
|
|
112
|
+
const pkField = model.metadata.fields.find((field) => field.primaryKey);
|
|
113
|
+
if (!pkField) throw new Error(`Model '${model.metadata.name}' cannot attach a manager without a primary key field.`);
|
|
114
|
+
const rawMeta = {
|
|
115
|
+
table: model.metadata.table,
|
|
116
|
+
pk: pkField.name,
|
|
117
|
+
columns: Object.fromEntries(model.metadata.fields.map((field) => [field.name, field.type]))
|
|
118
|
+
};
|
|
119
|
+
return sqlSafetyAdapter.validate({
|
|
120
|
+
kind: "insert",
|
|
121
|
+
meta: rawMeta,
|
|
122
|
+
writeKeys: Object.keys(rawMeta.columns)
|
|
123
|
+
}).meta;
|
|
124
|
+
}
|
|
125
|
+
query() {
|
|
126
|
+
return new QuerySet(this.queryExecutor, {});
|
|
127
|
+
}
|
|
128
|
+
async findById(id) {
|
|
129
|
+
const filter = { [this.meta.pk]: id };
|
|
130
|
+
return this.query().filter(filter).fetchOne();
|
|
131
|
+
}
|
|
132
|
+
async getOrThrow(id) {
|
|
133
|
+
const result = await this.findById(id);
|
|
134
|
+
if (!result) throw new NotFoundError(`${this.model.metadata.name} with ${this.meta.pk}=${String(id)} not found`);
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
async create(input) {
|
|
138
|
+
const prepared = await this.runBeforeCreate(input);
|
|
139
|
+
const preparedKeys = Object.keys(prepared);
|
|
140
|
+
if (preparedKeys.length === 0) throw new Error(`Cannot create ${this.model.metadata.name} without any values.`);
|
|
141
|
+
const validatedPlan = sqlSafetyAdapter.validate({
|
|
142
|
+
kind: "insert",
|
|
143
|
+
meta: this.meta,
|
|
144
|
+
writeKeys: preparedKeys
|
|
145
|
+
});
|
|
146
|
+
const compiled = this.mutationCompiler.compileInsert(validatedPlan, preparedKeys.map((key) => prepared[key]));
|
|
147
|
+
const result = await this.queryExecutor.client.query(compiled.sql, compiled.params);
|
|
148
|
+
const created = result.rows[0];
|
|
149
|
+
await this.model.hooks?.afterCreate?.({
|
|
150
|
+
record: created,
|
|
151
|
+
model: this.model,
|
|
152
|
+
manager: this
|
|
153
|
+
});
|
|
154
|
+
return created;
|
|
155
|
+
}
|
|
156
|
+
async update(id, patch) {
|
|
157
|
+
const current = await this.getOrThrow(id);
|
|
158
|
+
const prepared = await this.runBeforeUpdate(id, patch, current);
|
|
159
|
+
const preparedKeys = Object.keys(prepared);
|
|
160
|
+
if (preparedKeys.length === 0) throw new Error(`Cannot update ${this.model.metadata.name} without any values.`);
|
|
161
|
+
const validatedPlan = sqlSafetyAdapter.validate({
|
|
162
|
+
kind: "update",
|
|
163
|
+
meta: this.meta,
|
|
164
|
+
writeKeys: preparedKeys
|
|
165
|
+
});
|
|
166
|
+
const compiled = this.mutationCompiler.compileUpdate(validatedPlan, preparedKeys.map((key) => prepared[key]), id);
|
|
167
|
+
const result = await this.queryExecutor.client.query(compiled.sql, compiled.params);
|
|
168
|
+
const updated = result.rows[0];
|
|
169
|
+
await this.model.hooks?.afterUpdate?.({
|
|
170
|
+
id,
|
|
171
|
+
patch: prepared,
|
|
172
|
+
previous: current,
|
|
173
|
+
record: updated,
|
|
174
|
+
model: this.model,
|
|
175
|
+
manager: this
|
|
176
|
+
});
|
|
177
|
+
return updated;
|
|
178
|
+
}
|
|
179
|
+
async delete(id) {
|
|
180
|
+
const current = await this.getOrThrow(id);
|
|
181
|
+
await this.model.hooks?.beforeDelete?.({
|
|
182
|
+
id,
|
|
183
|
+
current,
|
|
184
|
+
model: this.model,
|
|
185
|
+
manager: this
|
|
186
|
+
});
|
|
187
|
+
const validatedPlan = sqlSafetyAdapter.validate({
|
|
188
|
+
kind: "delete",
|
|
189
|
+
meta: this.meta
|
|
190
|
+
});
|
|
191
|
+
const compiled = this.mutationCompiler.compileDelete(validatedPlan, id);
|
|
192
|
+
await this.queryExecutor.client.query(compiled.sql, compiled.params);
|
|
193
|
+
await this.model.hooks?.afterDelete?.({
|
|
194
|
+
id,
|
|
195
|
+
previous: current,
|
|
196
|
+
model: this.model,
|
|
197
|
+
manager: this
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
async bulkCreate(inputs) {
|
|
201
|
+
if (inputs.length === 0) return [];
|
|
202
|
+
const perRowPrepared = await Promise.all(inputs.map((input) => this.runBeforeCreate(input)));
|
|
203
|
+
const batchPrepared = await this.model.hooks?.beforeBulkCreate?.({
|
|
204
|
+
rows: perRowPrepared,
|
|
205
|
+
model: this.model,
|
|
206
|
+
manager: this
|
|
207
|
+
}) ?? perRowPrepared;
|
|
208
|
+
const preparedKeys = Object.keys(batchPrepared[0] ?? {});
|
|
209
|
+
if (preparedKeys.length === 0) throw new Error(`Cannot create ${this.model.metadata.name} without any values.`);
|
|
210
|
+
const validatedPlan = sqlSafetyAdapter.validate({
|
|
211
|
+
kind: "insert",
|
|
212
|
+
meta: this.meta,
|
|
213
|
+
writeKeys: preparedKeys
|
|
214
|
+
});
|
|
215
|
+
const valueRows = batchPrepared.map((input) => preparedKeys.map((key) => input[key]));
|
|
216
|
+
const compiled = this.mutationCompiler.compileBulkInsert(validatedPlan, valueRows);
|
|
217
|
+
const result = await this.queryExecutor.client.query(compiled.sql, compiled.params);
|
|
218
|
+
await Promise.all(result.rows.map((record) => this.model.hooks?.afterCreate?.({
|
|
219
|
+
record,
|
|
220
|
+
model: this.model,
|
|
221
|
+
manager: this
|
|
222
|
+
})));
|
|
223
|
+
await this.model.hooks?.afterBulkCreate?.({
|
|
224
|
+
records: result.rows,
|
|
225
|
+
model: this.model,
|
|
226
|
+
manager: this
|
|
227
|
+
});
|
|
228
|
+
return result.rows;
|
|
229
|
+
}
|
|
230
|
+
async runBeforeCreate(data) {
|
|
231
|
+
return await this.model.hooks?.beforeCreate?.({
|
|
232
|
+
data,
|
|
233
|
+
model: this.model,
|
|
234
|
+
manager: this
|
|
235
|
+
}) ?? data;
|
|
236
|
+
}
|
|
237
|
+
async runBeforeUpdate(id, patch, current) {
|
|
238
|
+
return await this.model.hooks?.beforeUpdate?.({
|
|
239
|
+
id,
|
|
240
|
+
patch,
|
|
241
|
+
current,
|
|
242
|
+
model: this.model,
|
|
243
|
+
manager: this
|
|
244
|
+
}) ?? patch;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/runtime/TangoRuntime.ts
|
|
250
|
+
var TangoRuntime = class TangoRuntime {
|
|
251
|
+
static BRAND = "tango.orm.runtime";
|
|
252
|
+
__tangoBrand = TangoRuntime.BRAND;
|
|
253
|
+
loadedConfig;
|
|
254
|
+
clientPromise = null;
|
|
255
|
+
constructor(loadLoadedConfig) {
|
|
256
|
+
this.loadedConfig = loadLoadedConfig();
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Narrow an unknown value to `TangoRuntime`.
|
|
260
|
+
*/
|
|
261
|
+
static isTangoRuntime(value) {
|
|
262
|
+
return typeof value === "object" && value !== null && value.__tangoBrand === TangoRuntime.BRAND;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Return the loaded Tango config snapshot for the active environment.
|
|
266
|
+
*/
|
|
267
|
+
getConfig() {
|
|
268
|
+
return this.loadedConfig;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Return the configured SQL dialect for the current runtime.
|
|
272
|
+
*/
|
|
273
|
+
getDialect() {
|
|
274
|
+
return this.loadedConfig.current.db.adapter;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Return the shared DB client, creating it once on first access.
|
|
278
|
+
*/
|
|
279
|
+
async getClient() {
|
|
280
|
+
if (!this.clientPromise) {
|
|
281
|
+
const db = this.loadedConfig.current.db;
|
|
282
|
+
this.clientPromise = connectDB({
|
|
283
|
+
adapter: db.adapter,
|
|
284
|
+
url: db.url,
|
|
285
|
+
host: db.host,
|
|
286
|
+
port: db.port,
|
|
287
|
+
database: db.database,
|
|
288
|
+
user: db.user,
|
|
289
|
+
password: db.password,
|
|
290
|
+
filename: db.filename,
|
|
291
|
+
maxConnections: db.maxConnections
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return this.clientPromise;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Close and clear the cached DB client so tests can start fresh.
|
|
298
|
+
*/
|
|
299
|
+
async reset() {
|
|
300
|
+
if (!this.clientPromise) return;
|
|
301
|
+
const client = await this.clientPromise;
|
|
302
|
+
this.clientPromise = null;
|
|
303
|
+
await client.close();
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
//#endregion
|
|
308
|
+
//#region src/runtime/defaultRuntime.ts
|
|
309
|
+
let defaultRuntime = null;
|
|
310
|
+
function initializeTangoRuntime(fromFile) {
|
|
311
|
+
defaultRuntime = new TangoRuntime(() => loadConfig(fromFile));
|
|
312
|
+
return defaultRuntime;
|
|
313
|
+
}
|
|
314
|
+
function getTangoRuntime() {
|
|
315
|
+
if (!defaultRuntime) defaultRuntime = new TangoRuntime(() => loadConfigFromProjectRoot());
|
|
316
|
+
return defaultRuntime;
|
|
317
|
+
}
|
|
318
|
+
async function resetTangoRuntime() {
|
|
319
|
+
if (!defaultRuntime) return;
|
|
320
|
+
const runtime = defaultRuntime;
|
|
321
|
+
defaultRuntime = null;
|
|
322
|
+
await runtime.reset();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region src/manager/registerModelObjects.ts
|
|
327
|
+
const managerCache = new WeakMap();
|
|
328
|
+
let hasRegisteredModelObjects = false;
|
|
329
|
+
function defineObjectsProperty(model) {
|
|
330
|
+
Object.defineProperty(model, "objects", {
|
|
331
|
+
configurable: true,
|
|
332
|
+
enumerable: true,
|
|
333
|
+
get() {
|
|
334
|
+
const runtime = getTangoRuntime();
|
|
335
|
+
const cached = managerCache.get(model);
|
|
336
|
+
if (cached && cached.runtime === runtime) return cached.manager;
|
|
337
|
+
const manager = new ModelManager(model, runtime);
|
|
338
|
+
managerCache.set(model, {
|
|
339
|
+
runtime,
|
|
340
|
+
manager
|
|
341
|
+
});
|
|
342
|
+
return manager;
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
function registerModelObjects() {
|
|
347
|
+
if (hasRegisteredModelObjects) return;
|
|
348
|
+
registerModelAugmentor(defineObjectsProperty);
|
|
349
|
+
hasRegisteredModelObjects = true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
//#endregion
|
|
353
|
+
export { ModelManager, TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime };
|
|
354
|
+
//# sourceMappingURL=registerModelObjects-emX7Hja9.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { LoadedConfig } from '@danceroutine/tango-config';
|
|
2
|
+
import type { DBClient } from '../connection/index';
|
|
3
|
+
import type { Dialect } from '../query/domain/index';
|
|
4
|
+
/**
|
|
5
|
+
* Framework-owned database runtime that resolves Tango config and lazily
|
|
6
|
+
* creates the shared DB client used by manager-backed models.
|
|
7
|
+
*/
|
|
8
|
+
export declare class TangoRuntime {
|
|
9
|
+
static readonly BRAND: "tango.orm.runtime";
|
|
10
|
+
readonly __tangoBrand: typeof TangoRuntime.BRAND;
|
|
11
|
+
private readonly loadedConfig;
|
|
12
|
+
private clientPromise;
|
|
13
|
+
constructor(loadLoadedConfig: () => LoadedConfig);
|
|
14
|
+
/**
|
|
15
|
+
* Narrow an unknown value to `TangoRuntime`.
|
|
16
|
+
*/
|
|
17
|
+
static isTangoRuntime(value: unknown): value is TangoRuntime;
|
|
18
|
+
/**
|
|
19
|
+
* Return the loaded Tango config snapshot for the active environment.
|
|
20
|
+
*/
|
|
21
|
+
getConfig(): LoadedConfig;
|
|
22
|
+
/**
|
|
23
|
+
* Return the configured SQL dialect for the current runtime.
|
|
24
|
+
*/
|
|
25
|
+
getDialect(): Dialect;
|
|
26
|
+
/**
|
|
27
|
+
* Return the shared DB client, creating it once on first access.
|
|
28
|
+
*/
|
|
29
|
+
getClient(): Promise<DBClient>;
|
|
30
|
+
/**
|
|
31
|
+
* Close and clear the cached DB client so tests can start fresh.
|
|
32
|
+
*/
|
|
33
|
+
reset(): Promise<void>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TangoRuntime } from './TangoRuntime';
|
|
2
|
+
/**
|
|
3
|
+
* Initialize the process-default Tango runtime from a Tango config loader.
|
|
4
|
+
*/
|
|
5
|
+
export declare function initializeTangoRuntime(fromFile: () => unknown): TangoRuntime;
|
|
6
|
+
/**
|
|
7
|
+
* Return the process-default Tango runtime, lazily loading Tango config on first access.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getTangoRuntime(): TangoRuntime;
|
|
10
|
+
/**
|
|
11
|
+
* Reset the process-default Tango runtime and release any cached client.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resetTangoRuntime(): Promise<void>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { ModelManager } from '../manager/ModelManager';
|
|
3
|
+
/**
|
|
4
|
+
* Domain boundary barrel: centralizes Tango runtime ownership APIs.
|
|
5
|
+
*/
|
|
6
|
+
declare global {
|
|
7
|
+
interface TangoSchemaModelAugmentations<TSchema extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>> {
|
|
8
|
+
readonly objects: ModelManager<z.output<TSchema>>;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export { registerModelObjects } from '../manager/registerModelObjects';
|
|
12
|
+
export { TangoRuntime } from './TangoRuntime';
|
|
13
|
+
export { getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from './defaultRuntime';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "../PostgresAdapter-C9a1XJRx.js";
|
|
2
|
+
import "../SqliteAdapter-Dp6VRXmz.js";
|
|
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";
|
|
7
|
+
|
|
8
|
+
export { TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { __export } from "./chunk-DLY2FNSh.js";
|
|
2
|
+
import { TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime } from "./registerModelObjects-emX7Hja9.js";
|
|
3
|
+
|
|
4
|
+
//#region src/runtime/index.ts
|
|
5
|
+
var runtime_exports = {};
|
|
6
|
+
__export(runtime_exports, {
|
|
7
|
+
TangoRuntime: () => TangoRuntime,
|
|
8
|
+
getTangoRuntime: () => getTangoRuntime,
|
|
9
|
+
initializeTangoRuntime: () => initializeTangoRuntime,
|
|
10
|
+
registerModelObjects: () => registerModelObjects,
|
|
11
|
+
resetTangoRuntime: () => resetTangoRuntime
|
|
12
|
+
});
|
|
13
|
+
registerModelObjects();
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { runtime_exports };
|
|
17
|
+
//# sourceMappingURL=runtime-7U5_XDad.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|