@c9up/atlas 0.1.19 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -14
- package/db.darwin-arm64.node +0 -0
- package/db.darwin-x64.node +0 -0
- package/db.linux-arm64-gnu.node +0 -0
- package/db.linux-x64-gnu.node +0 -0
- package/db.win32-x64-msvc.node +0 -0
- package/dist/AtlasProvider.d.ts +6 -0
- package/dist/AtlasProvider.d.ts.map +1 -1
- package/dist/AtlasProvider.js +2 -2
- package/dist/AtlasProvider.js.map +1 -1
- package/dist/BaseEntity.d.ts +164 -5
- package/dist/BaseEntity.d.ts.map +1 -1
- package/dist/BaseEntity.js +339 -33
- package/dist/BaseEntity.js.map +1 -1
- package/dist/BaseModel.d.ts +91 -0
- package/dist/BaseModel.d.ts.map +1 -0
- package/dist/BaseModel.js +193 -0
- package/dist/BaseModel.js.map +1 -0
- package/dist/BaseRepository.d.ts +71 -15
- package/dist/BaseRepository.d.ts.map +1 -1
- package/dist/BaseRepository.js +1355 -384
- package/dist/BaseRepository.js.map +1 -1
- package/dist/ModelQuery.d.ts +341 -18
- package/dist/ModelQuery.d.ts.map +1 -1
- package/dist/ModelQuery.js +1406 -177
- package/dist/ModelQuery.js.map +1 -1
- package/dist/Transaction.d.ts +17 -0
- package/dist/Transaction.d.ts.map +1 -1
- package/dist/Transaction.js +57 -5
- package/dist/Transaction.js.map +1 -1
- package/dist/adapters/NapiDbAdapter.d.ts +33 -4
- package/dist/adapters/NapiDbAdapter.d.ts.map +1 -1
- package/dist/adapters/NapiDbAdapter.js +101 -11
- package/dist/adapters/NapiDbAdapter.js.map +1 -1
- package/dist/console/migrationCommands.d.ts +48 -0
- package/dist/console/migrationCommands.d.ts.map +1 -0
- package/dist/console/migrationCommands.js +220 -0
- package/dist/console/migrationCommands.js.map +1 -0
- package/dist/decorators/entity.d.ts +37 -6
- package/dist/decorators/entity.d.ts.map +1 -1
- package/dist/decorators/entity.js +32 -2
- package/dist/decorators/entity.js.map +1 -1
- package/dist/events.d.ts +64 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +82 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/metadata-keys.d.ts +3 -2
- package/dist/metadata-keys.d.ts.map +1 -1
- package/dist/naming/NamingStrategy.d.ts +7 -0
- package/dist/naming/NamingStrategy.d.ts.map +1 -1
- package/dist/naming/NamingStrategy.js +16 -0
- package/dist/naming/NamingStrategy.js.map +1 -1
- package/dist/schema/Migration.d.ts +26 -3
- package/dist/schema/Migration.d.ts.map +1 -1
- package/dist/schema/Migration.js +33 -24
- package/dist/schema/Migration.js.map +1 -1
- package/dist/schema/MigrationRunner.d.ts +43 -32
- package/dist/schema/MigrationRunner.d.ts.map +1 -1
- package/dist/schema/MigrationRunner.js +211 -26
- package/dist/schema/MigrationRunner.js.map +1 -1
- package/dist/schema/Schema.d.ts +57 -0
- package/dist/schema/Schema.d.ts.map +1 -1
- package/dist/schema/Schema.js +138 -3
- package/dist/schema/Schema.js.map +1 -1
- package/dist/schema/TableBuilder.d.ts +247 -8
- package/dist/schema/TableBuilder.d.ts.map +1 -1
- package/dist/schema/TableBuilder.js +607 -41
- package/dist/schema/TableBuilder.js.map +1 -1
- package/dist/schema/catalog.d.ts +47 -0
- package/dist/schema/catalog.d.ts.map +1 -0
- package/dist/schema/catalog.js +111 -0
- package/dist/schema/catalog.js.map +1 -0
- package/dist/schema/types.d.ts +150 -1
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +11 -0
- package/dist/schema/types.js.map +1 -1
- package/dist/services/db.d.ts +6 -0
- package/dist/services/db.d.ts.map +1 -1
- package/dist/services/db.js +17 -0
- package/dist/services/db.js.map +1 -1
- package/dist/testing/DatabaseCleanup.d.ts +7 -4
- package/dist/testing/DatabaseCleanup.d.ts.map +1 -1
- package/dist/testing/DatabaseCleanup.js +21 -18
- package/dist/testing/DatabaseCleanup.js.map +1 -1
- package/dist/testing/Factory.d.ts +70 -5
- package/dist/testing/Factory.d.ts.map +1 -1
- package/dist/testing/Factory.js +209 -10
- package/dist/testing/Factory.js.map +1 -1
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +3 -1
- package/scripts/guard-publish.mjs +15 -0
- package/src/AtlasProvider.ts +8 -1
- package/src/BaseEntity.ts +431 -41
- package/src/BaseModel.ts +324 -0
- package/src/BaseRepository.ts +1589 -419
- package/src/ModelQuery.ts +1817 -203
- package/src/Transaction.ts +68 -5
- package/src/adapters/NapiDbAdapter.ts +159 -10
- package/src/console/migrationCommands.ts +258 -0
- package/src/decorators/entity.ts +53 -6
- package/src/events.ts +112 -0
- package/src/index.ts +19 -0
- package/src/metadata-keys.ts +3 -2
- package/src/naming/NamingStrategy.ts +23 -0
- package/src/schema/Migration.ts +42 -3
- package/src/schema/MigrationRunner.ts +270 -27
- package/src/schema/Schema.ts +210 -3
- package/src/schema/TableBuilder.ts +735 -41
- package/src/schema/catalog.ts +166 -0
- package/src/schema/types.ts +137 -2
- package/src/services/db.ts +28 -0
- package/src/testing/DatabaseCleanup.ts +23 -22
- package/src/testing/Factory.ts +332 -15
|
@@ -13,14 +13,33 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @implements MISS-18, Story 32.13
|
|
15
15
|
*/
|
|
16
|
+
import { type Faker } from "@faker-js/faker";
|
|
16
17
|
import type { BaseEntity } from "../BaseEntity.js";
|
|
17
18
|
import { type DatabaseConnection } from "../BaseRepository.js";
|
|
18
19
|
type EntityConstructor<T extends BaseEntity> = new () => T;
|
|
20
|
+
/** Resolves the factory that builds a related model (Lucid `.relation`). */
|
|
21
|
+
type RelationResolver = () => FactoryBuilder<BaseEntity>;
|
|
22
|
+
/**
|
|
23
|
+
* Context handed to the `define` callback (Adonis Lucid parity). Currently just
|
|
24
|
+
* a Faker instance for generating fake data. A callback that takes no argument
|
|
25
|
+
* keeps working — it simply ignores the context.
|
|
26
|
+
*/
|
|
27
|
+
export interface FactoryContext {
|
|
28
|
+
faker: Faker;
|
|
29
|
+
}
|
|
30
|
+
/** Attributes callback — receives {@link FactoryContext}, returns the row shape. */
|
|
31
|
+
type DefaultsFn = (ctx: FactoryContext) => Record<string, unknown>;
|
|
19
32
|
/** A named state — mutates an in-progress data object in place. */
|
|
20
33
|
type StateFn<D> = (data: D) => void;
|
|
21
34
|
export interface FactoryBuilder<T extends BaseEntity> {
|
|
22
35
|
/** Override specific fields for the next call (reset after consumption). */
|
|
23
36
|
merge(overrides: Partial<Record<string, unknown>>): FactoryBuilder<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Like {@link merge} but deep — nested plain objects are merged key by key
|
|
39
|
+
* instead of replaced wholesale (Lucid `mergeRecursive`). Arrays and
|
|
40
|
+
* non-plain values still replace. Reset after consumption like `merge`.
|
|
41
|
+
*/
|
|
42
|
+
mergeRecursive(overrides: Partial<Record<string, unknown>>): FactoryBuilder<T>;
|
|
24
43
|
/** Declare a named variation of this factory, stored on the factory's state map. */
|
|
25
44
|
state(name: string, fn: StateFn<Record<string, unknown>>): FactoryBuilder<T>;
|
|
26
45
|
/**
|
|
@@ -31,19 +50,65 @@ export interface FactoryBuilder<T extends BaseEntity> {
|
|
|
31
50
|
* (audit 2026-06-13). `merge()` behaves the same way.
|
|
32
51
|
*/
|
|
33
52
|
apply(...stateNames: string[]): FactoryBuilder<T>;
|
|
34
|
-
/**
|
|
35
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Bind a connection (e.g. a transaction) used by subsequent
|
|
55
|
+
* `create`/`createMany` calls that pass no explicit `db` (Adonis Lucid
|
|
56
|
+
* `.client`). The binding persists until changed. Ideal for test isolation:
|
|
57
|
+
* `factory.client(trx).create()`.
|
|
58
|
+
*/
|
|
59
|
+
client(connection: DatabaseConnection): FactoryBuilder<T>;
|
|
60
|
+
/**
|
|
61
|
+
* Like {@link client} but resolves a connection registered under `name` via
|
|
62
|
+
* atlas's connection registry (Adonis Lucid `.connection`). Throws if no
|
|
63
|
+
* connection is registered under that name.
|
|
64
|
+
*/
|
|
65
|
+
connection(name: string): FactoryBuilder<T>;
|
|
66
|
+
/**
|
|
67
|
+
* Create and persist a single entity (fires lifecycle hooks via
|
|
68
|
+
* `repo.create`). `db` is optional when a connection was bound with
|
|
69
|
+
* {@link client} / {@link connection}.
|
|
70
|
+
*/
|
|
71
|
+
create(db?: DatabaseConnection): Promise<T>;
|
|
36
72
|
/** Create and persist multiple entities (fires hooks per row). */
|
|
37
|
-
createMany(count: number, db
|
|
73
|
+
createMany(count: number, db?: DatabaseConnection): Promise<T[]>;
|
|
38
74
|
/** Build the data object without persisting and without instantiating an entity. */
|
|
39
75
|
make(): Record<string, unknown>;
|
|
40
76
|
/** Build multiple data objects without persisting. */
|
|
41
77
|
makeMany(count: number): Record<string, unknown>[];
|
|
42
78
|
/**
|
|
43
79
|
* Build an entity INSTANCE without persisting it (Lucid's `makeStubbed`).
|
|
44
|
-
*
|
|
80
|
+
* The instance is marked persisted and, unless the build already supplied a
|
|
81
|
+
* primary key, given a process-unique stub id — so it looks like a saved row
|
|
82
|
+
* (relations, serialization, `$isPersisted`) without touching the DB.
|
|
45
83
|
*/
|
|
46
84
|
makeStubbed(): T;
|
|
85
|
+
/** Build many stubbed instances, each with its own stub id ({@link makeStubbed}). */
|
|
86
|
+
makeStubbedMany(count: number): T[];
|
|
87
|
+
/**
|
|
88
|
+
* Declare which factory builds a relation (Adonis Lucid `.relation`), so
|
|
89
|
+
* `.with(name)` can create related rows. `name` must match a relation
|
|
90
|
+
* property declared with `@HasMany`/`@HasOne`/`@BelongsTo`/`@ManyToMany`.
|
|
91
|
+
*/
|
|
92
|
+
relation(name: string, resolver: RelationResolver): FactoryBuilder<T>;
|
|
93
|
+
/**
|
|
94
|
+
* Queue related rows to create together with the next `create`/`createMany`
|
|
95
|
+
* (Adonis Lucid `.with`). `count` defaults to 1 (ignored past 1 for hasOne).
|
|
96
|
+
* The callback receives the related factory to customize it (`merge`/`apply`).
|
|
97
|
+
*
|
|
98
|
+
* One level deep: the related rows are persisted through the parent's
|
|
99
|
+
* relation proxy (which wires the FK / pivot), so a nested `.with()` on the
|
|
100
|
+
* callback's factory is not itself applied. `.with()` runs on persistence
|
|
101
|
+
* only — `make`/`makeStubbed` ignore it.
|
|
102
|
+
*/
|
|
103
|
+
with(name: string, count?: number, callback?: (factory: FactoryBuilder<BaseEntity>) => void): FactoryBuilder<T>;
|
|
104
|
+
/**
|
|
105
|
+
* Register a callback that runs on the built entity INSTANCE before it is
|
|
106
|
+
* persisted (Adonis Lucid `.tap`). Multiple taps run in order. Applies to the
|
|
107
|
+
* instance-producing paths — `create`/`createMany`/`makeStubbed`/
|
|
108
|
+
* `makeStubbedMany` — and is reset after consumption; `make`/`makeMany`
|
|
109
|
+
* return plain data, so they ignore it.
|
|
110
|
+
*/
|
|
111
|
+
tap(fn: (entity: T) => void): FactoryBuilder<T>;
|
|
47
112
|
}
|
|
48
113
|
/**
|
|
49
114
|
* Define a model factory.
|
|
@@ -53,6 +118,6 @@ export interface FactoryBuilder<T extends BaseEntity> {
|
|
|
53
118
|
* name: 'Test User',
|
|
54
119
|
* }))
|
|
55
120
|
*/
|
|
56
|
-
export declare function factory<T extends BaseEntity>(entityClass: EntityConstructor<T>, defaults:
|
|
121
|
+
export declare function factory<T extends BaseEntity>(entityClass: EntityConstructor<T>, defaults: DefaultsFn): FactoryBuilder<T>;
|
|
57
122
|
export {};
|
|
58
123
|
//# sourceMappingURL=Factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Factory.d.ts","sourceRoot":"","sources":["../../src/testing/Factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAkB,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"Factory.d.ts","sourceRoot":"","sources":["../../src/testing/Factory.ts"],"names":[],"mappings":"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"}
|
package/dist/testing/Factory.js
CHANGED
|
@@ -13,7 +13,43 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @implements MISS-18, Story 32.13
|
|
15
15
|
*/
|
|
16
|
+
import { faker } from "@faker-js/faker";
|
|
16
17
|
import { BaseRepository } from "../BaseRepository.js";
|
|
18
|
+
import { getPrimaryKey, getRelationMetadata } from "../decorators/entity.js";
|
|
19
|
+
import { getConnection } from "../services/db.js";
|
|
20
|
+
/**
|
|
21
|
+
* Process-wide counter for stubbed primary keys (Lucid's stub id). Every
|
|
22
|
+
* `makeStubbed*` build with no explicit PK gets the next value, so stubbed
|
|
23
|
+
* instances have stable, distinct, DB-free identifiers — enough to look
|
|
24
|
+
* persisted and to key relations/serialization without a round trip.
|
|
25
|
+
*/
|
|
26
|
+
let stubIdCounter = 0;
|
|
27
|
+
/** Keys that must never be written through a recursive merge — prototype-pollution guard. */
|
|
28
|
+
const FORBIDDEN_MERGE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
29
|
+
function isPlainObject(value) {
|
|
30
|
+
if (value === null || typeof value !== "object")
|
|
31
|
+
return false;
|
|
32
|
+
const proto = Object.getPrototypeOf(value);
|
|
33
|
+
return proto === Object.prototype || proto === null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Deep-merge `source` into `target` (Lucid `mergeRecursive`). Plain objects are
|
|
37
|
+
* merged key by key; arrays and every non-plain value replace wholesale. Returns
|
|
38
|
+
* a fresh object — neither argument is mutated. Skips prototype-pollution keys.
|
|
39
|
+
*/
|
|
40
|
+
function deepMerge(target, source) {
|
|
41
|
+
const out = { ...target };
|
|
42
|
+
for (const [key, value] of Object.entries(source)) {
|
|
43
|
+
if (FORBIDDEN_MERGE_KEYS.has(key))
|
|
44
|
+
continue;
|
|
45
|
+
const existing = out[key];
|
|
46
|
+
out[key] =
|
|
47
|
+
isPlainObject(existing) && isPlainObject(value)
|
|
48
|
+
? deepMerge(existing, value)
|
|
49
|
+
: value;
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
17
53
|
/**
|
|
18
54
|
* Define a model factory.
|
|
19
55
|
*
|
|
@@ -27,12 +63,61 @@ export function factory(entityClass, defaults) {
|
|
|
27
63
|
const states = new Map();
|
|
28
64
|
// Transient state — resets after every `make`/`create`.
|
|
29
65
|
let pendingOverrides = {};
|
|
66
|
+
// Recursive overrides are kept apart from the shallow `pendingOverrides`
|
|
67
|
+
// because they must deep-merge into `defaults()`, which only exists at build
|
|
68
|
+
// time — a shallow spread here would clobber a whole nested object.
|
|
69
|
+
let pendingRecursive = {};
|
|
30
70
|
let pendingStates = [];
|
|
71
|
+
// Relations: persistent factory resolvers keyed by relation name, plus the
|
|
72
|
+
// transient `.with()` queue consumed by create()/createMany().
|
|
73
|
+
const relations = new Map();
|
|
74
|
+
let pendingWith = [];
|
|
75
|
+
// Transient `.tap()` callbacks run on the built instance before persistence.
|
|
76
|
+
let pendingTap = [];
|
|
77
|
+
// Persistent connection bound via `.client()`/`.connection()`, used when
|
|
78
|
+
// create()/createMany() are called without an explicit `db`.
|
|
79
|
+
let boundClient;
|
|
80
|
+
/** The connection to persist through: the explicit arg wins over the bound one. */
|
|
81
|
+
const resolveConnection = (db) => {
|
|
82
|
+
const conn = db ?? boundClient;
|
|
83
|
+
if (!conn) {
|
|
84
|
+
throw new Error(`Factory ${entityClass.name}: no connection — pass one to create()/createMany() or bind one with .client()/.connection().`);
|
|
85
|
+
}
|
|
86
|
+
return conn;
|
|
87
|
+
};
|
|
88
|
+
// Primary-key property, resolved once, for stub-id assignment. Same fallback
|
|
89
|
+
// as BaseRepository so a model without an explicit `@PrimaryKey` uses `id`.
|
|
90
|
+
const primaryKey = getPrimaryKey(entityClass) ?? "id";
|
|
91
|
+
/** Hydrate a fresh (not-yet-persisted) instance from a data object. */
|
|
92
|
+
const newInstance = (data) => {
|
|
93
|
+
const entity = new entityClass();
|
|
94
|
+
for (const [key, value] of Object.entries(data)) {
|
|
95
|
+
entity.setProp(key, value);
|
|
96
|
+
}
|
|
97
|
+
return entity;
|
|
98
|
+
};
|
|
99
|
+
/** Build a stubbed instance: hydrate, run taps, give it a stub id if none was
|
|
100
|
+
* supplied, then mark persisted so it mirrors a fetched row. Taps run before
|
|
101
|
+
* `markAsPersisted` so tapped fields land in the clean snapshot. */
|
|
102
|
+
const stub = (data, taps) => {
|
|
103
|
+
const entity = newInstance(data);
|
|
104
|
+
for (const tap of taps)
|
|
105
|
+
tap(entity);
|
|
106
|
+
if (data[primaryKey] === undefined) {
|
|
107
|
+
entity.setProp(primaryKey, ++stubIdCounter);
|
|
108
|
+
}
|
|
109
|
+
entity.markAsPersisted();
|
|
110
|
+
return entity;
|
|
111
|
+
};
|
|
31
112
|
const buildData = () => {
|
|
32
|
-
|
|
33
|
-
...defaults(),
|
|
113
|
+
let data = {
|
|
114
|
+
...defaults({ faker }),
|
|
34
115
|
...pendingOverrides,
|
|
35
116
|
};
|
|
117
|
+
// Deep overrides layer on top of the shallow one so nested defaults survive.
|
|
118
|
+
if (Object.keys(pendingRecursive).length > 0) {
|
|
119
|
+
data = deepMerge(data, pendingRecursive);
|
|
120
|
+
}
|
|
36
121
|
for (const name of pendingStates) {
|
|
37
122
|
const fn = states.get(name);
|
|
38
123
|
if (!fn)
|
|
@@ -43,13 +128,77 @@ export function factory(entityClass, defaults) {
|
|
|
43
128
|
};
|
|
44
129
|
const resetPending = () => {
|
|
45
130
|
pendingOverrides = {};
|
|
131
|
+
pendingRecursive = {};
|
|
46
132
|
pendingStates = [];
|
|
133
|
+
pendingTap = [];
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Persist one row. With no taps this is the plain `repo.create(data)` path,
|
|
137
|
+
* untouched. With taps, the instance is built, tapped, then saved — so a tap
|
|
138
|
+
* can mutate the model before the INSERT (Adonis Lucid `.tap`). `save` on a
|
|
139
|
+
* fresh instance runs the same create hooks as `create`.
|
|
140
|
+
*/
|
|
141
|
+
const persist = async (repo, data, taps) => {
|
|
142
|
+
if (taps.length === 0)
|
|
143
|
+
return repo.create(data);
|
|
144
|
+
const entity = newInstance(data);
|
|
145
|
+
for (const tap of taps)
|
|
146
|
+
tap(entity);
|
|
147
|
+
await repo.save(entity);
|
|
148
|
+
return entity;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Persist the queued `.with()` relations for one just-created parent, routing
|
|
152
|
+
* through the parent's relation proxy so the FK / pivot is wired by the
|
|
153
|
+
* already-tested relation-write code (not re-derived here).
|
|
154
|
+
*/
|
|
155
|
+
const applyRelations = async (parent, reqs, db) => {
|
|
156
|
+
const meta = getRelationMetadata(entityClass);
|
|
157
|
+
for (const req of reqs) {
|
|
158
|
+
const relMeta = meta.find((r) => r.propertyKey === req.name);
|
|
159
|
+
if (!relMeta) {
|
|
160
|
+
throw new Error(`Factory .with('${req.name}'): '${req.name}' is not a declared relation on ${entityClass.name}`);
|
|
161
|
+
}
|
|
162
|
+
const resolver = relations.get(req.name);
|
|
163
|
+
if (!resolver) {
|
|
164
|
+
throw new Error(`Factory .with('${req.name}'): no related factory — declare it with .relation('${req.name}', () => XFactory)`);
|
|
165
|
+
}
|
|
166
|
+
const childFactory = resolver();
|
|
167
|
+
if (req.callback)
|
|
168
|
+
req.callback(childFactory);
|
|
169
|
+
const proxy = parent.related(req.name);
|
|
170
|
+
if (proxy.type === "hasMany") {
|
|
171
|
+
await proxy.createMany(childFactory.makeMany(req.count));
|
|
172
|
+
}
|
|
173
|
+
else if (proxy.type === "hasOne") {
|
|
174
|
+
await proxy.create(childFactory.make());
|
|
175
|
+
}
|
|
176
|
+
else if (proxy.type === "manyToMany") {
|
|
177
|
+
// The m2m proxy's create() inserts the related row AND the pivot link.
|
|
178
|
+
for (const row of childFactory.makeMany(req.count)) {
|
|
179
|
+
await proxy.create(row);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else if (proxy.type === "belongsTo") {
|
|
183
|
+
// FK lives on the parent: create the owner, then associate re-saves
|
|
184
|
+
// the parent with the FK set.
|
|
185
|
+
const owner = await childFactory.create(db);
|
|
186
|
+
await proxy.associate(owner);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
throw new Error(`Factory .with('${req.name}'): '${relMeta.type}' relations are not supported`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
47
192
|
};
|
|
48
193
|
const builder = {
|
|
49
194
|
merge(overrides) {
|
|
50
195
|
pendingOverrides = { ...pendingOverrides, ...overrides };
|
|
51
196
|
return builder;
|
|
52
197
|
},
|
|
198
|
+
mergeRecursive(overrides) {
|
|
199
|
+
pendingRecursive = deepMerge(pendingRecursive, overrides);
|
|
200
|
+
return builder;
|
|
201
|
+
},
|
|
53
202
|
state(name, fn) {
|
|
54
203
|
states.set(name, fn);
|
|
55
204
|
return builder;
|
|
@@ -58,6 +207,30 @@ export function factory(entityClass, defaults) {
|
|
|
58
207
|
pendingStates.push(...names);
|
|
59
208
|
return builder;
|
|
60
209
|
},
|
|
210
|
+
relation(name, resolver) {
|
|
211
|
+
relations.set(name, resolver);
|
|
212
|
+
return builder;
|
|
213
|
+
},
|
|
214
|
+
with(name, count = 1, callback) {
|
|
215
|
+
pendingWith.push({ name, count, callback });
|
|
216
|
+
return builder;
|
|
217
|
+
},
|
|
218
|
+
tap(fn) {
|
|
219
|
+
pendingTap.push(fn);
|
|
220
|
+
return builder;
|
|
221
|
+
},
|
|
222
|
+
client(connection) {
|
|
223
|
+
boundClient = connection;
|
|
224
|
+
return builder;
|
|
225
|
+
},
|
|
226
|
+
connection(name) {
|
|
227
|
+
const conn = getConnection(name);
|
|
228
|
+
if (!conn) {
|
|
229
|
+
throw new Error(`Factory ${entityClass.name}: no connection registered under '${name}'.`);
|
|
230
|
+
}
|
|
231
|
+
boundClient = conn;
|
|
232
|
+
return builder;
|
|
233
|
+
},
|
|
61
234
|
make() {
|
|
62
235
|
const data = buildData();
|
|
63
236
|
resetPending();
|
|
@@ -75,25 +248,51 @@ export function factory(entityClass, defaults) {
|
|
|
75
248
|
return rows;
|
|
76
249
|
},
|
|
77
250
|
makeStubbed() {
|
|
251
|
+
const taps = pendingTap;
|
|
78
252
|
const data = buildData();
|
|
253
|
+
const entity = stub(data, taps);
|
|
79
254
|
resetPending();
|
|
80
|
-
const entity = new entityClass();
|
|
81
|
-
for (const [key, value] of Object.entries(data)) {
|
|
82
|
-
entity.setProp(key, value);
|
|
83
|
-
}
|
|
84
255
|
return entity;
|
|
85
256
|
},
|
|
257
|
+
makeStubbedMany(count) {
|
|
258
|
+
// Re-evaluate defaults per row (distinct Date.now()/faker values), same
|
|
259
|
+
// as makeMany; each row then gets its own stub id + taps via `stub`.
|
|
260
|
+
const taps = pendingTap;
|
|
261
|
+
const rows = [];
|
|
262
|
+
for (let i = 0; i < count; i++) {
|
|
263
|
+
rows.push(stub(buildData(), taps));
|
|
264
|
+
}
|
|
265
|
+
resetPending();
|
|
266
|
+
return rows;
|
|
267
|
+
},
|
|
86
268
|
async create(db) {
|
|
269
|
+
const conn = resolveConnection(db);
|
|
270
|
+
// Capture + clear the relation/tap queues before make() (which resets
|
|
271
|
+
// pending state) so they aren't lost and a later create() starts clean.
|
|
272
|
+
const withReqs = pendingWith;
|
|
273
|
+
pendingWith = [];
|
|
274
|
+
const taps = pendingTap;
|
|
87
275
|
const data = builder.make();
|
|
88
|
-
const repo = new BaseRepository(entityClass,
|
|
89
|
-
|
|
276
|
+
const repo = new BaseRepository(entityClass, conn);
|
|
277
|
+
const entity = await persist(repo, data, taps);
|
|
278
|
+
if (withReqs.length > 0)
|
|
279
|
+
await applyRelations(entity, withReqs, conn);
|
|
280
|
+
return entity;
|
|
90
281
|
},
|
|
91
282
|
async createMany(count, db) {
|
|
283
|
+
const conn = resolveConnection(db);
|
|
284
|
+
const withReqs = pendingWith;
|
|
285
|
+
pendingWith = [];
|
|
286
|
+
const taps = pendingTap;
|
|
92
287
|
const rows = builder.makeMany(count);
|
|
93
|
-
const repo = new BaseRepository(entityClass,
|
|
288
|
+
const repo = new BaseRepository(entityClass, conn);
|
|
94
289
|
const created = [];
|
|
95
290
|
for (const data of rows) {
|
|
96
|
-
|
|
291
|
+
const entity = await persist(repo, data, taps);
|
|
292
|
+
// Each created parent gets its own related rows (Lucid semantics).
|
|
293
|
+
if (withReqs.length > 0)
|
|
294
|
+
await applyRelations(entity, withReqs, conn);
|
|
295
|
+
created.push(entity);
|
|
97
296
|
}
|
|
98
297
|
return created;
|
|
99
298
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Factory.js","sourceRoot":"","sources":["../../src/testing/Factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"Factory.js","sourceRoot":"","sources":["../../src/testing/Factory.ts"],"names":[],"mappings":"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"}
|
package/index.darwin-arm64.node
CHANGED
|
Binary file
|
package/index.darwin-x64.node
CHANGED
|
Binary file
|
|
Binary file
|
package/index.linux-x64-gnu.node
CHANGED
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c9up/atlas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Atlas — Data Mapper ORM for the Ream framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
+
"@c9up/chronos": "^0.1.6",
|
|
43
|
+
"@faker-js/faker": "^9",
|
|
42
44
|
"reflect-metadata": "^0.2"
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Refuse a LOCAL `npm/pnpm publish`. Atlas ships prebuilt multi-platform NAPI
|
|
2
|
+
// binaries (index.<suffix>.node / db.<suffix>.node) that only the CI matrix
|
|
3
|
+
// assembles + downloads before publishing. A local publish would package
|
|
4
|
+
// whatever single-platform / stale `.node` files happen to be on disk, so the
|
|
5
|
+
// published tarball would be broken on every other platform. Publishing MUST go
|
|
6
|
+
// through the workflow_dispatch CI job (which sets CI=true).
|
|
7
|
+
if (!process.env.CI) {
|
|
8
|
+
console.error(
|
|
9
|
+
"@c9up/atlas: refusing a local publish.\n" +
|
|
10
|
+
"Publish only via the CI workflow — it builds and bundles the NAPI\n" +
|
|
11
|
+
"binaries for every platform. A local `npm publish` would ship\n" +
|
|
12
|
+
"incomplete/stale `.node` files. Run the publish workflow instead.",
|
|
13
|
+
);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
package/src/AtlasProvider.ts
CHANGED
|
@@ -81,6 +81,12 @@ export interface ConnectionConfig {
|
|
|
81
81
|
poolMin?: number;
|
|
82
82
|
/** Maximum pool connections (default: 10) */
|
|
83
83
|
poolMax?: number;
|
|
84
|
+
/**
|
|
85
|
+
* Emit a `db:query` event for every statement on this connection (Lucid's
|
|
86
|
+
* `debug` connection option). Off by default — subscribe with `onDbQuery`
|
|
87
|
+
* to receive them; with no subscriber nothing is emitted either way.
|
|
88
|
+
*/
|
|
89
|
+
debug?: boolean;
|
|
84
90
|
/**
|
|
85
91
|
* Connection-level pragmas (sqlite only). Each entry becomes a
|
|
86
92
|
* `PRAGMA <key> = <value>;` issued before the first query.
|
|
@@ -163,7 +169,7 @@ export default class AtlasProvider {
|
|
|
163
169
|
// leaks pools/sockets.
|
|
164
170
|
const entries = Object.entries(connections);
|
|
165
171
|
const results = await Promise.allSettled(
|
|
166
|
-
entries.map(([, settings]) =>
|
|
172
|
+
entries.map(([name, settings]) =>
|
|
167
173
|
createNapiConnection(
|
|
168
174
|
settings.url,
|
|
169
175
|
settings.poolMin ?? 1,
|
|
@@ -174,6 +180,7 @@ export default class AtlasProvider {
|
|
|
174
180
|
backoffMs: settings.connectBackoffMs,
|
|
175
181
|
timeoutMs: settings.connectTimeoutMs,
|
|
176
182
|
},
|
|
183
|
+
{ debug: settings.debug ?? false, connectionName: name },
|
|
177
184
|
),
|
|
178
185
|
),
|
|
179
186
|
);
|