@apso/cli 0.41.2 → 0.42.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.
- package/dist/commands/generate.js +5 -0
- package/dist/lib/apsorc-parser.d.ts +11 -0
- package/dist/lib/apsorc-parser.js +41 -3
- package/dist/lib/utils/crud-deps.d.ts +8 -0
- package/dist/lib/utils/crud-deps.js +15 -4
- package/dist/lib/utils/pglite-upgrade.d.ts +22 -0
- package/dist/lib/utils/pglite-upgrade.js +158 -0
- package/dist/lib/verify/index.js +4 -2
- package/npm-shrinkwrap.json +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@ const perf_hooks_1 = require("perf_hooks");
|
|
|
11
11
|
const file_system_1 = require("../lib/utils/file-system");
|
|
12
12
|
const git_hooks_1 = require("../lib/utils/git-hooks");
|
|
13
13
|
const crud_deps_1 = require("../lib/utils/crud-deps");
|
|
14
|
+
const pglite_upgrade_1 = require("../lib/utils/pglite-upgrade");
|
|
14
15
|
class Generate extends base_command_1.default {
|
|
15
16
|
async run() {
|
|
16
17
|
var _a, _b;
|
|
@@ -249,6 +250,10 @@ class Generate extends base_command_1.default {
|
|
|
249
250
|
if (added.length > 0) {
|
|
250
251
|
console.log(`[apso] Added ${added.join(", ")} to package.json (the generated code imports them). Run npm install before building.`);
|
|
251
252
|
}
|
|
253
|
+
// The pre-deploy checks run on PGlite; give a stock v1 config support.
|
|
254
|
+
if ((0, pglite_upgrade_1.upgradeOrmConfigForPglite)(process.cwd())) {
|
|
255
|
+
console.log("[apso] Updated src/orm.config.ts so `apso migrate verify` and `apso test smoke` can run on a local PGlite database. Run npm install before building.");
|
|
256
|
+
}
|
|
252
257
|
}
|
|
253
258
|
const totalBuildTime = perf_hooks_1.performance.now() - totalBuildStart;
|
|
254
259
|
console.log(`[apso] Finished building all entities in ${totalBuildTime.toFixed(2)} ms`);
|
|
@@ -71,6 +71,17 @@ export declare class ApsorcNamingError extends Error {
|
|
|
71
71
|
* schema builder runs the same rules, so a schema that passes there passes here.
|
|
72
72
|
*/
|
|
73
73
|
export declare const assertCodegenSafeNames: (apsorc: Pick<ApsorcType, "entities" | "relationships">) => void;
|
|
74
|
+
/**
|
|
75
|
+
* Drop indexes the database cannot create alongside another. TypeORM names an
|
|
76
|
+
* index from its table and columns only, so a plain and a unique index on the
|
|
77
|
+
* same columns get one name and the second CREATE fails, rolling back the
|
|
78
|
+
* schema (prod svc 52: Warehouse.manager_email). The unique index also serves
|
|
79
|
+
* lookups, so it is kept; exact duplicates are dropped too.
|
|
80
|
+
*
|
|
81
|
+
* @param {Entity} entity - An entity from .apsorc.
|
|
82
|
+
* @returns {Entity} The entity, with a filtered copy of its indexes when needed.
|
|
83
|
+
*/
|
|
84
|
+
export declare const dedupeIndexes: (entity: Entity) => Entity;
|
|
74
85
|
export declare const parseApsorcV2: (apsorc: ApsorcType) => ParsedApsorcData;
|
|
75
86
|
export declare const parseApsorc: () => ParsedApsorc;
|
|
76
87
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.findConfigPath = exports.readApsorcFile = exports.parseApsorc = exports.parseApsorcV2 = exports.assertCodegenSafeNames = exports.ApsorcNamingError = exports.parseApsorcV1 = exports.ApiType = void 0;
|
|
3
|
+
exports.findConfigPath = exports.readApsorcFile = exports.parseApsorc = exports.parseApsorcV2 = exports.dedupeIndexes = exports.assertCodegenSafeNames = exports.ApsorcNamingError = exports.parseApsorcV1 = exports.ApiType = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const fs = tslib_1.__importStar(require("fs"));
|
|
6
6
|
const path = tslib_1.__importStar(require("path"));
|
|
@@ -55,11 +55,46 @@ const assertCodegenSafeNames = (apsorc) => {
|
|
|
55
55
|
throw new ApsorcNamingError(`${error.message}${more > 0 ? ` (${more} more error${more === 1 ? "" : "s"})` : ""} Run "apso schema lint" to see every issue, or "apso schema lint --fix" to apply the safe fixes.`, error.rule, error.entity || "", error.field);
|
|
56
56
|
};
|
|
57
57
|
exports.assertCodegenSafeNames = assertCodegenSafeNames;
|
|
58
|
+
const columns = (fields) => fields.join(",");
|
|
59
|
+
/**
|
|
60
|
+
* Drop indexes the database cannot create alongside another. TypeORM names an
|
|
61
|
+
* index from its table and columns only, so a plain and a unique index on the
|
|
62
|
+
* same columns get one name and the second CREATE fails, rolling back the
|
|
63
|
+
* schema (prod svc 52: Warehouse.manager_email). The unique index also serves
|
|
64
|
+
* lookups, so it is kept; exact duplicates are dropped too.
|
|
65
|
+
*
|
|
66
|
+
* @param {Entity} entity - An entity from .apsorc.
|
|
67
|
+
* @returns {Entity} The entity, with a filtered copy of its indexes when needed.
|
|
68
|
+
*/
|
|
69
|
+
const dedupeIndexes = (entity) => {
|
|
70
|
+
var _a;
|
|
71
|
+
if (!((_a = entity.indexes) === null || _a === void 0 ? void 0 : _a.length))
|
|
72
|
+
return entity;
|
|
73
|
+
const uniqueColumns = new Set(entity.indexes
|
|
74
|
+
.filter((index) => index.unique)
|
|
75
|
+
.map((index) => columns(index.fields)));
|
|
76
|
+
const seen = new Set();
|
|
77
|
+
const indexes = entity.indexes.filter((index) => {
|
|
78
|
+
const key = `${columns(index.fields)}|${index.unique ? "unique" : ""}`;
|
|
79
|
+
if (seen.has(key) ||
|
|
80
|
+
(!index.unique && uniqueColumns.has(columns(index.fields))))
|
|
81
|
+
return false;
|
|
82
|
+
seen.add(key);
|
|
83
|
+
return true;
|
|
84
|
+
});
|
|
85
|
+
return indexes.length === entity.indexes.length
|
|
86
|
+
? entity
|
|
87
|
+
: { ...entity, indexes };
|
|
88
|
+
};
|
|
89
|
+
exports.dedupeIndexes = dedupeIndexes;
|
|
58
90
|
const parseApsorcV2 = (apsorc) => {
|
|
59
91
|
const { entities, relationships: apsoRelationships } = apsorc;
|
|
60
92
|
(0, exports.assertCodegenSafeNames)(apsorc);
|
|
61
93
|
const relationshipMap = (0, relationships_1.parseRelationships)(apsoRelationships);
|
|
62
|
-
return {
|
|
94
|
+
return {
|
|
95
|
+
entities: entities.map((entity) => (0, exports.dedupeIndexes)(entity)),
|
|
96
|
+
relationshipMap,
|
|
97
|
+
};
|
|
63
98
|
};
|
|
64
99
|
exports.parseApsorcV2 = parseApsorcV2;
|
|
65
100
|
const parseRc = () => {
|
|
@@ -156,7 +191,10 @@ const readApsorcFile = () => {
|
|
|
156
191
|
if (!configPath) {
|
|
157
192
|
throw new Error("No .apsorc found in this directory or any parent.");
|
|
158
193
|
}
|
|
159
|
-
return {
|
|
194
|
+
return {
|
|
195
|
+
configPath,
|
|
196
|
+
apsorc: JSON.parse(fs.readFileSync(configPath).toString()),
|
|
197
|
+
};
|
|
160
198
|
};
|
|
161
199
|
exports.readApsorcFile = readApsorcFile;
|
|
162
200
|
const findConfigPath = () => {
|
|
@@ -16,3 +16,11 @@ export declare const APSO_CRUD_DEPS: Record<string, string>;
|
|
|
16
16
|
* @returns {string[]} Names added (empty when nothing changed or no package.json).
|
|
17
17
|
*/
|
|
18
18
|
export declare function ensureCrudDeps(projectDir: string): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Add the given dependencies to package.json where it doesn't declare them.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} projectDir - Directory holding the project's package.json.
|
|
23
|
+
* @param {Record<string, string>} deps - Package names and version ranges.
|
|
24
|
+
* @returns {string[]} Names added (empty when nothing changed or no package.json).
|
|
25
|
+
*/
|
|
26
|
+
export declare function addMissingDeps(projectDir: string, deps: Record<string, string>): string[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ensureCrudDeps = exports.APSO_CRUD_DEPS = void 0;
|
|
3
|
+
exports.addMissingDeps = exports.ensureCrudDeps = exports.APSO_CRUD_DEPS = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const fs = tslib_1.__importStar(require("fs"));
|
|
6
6
|
const path = tslib_1.__importStar(require("path"));
|
|
@@ -27,6 +27,17 @@ exports.APSO_CRUD_DEPS = {
|
|
|
27
27
|
* @returns {string[]} Names added (empty when nothing changed or no package.json).
|
|
28
28
|
*/
|
|
29
29
|
function ensureCrudDeps(projectDir) {
|
|
30
|
+
return addMissingDeps(projectDir, exports.APSO_CRUD_DEPS);
|
|
31
|
+
}
|
|
32
|
+
exports.ensureCrudDeps = ensureCrudDeps;
|
|
33
|
+
/**
|
|
34
|
+
* Add the given dependencies to package.json where it doesn't declare them.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} projectDir - Directory holding the project's package.json.
|
|
37
|
+
* @param {Record<string, string>} deps - Package names and version ranges.
|
|
38
|
+
* @returns {string[]} Names added (empty when nothing changed or no package.json).
|
|
39
|
+
*/
|
|
40
|
+
function addMissingDeps(projectDir, deps) {
|
|
30
41
|
var _a;
|
|
31
42
|
const pkgPath = path.join(projectDir, "package.json");
|
|
32
43
|
if (!fs.existsSync(pkgPath))
|
|
@@ -34,14 +45,14 @@ function ensureCrudDeps(projectDir) {
|
|
|
34
45
|
const raw = fs.readFileSync(pkgPath, "utf8");
|
|
35
46
|
const pkg = JSON.parse(raw);
|
|
36
47
|
const declared = { ...pkg.devDependencies, ...pkg.dependencies };
|
|
37
|
-
const missing = Object.keys(
|
|
48
|
+
const missing = Object.keys(deps).filter((name) => !declared[name]);
|
|
38
49
|
if (missing.length === 0)
|
|
39
50
|
return [];
|
|
40
51
|
pkg.dependencies = (_a = pkg.dependencies) !== null && _a !== void 0 ? _a : {};
|
|
41
52
|
for (const name of missing)
|
|
42
|
-
pkg.dependencies[name] =
|
|
53
|
+
pkg.dependencies[name] = deps[name];
|
|
43
54
|
pkg.dependencies = Object.fromEntries(Object.entries(pkg.dependencies).sort(([a], [b]) => a.localeCompare(b)));
|
|
44
55
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + (raw.endsWith("\n") ? "\n" : ""));
|
|
45
56
|
return missing;
|
|
46
57
|
}
|
|
47
|
-
exports.
|
|
58
|
+
exports.addMissingDeps = addMissingDeps;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PGlite packages the upgraded orm.config.ts loads. Versions match the pinned
|
|
3
|
+
* service-template-ts tag (see TEMPLATE_REFS in ./template.ts).
|
|
4
|
+
*/
|
|
5
|
+
export declare const PGLITE_DEPS: Record<string, string>;
|
|
6
|
+
/** src/orm.config.ts as the v1 template shipped it (no PGlite support). */
|
|
7
|
+
export declare const ORM_CONFIG_V1 = "import { ConfigModule, ConfigService } from '@nestjs/config';\nimport { DataSource } from 'typeorm';\nimport {\n TypeOrmModuleAsyncOptions,\n TypeOrmModuleOptions,\n} from '@nestjs/typeorm';\nimport { join } from 'path';\nimport AppConfig from './config';\n\nconst sslConfig = process.env.DB_SSL\n ? {\n ssl: true,\n extra: {\n ssl: {\n rejectUnauthorized: false,\n },\n },\n }\n : {};\n\nconst ormConfig = {\n type: AppConfig.database.type as any,\n host: AppConfig.database.host,\n port: parseInt(AppConfig.database.port, 10),\n username: AppConfig.database.username,\n database: AppConfig.database.database,\n password: AppConfig.database.password,\n schema: AppConfig.database.schema,\n entities: [join(__dirname, '**', '*.entity.js')],\n migrations: [join(__dirname, '**', 'migrations/*-migration.js')],\n synchronize: AppConfig.database.synchronize,\n logging: AppConfig.database.logging,\n ...sslConfig,\n};\n\nexport const typeOrmAsyncConfig: TypeOrmModuleAsyncOptions = {\n imports: [ConfigModule],\n inject: [ConfigService],\n useFactory: async (): Promise<TypeOrmModuleOptions> => {\n console.log('ORM CONFIG', ormConfig);\n return ormConfig;\n },\n};\n\nexport default new DataSource(ormConfig);\n";
|
|
8
|
+
/**
|
|
9
|
+
* The v1 orm.config.ts with a PGlite branch for DATABASE_TYPE=pglite. Same
|
|
10
|
+
* exports and same behavior for every other database type.
|
|
11
|
+
*/
|
|
12
|
+
export declare const ORM_CONFIG_V1_PGLITE = "import { ConfigModule, ConfigService } from '@nestjs/config';\nimport { DataSource } from 'typeorm';\nimport {\n TypeOrmModuleAsyncOptions,\n TypeOrmModuleOptions,\n} from '@nestjs/typeorm';\nimport { join } from 'path';\nimport AppConfig from './config';\n\n// DATABASE_TYPE=pglite runs on an in-process Postgres (PGlite) for local\n// checks: apso migrate verify, apso test smoke, and the in-browser editor.\n// PGLITE_DATA_DIR keeps the database on disk between commands.\nconst usePGlite = process.env.DATABASE_TYPE === 'pglite';\n\nconst sslConfig = process.env.DB_SSL\n ? {\n ssl: true,\n extra: {\n ssl: {\n rejectUnauthorized: false,\n },\n },\n }\n : {};\n\nconst ormConfig = {\n ...(usePGlite\n ? {\n type: 'postgres' as const,\n // Loaded only for PGlite so production installs never need it.\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n driver: new (require('typeorm-pglite').PGliteDriver)({\n dataDir: process.env.PGLITE_DATA_DIR,\n }).driver,\n }\n : {\n type: AppConfig.database.type as any,\n host: AppConfig.database.host,\n port: parseInt(AppConfig.database.port, 10),\n username: AppConfig.database.username,\n database: AppConfig.database.database,\n password: AppConfig.database.password,\n schema: AppConfig.database.schema,\n ...sslConfig,\n }),\n entities: [join(__dirname, '**', '*.entity.js')],\n migrations: [join(__dirname, '**', 'migrations/*-migration.js')],\n synchronize: AppConfig.database.synchronize,\n logging: AppConfig.database.logging,\n};\n\nexport const typeOrmAsyncConfig: TypeOrmModuleAsyncOptions = {\n imports: [ConfigModule],\n inject: [ConfigService],\n useFactory: async (): Promise<TypeOrmModuleOptions> => {\n console.log('ORM CONFIG', { ...ormConfig, driver: usePGlite ? '[PGliteDriver]' : undefined });\n return ormConfig;\n },\n};\n\nexport default new DataSource(ormConfig);\n";
|
|
13
|
+
/**
|
|
14
|
+
* Give a v1-template project PGlite support so the pre-deploy checks (apso
|
|
15
|
+
* migrate verify, apso test smoke) can run. Replaces src/orm.config.ts only
|
|
16
|
+
* when it is still the stock v1 file, so a customized config is never
|
|
17
|
+
* overwritten, and declares the PGlite packages.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} projectDir - The service project root.
|
|
20
|
+
* @returns {boolean} True when orm.config.ts was upgraded.
|
|
21
|
+
*/
|
|
22
|
+
export declare function upgradeOrmConfigForPglite(projectDir: string): boolean;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.upgradeOrmConfigForPglite = exports.ORM_CONFIG_V1_PGLITE = exports.ORM_CONFIG_V1 = exports.PGLITE_DEPS = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
|
+
const crud_deps_1 = require("./crud-deps");
|
|
8
|
+
/**
|
|
9
|
+
* PGlite packages the upgraded orm.config.ts loads. Versions match the pinned
|
|
10
|
+
* service-template-ts tag (see TEMPLATE_REFS in ./template.ts).
|
|
11
|
+
*/
|
|
12
|
+
exports.PGLITE_DEPS = {
|
|
13
|
+
"@electric-sql/pglite": "^0.5.2",
|
|
14
|
+
"typeorm-pglite": "^0.3.2",
|
|
15
|
+
};
|
|
16
|
+
/** src/orm.config.ts as the v1 template shipped it (no PGlite support). */
|
|
17
|
+
exports.ORM_CONFIG_V1 = `import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
18
|
+
import { DataSource } from 'typeorm';
|
|
19
|
+
import {
|
|
20
|
+
TypeOrmModuleAsyncOptions,
|
|
21
|
+
TypeOrmModuleOptions,
|
|
22
|
+
} from '@nestjs/typeorm';
|
|
23
|
+
import { join } from 'path';
|
|
24
|
+
import AppConfig from './config';
|
|
25
|
+
|
|
26
|
+
const sslConfig = process.env.DB_SSL
|
|
27
|
+
? {
|
|
28
|
+
ssl: true,
|
|
29
|
+
extra: {
|
|
30
|
+
ssl: {
|
|
31
|
+
rejectUnauthorized: false,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
: {};
|
|
36
|
+
|
|
37
|
+
const ormConfig = {
|
|
38
|
+
type: AppConfig.database.type as any,
|
|
39
|
+
host: AppConfig.database.host,
|
|
40
|
+
port: parseInt(AppConfig.database.port, 10),
|
|
41
|
+
username: AppConfig.database.username,
|
|
42
|
+
database: AppConfig.database.database,
|
|
43
|
+
password: AppConfig.database.password,
|
|
44
|
+
schema: AppConfig.database.schema,
|
|
45
|
+
entities: [join(__dirname, '**', '*.entity.js')],
|
|
46
|
+
migrations: [join(__dirname, '**', 'migrations/*-migration.js')],
|
|
47
|
+
synchronize: AppConfig.database.synchronize,
|
|
48
|
+
logging: AppConfig.database.logging,
|
|
49
|
+
...sslConfig,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const typeOrmAsyncConfig: TypeOrmModuleAsyncOptions = {
|
|
53
|
+
imports: [ConfigModule],
|
|
54
|
+
inject: [ConfigService],
|
|
55
|
+
useFactory: async (): Promise<TypeOrmModuleOptions> => {
|
|
56
|
+
console.log('ORM CONFIG', ormConfig);
|
|
57
|
+
return ormConfig;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default new DataSource(ormConfig);
|
|
62
|
+
`;
|
|
63
|
+
/**
|
|
64
|
+
* The v1 orm.config.ts with a PGlite branch for DATABASE_TYPE=pglite. Same
|
|
65
|
+
* exports and same behavior for every other database type.
|
|
66
|
+
*/
|
|
67
|
+
exports.ORM_CONFIG_V1_PGLITE = `import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
68
|
+
import { DataSource } from 'typeorm';
|
|
69
|
+
import {
|
|
70
|
+
TypeOrmModuleAsyncOptions,
|
|
71
|
+
TypeOrmModuleOptions,
|
|
72
|
+
} from '@nestjs/typeorm';
|
|
73
|
+
import { join } from 'path';
|
|
74
|
+
import AppConfig from './config';
|
|
75
|
+
|
|
76
|
+
// DATABASE_TYPE=pglite runs on an in-process Postgres (PGlite) for local
|
|
77
|
+
// checks: apso migrate verify, apso test smoke, and the in-browser editor.
|
|
78
|
+
// PGLITE_DATA_DIR keeps the database on disk between commands.
|
|
79
|
+
const usePGlite = process.env.DATABASE_TYPE === 'pglite';
|
|
80
|
+
|
|
81
|
+
const sslConfig = process.env.DB_SSL
|
|
82
|
+
? {
|
|
83
|
+
ssl: true,
|
|
84
|
+
extra: {
|
|
85
|
+
ssl: {
|
|
86
|
+
rejectUnauthorized: false,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
: {};
|
|
91
|
+
|
|
92
|
+
const ormConfig = {
|
|
93
|
+
...(usePGlite
|
|
94
|
+
? {
|
|
95
|
+
type: 'postgres' as const,
|
|
96
|
+
// Loaded only for PGlite so production installs never need it.
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
98
|
+
driver: new (require('typeorm-pglite').PGliteDriver)({
|
|
99
|
+
dataDir: process.env.PGLITE_DATA_DIR,
|
|
100
|
+
}).driver,
|
|
101
|
+
}
|
|
102
|
+
: {
|
|
103
|
+
type: AppConfig.database.type as any,
|
|
104
|
+
host: AppConfig.database.host,
|
|
105
|
+
port: parseInt(AppConfig.database.port, 10),
|
|
106
|
+
username: AppConfig.database.username,
|
|
107
|
+
database: AppConfig.database.database,
|
|
108
|
+
password: AppConfig.database.password,
|
|
109
|
+
schema: AppConfig.database.schema,
|
|
110
|
+
...sslConfig,
|
|
111
|
+
}),
|
|
112
|
+
entities: [join(__dirname, '**', '*.entity.js')],
|
|
113
|
+
migrations: [join(__dirname, '**', 'migrations/*-migration.js')],
|
|
114
|
+
synchronize: AppConfig.database.synchronize,
|
|
115
|
+
logging: AppConfig.database.logging,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const typeOrmAsyncConfig: TypeOrmModuleAsyncOptions = {
|
|
119
|
+
imports: [ConfigModule],
|
|
120
|
+
inject: [ConfigService],
|
|
121
|
+
useFactory: async (): Promise<TypeOrmModuleOptions> => {
|
|
122
|
+
console.log('ORM CONFIG', { ...ormConfig, driver: usePGlite ? '[PGliteDriver]' : undefined });
|
|
123
|
+
return ormConfig;
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export default new DataSource(ormConfig);
|
|
128
|
+
`;
|
|
129
|
+
const squash = (s) => s.replace(/\s+/g, "");
|
|
130
|
+
/**
|
|
131
|
+
* Give a v1-template project PGlite support so the pre-deploy checks (apso
|
|
132
|
+
* migrate verify, apso test smoke) can run. Replaces src/orm.config.ts only
|
|
133
|
+
* when it is still the stock v1 file, so a customized config is never
|
|
134
|
+
* overwritten, and declares the PGlite packages.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} projectDir - The service project root.
|
|
137
|
+
* @returns {boolean} True when orm.config.ts was upgraded.
|
|
138
|
+
*/
|
|
139
|
+
function upgradeOrmConfigForPglite(projectDir) {
|
|
140
|
+
const file = path.join(projectDir, "src", "orm.config.ts");
|
|
141
|
+
if (!fs.existsSync(file))
|
|
142
|
+
return false;
|
|
143
|
+
const current = fs.readFileSync(file, "utf8");
|
|
144
|
+
if (squash(current) === squash(exports.ORM_CONFIG_V1)) {
|
|
145
|
+
fs.writeFileSync(file, exports.ORM_CONFIG_V1_PGLITE);
|
|
146
|
+
(0, crud_deps_1.addMissingDeps)(projectDir, exports.PGLITE_DEPS);
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
// typeorm-pglite 0.3.4 takes an options object; given the data dir as a
|
|
150
|
+
// string it runs in memory, so each command starts from an empty database.
|
|
151
|
+
// { dataDir } works with 0.3.2 too.
|
|
152
|
+
const fixed = current.replace(/new PGliteDriver\(\s*process\.env\.PGLITE_DATA_DIR(?:\s*\|\|\s*undefined)?\s*\)/g, "new PGliteDriver({ dataDir: process.env.PGLITE_DATA_DIR })");
|
|
153
|
+
if (fixed === current)
|
|
154
|
+
return false;
|
|
155
|
+
fs.writeFileSync(file, fixed);
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
exports.upgradeOrmConfigForPglite = upgradeOrmConfigForPglite;
|
package/dist/lib/verify/index.js
CHANGED
|
@@ -173,11 +173,13 @@ async function verifyMigration(projectDir, baselineApsorc, migrationFile, cliBin
|
|
|
173
173
|
try {
|
|
174
174
|
if (!done(await buildBaseline(projectDir, baselineApsorc, dataDir, cliBin)))
|
|
175
175
|
return { ok: false, steps };
|
|
176
|
-
if (!skipBuild && !done(step("build", await build(projectDir))))
|
|
177
|
-
return { ok: false, steps };
|
|
178
176
|
const compiled = path
|
|
179
177
|
.join("dist", path.relative("src", migrationFile))
|
|
180
178
|
.replace(/\.ts$/, ".js");
|
|
179
|
+
// --skip-build still builds when the migration isn't compiled yet.
|
|
180
|
+
const needsBuild = !skipBuild || !fs.existsSync(path.join(projectDir, compiled));
|
|
181
|
+
if (needsBuild && !done(step("build", await build(projectDir))))
|
|
182
|
+
return { ok: false, steps };
|
|
181
183
|
const migrate = await run(process.execPath, ["-e", RUN_ONE_MIGRATION, compiled], projectDir, (0, exports.pgliteEnv)(dataDir));
|
|
182
184
|
if (!done({ ...step("migrate", migrate), output: tail(migrate.output) }))
|
|
183
185
|
return { ok: false, steps };
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apso/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@apso/cli",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.42.1",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@apso/schema-tools": "^0.2.0",
|
package/oclif.manifest.json
CHANGED