@c9up/atlas 0.1.19 → 0.2.1

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 (250) hide show
  1. package/README.md +63 -14
  2. package/db.darwin-arm64.node +0 -0
  3. package/db.darwin-x64.node +0 -0
  4. package/db.linux-arm64-gnu.node +0 -0
  5. package/db.linux-x64-gnu.node +0 -0
  6. package/db.win32-x64-msvc.node +0 -0
  7. package/dist/AtlasProvider.d.ts +66 -7
  8. package/dist/AtlasProvider.d.ts.map +1 -1
  9. package/dist/AtlasProvider.js +205 -39
  10. package/dist/AtlasProvider.js.map +1 -1
  11. package/dist/BaseEntity.d.ts +181 -5
  12. package/dist/BaseEntity.d.ts.map +1 -1
  13. package/dist/BaseEntity.js +339 -33
  14. package/dist/BaseEntity.js.map +1 -1
  15. package/dist/BaseModel.d.ts +127 -0
  16. package/dist/BaseModel.d.ts.map +1 -0
  17. package/dist/BaseModel.js +250 -0
  18. package/dist/BaseModel.js.map +1 -0
  19. package/dist/BaseRepository.d.ts +81 -15
  20. package/dist/BaseRepository.d.ts.map +1 -1
  21. package/dist/BaseRepository.js +1433 -387
  22. package/dist/BaseRepository.js.map +1 -1
  23. package/dist/ConnectionManager.d.ts +106 -0
  24. package/dist/ConnectionManager.d.ts.map +1 -0
  25. package/dist/ConnectionManager.js +228 -0
  26. package/dist/ConnectionManager.js.map +1 -0
  27. package/dist/ModelQuery.d.ts +577 -41
  28. package/dist/ModelQuery.d.ts.map +1 -1
  29. package/dist/ModelQuery.js +2188 -291
  30. package/dist/ModelQuery.js.map +1 -1
  31. package/dist/Transaction.d.ts +71 -1
  32. package/dist/Transaction.d.ts.map +1 -1
  33. package/dist/Transaction.js +138 -24
  34. package/dist/Transaction.js.map +1 -1
  35. package/dist/adapters/NapiDbAdapter.d.ts +44 -4
  36. package/dist/adapters/NapiDbAdapter.d.ts.map +1 -1
  37. package/dist/adapters/NapiDbAdapter.js +131 -13
  38. package/dist/adapters/NapiDbAdapter.js.map +1 -1
  39. package/dist/console/contract.d.ts +62 -0
  40. package/dist/console/contract.d.ts.map +1 -0
  41. package/dist/console/contract.js +38 -0
  42. package/dist/console/contract.js.map +1 -0
  43. package/dist/console/factoryCommands.d.ts +23 -0
  44. package/dist/console/factoryCommands.d.ts.map +1 -0
  45. package/dist/console/factoryCommands.js +62 -0
  46. package/dist/console/factoryCommands.js.map +1 -0
  47. package/dist/console/migrationCommands.d.ts +78 -0
  48. package/dist/console/migrationCommands.d.ts.map +1 -0
  49. package/dist/console/migrationCommands.js +327 -0
  50. package/dist/console/migrationCommands.js.map +1 -0
  51. package/dist/console/schemaCheckCommand.d.ts +11 -17
  52. package/dist/console/schemaCheckCommand.d.ts.map +1 -1
  53. package/dist/console/schemaCheckCommand.js +21 -15
  54. package/dist/console/schemaCheckCommand.js.map +1 -1
  55. package/dist/console/schemaDumpCommand.d.ts +30 -0
  56. package/dist/console/schemaDumpCommand.d.ts.map +1 -0
  57. package/dist/console/schemaDumpCommand.js +69 -0
  58. package/dist/console/schemaDumpCommand.js.map +1 -0
  59. package/dist/console/schemaGenerateCommand.d.ts +100 -0
  60. package/dist/console/schemaGenerateCommand.d.ts.map +1 -0
  61. package/dist/console/schemaGenerateCommand.js +246 -0
  62. package/dist/console/schemaGenerateCommand.js.map +1 -0
  63. package/dist/console/seederCommands.d.ts +46 -0
  64. package/dist/console/seederCommands.d.ts.map +1 -0
  65. package/dist/console/seederCommands.js +136 -0
  66. package/dist/console/seederCommands.js.map +1 -0
  67. package/dist/decorators/entity.d.ts +50 -8
  68. package/dist/decorators/entity.d.ts.map +1 -1
  69. package/dist/decorators/entity.js +42 -2
  70. package/dist/decorators/entity.js.map +1 -1
  71. package/dist/decorators/hooks.d.ts +3 -3
  72. package/dist/decorators/hooks.d.ts.map +1 -1
  73. package/dist/decorators/hooks.js.map +1 -1
  74. package/dist/events.d.ts +69 -0
  75. package/dist/events.d.ts.map +1 -0
  76. package/dist/events.js +82 -0
  77. package/dist/events.js.map +1 -0
  78. package/dist/factories.d.ts +8 -0
  79. package/dist/factories.d.ts.map +1 -0
  80. package/dist/factories.js +8 -0
  81. package/dist/factories.js.map +1 -0
  82. package/dist/index.d.ts +15 -5
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +14 -3
  85. package/dist/index.js.map +1 -1
  86. package/dist/lucid-schema.d.ts +15 -0
  87. package/dist/lucid-schema.d.ts.map +1 -0
  88. package/dist/lucid-schema.js +16 -0
  89. package/dist/lucid-schema.js.map +1 -0
  90. package/dist/metadata-keys.d.ts +3 -2
  91. package/dist/metadata-keys.d.ts.map +1 -1
  92. package/dist/naming/NamingStrategy.d.ts +7 -0
  93. package/dist/naming/NamingStrategy.d.ts.map +1 -1
  94. package/dist/naming/NamingStrategy.js +16 -0
  95. package/dist/naming/NamingStrategy.js.map +1 -1
  96. package/dist/orm.d.ts +14 -0
  97. package/dist/orm.d.ts.map +1 -0
  98. package/dist/orm.js +14 -0
  99. package/dist/orm.js.map +1 -0
  100. package/dist/query/DatabaseQueryBuilder.d.ts +557 -0
  101. package/dist/query/DatabaseQueryBuilder.d.ts.map +1 -0
  102. package/dist/query/DatabaseQueryBuilder.js +1798 -0
  103. package/dist/query/DatabaseQueryBuilder.js.map +1 -0
  104. package/dist/query/DmlBuilder.d.ts +62 -0
  105. package/dist/query/DmlBuilder.d.ts.map +1 -0
  106. package/dist/query/DmlBuilder.js +84 -0
  107. package/dist/query/DmlBuilder.js.map +1 -0
  108. package/dist/query/QueryBuilder.d.ts +5 -0
  109. package/dist/query/QueryBuilder.d.ts.map +1 -1
  110. package/dist/query/QueryBuilder.js +7 -0
  111. package/dist/query/QueryBuilder.js.map +1 -1
  112. package/dist/query/RawQueryBuilder.d.ts +47 -0
  113. package/dist/query/RawQueryBuilder.d.ts.map +1 -0
  114. package/dist/query/RawQueryBuilder.js +138 -0
  115. package/dist/query/RawQueryBuilder.js.map +1 -0
  116. package/dist/query/interpolate.d.ts +45 -0
  117. package/dist/query/interpolate.d.ts.map +1 -0
  118. package/dist/query/interpolate.js +51 -0
  119. package/dist/query/interpolate.js.map +1 -0
  120. package/dist/query/native.d.ts +8 -0
  121. package/dist/query/native.d.ts.map +1 -1
  122. package/dist/query/native.js +14 -0
  123. package/dist/query/native.js.map +1 -1
  124. package/dist/query/operators.d.ts +4 -0
  125. package/dist/query/operators.d.ts.map +1 -0
  126. package/dist/query/operators.js +27 -0
  127. package/dist/query/operators.js.map +1 -0
  128. package/dist/schema/Migration.d.ts +50 -3
  129. package/dist/schema/Migration.d.ts.map +1 -1
  130. package/dist/schema/Migration.js +60 -24
  131. package/dist/schema/Migration.js.map +1 -1
  132. package/dist/schema/MigrationRunner.d.ts +95 -34
  133. package/dist/schema/MigrationRunner.d.ts.map +1 -1
  134. package/dist/schema/MigrationRunner.js +523 -68
  135. package/dist/schema/MigrationRunner.js.map +1 -1
  136. package/dist/schema/Schema.d.ts +114 -0
  137. package/dist/schema/Schema.d.ts.map +1 -1
  138. package/dist/schema/Schema.js +272 -3
  139. package/dist/schema/Schema.js.map +1 -1
  140. package/dist/schema/SchemaDumper.d.ts +121 -0
  141. package/dist/schema/SchemaDumper.d.ts.map +1 -0
  142. package/dist/schema/SchemaDumper.js +365 -0
  143. package/dist/schema/SchemaDumper.js.map +1 -0
  144. package/dist/schema/Seeder.d.ts +13 -0
  145. package/dist/schema/Seeder.d.ts.map +1 -1
  146. package/dist/schema/Seeder.js +28 -5
  147. package/dist/schema/Seeder.js.map +1 -1
  148. package/dist/schema/TableBuilder.d.ts +274 -16
  149. package/dist/schema/TableBuilder.d.ts.map +1 -1
  150. package/dist/schema/TableBuilder.js +656 -52
  151. package/dist/schema/TableBuilder.js.map +1 -1
  152. package/dist/schema/catalog.d.ts +71 -0
  153. package/dist/schema/catalog.d.ts.map +1 -0
  154. package/dist/schema/catalog.js +158 -0
  155. package/dist/schema/catalog.js.map +1 -0
  156. package/dist/schema/introspect.d.ts +1 -1
  157. package/dist/schema/introspect.d.ts.map +1 -1
  158. package/dist/schema/introspect.js +26 -11
  159. package/dist/schema/introspect.js.map +1 -1
  160. package/dist/schema/types.d.ts +150 -1
  161. package/dist/schema/types.d.ts.map +1 -1
  162. package/dist/schema/types.js +11 -0
  163. package/dist/schema/types.js.map +1 -1
  164. package/dist/seeders.d.ts +7 -0
  165. package/dist/seeders.d.ts.map +1 -0
  166. package/dist/seeders.js +7 -0
  167. package/dist/seeders.js.map +1 -0
  168. package/dist/services/db.d.ts +122 -5
  169. package/dist/services/db.d.ts.map +1 -1
  170. package/dist/services/db.js +187 -14
  171. package/dist/services/db.js.map +1 -1
  172. package/dist/testing/DatabaseCleanup.d.ts +33 -7
  173. package/dist/testing/DatabaseCleanup.d.ts.map +1 -1
  174. package/dist/testing/DatabaseCleanup.js +54 -24
  175. package/dist/testing/DatabaseCleanup.js.map +1 -1
  176. package/dist/testing/DbAssertions.d.ts +48 -0
  177. package/dist/testing/DbAssertions.d.ts.map +1 -0
  178. package/dist/testing/DbAssertions.js +80 -0
  179. package/dist/testing/DbAssertions.js.map +1 -0
  180. package/dist/testing/Factory.d.ts +166 -15
  181. package/dist/testing/Factory.d.ts.map +1 -1
  182. package/dist/testing/Factory.js +497 -23
  183. package/dist/testing/Factory.js.map +1 -1
  184. package/dist/testing/TestUtils.d.ts +49 -0
  185. package/dist/testing/TestUtils.d.ts.map +1 -0
  186. package/dist/testing/TestUtils.js +79 -0
  187. package/dist/testing/TestUtils.js.map +1 -0
  188. package/dist/testing/index.d.ts +3 -1
  189. package/dist/testing/index.d.ts.map +1 -1
  190. package/dist/testing/index.js +3 -1
  191. package/dist/testing/index.js.map +1 -1
  192. package/dist/types/relations.d.ts +31 -0
  193. package/dist/types/relations.d.ts.map +1 -0
  194. package/dist/types/relations.js +20 -0
  195. package/dist/types/relations.js.map +1 -0
  196. package/index.darwin-arm64.node +0 -0
  197. package/index.darwin-x64.node +0 -0
  198. package/index.linux-arm64-gnu.node +0 -0
  199. package/index.linux-x64-gnu.node +0 -0
  200. package/index.win32-x64-msvc.node +0 -0
  201. package/package.json +32 -2
  202. package/scripts/guard-publish.mjs +15 -0
  203. package/src/AtlasProvider.ts +305 -52
  204. package/src/BaseEntity.ts +460 -41
  205. package/src/BaseModel.ts +461 -0
  206. package/src/BaseRepository.ts +1710 -421
  207. package/src/ConnectionManager.ts +298 -0
  208. package/src/ModelQuery.ts +2998 -335
  209. package/src/Transaction.ts +227 -30
  210. package/src/adapters/NapiDbAdapter.ts +224 -17
  211. package/src/console/contract.ts +96 -0
  212. package/src/console/factoryCommands.ts +73 -0
  213. package/src/console/migrationCommands.ts +448 -0
  214. package/src/console/schemaCheckCommand.ts +26 -22
  215. package/src/console/schemaDumpCommand.ts +96 -0
  216. package/src/console/schemaGenerateCommand.ts +380 -0
  217. package/src/console/seederCommands.ts +174 -0
  218. package/src/decorators/entity.ts +71 -8
  219. package/src/decorators/hooks.ts +5 -3
  220. package/src/events.ts +117 -0
  221. package/src/factories.ts +10 -0
  222. package/src/index.ts +69 -3
  223. package/src/lucid-schema.ts +22 -0
  224. package/src/metadata-keys.ts +3 -2
  225. package/src/naming/NamingStrategy.ts +23 -0
  226. package/src/orm.ts +13 -0
  227. package/src/query/DatabaseQueryBuilder.ts +2724 -0
  228. package/src/query/DmlBuilder.ts +131 -0
  229. package/src/query/QueryBuilder.ts +8 -0
  230. package/src/query/RawQueryBuilder.ts +173 -0
  231. package/src/query/interpolate.ts +73 -0
  232. package/src/query/native.ts +29 -0
  233. package/src/query/operators.ts +27 -0
  234. package/src/schema/Migration.ts +71 -3
  235. package/src/schema/MigrationRunner.ts +676 -69
  236. package/src/schema/Schema.ts +359 -3
  237. package/src/schema/SchemaDumper.ts +518 -0
  238. package/src/schema/Seeder.ts +47 -10
  239. package/src/schema/TableBuilder.ts +783 -52
  240. package/src/schema/catalog.ts +236 -0
  241. package/src/schema/introspect.ts +26 -9
  242. package/src/schema/types.ts +137 -2
  243. package/src/seeders.ts +16 -0
  244. package/src/services/db.ts +361 -21
  245. package/src/testing/DatabaseCleanup.ts +78 -25
  246. package/src/testing/DbAssertions.ts +127 -0
  247. package/src/testing/Factory.ts +837 -40
  248. package/src/testing/TestUtils.ts +123 -0
  249. package/src/testing/index.ts +12 -1
  250. package/src/types/relations.ts +43 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * `db()` — a helix plugin (AdonisJS Lucid database-assertions parity) that
3
+ * injects database assertions on the test context as `ctx.db`:
4
+ *
5
+ * // tests/bootstrap.ts
6
+ * import { configure } from "@c9up/helix";
7
+ * import { db } from "@c9up/atlas/testing";
8
+ * await configure({ plugins: [db(connection)] });
9
+ *
10
+ * test("registers the user", async ({ db }) => {
11
+ * await db.assertHas("users", { email: "a@b.c" });
12
+ * await db.assertCount("users", 1);
13
+ * });
14
+ *
15
+ * Values are always bound as parameters; table/column identifiers are validated
16
+ * against a strict pattern (letters, digits, `_`, `.`) and quoted, so neither a
17
+ * value nor an identifier can inject SQL.
18
+ *
19
+ * NOTE (namespace): the AdonisJS docs expose these as `db.assert*`; the exact
20
+ * surface is re-verified against the Adonis docs when available. Model-based
21
+ * `assertModelExists`/`assertModelMissing` (entity PK metadata) are pending.
22
+ */
23
+ /** Reject identifiers that could break out of the quoted context. */
24
+ function quoteIdent(name) {
25
+ if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(name)) {
26
+ throw new Error(`db assertion: unsafe identifier ${JSON.stringify(name)}`);
27
+ }
28
+ return `"${name.replace(/\./g, '"."')}"`;
29
+ }
30
+ async function countRows(conn, table, payload) {
31
+ let where = "";
32
+ let params = [];
33
+ if (payload) {
34
+ const keys = Object.keys(payload);
35
+ if (keys.length > 0) {
36
+ where = ` WHERE ${keys.map((k) => `${quoteIdent(k)} = ?`).join(" AND ")}`;
37
+ params = keys.map((k) => payload[k]);
38
+ }
39
+ }
40
+ const rows = await conn.query(`SELECT COUNT(*) AS c FROM ${quoteIdent(table)}${where}`, params);
41
+ return Number(rows[0]?.c ?? 0);
42
+ }
43
+ /** Build the assertion surface bound to a connection. */
44
+ export function createDbAssertions(conn) {
45
+ return {
46
+ async assertHas(table, payload) {
47
+ const n = await countRows(conn, table, payload);
48
+ if (n === 0) {
49
+ throw new Error(`Expected "${table}" to have a row matching ${JSON.stringify(payload)}, found none.`);
50
+ }
51
+ },
52
+ async assertMissing(table, payload) {
53
+ const n = await countRows(conn, table, payload);
54
+ if (n > 0) {
55
+ throw new Error(`Expected "${table}" to have NO row matching ${JSON.stringify(payload)}, found ${n}.`);
56
+ }
57
+ },
58
+ async assertCount(table, expected, payload) {
59
+ const n = await countRows(conn, table, payload);
60
+ if (n !== expected) {
61
+ const scope = payload ? ` matching ${JSON.stringify(payload)}` : "";
62
+ throw new Error(`Expected "${table}" to have ${expected} row(s)${scope}, found ${n}.`);
63
+ }
64
+ },
65
+ async assertEmpty(table) {
66
+ const n = await countRows(conn, table);
67
+ if (n > 0) {
68
+ throw new Error(`Expected "${table}" to be empty, found ${n} row(s).`);
69
+ }
70
+ },
71
+ };
72
+ }
73
+ /** The `db()` helix plugin — registers {@link DbAssertions} as `ctx.db`. */
74
+ export function db(conn) {
75
+ const assertions = createDbAssertions(conn);
76
+ return (api) => {
77
+ api.context.macro("db", assertions);
78
+ };
79
+ }
80
+ //# sourceMappingURL=DbAssertions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DbAssertions.js","sourceRoot":"","sources":["../../src/testing/DbAssertions.ts"],"names":[],"mappings":"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"}
@@ -13,16 +13,58 @@
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;
19
- /** A named state mutates an in-progress data object in place. */
20
- type StateFn<D> = (data: D) => void;
20
+ /** Resolves the factory that builds a related model (Lucid `.relation`). */
21
+ type RelationResolver = () => FactoryBuilder<BaseEntity>;
22
+ /**
23
+ * Runtime context handed to the factory callbacks (Adonis Lucid parity):
24
+ * `faker` for fake data, `isStubbed` (true during a `makeStubbed*` build), and
25
+ * `$trx` — the bound transaction/connection, if any, so a hook's own DB queries
26
+ * commit/roll back alongside the factory. A callback that ignores it keeps
27
+ * working.
28
+ */
29
+ export interface FactoryContext {
30
+ faker: Faker;
31
+ isStubbed: boolean;
32
+ $trx?: DatabaseConnection;
33
+ }
34
+ /** Attributes callback — receives {@link FactoryContext}, returns the row shape. */
35
+ type DefaultsFn = (ctx: FactoryContext) => Record<string, unknown>;
36
+ /**
37
+ * A named state — mutates the built model INSTANCE (Adonis Lucid: states receive
38
+ * the instance + runtime context, not a raw data object).
39
+ */
40
+ type StateFn<T extends BaseEntity> = (model: T, ctx: FactoryContext) => void;
41
+ /**
42
+ * A `merge` callback (Adonis Lucid) — receives the built model INSTANCE, the
43
+ * resolved attributes, and the runtime context, e.g.
44
+ * `.merge((user, attributes) => { user.merge(attributes) })`.
45
+ */
46
+ type MergeFn<T extends BaseEntity> = (model: T, attributes: Record<string, unknown>, ctx: FactoryContext) => void;
21
47
  export interface FactoryBuilder<T extends BaseEntity> {
22
- /** Override specific fields for the next call (reset after consumption). */
23
- merge(overrides: Partial<Record<string, unknown>>): FactoryBuilder<T>;
24
- /** Declare a named variation of this factory, stored on the factory's state map. */
25
- state(name: string, fn: StateFn<Record<string, unknown>>): FactoryBuilder<T>;
48
+ /**
49
+ * Override specific fields for the next call (reset after consumption). Pass an
50
+ * object to shallow-merge, a CALLBACK to mutate the resolved attributes
51
+ * imperatively (Adonis Lucid `merge`), or an ARRAY to override per row on
52
+ * `makeMany`/`createMany` — `merge([{a:1},{a:2}]).createMany(2)` applies index
53
+ * `i` to row `i` (rows past the array length keep the plain defaults).
54
+ */
55
+ merge(overrides: Partial<Record<string, unknown>> | MergeFn<T> | Array<Partial<Record<string, unknown>>>): FactoryBuilder<T>;
56
+ /**
57
+ * Like {@link merge} but deep — nested plain objects are merged key by key
58
+ * instead of replaced wholesale (Lucid `mergeRecursive`). Arrays and
59
+ * non-plain values still replace. Reset after consumption like `merge`.
60
+ */
61
+ mergeRecursive(overrides: Partial<Record<string, unknown>>): FactoryBuilder<T>;
62
+ /**
63
+ * Declare a named variation. The callback receives the built model INSTANCE
64
+ * and the runtime context (Adonis Lucid `state`), e.g.
65
+ * `.state('admin', (user) => { user.role = 'admin' })`.
66
+ */
67
+ state(name: string, fn: StateFn<T>): FactoryBuilder<T>;
26
68
  /**
27
69
  * Activate one or more declared states for the NEXT build. Multiple applies
28
70
  * compose (all fire, in order). NOTE: this mutates the builder's shared
@@ -31,19 +73,107 @@ export interface FactoryBuilder<T extends BaseEntity> {
31
73
  * (audit 2026-06-13). `merge()` behaves the same way.
32
74
  */
33
75
  apply(...stateNames: string[]): FactoryBuilder<T>;
34
- /** Create and persist a single entity (fires lifecycle hooks via `repo.create`). */
35
- create(db: DatabaseConnection): Promise<T>;
76
+ /**
77
+ * Bind a connection (e.g. a transaction) used by subsequent
78
+ * `create`/`createMany` calls that pass no explicit `db` (Adonis Lucid
79
+ * `.client`). The binding persists until changed. Ideal for test isolation:
80
+ * `factory.client(trx).create()`.
81
+ */
82
+ client(connection: DatabaseConnection): FactoryBuilder<T>;
83
+ /**
84
+ * Like {@link client} but resolves a connection registered under `name` via
85
+ * atlas's connection registry (Adonis Lucid `.connection`). Throws if no
86
+ * connection is registered under that name.
87
+ */
88
+ connection(name: string): FactoryBuilder<T>;
89
+ /**
90
+ * Create and persist a single entity (fires lifecycle hooks via
91
+ * `repo.create`). `db` is optional when a connection was bound with
92
+ * {@link client} / {@link connection}.
93
+ */
94
+ create(db?: DatabaseConnection): Promise<T>;
36
95
  /** Create and persist multiple entities (fires hooks per row). */
37
- createMany(count: number, db: DatabaseConnection): Promise<T[]>;
38
- /** Build the data object without persisting and without instantiating an entity. */
39
- make(): Record<string, unknown>;
40
- /** Build multiple data objects without persisting. */
41
- makeMany(count: number): Record<string, unknown>[];
96
+ createMany(count: number, db?: DatabaseConnection): Promise<T[]>;
97
+ /**
98
+ * Build an entity INSTANCE without persisting it (Adonis Lucid `make`). The
99
+ * instance has NO primary key and `$isPersisted === false` — use it to
100
+ * exercise model logic (computed props, validation) with no DB round trip.
101
+ * For an instance that looks persisted (stub id, `$isPersisted === true`),
102
+ * use {@link makeStubbed}.
103
+ */
104
+ make(): T;
105
+ /** Build many un-persisted instances (Adonis Lucid `makeMany`). */
106
+ makeMany(count: number): T[];
42
107
  /**
43
108
  * Build an entity INSTANCE without persisting it (Lucid's `makeStubbed`).
44
- * Useful when you need a `new User()` object but want to avoid the DB.
109
+ * The instance is marked persisted and, unless the build already supplied a
110
+ * primary key, given a process-unique stub id — so it looks like a saved row
111
+ * (relations, serialization, `$isPersisted`) without touching the DB.
45
112
  */
46
113
  makeStubbed(): T;
114
+ /** Build many stubbed instances, each with its own stub id ({@link makeStubbed}). */
115
+ makeStubbedMany(count: number): T[];
116
+ /**
117
+ * Declare which factory builds a relation (Adonis Lucid `.relation`), so
118
+ * `.with(name)` can create related rows. `name` must match a relation
119
+ * property declared with `@HasMany`/`@HasOne`/`@BelongsTo`/`@ManyToMany`.
120
+ */
121
+ relation(name: string, resolver: RelationResolver): FactoryBuilder<T>;
122
+ /**
123
+ * Queue related rows to create together with the next `create`/`createMany`
124
+ * (Adonis Lucid `.with`). `count` defaults to 1 (ignored past 1 for hasOne).
125
+ * The callback receives the related factory to customize it — `merge`/`apply`,
126
+ * `.pivotAttributes()` for m2m pivot columns, and its own nested `.with()`
127
+ * (arbitrarily deep, Adonis Lucid nested factories). `.with()` runs on
128
+ * persistence only — `make`/`makeStubbed` ignore it.
129
+ */
130
+ with(name: string, count?: number, callback?: (factory: FactoryBuilder<BaseEntity>) => void): FactoryBuilder<T>;
131
+ /**
132
+ * Register a callback that runs on the built entity INSTANCE (Adonis Lucid
133
+ * `.tap`). Receives the model, the runtime {@link FactoryContext}, and this
134
+ * factory builder. Multiple taps run in order, on every instance-producing
135
+ * path (`make`/`makeMany`/`create`/`createMany`/`makeStubbed*`); reset after
136
+ * consumption.
137
+ */
138
+ tap(fn: (model: T, ctx: FactoryContext, builder: FactoryBuilder<T>) => void): FactoryBuilder<T>;
139
+ /**
140
+ * Replace the default `new Model()` instantiation (Adonis Lucid `.newUp`).
141
+ * The callback receives the resolved attributes and the runtime context and
142
+ * returns the model instance to use for every subsequent build.
143
+ */
144
+ newUp(fn: (attributes: Record<string, unknown>, ctx: FactoryContext) => T): FactoryBuilder<T>;
145
+ /**
146
+ * Set pivot columns for the NEXT many-to-many `.with()` link (Adonis Lucid
147
+ * `.pivotAttributes`). Called on the RELATED factory inside a `.with()`
148
+ * callback; the values are written on the pivot row alongside the link. A
149
+ * single object applies to every linked row; pass an ARRAY for different
150
+ * values per row (its length should match the related-row count).
151
+ */
152
+ pivotAttributes(attrs: Record<string, unknown> | Array<Record<string, unknown>>): FactoryBuilder<T>;
153
+ /**
154
+ * Bind the connection/transaction for subsequent `create`/`createMany` via an
155
+ * options object (Adonis Lucid `.query({ client }) / .query({ connection })`).
156
+ * Sugar over {@link client} / {@link connection}; `client` wins over `connection`.
157
+ */
158
+ query(options: {
159
+ client?: DatabaseConnection;
160
+ connection?: string;
161
+ }): FactoryBuilder<T>;
162
+ /**
163
+ * Register a lifecycle hook that runs BEFORE the given event (Adonis Lucid
164
+ * factory `before`). `create` fires before the INSERT; `makeStubbed` fires
165
+ * before the stub is finalised (so it can assign the primary key). The
166
+ * callback receives the factory and the model instance. Persistent (declared
167
+ * once, applies to every build).
168
+ */
169
+ before(event: "create" | "makeStubbed", callback: (factory: FactoryBuilder<T>, model: T, ctx: FactoryContext) => void): FactoryBuilder<T>;
170
+ /**
171
+ * Register a lifecycle hook that runs AFTER the given event (Adonis Lucid
172
+ * factory `after`). `create` fires after the INSERT; `makeStubbed` after the
173
+ * stub is built. `make` fires after an un-persisted `make`/`makeMany` instance
174
+ * is built and tapped (Adonis Lucid `after('make')`). Persistent.
175
+ */
176
+ after(event: "make" | "create" | "makeStubbed", callback: (factory: FactoryBuilder<T>, model: T, ctx: FactoryContext) => void): FactoryBuilder<T>;
47
177
  }
48
178
  /**
49
179
  * Define a model factory.
@@ -53,6 +183,27 @@ export interface FactoryBuilder<T extends BaseEntity> {
53
183
  * name: 'Test User',
54
184
  * }))
55
185
  */
56
- export declare function factory<T extends BaseEntity>(entityClass: EntityConstructor<T>, defaults: () => Record<string, unknown>): FactoryBuilder<T>;
186
+ /**
187
+ * Adonis Lucid `Factory.define(Model, callback).build()` entry point. `define`
188
+ * captures the model and its defaults; `build()` returns the usable factory
189
+ * builder. Equivalent to the one-call {@link factory} shorthand, which stays.
190
+ *
191
+ * const UserFactory = Factory.define(User, ({ faker }) => ({
192
+ * email: faker.internet.email(),
193
+ * })).build()
194
+ */
195
+ export declare const Factory: {
196
+ define<T extends BaseEntity>(entityClass: EntityConstructor<T>, defaults: DefaultsFn): {
197
+ build(): FactoryBuilder<T>;
198
+ };
199
+ /**
200
+ * Override the global stub-id generator (Adonis Lucid `Factory.stubId`). Use
201
+ * when your models have non-integer primary keys — the callback receives the
202
+ * running counter and the instance and returns the id to assign. Pass
203
+ * `null`/nothing to restore the default incrementing integer.
204
+ */
205
+ stubId(generator?: ((counter: number, model: BaseEntity) => unknown) | null): void;
206
+ };
207
+ export declare function factory<T extends BaseEntity>(entityClass: EntityConstructor<T>, defaults: DefaultsFn): FactoryBuilder<T>;
57
208
  export {};
58
209
  //# 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;AAE/E,KAAK,iBAAiB,CAAC,CAAC,SAAS,UAAU,IAAI,UAAU,CAAC,CAAC;AAE3D,mEAAmE;AACnE,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;AAEpC,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,UAAU;IACnD,4EAA4E;IAC5E,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAEtE,oFAAoF;IACpF,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAE7E;;;;;;OAMG;IACH,KAAK,CAAC,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAElD,oFAAoF;IACpF,MAAM,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE3C,kEAAkE;IAClE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhE,oFAAoF;IACpF,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEhC,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAEnD;;;OAGG;IACH,WAAW,IAAI,CAAC,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,UAAU,EAC3C,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC,EACjC,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACrC,cAAc,CAAC,CAAC,CAAC,CA0FnB"}
1
+ {"version":3,"file":"Factory.d.ts","sourceRoot":"","sources":["../../src/testing/Factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,KAAK,EAAS,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAkB,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK/E,KAAK,iBAAiB,CAAC,CAAC,SAAS,UAAU,IAAI,UAAU,CAAC,CAAC;AAE3D,4EAA4E;AAC5E,KAAK,gBAAgB,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,CAAC;AAkCzD;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,kBAAkB,CAAC;CAC1B;AAED,oFAAoF;AACpF,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnE;;;GAGG;AACH,KAAK,OAAO,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;AA+C7E;;;;GAIG;AACH,KAAK,OAAO,CAAC,CAAC,SAAS,UAAU,IAAI,CACpC,KAAK,EAAE,CAAC,EACR,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,GAAG,EAAE,cAAc,KACf,IAAI,CAAC;AAEV,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,UAAU;IACnD;;;;;;OAMG;IACH,KAAK,CACJ,SAAS,EACN,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAChC,OAAO,CAAC,CAAC,CAAC,GACV,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GACxC,cAAc,CAAC,CAAC,CAAC,CAAC;IAErB;;;;OAIG;IACH,cAAc,CACb,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACzC,cAAc,CAAC,CAAC,CAAC,CAAC;IAErB;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAEvD;;;;;;OAMG;IACH,KAAK,CAAC,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAElD;;;;;OAKG;IACH,MAAM,CAAC,UAAU,EAAE,kBAAkB,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAE1D;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAE5C;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE5C,kEAAkE;IAClE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAEjE;;;;;;OAMG;IACH,IAAI,IAAI,CAAC,CAAC;IAEV,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;IAE7B;;;;;OAKG;IACH,WAAW,IAAI,CAAC,CAAC;IAEjB,qFAAqF;IACrF,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;IAEpC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAEtE;;;;;;;OAOG;IACH,IAAI,CACH,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,IAAI,GACtD,cAAc,CAAC,CAAC,CAAC,CAAC;IAErB;;;;;;OAMG;IACH,GAAG,CACF,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,GACrE,cAAc,CAAC,CAAC,CAAC,CAAC;IAErB;;;;OAIG;IACH,KAAK,CACJ,EAAE,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,cAAc,KAAK,CAAC,GACjE,cAAc,CAAC,CAAC,CAAC,CAAC;IAErB;;;;;;OAMG;IACH,eAAe,CACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC7D,cAAc,CAAC,CAAC,CAAC,CAAC;IAErB;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE;QACd,MAAM,CAAC,EAAE,kBAAkB,CAAC;QAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAEtB;;;;;;OAMG;IACH,MAAM,CACL,KAAK,EAAE,QAAQ,GAAG,aAAa,EAC/B,QAAQ,EAAE,CACT,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,KAAK,EAAE,CAAC,EACR,GAAG,EAAE,cAAc,KACf,IAAI,GACP,cAAc,CAAC,CAAC,CAAC,CAAC;IAErB;;;;;OAKG;IACH,KAAK,CACJ,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,aAAa,EACxC,QAAQ,EAAE,CACT,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAC1B,KAAK,EAAE,CAAC,EACR,GAAG,EAAE,cAAc,KACf,IAAI,GACP,cAAc,CAAC,CAAC,CAAC,CAAC;CACrB;AAED;;;;;;;GAOG;AACH;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO;WACZ,CAAC,SAAS,UAAU,eACb,iBAAiB,CAAC,CAAC,CAAC,YACvB,UAAU,GAClB;QAAE,KAAK,IAAI,cAAc,CAAC,CAAC,CAAC,CAAA;KAAE;IAIjC;;;;;OAKG;uBACgB,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,GAAG,IAAI;CAG3E,CAAC;AAEF,wBAAgB,OAAO,CAAC,CAAC,SAAS,UAAU,EAC3C,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC,EACjC,QAAQ,EAAE,UAAU,GAClB,cAAc,CAAC,CAAC,CAAC,CAslBnB"}