@c9up/atlas 0.3.5 → 0.3.7
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/db.win32-x64-msvc.node +0 -0
- package/dist/AtlasProvider.d.ts +53 -16
- package/dist/AtlasProvider.d.ts.map +1 -1
- package/dist/AtlasProvider.js +10 -3
- package/dist/AtlasProvider.js.map +1 -1
- package/dist/BaseRepository.d.ts.map +1 -1
- package/dist/BaseRepository.js +53 -0
- package/dist/BaseRepository.js.map +1 -1
- package/dist/adapters/NapiDbAdapter.d.ts.map +1 -1
- package/dist/adapters/NapiDbAdapter.js +10 -2
- package/dist/adapters/NapiDbAdapter.js.map +1 -1
- package/dist/configure.d.ts +1 -0
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +12 -1
- package/dist/configure.js.map +1 -1
- package/dist/console/index.d.ts +39 -0
- package/dist/console/index.d.ts.map +1 -0
- package/dist/console/index.js +144 -0
- package/dist/console/index.js.map +1 -0
- package/dist/console/migrationCommands.d.ts +12 -0
- package/dist/console/migrationCommands.d.ts.map +1 -1
- package/dist/console/migrationCommands.js +5 -0
- package/dist/console/migrationCommands.js.map +1 -1
- package/dist/console/schemaCheckCommand.d.ts +7 -5
- package/dist/console/schemaCheckCommand.d.ts.map +1 -1
- package/dist/console/schemaCheckCommand.js +16 -5
- package/dist/console/schemaCheckCommand.js.map +1 -1
- package/dist/decorators/entity.d.ts +38 -5
- package/dist/decorators/entity.d.ts.map +1 -1
- package/dist/decorators/entity.js +40 -9
- package/dist/decorators/entity.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/db.d.ts +24 -1
- package/dist/services/db.d.ts.map +1 -1
- package/dist/services/db.js +66 -0
- package/dist/services/db.js.map +1 -1
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +5 -1
- package/src/AtlasProvider.ts +66 -19
- package/src/BaseRepository.ts +57 -0
- package/src/adapters/NapiDbAdapter.ts +10 -2
- package/src/configure.ts +13 -1
- package/src/console/index.ts +202 -0
- package/src/console/migrationCommands.ts +17 -0
- package/src/console/schemaCheckCommand.ts +19 -6
- package/src/decorators/entity.ts +53 -12
- package/src/index.ts +1 -0
- package/src/services/db.ts +84 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/services/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/services/db.ts"],"names":[],"mappings":"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"}
|
package/dist/services/db.js
CHANGED
|
@@ -36,6 +36,72 @@ export function clearDb(connection) {
|
|
|
36
36
|
export function getDb() {
|
|
37
37
|
return instance;
|
|
38
38
|
}
|
|
39
|
+
// The config the provider booted with. Commands need it: `migration:run` has to
|
|
40
|
+
// know where the migration files are, and Lucid answers that from the config
|
|
41
|
+
// too (`connection.config.migrations.paths`, read through `lucid.db`). Atlas has
|
|
42
|
+
// no framework container to read, so the provider records it here.
|
|
43
|
+
let databaseConfig;
|
|
44
|
+
/** @internal Record the booted config (called by AtlasProvider). */
|
|
45
|
+
export function setDatabaseConfig(config, defaultName) {
|
|
46
|
+
databaseConfig = { config, defaultName };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @internal Forget the config IF it is still the one `config` describes.
|
|
50
|
+
* Ownership-guarded for the same reason {@link clearDb} is: a second provider
|
|
51
|
+
* may have rebound it, and the older provider's shutdown must not clear the
|
|
52
|
+
* newer binding.
|
|
53
|
+
*/
|
|
54
|
+
export function clearDatabaseConfig(config) {
|
|
55
|
+
if (databaseConfig?.config === config)
|
|
56
|
+
databaseConfig = undefined;
|
|
57
|
+
}
|
|
58
|
+
/** The config the application booted with, or `undefined` before boot. */
|
|
59
|
+
export function getDatabaseConfig() {
|
|
60
|
+
return databaseConfig?.config;
|
|
61
|
+
}
|
|
62
|
+
/** The default connection's name — Lucid `db.primaryConnectionName`. */
|
|
63
|
+
export function primaryConnectionName() {
|
|
64
|
+
return databaseConfig?.defaultName ?? "primary";
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* One connection's config, by name (default connection when unnamed).
|
|
68
|
+
*
|
|
69
|
+
* Read from the manager's node first — that is where Lucid keeps `migrations`,
|
|
70
|
+
* `seeders` and `schemaGeneration`, and the shape we mirror. The top level is
|
|
71
|
+
* the fallback, because the single-connection form IS the connection config,
|
|
72
|
+
* and because an app that set `migrations` there before these keys were
|
|
73
|
+
* per-connection must keep working.
|
|
74
|
+
*/
|
|
75
|
+
export function connectionConfigFor(name) {
|
|
76
|
+
const resolved = name ?? primaryConnectionName();
|
|
77
|
+
const top = databaseConfig?.config;
|
|
78
|
+
// The manager knows a connection once the provider has registered it; before
|
|
79
|
+
// that — a command running against a config nobody opened yet — the declared
|
|
80
|
+
// `connections` entry is the same information.
|
|
81
|
+
const declared = manager.get(resolved)?.config ?? top?.connections?.[resolved];
|
|
82
|
+
if (top === undefined)
|
|
83
|
+
return declared ?? {};
|
|
84
|
+
if (declared === undefined)
|
|
85
|
+
return top;
|
|
86
|
+
return {
|
|
87
|
+
...top,
|
|
88
|
+
...declared,
|
|
89
|
+
// These three are merged a level down rather than replaced: the top level
|
|
90
|
+
// is the single-connection form of the same config, so a connection that
|
|
91
|
+
// names only its paths must not drop a `tableName` set beside it.
|
|
92
|
+
migrations: mergeOrUndefined(top.migrations, declared.migrations),
|
|
93
|
+
seeders: mergeOrUndefined(top.seeders, declared.seeders),
|
|
94
|
+
schemaGeneration: mergeOrUndefined(top.schemaGeneration, declared.schemaGeneration),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** `{...a, ...b}`, or `undefined` when neither side has anything to merge. */
|
|
98
|
+
function mergeOrUndefined(base, override) {
|
|
99
|
+
if (base === undefined)
|
|
100
|
+
return override;
|
|
101
|
+
if (override === undefined)
|
|
102
|
+
return base;
|
|
103
|
+
return { ...base, ...override };
|
|
104
|
+
}
|
|
39
105
|
// The shared connection manager (Lucid `db.manager`) — the single owner of named
|
|
40
106
|
// connections. Backs `BaseModel.connection = 'analytics'` so a model resolves a
|
|
41
107
|
// non-default connection from a plain import (AdonisJS `static connection`).
|
package/dist/services/db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/services/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/services/db.ts"],"names":[],"mappings":"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"}
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c9up/atlas",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "Atlas — Data Mapper ORM for the Ream framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -48,6 +48,10 @@
|
|
|
48
48
|
"types": "./dist/factories.d.ts",
|
|
49
49
|
"import": "./dist/factories.js"
|
|
50
50
|
},
|
|
51
|
+
"./commands": {
|
|
52
|
+
"types": "./dist/console/index.d.ts",
|
|
53
|
+
"import": "./dist/console/index.js"
|
|
54
|
+
},
|
|
51
55
|
"./seeders": {
|
|
52
56
|
"types": "./dist/seeders.d.ts",
|
|
53
57
|
"import": "./dist/seeders.js"
|
package/src/AtlasProvider.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type AsyncDatabaseConnection,
|
|
26
26
|
createNapiConnection,
|
|
27
27
|
} from "./adapters/NapiDbAdapter.js";
|
|
28
|
+
import type { SchemaGenerateOptions } from "./console/schemaGenerateCommand.js";
|
|
28
29
|
import { clearCastRegistry, setAtlasDialect } from "./query/native.js";
|
|
29
30
|
import {
|
|
30
31
|
type DatabaseAdapter,
|
|
@@ -145,31 +146,27 @@ export interface ConnectionConfig {
|
|
|
145
146
|
* make each `connectRetries` attempt give up faster (e.g. 5 × 2s).
|
|
146
147
|
*/
|
|
147
148
|
connectTimeoutMs?: number;
|
|
148
|
-
}
|
|
149
149
|
|
|
150
|
-
/** Full database config — single-connection (legacy) OR multi-connection. */
|
|
151
|
-
export interface AtlasDatabaseConfig extends ConnectionConfig {
|
|
152
|
-
/**
|
|
153
|
-
* Name of the default connection when `connections` is set (Lucid's top-level
|
|
154
|
-
* `connection`). `default` is a deprecated alias — `connection` wins when both
|
|
155
|
-
* are set. Defaults to `"primary"`.
|
|
156
|
-
*/
|
|
157
|
-
connection?: string;
|
|
158
|
-
/** @deprecated Use {@link connection} (the Lucid key). */
|
|
159
|
-
default?: string;
|
|
160
|
-
/** Named connections. When present, top-level `url` is treated as `connections[default].url`. */
|
|
161
|
-
connections?: Record<string, ConnectionConfig>;
|
|
162
150
|
migrations?: {
|
|
163
151
|
/** @deprecated Use the Lucid-shaped {@link paths}. */
|
|
164
152
|
path?: string;
|
|
165
153
|
/** Migration directories, Lucid-shaped — `paths: ['database/migrations']`. */
|
|
166
154
|
paths?: string[];
|
|
167
155
|
/**
|
|
168
|
-
* Custom name for the migrations tracking table
|
|
169
|
-
*
|
|
170
|
-
*
|
|
156
|
+
* Custom name for the migrations tracking table — Adonis Lucid
|
|
157
|
+
* `migrations.tableName`. Defaults to `"ream_migrations"`. Must match
|
|
158
|
+
* `/^[A-Za-z_][A-Za-z0-9_]*$/` — the `MigrationRunner` constructor throws
|
|
159
|
+
* `AtlasError("MIGRATION_INVALID_TABLE_NAME")` otherwise.
|
|
171
160
|
*/
|
|
161
|
+
tableName?: string;
|
|
162
|
+
/** @deprecated Use the Lucid-shaped {@link tableName}, which wins when both are set. */
|
|
172
163
|
table?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Refuse rollback / reset / refresh / fresh / wipe when `NODE_ENV` is
|
|
166
|
+
* `production`, unless the command is given `--force` (Adonis Lucid
|
|
167
|
+
* `migrations.disableRollbacksInProduction`). On by default.
|
|
168
|
+
*/
|
|
169
|
+
disableRollbacksInProduction?: boolean;
|
|
173
170
|
/**
|
|
174
171
|
* Allow the boot-time auto-migrate in production. OFF by default:
|
|
175
172
|
* starting the app should NOT silently mutate the schema in prod (Adonis
|
|
@@ -192,6 +189,47 @@ export interface AtlasDatabaseConfig extends ConnectionConfig {
|
|
|
192
189
|
*/
|
|
193
190
|
disableTransactions?: boolean;
|
|
194
191
|
};
|
|
192
|
+
/**
|
|
193
|
+
* Where the seeder files live, and how they are ordered. Lucid keeps this on
|
|
194
|
+
* the connection too (`seeders: { paths: ['database/seeders'] }`); the
|
|
195
|
+
* commands default to `database/seeders` when it is absent.
|
|
196
|
+
*/
|
|
197
|
+
seeders?: {
|
|
198
|
+
/** Seeder directories. Only the first is used — one connection, one source. */
|
|
199
|
+
paths?: string[];
|
|
200
|
+
/** Sort files numerically (`2_x` before `10_x`) — Lucid `naturalSort`. */
|
|
201
|
+
naturalSort?: boolean;
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Where `make:factory` scaffolds. Not a Lucid key — Lucid resolves it from
|
|
205
|
+
* the application's `database/factories` directory, which atlas cannot read
|
|
206
|
+
* without depending on the framework, so it is configured here and defaults
|
|
207
|
+
* to the same path.
|
|
208
|
+
*/
|
|
209
|
+
factories?: {
|
|
210
|
+
/** Directory the factory files are scaffolded into. */
|
|
211
|
+
path?: string;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Schema-file generation — Lucid `schemaGeneration`, on the connection.
|
|
215
|
+
* `schema:generate` needs `outputPath`; without it the command says so
|
|
216
|
+
* rather than guessing a path to write into.
|
|
217
|
+
*/
|
|
218
|
+
schemaGeneration?: SchemaGenerateOptions;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Full database config — single-connection (legacy) OR multi-connection. */
|
|
222
|
+
export interface AtlasDatabaseConfig extends ConnectionConfig {
|
|
223
|
+
/**
|
|
224
|
+
* Name of the default connection when `connections` is set (Lucid's top-level
|
|
225
|
+
* `connection`). `default` is a deprecated alias — `connection` wins when both
|
|
226
|
+
* are set. Defaults to `"primary"`.
|
|
227
|
+
*/
|
|
228
|
+
connection?: string;
|
|
229
|
+
/** @deprecated Use {@link connection} (the Lucid key). */
|
|
230
|
+
default?: string;
|
|
231
|
+
/** Named connections. When present, top-level `url` is treated as `connections[default].url`. */
|
|
232
|
+
connections?: Record<string, ConnectionConfig>;
|
|
195
233
|
/**
|
|
196
234
|
* Boot-time schema verification. When set, atlas reconciles each listed
|
|
197
235
|
* model's `@Column` metadata against the LIVE database schema after boot and
|
|
@@ -411,6 +449,10 @@ export default class AtlasProvider {
|
|
|
411
449
|
// `import db from '@c9up/atlas/services/db'` from anywhere.
|
|
412
450
|
dbServices.setDb(defaultConn);
|
|
413
451
|
|
|
452
|
+
// Record the config too: the commands atlas ships read their paths from
|
|
453
|
+
// it, the way Lucid's read `connection.config.migrations.paths`.
|
|
454
|
+
dbServices.setDatabaseConfig(config, defaultName);
|
|
455
|
+
|
|
414
456
|
// The dialect set module-wide is the DEFAULT connection's dialect.
|
|
415
457
|
// Per-connection dialect (when a user hits a non-default) is read from
|
|
416
458
|
// the connection URL at query time by each call site that cares.
|
|
@@ -445,7 +487,7 @@ export default class AtlasProvider {
|
|
|
445
487
|
migrationsPath,
|
|
446
488
|
connections[defaultName]?.url,
|
|
447
489
|
defaultConn,
|
|
448
|
-
config.migrations?.table,
|
|
490
|
+
config.migrations?.tableName ?? config.migrations?.table,
|
|
449
491
|
{
|
|
450
492
|
naturalSort: config.migrations?.naturalSort,
|
|
451
493
|
disableTransactions: config.migrations?.disableTransactions,
|
|
@@ -457,7 +499,7 @@ export default class AtlasProvider {
|
|
|
457
499
|
migrationsPath,
|
|
458
500
|
connections[defaultName]?.url,
|
|
459
501
|
defaultConn,
|
|
460
|
-
config.migrations?.table,
|
|
502
|
+
config.migrations?.tableName ?? config.migrations?.table,
|
|
461
503
|
{
|
|
462
504
|
naturalSort: config.migrations?.naturalSort,
|
|
463
505
|
disableTransactions: config.migrations?.disableTransactions,
|
|
@@ -466,6 +508,7 @@ export default class AtlasProvider {
|
|
|
466
508
|
}
|
|
467
509
|
} catch (err) {
|
|
468
510
|
await Promise.allSettled(successes.map((s) => s.conn.close()));
|
|
511
|
+
dbServices.clearDatabaseConfig(config);
|
|
469
512
|
for (const { name, conn } of successes) {
|
|
470
513
|
dbServices.clearDb(conn);
|
|
471
514
|
dbServices.unregisterConnection(name, conn);
|
|
@@ -502,7 +545,11 @@ export default class AtlasProvider {
|
|
|
502
545
|
// registry entries (boot registered them), so `getConnection(name)` /
|
|
503
546
|
// `BaseModel.connection` / `Factory.connection()` can't hand out a CLOSED
|
|
504
547
|
// handle after shutdown.
|
|
505
|
-
const { clearDb, unregisterConnection } = await import(
|
|
548
|
+
const { clearDatabaseConfig, clearDb, unregisterConnection } = await import(
|
|
549
|
+
"./services/db.js"
|
|
550
|
+
);
|
|
551
|
+
const booted = this.app.config.get<AtlasDatabaseConfig>("database");
|
|
552
|
+
if (booted) clearDatabaseConfig(booted);
|
|
506
553
|
for (const [name, conn] of named) {
|
|
507
554
|
clearDb(conn);
|
|
508
555
|
unregisterConnection(name, conn);
|
package/src/BaseRepository.ts
CHANGED
|
@@ -198,6 +198,30 @@ const POSTGRES_CAST_TYPES = new Set([
|
|
|
198
198
|
"float",
|
|
199
199
|
]);
|
|
200
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Parse a JSON column's text, or hand back the text unchanged.
|
|
203
|
+
*
|
|
204
|
+
* Unparseable text is a row the column's type says cannot exist — on SQLite it
|
|
205
|
+
* can, because the column is TEXT there and nothing enforces the shape. Failing
|
|
206
|
+
* the hydration would make the whole row unreadable, including the columns that
|
|
207
|
+
* are fine, so the raw string is returned: visible at the use site, and nothing
|
|
208
|
+
* is lost or rewritten.
|
|
209
|
+
*/
|
|
210
|
+
function parseJsonColumn(text: string): unknown {
|
|
211
|
+
try {
|
|
212
|
+
return JSON.parse(text);
|
|
213
|
+
} catch {
|
|
214
|
+
return text;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Whether a declared `@Column({ type })` is a JSON column. */
|
|
219
|
+
function isJsonType(type: string | undefined): boolean {
|
|
220
|
+
if (type === undefined) return false;
|
|
221
|
+
const normalized = type.trim().toLowerCase();
|
|
222
|
+
return normalized === "json" || normalized === "jsonb";
|
|
223
|
+
}
|
|
224
|
+
|
|
201
225
|
/**
|
|
202
226
|
* Snake column → logical type for params needing a Postgres `$N::<type>` cast.
|
|
203
227
|
* sqlx binds JS strings as `text`; Postgres won't implicitly coerce that to
|
|
@@ -266,6 +290,14 @@ export class BaseRepository<T extends BaseEntity> {
|
|
|
266
290
|
#columnMap: Map<string, string>; // property/db name → resolved db column (cached)
|
|
267
291
|
#columnByDbName: Map<string, string>; // resolved db column → property (for hydrate)
|
|
268
292
|
#dateColumns: Record<string, DateColumnConfig>;
|
|
293
|
+
/**
|
|
294
|
+
* Properties declared `@Column({ type: 'json' })` / `'jsonb'`.
|
|
295
|
+
*
|
|
296
|
+
* They get the same treatment date columns get: serialised on the way down,
|
|
297
|
+
* parsed on the way back, without the application writing a `prepare` /
|
|
298
|
+
* `consume` pair for a conversion the declared type already states.
|
|
299
|
+
*/
|
|
300
|
+
#jsonColumns: Set<string>;
|
|
269
301
|
/** Snake column → logical type for params needing a Postgres `::cast`. */
|
|
270
302
|
#castTypes: Record<string, string>;
|
|
271
303
|
/**
|
|
@@ -343,6 +375,11 @@ export class BaseRepository<T extends BaseEntity> {
|
|
|
343
375
|
this.#columns = columnsMeta.map((c) => c.propertyKey);
|
|
344
376
|
this.#softDeletes = hasSoftDeletes(entityClass);
|
|
345
377
|
this.#dateColumns = getDateColumnConfig(entityClass);
|
|
378
|
+
this.#jsonColumns = new Set(
|
|
379
|
+
columnsMeta
|
|
380
|
+
.filter((col) => isJsonType(col.type))
|
|
381
|
+
.map((col) => col.propertyKey),
|
|
382
|
+
);
|
|
346
383
|
|
|
347
384
|
// Lift per-column `prepare` / `consume` callbacks directly from metadata.
|
|
348
385
|
// No global registry, no late-registration concern: callbacks are baked
|
|
@@ -1419,6 +1456,18 @@ export class BaseRepository<T extends BaseEntity> {
|
|
|
1419
1456
|
// Branch order mirrors Lucid's `prepareDateColumn` (strings pass through,
|
|
1420
1457
|
// `DateTime` is formatted, anything else throws naming the column) — see
|
|
1421
1458
|
// `#prepareDateString` for the one named deviation.
|
|
1459
|
+
// A JSON column takes the value as JSON text — objects and arrays alike.
|
|
1460
|
+
// The binder underneath is typed strictly, so nothing downstream guesses
|
|
1461
|
+
// what a JS value meant, and doing the encoding here is what makes the
|
|
1462
|
+
// three dialects behave identically. A string is passed through: it is
|
|
1463
|
+
// already JSON text, or a scalar the column accepts as-is.
|
|
1464
|
+
if (
|
|
1465
|
+
this.#jsonColumns.has(propertyKey) &&
|
|
1466
|
+
typeof value === "object" &&
|
|
1467
|
+
value !== null
|
|
1468
|
+
) {
|
|
1469
|
+
return JSON.stringify(value);
|
|
1470
|
+
}
|
|
1422
1471
|
const dateColumn = this.#dateColumns[propertyKey];
|
|
1423
1472
|
if (dateColumn && value != null) {
|
|
1424
1473
|
// `@column.date()` persists the date alone, like Lucid's
|
|
@@ -1500,6 +1549,14 @@ export class BaseRepository<T extends BaseEntity> {
|
|
|
1500
1549
|
if (this.#dateColumns[propertyKey] && value != null) {
|
|
1501
1550
|
return dateTimeAtlasAdapter.consume(value);
|
|
1502
1551
|
}
|
|
1552
|
+
// A JSON column hydrates to the value it holds, not to its text. The
|
|
1553
|
+
// native Postgres pool already decodes `json`/`jsonb` to a real value;
|
|
1554
|
+
// this is what makes MySQL and SQLite — where the column is TEXT — agree
|
|
1555
|
+
// with it, instead of handing the application a string on two dialects
|
|
1556
|
+
// out of three.
|
|
1557
|
+
if (this.#jsonColumns.has(propertyKey) && typeof value === "string") {
|
|
1558
|
+
return parseJsonColumn(value);
|
|
1559
|
+
}
|
|
1503
1560
|
return value;
|
|
1504
1561
|
}
|
|
1505
1562
|
|
|
@@ -45,6 +45,11 @@ function napiReplacer(_key: string, value: unknown): unknown {
|
|
|
45
45
|
*
|
|
46
46
|
* Only the TOP level is checked: a nested array is a JSON value inside an
|
|
47
47
|
* object being bound to a `json`/`jsonb` column, which is legitimate.
|
|
48
|
+
*
|
|
49
|
+
* A column declared `@Column({ type: 'json' })` never reaches here as an array:
|
|
50
|
+
* the repository serialises it on the way down, the way it lowers a date
|
|
51
|
+
* column. This fires for the list that was meant to be an `IN`, and for a raw
|
|
52
|
+
* query with no entity behind it to say what the column holds.
|
|
48
53
|
*/
|
|
49
54
|
function assertNoArrayParams(params: readonly unknown[] | undefined): void {
|
|
50
55
|
if (!params) return;
|
|
@@ -52,8 +57,11 @@ function assertNoArrayParams(params: readonly unknown[] | undefined): void {
|
|
|
52
57
|
if (!Array.isArray(value)) continue;
|
|
53
58
|
throw new Error(
|
|
54
59
|
`[E_ARRAY_PARAM] Parameter $${index + 1} is an array, which cannot be bound as a single value. ` +
|
|
55
|
-
"
|
|
56
|
-
"and so does building the placeholders yourself:
|
|
60
|
+
"For a list of values, expand it into one placeholder per element — `whereIn(column, values)` " +
|
|
61
|
+
"does this, and so does building the placeholders yourself: " +
|
|
62
|
+
"`IN (${values.map((_, i) => '$' + (i + 1)).join(', ')})`. " +
|
|
63
|
+
"For a JSON column, declare it — `@Column({ type: 'jsonb' })` — and the array is serialised " +
|
|
64
|
+
"and parsed for you; on a raw query with no entity behind it, pass `JSON.stringify(value)`. " +
|
|
57
65
|
"Binding the array itself sends Postgres text where it expects an array, and it reports " +
|
|
58
66
|
"a nonsensical dimension count rather than a type error.",
|
|
59
67
|
);
|
package/src/configure.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
interface Codemods {
|
|
2
2
|
addProvider(importPath: string): Promise<void>;
|
|
3
|
+
registerCommand(importPath: string): Promise<void>;
|
|
3
4
|
addEnvVars(vars: Record<string, string>): Promise<void>;
|
|
4
5
|
writeFile(
|
|
5
6
|
filePath: string,
|
|
@@ -10,6 +11,11 @@ interface Codemods {
|
|
|
10
11
|
|
|
11
12
|
export async function configure(codemods: Codemods): Promise<void> {
|
|
12
13
|
await codemods.addProvider("@c9up/atlas/provider");
|
|
14
|
+
// `reamrc.commands` is how a package ships commands — the same channel Lucid
|
|
15
|
+
// uses (`@adonisjs/lucid/commands`). Every migration / seeder / schema
|
|
16
|
+
// command comes from here, configured by `config/database.ts`; none of them
|
|
17
|
+
// needs a line in the `ream` binary.
|
|
18
|
+
await codemods.registerCommand("@c9up/atlas/commands");
|
|
13
19
|
await codemods.addEnvVars({
|
|
14
20
|
DB_HOST: "localhost",
|
|
15
21
|
DB_PORT: "5432",
|
|
@@ -22,12 +28,18 @@ export async function configure(codemods: Codemods): Promise<void> {
|
|
|
22
28
|
`import { defineConfig } from '@c9up/atlas'
|
|
23
29
|
|
|
24
30
|
export default defineConfig({
|
|
25
|
-
|
|
31
|
+
connection: 'postgres',
|
|
26
32
|
connections: {
|
|
27
33
|
postgres: {
|
|
28
34
|
url:
|
|
29
35
|
process.env.DATABASE_URL ??
|
|
30
36
|
\`postgres://\${process.env.DB_USER ?? 'postgres'}:\${process.env.DB_PASSWORD ?? ''}@\${process.env.DB_HOST ?? 'localhost'}:\${process.env.DB_PORT ?? '5432'}/\${process.env.DB_DATABASE ?? 'ream'}\`,
|
|
37
|
+
migrations: {
|
|
38
|
+
paths: ['database/migrations'],
|
|
39
|
+
},
|
|
40
|
+
seeders: {
|
|
41
|
+
paths: ['database/seeders'],
|
|
42
|
+
},
|
|
31
43
|
},
|
|
32
44
|
},
|
|
33
45
|
})
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@c9up/atlas/commands` — every command atlas ships, configured from
|
|
3
|
+
* `config/database.ts`.
|
|
4
|
+
*
|
|
5
|
+
* // reamrc.ts, written by `configure()`
|
|
6
|
+
* commands: [() => import('@c9up/atlas/commands')]
|
|
7
|
+
*
|
|
8
|
+
* This is the shape Adonis Lucid ships (`@adonisjs/lucid/commands`, a module
|
|
9
|
+
* exporting `getMetaData` / `getCommand`), and it is the whole point: a package
|
|
10
|
+
* adds commands by shipping them, never by a change to the `ream` binary.
|
|
11
|
+
*
|
|
12
|
+
* Where the paths come from is Lucid's answer too — the connection's config
|
|
13
|
+
* (`migrations.paths`, `seeders.paths`, `schemaGeneration.outputPath`). Lucid
|
|
14
|
+
* reads it through the container; atlas reads it from its own locator, which
|
|
15
|
+
* the provider fills at boot, so nothing here imports `@c9up/ream`.
|
|
16
|
+
*
|
|
17
|
+
* The option objects below use getters on purpose. A command class is built
|
|
18
|
+
* when this module is imported — before the application boots — while every
|
|
19
|
+
* `options.x` is read inside `run()`, after it. A plain object would capture
|
|
20
|
+
* the config that did not exist yet.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
connectionConfigFor,
|
|
25
|
+
getDatabaseConfig,
|
|
26
|
+
primaryConnectionName,
|
|
27
|
+
} from "../services/db.js";
|
|
28
|
+
import type { AtlasCommandClass } from "./contract.js";
|
|
29
|
+
import {
|
|
30
|
+
type FactoryCommandOptions,
|
|
31
|
+
makeFactoryCommand,
|
|
32
|
+
} from "./factoryCommands.js";
|
|
33
|
+
import {
|
|
34
|
+
dbWipeCommand,
|
|
35
|
+
type MigrationCommandOptions,
|
|
36
|
+
makeMigrationCommand,
|
|
37
|
+
migrationFreshCommand,
|
|
38
|
+
migrationRefreshCommand,
|
|
39
|
+
migrationResetCommand,
|
|
40
|
+
migrationRollbackCommand,
|
|
41
|
+
migrationRunCommand,
|
|
42
|
+
migrationStatusCommand,
|
|
43
|
+
migrationUnlockCommand,
|
|
44
|
+
} from "./migrationCommands.js";
|
|
45
|
+
import { schemaCheckCommand } from "./schemaCheckCommand.js";
|
|
46
|
+
import {
|
|
47
|
+
type SchemaDumpCommandOptions,
|
|
48
|
+
schemaDumpCommand,
|
|
49
|
+
} from "./schemaDumpCommand.js";
|
|
50
|
+
import {
|
|
51
|
+
type SchemaGenerateOptions,
|
|
52
|
+
schemaGenerateCommand,
|
|
53
|
+
} from "./schemaGenerateCommand.js";
|
|
54
|
+
import {
|
|
55
|
+
dbSeedCommand,
|
|
56
|
+
makeSeederCommand,
|
|
57
|
+
type SeederCommandOptions,
|
|
58
|
+
} from "./seederCommands.js";
|
|
59
|
+
|
|
60
|
+
/** Lucid's defaults, for a config that leaves the paths out. */
|
|
61
|
+
const DEFAULT_MIGRATIONS_DIR = "database/migrations";
|
|
62
|
+
const DEFAULT_SEEDERS_DIR = "database/seeders";
|
|
63
|
+
const DEFAULT_FACTORIES_DIR = "database/factories";
|
|
64
|
+
|
|
65
|
+
/** The default connection's config — per-connection first, then the top level. */
|
|
66
|
+
function connection() {
|
|
67
|
+
return connectionConfigFor();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function migrationsDir(): string {
|
|
71
|
+
const migrations = connection().migrations;
|
|
72
|
+
return migrations?.paths?.[0] ?? migrations?.path ?? DEFAULT_MIGRATIONS_DIR;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const migrationOptions: MigrationCommandOptions = {
|
|
76
|
+
get migrationsDir() {
|
|
77
|
+
return migrationsDir();
|
|
78
|
+
},
|
|
79
|
+
get naturalSort() {
|
|
80
|
+
return connection().migrations?.naturalSort;
|
|
81
|
+
},
|
|
82
|
+
get disableTransactions() {
|
|
83
|
+
return connection().migrations?.disableTransactions;
|
|
84
|
+
},
|
|
85
|
+
get tableName() {
|
|
86
|
+
return connection().migrations?.tableName ?? connection().migrations?.table;
|
|
87
|
+
},
|
|
88
|
+
get disableRollbacksInProduction() {
|
|
89
|
+
return connection().migrations?.disableRollbacksInProduction;
|
|
90
|
+
},
|
|
91
|
+
get schemaGeneration() {
|
|
92
|
+
return connection().schemaGeneration;
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const seederOptions: SeederCommandOptions = {
|
|
97
|
+
get seedersDir() {
|
|
98
|
+
return connection().seeders?.paths?.[0] ?? DEFAULT_SEEDERS_DIR;
|
|
99
|
+
},
|
|
100
|
+
get naturalSort() {
|
|
101
|
+
return connection().seeders?.naturalSort;
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const factoryOptions: FactoryCommandOptions = {
|
|
106
|
+
get factoriesDir() {
|
|
107
|
+
return connection().factories?.path ?? DEFAULT_FACTORIES_DIR;
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const schemaDumpOptions: SchemaDumpCommandOptions = {
|
|
112
|
+
get migrationsDir() {
|
|
113
|
+
return migrationsDir();
|
|
114
|
+
},
|
|
115
|
+
get schemaTableName() {
|
|
116
|
+
return connection().migrations?.tableName ?? connection().migrations?.table;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// `outputPath` has no sensible default — a command that guessed one would write
|
|
121
|
+
// a generated file into a directory the project never chose. The command
|
|
122
|
+
// reports the missing key itself; an empty string is what it checks for.
|
|
123
|
+
const schemaGenerateOptions: SchemaGenerateOptions = {
|
|
124
|
+
get outputPath() {
|
|
125
|
+
return connection().schemaGeneration?.outputPath ?? "";
|
|
126
|
+
},
|
|
127
|
+
get excludeTables() {
|
|
128
|
+
return connection().schemaGeneration?.excludeTables;
|
|
129
|
+
},
|
|
130
|
+
get enabled() {
|
|
131
|
+
return connection().schemaGeneration?.enabled;
|
|
132
|
+
},
|
|
133
|
+
get rulesPaths() {
|
|
134
|
+
return connection().schemaGeneration?.rulesPaths;
|
|
135
|
+
},
|
|
136
|
+
get compact() {
|
|
137
|
+
return connection().schemaGeneration?.compact;
|
|
138
|
+
},
|
|
139
|
+
get schemas() {
|
|
140
|
+
return connection().schemaGeneration?.schemas;
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const COMMANDS: readonly AtlasCommandClass[] = [
|
|
145
|
+
migrationRunCommand(migrationOptions),
|
|
146
|
+
migrationRollbackCommand(migrationOptions),
|
|
147
|
+
migrationStatusCommand(migrationOptions),
|
|
148
|
+
migrationResetCommand(migrationOptions),
|
|
149
|
+
migrationRefreshCommand(migrationOptions),
|
|
150
|
+
migrationFreshCommand(migrationOptions),
|
|
151
|
+
migrationUnlockCommand(migrationOptions),
|
|
152
|
+
makeMigrationCommand(migrationOptions),
|
|
153
|
+
dbWipeCommand(migrationOptions),
|
|
154
|
+
dbSeedCommand(seederOptions),
|
|
155
|
+
makeSeederCommand(seederOptions),
|
|
156
|
+
makeFactoryCommand(factoryOptions),
|
|
157
|
+
schemaDumpCommand(schemaDumpOptions),
|
|
158
|
+
schemaGenerateCommand(schemaGenerateOptions),
|
|
159
|
+
schemaCheckCommand(() => getDatabaseConfig()?.verifySchema?.entities ?? []),
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
/** What the kernel reads to list a command without importing it. */
|
|
163
|
+
interface CommandMetaData {
|
|
164
|
+
commandName: string;
|
|
165
|
+
namespace: string | null;
|
|
166
|
+
description: string;
|
|
167
|
+
help?: string | string[];
|
|
168
|
+
aliases: string[];
|
|
169
|
+
options: Record<string, unknown>;
|
|
170
|
+
args: readonly unknown[];
|
|
171
|
+
flags: readonly unknown[];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function serialize(command: AtlasCommandClass): CommandMetaData {
|
|
175
|
+
const colon = command.commandName.indexOf(":");
|
|
176
|
+
return {
|
|
177
|
+
commandName: command.commandName,
|
|
178
|
+
namespace: colon === -1 ? null : command.commandName.slice(0, colon),
|
|
179
|
+
description: command.description,
|
|
180
|
+
help: command.help,
|
|
181
|
+
aliases: [],
|
|
182
|
+
options: { ...command.options },
|
|
183
|
+
args: command.args ?? [],
|
|
184
|
+
flags: command.flags ?? [],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export async function getMetaData(): Promise<CommandMetaData[]> {
|
|
189
|
+
return COMMANDS.map(serialize);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export async function getCommand(
|
|
193
|
+
metadata: CommandMetaData,
|
|
194
|
+
): Promise<AtlasCommandClass | null> {
|
|
195
|
+
return (
|
|
196
|
+
COMMANDS.find((command) => command.commandName === metadata.commandName) ??
|
|
197
|
+
null
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** The connection these commands run against — Lucid `db.primaryConnectionName`. */
|
|
202
|
+
export { primaryConnectionName };
|