@danceroutine/tango-orm 1.11.1 → 1.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/Adapter-DKxAaL4l.d.ts +73 -0
  2. package/dist/DBClient-DuYcXolQ.d.ts +27 -0
  3. package/dist/{InternalDialect-ClSaUNso.js → InternalDialect-U3mwJjKA.js} +3 -4
  4. package/dist/InternalDialect-U3mwJjKA.js.map +1 -0
  5. package/dist/QuerySetState-CjyvAUBs.d.ts +1310 -0
  6. package/dist/SqliteAdapter-6oyUmoJf.js +279 -0
  7. package/dist/SqliteAdapter-6oyUmoJf.js.map +1 -0
  8. package/dist/chunk-8H4AJuhK.js +14 -0
  9. package/dist/connection/index.d.ts +4 -11
  10. package/dist/connection/index.js +3 -6
  11. package/dist/{connection-Dmhgx31M.js → connection-D-E6_Yf1.js} +28 -30
  12. package/dist/connection-D-E6_Yf1.js.map +1 -0
  13. package/dist/{defaultRuntime-DzqBQ9Hb.js → defaultRuntime-CdTX8cXm.js} +41 -35
  14. package/dist/defaultRuntime-CdTX8cXm.js.map +1 -0
  15. package/dist/index-B-aibguC.d.ts +226 -0
  16. package/dist/index-D9B6gKez.d.ts +70 -0
  17. package/dist/index-rjKca3U_.d.ts +31 -0
  18. package/dist/index-uuG57Y7C.d.ts +97 -0
  19. package/dist/index.d.ts +9 -22
  20. package/dist/index.js +9 -12
  21. package/dist/manager/index.d.ts +4 -12
  22. package/dist/manager/index.js +3 -9
  23. package/dist/{manager-DrDTiCAz.js → manager-CiYqAYpn.js} +7 -11
  24. package/dist/{manager-DrDTiCAz.js.map → manager-CiYqAYpn.js.map} +1 -1
  25. package/dist/query/index.d.ts +3 -14
  26. package/dist/query/index.js +2 -4
  27. package/dist/{query-DUZnBFhf.js → query-CP1UMIX6.js} +163 -121
  28. package/dist/query-CP1UMIX6.js.map +1 -0
  29. package/dist/registerModelObjects-C-MliIiM.d.ts +229 -0
  30. package/dist/{registerModelObjects-22ZJKoit.js → registerModelObjects-DZfZ20fa.js} +119 -69
  31. package/dist/registerModelObjects-DZfZ20fa.js.map +1 -0
  32. package/dist/runtime/index.d.ts +3 -15
  33. package/dist/runtime/index.js +15 -8
  34. package/dist/runtime/index.js.map +1 -0
  35. package/dist/transaction/index.d.ts +2 -6
  36. package/dist/transaction/index.js +2 -7
  37. package/dist/{transaction-ZhfDf-f8.js → transaction-2_2m7VUo.js} +26 -10
  38. package/dist/transaction-2_2m7VUo.js.map +1 -0
  39. package/package.json +7 -7
  40. package/dist/InternalDialect-ClSaUNso.js.map +0 -1
  41. package/dist/PostgresAdapter-CXKdKBG-.js +0 -4
  42. package/dist/PostgresAdapter-DySFW6vy.js +0 -128
  43. package/dist/PostgresAdapter-DySFW6vy.js.map +0 -1
  44. package/dist/SqliteAdapter-CDdOjRmW.js +0 -151
  45. package/dist/SqliteAdapter-CDdOjRmW.js.map +0 -1
  46. package/dist/SqliteAdapter-mjtXuVTg.js +0 -4
  47. package/dist/chunk-DLY2FNSh.js +0 -12
  48. package/dist/connection/adapters/Adapter.d.ts +0 -60
  49. package/dist/connection/adapters/AdapterRegistry.d.ts +0 -44
  50. package/dist/connection/adapters/dialects/PostgresAdapter.d.ts +0 -30
  51. package/dist/connection/adapters/dialects/SqliteAdapter.d.ts +0 -22
  52. package/dist/connection/adapters/dialects/index.d.ts +0 -5
  53. package/dist/connection/adapters/index.d.ts +0 -8
  54. package/dist/connection/clients/DBClient.d.ts +0 -23
  55. package/dist/connection/clients/dialects/PostgresClient.d.ts +0 -54
  56. package/dist/connection/clients/dialects/SqliteClient.d.ts +0 -54
  57. package/dist/connection/clients/dialects/index.d.ts +0 -5
  58. package/dist/connection/clients/index.d.ts +0 -7
  59. package/dist/connection-Dmhgx31M.js.map +0 -1
  60. package/dist/defaultRuntime-DzqBQ9Hb.js.map +0 -1
  61. package/dist/manager/ManagerLike.d.ts +0 -34
  62. package/dist/manager/ModelManager.d.ts +0 -106
  63. package/dist/manager/internal/MutationCompiler.d.ts +0 -23
  64. package/dist/manager/internal/RuntimeBoundClient.d.ts +0 -20
  65. package/dist/manager/registerModelObjects.d.ts +0 -5
  66. package/dist/manager/relations/ManyToManyRelatedManager.d.ts +0 -181
  67. package/dist/manager/relations/ManyToManyRelatedQuerySet.d.ts +0 -62
  68. package/dist/manager/relations/MaterializedModelRecord.d.ts +0 -28
  69. package/dist/manager/relations/index.d.ts +0 -9
  70. package/dist/manager/relations/internal/ThroughTableManager.d.ts +0 -85
  71. package/dist/query/ModelQuerySet.d.ts +0 -20
  72. package/dist/query/QBuilder.d.ts +0 -29
  73. package/dist/query/QuerySet.d.ts +0 -215
  74. package/dist/query/compiler/QueryCompiler.d.ts +0 -49
  75. package/dist/query/compiler/index.d.ts +0 -4
  76. package/dist/query/domain/CompiledQuery.d.ts +0 -209
  77. package/dist/query/domain/Dialect.d.ts +0 -2
  78. package/dist/query/domain/Direction.d.ts +0 -2
  79. package/dist/query/domain/FilterInput.d.ts +0 -3
  80. package/dist/query/domain/FilterKey.d.ts +0 -4
  81. package/dist/query/domain/FilterValue.d.ts +0 -1
  82. package/dist/query/domain/LookupType.d.ts +0 -2
  83. package/dist/query/domain/OrderSpec.d.ts +0 -5
  84. package/dist/query/domain/OrderToken.d.ts +0 -1
  85. package/dist/query/domain/QNode.d.ts +0 -9
  86. package/dist/query/domain/QueryResult.d.ts +0 -35
  87. package/dist/query/domain/QuerySetState.d.ts +0 -13
  88. package/dist/query/domain/RelationMeta.d.ts +0 -56
  89. package/dist/query/domain/RelationTyping.d.ts +0 -163
  90. package/dist/query/domain/TableMeta.d.ts +0 -16
  91. package/dist/query/domain/TableMetaFactory.d.ts +0 -10
  92. package/dist/query/domain/WhereClause.d.ts +0 -4
  93. package/dist/query/domain/index.d.ts +0 -21
  94. package/dist/query/domain/internal/InternalDialect.d.ts +0 -4
  95. package/dist/query/domain/internal/InternalDirection.d.ts +0 -4
  96. package/dist/query/domain/internal/InternalLookupType.d.ts +0 -15
  97. package/dist/query/domain/internal/InternalPrefetchQueryKind.d.ts +0 -20
  98. package/dist/query/domain/internal/InternalQNodeType.d.ts +0 -6
  99. package/dist/query/domain/internal/InternalRelationKind.d.ts +0 -6
  100. package/dist/query/internal/isQNodeLike.d.ts +0 -3
  101. package/dist/query/planning/QueryPlanner.d.ts +0 -16
  102. package/dist/query/planning/domain/QueryHydrationPlan.d.ts +0 -20
  103. package/dist/query/planning/index.d.ts +0 -2
  104. package/dist/query-DUZnBFhf.js.map +0 -1
  105. package/dist/registerModelObjects-22ZJKoit.js.map +0 -1
  106. package/dist/runtime/TangoRuntime.d.ts +0 -56
  107. package/dist/runtime/defaultRuntime.d.ts +0 -13
  108. package/dist/runtime/internal/DBClientProvider.d.ts +0 -12
  109. package/dist/runtime/internal/PostgresDBClientProvider.d.ts +0 -12
  110. package/dist/runtime/internal/SqliteDBClientProvider.d.ts +0 -19
  111. package/dist/runtime/internal/createDBClientProvider.d.ts +0 -5
  112. package/dist/runtime-1H88J3nN.js +0 -18
  113. package/dist/runtime-1H88J3nN.js.map +0 -1
  114. package/dist/transaction/AtomicTransaction.d.ts +0 -32
  115. package/dist/transaction/UnitOfWork.d.ts +0 -52
  116. package/dist/transaction/atomic.d.ts +0 -2
  117. package/dist/transaction/internal/context/AsyncLocalTransactionEngine.d.ts +0 -21
  118. package/dist/transaction/internal/context/CallbackRecord.d.ts +0 -5
  119. package/dist/transaction/internal/context/FrameBoundTransaction.d.ts +0 -20
  120. package/dist/transaction/internal/context/FrameTransactionHandle.d.ts +0 -4
  121. package/dist/transaction/internal/context/TransactionEngine.d.ts +0 -16
  122. package/dist/transaction/internal/context/TransactionFrame.d.ts +0 -7
  123. package/dist/transaction/internal/context/TransactionState.d.ts +0 -10
  124. package/dist/transaction/internal/context/index.d.ts +0 -1
  125. package/dist/transaction-ZhfDf-f8.js.map +0 -1
  126. package/dist/validation/OrmSqlSafetyAdapter.d.ts +0 -22
  127. package/dist/validation/SQLValidationEngine.d.ts +0 -68
  128. package/dist/validation/SqlValidationPlan.d.ts +0 -43
  129. package/dist/validation/index.d.ts +0 -3
  130. package/dist/validation/internal/InternalSqlValidationPlanKind.d.ts +0 -25
  131. package/dist/validation/internal/InternalValidatedFilterDescriptorKind.d.ts +0 -4
@@ -0,0 +1,229 @@
1
+ import { t as DBClient } from "./DBClient-DuYcXolQ.js";
2
+ import { i as Dialect, t as Adapter } from "./Adapter-DKxAaL4l.js";
3
+ import { E as ManyToManyRelatedManager, F as QNode, H as TableMeta, I as FilterInput, N as QuerySet } from "./QuerySetState-CjyvAUBs.js";
4
+ import { ModelWriteHooks } from "@danceroutine/tango-schema";
5
+ import { LoadedConfig } from "@danceroutine/tango-config";
6
+ import { z } from "zod";
7
+ import { Model, PersistedModelOutput } from "@danceroutine/tango-schema/domain";
8
+ import { DecoratedFieldKind, InternalDecoratedFieldKind, RelationDecoratedSchema } from "@danceroutine/tango-schema/model";
9
+
10
+ //#region src/manager/relations/MaterializedModelRecord.d.ts
11
+ type IsAny<TValue> = 0 extends 1 & TValue ? true : false;
12
+ type AnyModel = Model<z.ZodObject<z.ZodRawShape>, string>;
13
+ type SchemaShape<TSchema> = TSchema extends z.ZodObject<infer TShape> ? TShape : never;
14
+ type RelationKindOf<TField> = TField extends RelationDecoratedSchema<z.ZodTypeAny, infer TKind extends DecoratedFieldKind, AnyModel, string | undefined, string | undefined> ? TKind : never;
15
+ type RelationTarget<TField> = TField extends RelationDecoratedSchema<z.ZodTypeAny, DecoratedFieldKind, infer TTarget, string | undefined, string | undefined> ? TTarget : never;
16
+ type RelationPublishedName<TField, TFallback extends string> = TField extends RelationDecoratedSchema<z.ZodTypeAny, DecoratedFieldKind, AnyModel, infer TName extends string | undefined, string | undefined> ? TName extends string ? TName : TFallback : TFallback;
17
+ type ModelRow<TTarget> = TTarget extends Model<infer TSchema extends z.ZodObject<z.ZodRawShape>, string> ? PersistedModelOutput<TSchema> : never;
18
+ type ManyToManyKeysOfShape<TShape extends z.ZodRawShape> = Extract<{ [K in keyof TShape]: IsAny<TShape[K]> extends true ? never : [RelationKindOf<TShape[K]>] extends [never] ? never : [RelationKindOf<TShape[K]>] extends [typeof InternalDecoratedFieldKind.MANY_TO_MANY] ? K : never }[keyof TShape], string>;
19
+ type ManyToManyManagers<TShape extends z.ZodRawShape> = { readonly [K in ManyToManyKeysOfShape<TShape> as K extends keyof TShape ? RelationPublishedName<TShape[K], K> : never]: K extends keyof TShape ? RelationTarget<TShape[K]> extends AnyModel ? ManyToManyRelatedManager<ModelRow<RelationTarget<TShape[K]>>> : never : never };
20
+ /**
21
+ * Persisted model record shape returned by ORM read and write paths.
22
+ *
23
+ * Combines the column-level {@link PersistedModelOutput} with a per-relation
24
+ * {@link ManyToManyRelatedManager} for every many-to-many field declared on the
25
+ * source schema. The manager properties are attached as non-enumerable accessors
26
+ * at runtime, so `JSON.stringify` and structural equality checks only see the
27
+ * column data.
28
+ */
29
+ type MaterializedModelRecord<TSchema extends z.ZodObject<z.ZodRawShape>> = PersistedModelOutput<TSchema> & ManyToManyManagers<SchemaShape<TSchema>>;
30
+ //#endregion
31
+ //#region src/manager/ManagerLike.d.ts
32
+ /**
33
+ * Public manager contract consumed by Tango resources and applications.
34
+ */
35
+ interface ManagerLike<TModelRow extends Record<string, unknown>, TSourceModel = unknown> {
36
+ readonly meta: TableMeta;
37
+ query(): QuerySet<TModelRow, TModelRow, TSourceModel>;
38
+ all(): QuerySet<TModelRow, TModelRow, TSourceModel>;
39
+ getOrCreate(args: {
40
+ where: FilterInput<TModelRow> | QNode<TModelRow>;
41
+ defaults?: Partial<TModelRow>;
42
+ }): Promise<{
43
+ record: TModelRow;
44
+ created: boolean;
45
+ }>;
46
+ updateOrCreate(args: {
47
+ where: FilterInput<TModelRow> | QNode<TModelRow>;
48
+ defaults?: Partial<TModelRow>;
49
+ update?: Partial<TModelRow>;
50
+ }): Promise<{
51
+ record: TModelRow;
52
+ created: boolean;
53
+ updated: boolean;
54
+ }>;
55
+ findById(id: TModelRow[keyof TModelRow]): Promise<TModelRow | null>;
56
+ getOrThrow(id: TModelRow[keyof TModelRow]): Promise<TModelRow>;
57
+ create(input: Partial<TModelRow>): Promise<TModelRow>;
58
+ update(id: TModelRow[keyof TModelRow], patch: Partial<TModelRow>): Promise<TModelRow>;
59
+ delete(id: TModelRow[keyof TModelRow]): Promise<void>;
60
+ bulkCreate(inputs: Partial<TModelRow>[]): Promise<TModelRow[]>;
61
+ }
62
+ //#endregion
63
+ //#region src/runtime/internal/DBClientProvider.d.ts
64
+ interface TransactionClientLease {
65
+ readonly client: DBClient;
66
+ release(): Promise<void>;
67
+ }
68
+ //#endregion
69
+ //#region src/runtime/TangoRuntime.d.ts
70
+ /**
71
+ * Framework-owned database runtime that resolves Tango config and lazily
72
+ * creates the shared connection provider used by manager-backed models.
73
+ */
74
+ declare class TangoRuntime {
75
+ static readonly BRAND: "tango.orm.runtime";
76
+ readonly __tangoBrand: typeof TangoRuntime.BRAND;
77
+ private readonly loadedConfig;
78
+ private providerPromise;
79
+ private runtimeClientPromise;
80
+ private cachedAdapter;
81
+ constructor(loadLoadedConfig: () => LoadedConfig);
82
+ /**
83
+ * Narrow an unknown value to `TangoRuntime`.
84
+ */
85
+ static isTangoRuntime(value: unknown): value is TangoRuntime;
86
+ /**
87
+ * Return the loaded Tango config snapshot for the active environment.
88
+ */
89
+ getConfig(): LoadedConfig;
90
+ /**
91
+ * Return the configured SQL dialect for the current runtime.
92
+ */
93
+ getDialect(): Dialect;
94
+ /**
95
+ * Return the adapter backing the configured dialect. Manager-side
96
+ * compilers use this to obtain placeholder formatters and dialect
97
+ * capabilities without branching on the raw dialect string.
98
+ */
99
+ getAdapter(): Adapter;
100
+ /**
101
+ * Return the runtime-bound DB client facade used by manager-backed code.
102
+ */
103
+ getClient(): Promise<DBClient>;
104
+ /**
105
+ * Execute SQL through the autocommit path owned by this runtime.
106
+ */
107
+ query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{
108
+ rows: T[];
109
+ }>;
110
+ /**
111
+ * Lease a transaction-scoped client for `transaction.atomic(...)`.
112
+ */
113
+ leaseTransactionClient(): Promise<TransactionClientLease>;
114
+ /**
115
+ * Close and clear the cached runtime resources so tests can start fresh.
116
+ */
117
+ reset(): Promise<void>;
118
+ private buildAdapterForDialect;
119
+ private getProvider;
120
+ }
121
+ //#endregion
122
+ //#region src/manager/ModelManager.d.ts
123
+ type ModelMetadataLike = Omit<Model['metadata'], 'key' | 'namespace' | 'fields'> & {
124
+ key?: string;
125
+ namespace?: string;
126
+ fields: Array<{
127
+ name: string;
128
+ type: string;
129
+ primaryKey?: boolean;
130
+ }>;
131
+ };
132
+ type ModelLike<TModelRow extends Record<string, unknown>> = {
133
+ metadata: ModelMetadataLike;
134
+ schema: {
135
+ parse(input: unknown): TModelRow;
136
+ };
137
+ hooks?: ModelWriteHooks<TModelRow>;
138
+ };
139
+ /**
140
+ * Model-backed data access API exposed as `Model.objects`.
141
+ */
142
+ declare class ModelManager<TModelRow extends Record<string, unknown>, TSourceModel = unknown> implements ManagerLike<TModelRow, TSourceModel> {
143
+ static readonly BRAND: "tango.orm.model_manager";
144
+ readonly __tangoBrand: typeof ModelManager.BRAND;
145
+ private readonly queryExecutor;
146
+ private readonly mutationCompiler;
147
+ private readonly model;
148
+ private readonly client;
149
+ private readonly adapter;
150
+ private readonly runtime;
151
+ constructor(model: ModelLike<TModelRow>, runtime: TangoRuntime);
152
+ get meta(): TableMeta;
153
+ /**
154
+ * Narrow an unknown value to `ModelManager`.
155
+ */
156
+ static isModelManager<TModelRow extends Record<string, unknown>>(value: unknown): value is ModelManager<TModelRow>;
157
+ private static createTableMeta;
158
+ private static mergeCreatePayloadFromWhere;
159
+ private static countDefinedValues;
160
+ private static collectPlainFieldsFromQNode;
161
+ private static omitLookupKeysFromAtom;
162
+ private static mergeCompatiblePartials;
163
+ query(): QuerySet<TModelRow, TModelRow, TSourceModel>;
164
+ all(): QuerySet<TModelRow, TModelRow, TSourceModel>;
165
+ findById(id: TModelRow[keyof TModelRow]): Promise<TModelRow | null>;
166
+ getOrThrow(id: TModelRow[keyof TModelRow]): Promise<TModelRow>;
167
+ getOrCreate(args: {
168
+ where: FilterInput<TModelRow> | QNode<TModelRow>;
169
+ defaults?: Partial<TModelRow>;
170
+ }): Promise<{
171
+ record: TModelRow;
172
+ created: boolean;
173
+ }>;
174
+ updateOrCreate(args: {
175
+ where: FilterInput<TModelRow> | QNode<TModelRow>;
176
+ defaults?: Partial<TModelRow>;
177
+ update?: Partial<TModelRow>;
178
+ }): Promise<{
179
+ record: TModelRow;
180
+ created: boolean;
181
+ updated: boolean;
182
+ }>;
183
+ create(input: Partial<TModelRow>): Promise<TModelRow>;
184
+ update(id: TModelRow[keyof TModelRow], patch: Partial<TModelRow>): Promise<TModelRow>;
185
+ delete(id: TModelRow[keyof TModelRow]): Promise<void>;
186
+ /**
187
+ * Build a {@link ManyToManyRelatedManager} bound to a single owner record
188
+ * for the supplied many-to-many relation. The returned manager performs
189
+ * its INSERT/DELETE writes through the shared runtime-bound client, so
190
+ * mutations enroll in any active `transaction.atomic(...)` boundary.
191
+ */
192
+ createManyToManyRelatedManager<TTarget extends Record<string, unknown>>(relationName: string, ownerPrimaryKey: unknown): ManyToManyRelatedManager<TTarget>;
193
+ /**
194
+ * Insert multiple rows in a single multi-row INSERT statement.
195
+ *
196
+ * All rows must share the same field set after hook processing. Rows with
197
+ * extra or missing fields relative to the first row will cause an error.
198
+ * If you need to insert rows with different field sets, use individual
199
+ * {@link create} calls instead.
200
+ */
201
+ bulkCreate(inputs: Partial<TModelRow>[]): Promise<TModelRow[]>;
202
+ /**
203
+ * Attach a {@link ManyToManyRelatedManager} as a non-enumerable property
204
+ * for every persisted many-to-many relation declared on the supplied
205
+ * record's model. Existing properties are left untouched so that prior
206
+ * hydration writes (such as prefetched arrays) survive the attach pass
207
+ * during the incremental rollout of related-manager hydration.
208
+ */
209
+ private attachOwnRelatedManagers;
210
+ private attachManyToManyRelatedManagers;
211
+ private resolveManagerForModelKey;
212
+ private resolveTargetExecutor;
213
+ private resolveTargetManager;
214
+ private requireManyToManyEdge;
215
+ private runBeforeCreate;
216
+ private runBeforeUpdate;
217
+ private getHookTransaction;
218
+ private assertUniformRowShape;
219
+ }
220
+ //#endregion
221
+ //#region src/manager/registerModelObjects.d.ts
222
+ /**
223
+ * Install the schema model augmentor that exposes `Model.objects`.
224
+ * This registration is idempotent so multiple Tango entrypoints can safely call it.
225
+ */
226
+ declare function registerModelObjects(): void;
227
+ //#endregion
228
+ export { MaterializedModelRecord as a, ManagerLike as i, ModelManager as n, TangoRuntime as r, registerModelObjects as t };
229
+ //# sourceMappingURL=registerModelObjects-C-MliIiM.d.ts.map
@@ -1,13 +1,42 @@
1
- import { InternalQNodeType, InternalRelationKind, InternalSqlValidationPlanKind, ModelQuerySet, OrmSqlSafetyAdapter, QBuilder, QueryResult, QuerySet, TableMetaFactory, isQNodeLike } from "./query-DUZnBFhf.js";
2
- import { RuntimeBoundClient, TransactionEngine, getTangoRuntime } from "./defaultRuntime-DzqBQ9Hb.js";
1
+ import { a as isQNodeLike, c as InternalRelationKind, f as OrmSqlSafetyAdapter, i as QBuilder, l as QueryResult, m as InternalQNodeType, n as ModelQuerySet, p as InternalSqlValidationPlanKind, r as QuerySet, s as TableMetaFactory } from "./query-CP1UMIX6.js";
2
+ import { a as RuntimeBoundClient, o as TransactionEngine, t as getTangoRuntime } from "./defaultRuntime-CdTX8cXm.js";
3
3
  import { NotFoundError } from "@danceroutine/tango-core";
4
4
  import { ModelRegistry, registerModelAugmentor } from "@danceroutine/tango-schema";
5
-
6
5
  //#region src/manager/relations/ManyToManyRelatedQuerySet.ts
7
6
  function applyShape(rows, shape) {
8
7
  return typeof shape === "function" ? rows.map(shape) : rows.map((row) => shape.parse(row));
9
8
  }
9
+ /**
10
+ * {@link QuerySet} returned by `post.tags.all()` on a many-to-many related
11
+ * manager.
12
+ *
13
+ * Behaves like a normal `QuerySet` over the target model from an application
14
+ * developer's perspective: you can chain `filter`, `exclude`, `orderBy`,
15
+ * `limit`, `offset`, and terminate with `fetch`, `fetchOne`, or `count`.
16
+ * Each chainable call returns another `ManyToManyRelatedQuerySet` so the
17
+ * chain keeps the membership scoping of the owning record.
18
+ *
19
+ * Two behaviors differ from a plain `QuerySet` and matter to application
20
+ * developers:
21
+ *
22
+ * - When the relation was loaded by `prefetchRelated(...)` and no chainable
23
+ * state has been added (no `filter`, `orderBy`, etc.), `fetch()` and
24
+ * `count()` resolve from the prefetch cache without issuing SQL.
25
+ * - Mutating the membership via `post.tags.add(tag)` or
26
+ * `post.tags.remove(tag)` invalidates that cache so follow-up reads go
27
+ * back to the database.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const post = await PostModel.objects.getOrThrow(postId);
32
+ * await post.tags.add(tag);
33
+ * const tags = await post.tags.all().filter({ color: 'red' }).orderBy('name').fetch();
34
+ * ```
35
+ *
36
+ * @template TTarget - The persisted target record shape (e.g. `Tag`).
37
+ */
10
38
  var ManyToManyRelatedQuerySet = class ManyToManyRelatedQuerySet extends QuerySet {
39
+ bridge;
11
40
  constructor(executor, bridge, state = {}) {
12
41
  super(executor, state);
13
42
  this.bridge = bridge;
@@ -15,10 +44,7 @@ var ManyToManyRelatedQuerySet = class ManyToManyRelatedQuerySet extends QuerySet
15
44
  async fetch(shape) {
16
45
  if (this.isStateTrivial()) {
17
46
  const cache = this.bridge.getCache();
18
- if (cache !== null) {
19
- const results = shape ? applyShape(cache, shape) : [...cache];
20
- return new QueryResult(results);
21
- }
47
+ if (cache !== null) return new QueryResult(shape ? applyShape(cache, shape) : [...cache]);
22
48
  }
23
49
  const ids = await this.bridge.fetchTargetIds();
24
50
  if (ids.length === 0) return new QueryResult([]);
@@ -26,8 +52,7 @@ var ManyToManyRelatedQuerySet = class ManyToManyRelatedQuerySet extends QuerySet
26
52
  return shape ? scopedQs.fetch(shape) : scopedQs.fetch();
27
53
  }
28
54
  async fetchOne(shape) {
29
- const result = shape ? await this.fetch(shape) : await this.fetch();
30
- return result.items[0] ?? null;
55
+ return (shape ? await this.fetch(shape) : await this.fetch()).items[0] ?? null;
31
56
  }
32
57
  async count() {
33
58
  if (this.isStateTrivial()) {
@@ -37,8 +62,7 @@ var ManyToManyRelatedQuerySet = class ManyToManyRelatedQuerySet extends QuerySet
37
62
  const ids = await this.bridge.fetchTargetIds();
38
63
  if (ids.length === 0) return 0;
39
64
  if (this.isStateTrivial()) return ids.length;
40
- const scopedQs = new ModelQuerySet(this.executor, this.scopedState(ids));
41
- return scopedQs.count();
65
+ return new ModelQuerySet(this.executor, this.scopedState(ids)).count();
42
66
  }
43
67
  spawn(state) {
44
68
  return new ManyToManyRelatedQuerySet(this.executor, this.bridge, state);
@@ -59,13 +83,15 @@ var ManyToManyRelatedQuerySet = class ManyToManyRelatedQuerySet extends QuerySet
59
83
  };
60
84
  }
61
85
  };
62
-
63
86
  //#endregion
64
87
  //#region src/manager/internal/MutationCompiler.ts
65
88
  const InternalDuplicateInsertPolicy = {
66
89
  ERROR: "error",
67
90
  IGNORE: "ignore"
68
91
  };
92
+ /**
93
+ * Internal compiler for manager-owned INSERT/UPDATE/DELETE statements.
94
+ */
69
95
  var MutationCompiler = class {
70
96
  adapter;
71
97
  placeholders;
@@ -144,16 +170,26 @@ var MutationCompiler = class {
144
170
  };
145
171
  }
146
172
  };
147
-
148
173
  //#endregion
149
174
  //#region src/manager/relations/internal/ThroughTableManager.ts
175
+ /**
176
+ * Internal helper that issues the INSERT, DELETE, and SELECT statements for
177
+ * a single many-to-many join table. Centralizes SQL safety validation and
178
+ * compilation so {@link ManyToManyRelatedManager} implementations only deal
179
+ * in primary-key values.
180
+ */
150
181
  var ThroughTableManager = class ThroughTableManager {
151
- constructor(client, mutationCompiler, descriptor, adapter, sqlSafetyAdapter$1 = new OrmSqlSafetyAdapter()) {
182
+ client;
183
+ mutationCompiler;
184
+ descriptor;
185
+ adapter;
186
+ sqlSafetyAdapter;
187
+ constructor(client, mutationCompiler, descriptor, adapter, sqlSafetyAdapter = new OrmSqlSafetyAdapter()) {
152
188
  this.client = client;
153
189
  this.mutationCompiler = mutationCompiler;
154
190
  this.descriptor = descriptor;
155
191
  this.adapter = adapter;
156
- this.sqlSafetyAdapter = sqlSafetyAdapter$1;
192
+ this.sqlSafetyAdapter = sqlSafetyAdapter;
157
193
  }
158
194
  /**
159
195
  * Derive a {@link ThroughTableLinkDescriptor} from the through-model
@@ -198,8 +234,7 @@ var ThroughTableManager = class ThroughTableManager {
198
234
  const targetColumn = validated.filterKeys[this.descriptor.targetColumn].field;
199
235
  const placeholder = this.adapter.placeholders.at(1);
200
236
  const sql = `SELECT ${targetColumn} AS target_id FROM ${validated.meta.table} WHERE ${sourceColumn} = ${placeholder}`;
201
- const result = await this.client.query(sql, [ownerPrimaryKey]);
202
- return result.rows.map((row) => row.target_id).filter((value) => typeof value === "string" || typeof value === "number");
237
+ return (await this.client.query(sql, [ownerPrimaryKey])).rows.map((row) => row.target_id).filter((value) => typeof value === "string" || typeof value === "number");
203
238
  }
204
239
  async insertLink(ownerPrimaryKey, targetPrimaryKey, options = {}) {
205
240
  await this.insertLinks(ownerPrimaryKey, [targetPrimaryKey], options);
@@ -258,10 +293,32 @@ var ThroughTableManager = class ThroughTableManager {
258
293
  await this.client.query(sql, [ownerPrimaryKey]);
259
294
  }
260
295
  };
261
-
262
296
  //#endregion
263
297
  //#region src/manager/relations/ManyToManyRelatedManager.ts
298
+ /**
299
+ * Django-style related manager exposed on materialized model records for each
300
+ * many-to-many relation.
301
+ *
302
+ * Use the manager to add or remove join-table membership and to query the
303
+ * related target rows. The owning record's primary key and the relation name
304
+ * are bound when the manager is attached, so application code does not need
305
+ * to pass them on every call.
306
+ *
307
+ * Prefetched memberships seed an internal cache that the queryset returned
308
+ * from `all()` short-circuits to without re-querying. Mutations through
309
+ * `add`, `remove`, `set`, `clear`, and `create` invalidate the cache so
310
+ * subsequent reads observe the updated membership. `set(...)` applies
311
+ * Django-shaped replacement semantics:
312
+ * it diffs the current relation membership against the supplied targets,
313
+ * removes any missing links, and inserts any new links inside one atomic
314
+ * write boundary. `clear()` removes every join row for the owner, and
315
+ * `create(...)` persists a new target row plus its join-row link inside one
316
+ * atomic boundary.
317
+ *
318
+ * @template TTarget - The persisted target record shape returned by `all()`.
319
+ */
264
320
  var ManyToManyRelatedManager = class ManyToManyRelatedManager {
321
+ inputs;
265
322
  static BRAND = "tango.orm.m2m_related_manager";
266
323
  __tangoBrand = ManyToManyRelatedManager.BRAND;
267
324
  prefetchCache = null;
@@ -319,7 +376,7 @@ var ManyToManyRelatedManager = class ManyToManyRelatedManager {
319
376
  const targetPrimaryKeys = this.resolveTargetPrimaryKeys(targets);
320
377
  if (targetPrimaryKeys.length === 0) return;
321
378
  if (targetPrimaryKeys.length === 1) await this.insertTargetPrimaryKeys(targetPrimaryKeys);
322
- else await this.inputs.runAtomic(() => this.insertTargetPrimaryKeys(targetPrimaryKeys));
379
+ else await this.inputs.runAtomic(() => this.insertTargetPrimaryKeys(targetPrimaryKeys));
323
380
  this.invalidateCache();
324
381
  }
325
382
  /**
@@ -331,7 +388,7 @@ else await this.inputs.runAtomic(() => this.insertTargetPrimaryKeys(targetPrimar
331
388
  const targetPrimaryKeys = this.resolveTargetPrimaryKeys(targets);
332
389
  if (targetPrimaryKeys.length === 0) return;
333
390
  if (targetPrimaryKeys.length === 1) await this.deleteTargetPrimaryKeys(targetPrimaryKeys);
334
- else await this.inputs.runAtomic(() => this.deleteTargetPrimaryKeys(targetPrimaryKeys));
391
+ else await this.inputs.runAtomic(() => this.deleteTargetPrimaryKeys(targetPrimaryKeys));
335
392
  this.invalidateCache();
336
393
  }
337
394
  /**
@@ -438,7 +495,7 @@ else await this.inputs.runAtomic(() => this.deleteTargetPrimaryKeys(targetPrimar
438
495
  }
439
496
  resolveTargetPrimaryKeys(targets) {
440
497
  const resolved = [];
441
- const seen = new Set();
498
+ const seen = /* @__PURE__ */ new Set();
442
499
  for (const target of targets) {
443
500
  const primaryKey = this.resolveTargetPrimaryKey(target);
444
501
  const canonical = this.canonicalizePrimaryKey(primaryKey);
@@ -452,7 +509,7 @@ else await this.inputs.runAtomic(() => this.deleteTargetPrimaryKeys(targetPrimar
452
509
  if (typeof target === "string" || typeof target === "number") return target;
453
510
  if (typeof target === "object" && target !== null) {
454
511
  const targetPrimaryKey = target[this.inputs.targetPrimaryKeyField];
455
- if (targetPrimaryKey === undefined || targetPrimaryKey === null) throw new Error(`Cannot resolve target primary key '${this.inputs.targetPrimaryKeyField}' for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'.`);
512
+ if (targetPrimaryKey === void 0 || targetPrimaryKey === null) throw new Error(`Cannot resolve target primary key '${this.inputs.targetPrimaryKeyField}' for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'.`);
456
513
  return targetPrimaryKey;
457
514
  }
458
515
  throw new Error(`Unsupported target reference for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'. Expected a record, a primary-key carrier, or a primary-key value.`);
@@ -467,10 +524,12 @@ else await this.inputs.runAtomic(() => this.deleteTargetPrimaryKeys(targetPrimar
467
524
  }
468
525
  }
469
526
  };
470
-
471
527
  //#endregion
472
528
  //#region src/manager/ModelManager.ts
473
529
  const sqlSafetyAdapter = new OrmSqlSafetyAdapter();
530
+ /**
531
+ * Model-backed data access API exposed as `Model.objects`.
532
+ */
474
533
  var ModelManager = class ModelManager {
475
534
  static BRAND = "tango.orm.model_manager";
476
535
  __tangoBrand = ModelManager.BRAND;
@@ -493,8 +552,7 @@ var ModelManager = class ModelManager {
493
552
  client: this.client,
494
553
  adapter: this.adapter,
495
554
  run: async (compiled) => {
496
- const result = await this.client.query(compiled.sql, compiled.params);
497
- return result.rows;
555
+ return (await this.client.query(compiled.sql, compiled.params)).rows;
498
556
  },
499
557
  attachPersistedRecordAccessors: (record, modelKey) => {
500
558
  this.attachManyToManyRelatedManagers(record, modelKey ?? this.model.metadata.key);
@@ -521,42 +579,34 @@ var ModelManager = class ModelManager {
521
579
  return validatedMeta;
522
580
  }
523
581
  static mergeCreatePayloadFromWhere(modelName, pkColumn, where, defaults) {
524
- const hasDefaultsArg = defaults !== undefined;
525
- const providedDefaults = defaults !== undefined ? { ...defaults } : undefined;
582
+ const hasDefaultsArg = defaults !== void 0;
583
+ const providedDefaults = defaults !== void 0 ? { ...defaults } : void 0;
526
584
  if (isQNodeLike(where)) {
527
585
  if (!hasDefaultsArg || !providedDefaults || Object.keys(providedDefaults).length === 0) throw new Error(`Cannot create ${modelName} from Q filters without defaults.`);
528
- const fromQ = ModelManager.collectPlainFieldsFromQNode(modelName, where);
529
- const merged$1 = {
530
- ...fromQ,
586
+ const merged = {
587
+ ...ModelManager.collectPlainFieldsFromQNode(modelName, where),
531
588
  ...providedDefaults
532
589
  };
533
- const keys$1 = Object.keys(merged$1).filter((key) => merged$1[key] !== undefined);
534
- const nonPkKeys$1 = keys$1.filter((key) => key !== pkColumn);
535
- if (nonPkKeys$1.length === 0) throw new Error(`Cannot create ${modelName} without any values.`);
536
- return merged$1;
590
+ if (Object.keys(merged).filter((key) => merged[key] !== void 0).filter((key) => key !== pkColumn).length === 0) throw new Error(`Cannot create ${modelName} without any values.`);
591
+ return merged;
537
592
  }
538
- const atom = where;
539
- const entries = Object.entries(atom);
593
+ const entries = Object.entries(where);
540
594
  const plainEntries = entries.filter(([key]) => !String(key).includes("__"));
541
595
  const lookupOnly = entries.length > 0 && plainEntries.length === 0;
542
- const fromAtom = plainEntries.length > 0 ? Object.fromEntries(plainEntries) : undefined;
543
596
  const mergeBase = {
544
- ...fromAtom,
597
+ ...plainEntries.length > 0 ? Object.fromEntries(plainEntries) : void 0,
545
598
  ...providedDefaults
546
599
  };
547
600
  if (lookupOnly && ModelManager.countDefinedValues(mergeBase, pkColumn) === 0) throw new Error(`Cannot create ${modelName} from lookup-only filters without defaults.`);
548
- const cleanedAtom = plainEntries.length > 0 ? Object.fromEntries(plainEntries) : {};
549
601
  const merged = {
550
- ...cleanedAtom,
602
+ ...plainEntries.length > 0 ? Object.fromEntries(plainEntries) : {},
551
603
  ...mergeBase
552
604
  };
553
- const keys = Object.keys(merged).filter((key) => merged[key] !== undefined);
554
- const nonPkKeys = keys.filter((key) => key !== pkColumn);
555
- if (nonPkKeys.length === 0) throw new Error(`Cannot create ${modelName} without any values.`);
605
+ if (Object.keys(merged).filter((key) => merged[key] !== void 0).filter((key) => key !== pkColumn).length === 0) throw new Error(`Cannot create ${modelName} without any values.`);
556
606
  return merged;
557
607
  }
558
608
  static countDefinedValues(payload, pkColumn) {
559
- return Object.entries(payload).filter(([key, value]) => key !== pkColumn && value !== undefined).length;
609
+ return Object.entries(payload).filter(([key, value]) => key !== pkColumn && value !== void 0).length;
560
610
  }
561
611
  static collectPlainFieldsFromQNode(modelName, node) {
562
612
  switch (node.kind) {
@@ -566,8 +616,7 @@ var ModelManager = class ModelManager {
566
616
  return ModelManager.mergeCompatiblePartials(partials);
567
617
  }
568
618
  case InternalQNodeType.OR: {
569
- const partials = (node.nodes ?? []).map((child) => ModelManager.collectPlainFieldsFromQNode(modelName, child));
570
- const nonEmpty = partials.filter((partial) => Object.keys(partial).length > 0);
619
+ const nonEmpty = (node.nodes ?? []).map((child) => ModelManager.collectPlainFieldsFromQNode(modelName, child)).filter((partial) => Object.keys(partial).length > 0);
571
620
  if (nonEmpty.length > 1) throw new Error(`Cannot derive a create payload from ${modelName} OR filters with multiple predicates. Supply defaults that fully describe the insert.`);
572
621
  return nonEmpty.length === 1 ? nonEmpty[0] : {};
573
622
  }
@@ -582,7 +631,7 @@ var ModelManager = class ModelManager {
582
631
  const merged = {};
583
632
  for (const partial of partials) for (const [key, value] of Object.entries(partial)) {
584
633
  const existing = merged[key];
585
- if (existing !== undefined && existing !== value) throw new Error(`Conflicting values for '${key}' while deriving create payload from Q filters.`);
634
+ if (existing !== void 0 && existing !== value) throw new Error(`Conflicting values for '${key}' while deriving create payload from Q filters.`);
586
635
  merged[key] = value;
587
636
  }
588
637
  return merged;
@@ -604,18 +653,16 @@ var ModelManager = class ModelManager {
604
653
  }
605
654
  async getOrCreate(args) {
606
655
  try {
607
- const record$1 = await this.query().get(args.where);
608
656
  return {
609
- record: record$1,
657
+ record: await this.query().get(args.where),
610
658
  created: false
611
659
  };
612
660
  } catch (error) {
613
661
  if (!NotFoundError.isNotFoundError(error)) throw error;
614
662
  }
615
663
  const merged = ModelManager.mergeCreatePayloadFromWhere(this.model.metadata.name, this.meta.pk, args.where, args.defaults);
616
- const record = await this.create(merged);
617
664
  return {
618
- record,
665
+ record: await this.create(merged),
619
666
  created: true
620
667
  };
621
668
  }
@@ -628,9 +675,8 @@ var ModelManager = class ModelManager {
628
675
  }
629
676
  if (!existing) {
630
677
  const merged = ModelManager.mergeCreatePayloadFromWhere(this.model.metadata.name, this.meta.pk, args.where, args.defaults);
631
- const record$1 = await this.create(merged);
632
678
  return {
633
- record: record$1,
679
+ record: await this.create(merged),
634
680
  created: true,
635
681
  updated: false
636
682
  };
@@ -642,9 +688,8 @@ var ModelManager = class ModelManager {
642
688
  updated: false
643
689
  };
644
690
  const id = existing[this.meta.pk];
645
- const record = await this.update(id, patch);
646
691
  return {
647
- record,
692
+ record: await this.update(id, patch),
648
693
  created: false,
649
694
  updated: true
650
695
  };
@@ -659,8 +704,7 @@ var ModelManager = class ModelManager {
659
704
  writeKeys: preparedKeys
660
705
  });
661
706
  const compiled = this.mutationCompiler.compileInsert(validatedPlan, preparedKeys.map((key) => prepared[key]));
662
- const result = await this.queryExecutor.client.query(compiled.sql, compiled.params);
663
- const created = result.rows[0];
707
+ const created = (await this.queryExecutor.client.query(compiled.sql, compiled.params)).rows[0];
664
708
  this.attachOwnRelatedManagers(created);
665
709
  await this.model.hooks?.afterCreate?.({
666
710
  record: created,
@@ -681,8 +725,7 @@ var ModelManager = class ModelManager {
681
725
  writeKeys: preparedKeys
682
726
  });
683
727
  const compiled = this.mutationCompiler.compileUpdate(validatedPlan, preparedKeys.map((key) => prepared[key]), id);
684
- const result = await this.queryExecutor.client.query(compiled.sql, compiled.params);
685
- const updated = result.rows[0];
728
+ const updated = (await this.queryExecutor.client.query(compiled.sql, compiled.params)).rows[0];
686
729
  this.attachOwnRelatedManagers(updated);
687
730
  await this.model.hooks?.afterUpdate?.({
688
731
  id,
@@ -727,8 +770,7 @@ var ModelManager = class ModelManager {
727
770
  */
728
771
  createManyToManyRelatedManager(relationName, ownerPrimaryKey) {
729
772
  const relation = this.requireManyToManyEdge(relationName);
730
- const registry = ModelRegistry.getOwner(this.model);
731
- const throughModel = registry.getByKey(relation.throughModelKey);
773
+ const throughModel = ModelRegistry.getOwner(this.model).getByKey(relation.throughModelKey);
732
774
  return ManyToManyRelatedManager.create({
733
775
  ownerPrimaryKey,
734
776
  relationName,
@@ -809,7 +851,7 @@ var ModelManager = class ModelManager {
809
851
  const relations = meta.relations;
810
852
  if (!relations) return;
811
853
  const ownerPrimaryKey = record[meta.pk];
812
- if (ownerPrimaryKey === undefined || ownerPrimaryKey === null) return;
854
+ if (ownerPrimaryKey === void 0 || ownerPrimaryKey === null) return;
813
855
  for (const [relationName, relation] of Object.entries(relations)) {
814
856
  if (relation.kind !== InternalRelationKind.MANY_TO_MANY) continue;
815
857
  if (Object.prototype.hasOwnProperty.call(record, relationName)) continue;
@@ -818,14 +860,19 @@ var ModelManager = class ModelManager {
818
860
  value: relatedManager,
819
861
  writable: true,
820
862
  configurable: true,
863
+ /**
864
+ * Non-enumerable so `Object.keys(record)`, `JSON.stringify(record)`,
865
+ * `{ ...record }`, and similar enumeration paths continue to
866
+ * see only the persisted columns. Application code reaches the
867
+ * manager through `record.tags`, never through enumeration.
868
+ */
821
869
  enumerable: false
822
870
  });
823
871
  }
824
872
  }
825
873
  resolveManagerForModelKey(modelKey) {
826
874
  if (modelKey === this.model.metadata.key) return this;
827
- const registry = ModelRegistry.getOwner(this.model);
828
- const otherModel = registry.getByKey(modelKey);
875
+ const otherModel = ModelRegistry.getOwner(this.model).getByKey(modelKey);
829
876
  if (!otherModel) return null;
830
877
  const candidate = otherModel.objects;
831
878
  return ModelManager.isModelManager(candidate) ? candidate : null;
@@ -889,10 +936,9 @@ var ModelManager = class ModelManager {
889
936
  throw new Error(`bulkCreate failed after hook processing: rows at indices [${indices.join(", ")}] have mismatched fields.\n${details}\nExpected fields (from row at index 0): [${sortedReferenceKeys.join(", ")}].`);
890
937
  }
891
938
  };
892
-
893
939
  //#endregion
894
940
  //#region src/manager/registerModelObjects.ts
895
- const managerCache = new WeakMap();
941
+ const managerCache = /* @__PURE__ */ new WeakMap();
896
942
  let hasRegisteredModelObjects = false;
897
943
  function defineObjectsProperty(model) {
898
944
  Object.defineProperty(model, "objects", {
@@ -911,12 +957,16 @@ function defineObjectsProperty(model) {
911
957
  }
912
958
  });
913
959
  }
960
+ /**
961
+ * Install the schema model augmentor that exposes `Model.objects`.
962
+ * This registration is idempotent so multiple Tango entrypoints can safely call it.
963
+ */
914
964
  function registerModelObjects() {
915
965
  if (hasRegisteredModelObjects) return;
916
966
  registerModelAugmentor(defineObjectsProperty);
917
967
  hasRegisteredModelObjects = true;
918
968
  }
919
-
920
969
  //#endregion
921
- export { ManyToManyRelatedManager, ManyToManyRelatedQuerySet, ModelManager, registerModelObjects };
922
- //# sourceMappingURL=registerModelObjects-22ZJKoit.js.map
970
+ export { ManyToManyRelatedQuerySet as i, ModelManager as n, ManyToManyRelatedManager as r, registerModelObjects as t };
971
+
972
+ //# sourceMappingURL=registerModelObjects-DZfZ20fa.js.map