vona-cli-set-api 1.1.156 → 1.1.159
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/index.js +80 -31
- package/dist/lib/bean/toolsBin/resolveTestCleanupConfig.d.ts +15 -0
- package/dist/lib/bean/toolsBin/testCleanupAdapters.d.ts +17 -0
- package/dist/lib/bean/toolsBin/testCleanupProcess.d.ts +1 -0
- package/dist/lib/utils.d.ts +1 -1
- package/dist-toolsIsolate/dbReset.js +19 -2
- package/package.json +4 -4
- package/templates/config/_tsconfig_project.json +1 -0
- package/templates/config/_tsconfig_source.json +1 -0
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { rollup } from 'rollup';
|
|
|
15
15
|
import compileTemplate from 'lodash/template.js';
|
|
16
16
|
import { createRequire } from 'node:module';
|
|
17
17
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
18
|
+
import { resolveTestRunId, TEST_RUN_ID_ENV, getTestAppName, resolveVonaLocalPaths, assertTestRunOwner, beanFullNameFromOnionName } from 'vona-core';
|
|
18
19
|
import * as dotenv from '@cabloy/dotenv';
|
|
19
20
|
import { getEnvFiles } from '@cabloy/dotenv';
|
|
20
21
|
import { glob } from '@cabloy/module-glob';
|
|
@@ -27,7 +28,6 @@ import { getOnionScenesMeta, getOnionMetasMeta, relativeNameToCapitalize } from
|
|
|
27
28
|
import { toUpperCaseFirstChar, stringToCapitalize, replaceTemplate as replaceTemplate$1 } from '@cabloy/word-utils';
|
|
28
29
|
import fs from 'node:fs';
|
|
29
30
|
import gogocode from 'gogocode';
|
|
30
|
-
import { beanFullNameFromOnionName } from 'vona-core';
|
|
31
31
|
|
|
32
32
|
function getEnvMeta(configMeta) {
|
|
33
33
|
return {
|
|
@@ -98,9 +98,8 @@ function copyTemplateIfNeed(fileSrc, fileDest) {
|
|
|
98
98
|
fse.copyFileSync(fileSrc, fileDest);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
function getImportEsm() {
|
|
102
|
-
|
|
103
|
-
return '--import=./.vona/register.js';
|
|
101
|
+
function getImportEsm(runtimeDir = '.vona') {
|
|
102
|
+
return `--import=./${runtimeDir}/register.js`;
|
|
104
103
|
}
|
|
105
104
|
|
|
106
105
|
function createConfigUtils(configMeta, configOptions) {
|
|
@@ -115,6 +114,10 @@ function createConfigUtils(configMeta, configOptions) {
|
|
|
115
114
|
function __loadEnvs() {
|
|
116
115
|
const meta = getEnvMeta(configMeta);
|
|
117
116
|
const envDir = path.join(configOptions.appDir, 'env');
|
|
117
|
+
const runId = resolveTestRunId(meta.mode, process.env[TEST_RUN_ID_ENV]);
|
|
118
|
+
if (runId && process.env.VONA_DB_RESET !== undefined) {
|
|
119
|
+
throw new Error('Isolated test cannot run a development database reset');
|
|
120
|
+
}
|
|
118
121
|
const envs = dotenv.loadEnvs(meta, envDir, '.env');
|
|
119
122
|
const res = Object.assign({
|
|
120
123
|
NODE_ENV: getNodeEnv(meta.mode)
|
|
@@ -122,6 +125,20 @@ function createConfigUtils(configMeta, configOptions) {
|
|
|
122
125
|
META_FLAVOR: meta.flavor,
|
|
123
126
|
META_MODE: meta.mode
|
|
124
127
|
});
|
|
128
|
+
if (runId) {
|
|
129
|
+
res[TEST_RUN_ID_ENV] = runId;
|
|
130
|
+
res.APP_NAME = getTestAppName(runId);
|
|
131
|
+
const port = Number(process.env.SERVER_LISTEN_PORT);
|
|
132
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
133
|
+
throw new Error('Isolated test requires an assigned SERVER_LISTEN_PORT');
|
|
134
|
+
}
|
|
135
|
+
res.SERVER_LISTEN_PORT = String(port);
|
|
136
|
+
res.SERVER_LISTEN_HOSTNAME = '127.0.0.1';
|
|
137
|
+
if (process.env.VONA_TEST_SERVER_ORIGIN === 'true') {
|
|
138
|
+
res.SERVER_SERVE_PROTOCOL = 'http';
|
|
139
|
+
res.SERVER_SERVE_HOST = `127.0.0.1:${port}`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
125
142
|
if (configOptions.workers !== undefined) {
|
|
126
143
|
res.SERVER_WORKERS = configOptions.workers.toString();
|
|
127
144
|
}
|
|
@@ -133,8 +150,8 @@ function createConfigUtils(configMeta, configOptions) {
|
|
|
133
150
|
res.SERVER_WORKERS = '1';
|
|
134
151
|
}
|
|
135
152
|
}
|
|
136
|
-
for (const key of ['NODE_ENV', 'SERVER_WORKERS', 'META_FLAVOR', 'META_MODE']) {
|
|
137
|
-
if (res[key] !== false) {
|
|
153
|
+
for (const key of ['NODE_ENV', 'SERVER_WORKERS', 'META_FLAVOR', 'META_MODE', TEST_RUN_ID_ENV]) {
|
|
154
|
+
if (res[key] !== undefined && res[key] !== false) {
|
|
138
155
|
process.env[key] = res[key];
|
|
139
156
|
}
|
|
140
157
|
}
|
|
@@ -257,6 +274,14 @@ async function generateEntryFiles(configMeta, configOptions, modulesMeta, env) {
|
|
|
257
274
|
}
|
|
258
275
|
|
|
259
276
|
async function generateVonaMeta(configMeta, configOptions) {
|
|
277
|
+
const paths = resolveVonaLocalPaths(configOptions.appDir, configMeta.mode);
|
|
278
|
+
if (paths.runId) {
|
|
279
|
+
if (configOptions.runtimeDir !== paths.generatedDir) {
|
|
280
|
+
throw new Error('Isolated test generated directory does not match its run ID');
|
|
281
|
+
}
|
|
282
|
+
assertTestRunOwner(paths.dataRoot, paths.runId);
|
|
283
|
+
assertTestRunOwner(paths.generatedRoot, paths.runId);
|
|
284
|
+
}
|
|
260
285
|
// config utils
|
|
261
286
|
const configUtils = createConfigUtils(configMeta, configOptions);
|
|
262
287
|
// env
|
|
@@ -725,29 +750,33 @@ class CliBinDbReset extends BeanCliBase {
|
|
|
725
750
|
// super
|
|
726
751
|
await super.execute();
|
|
727
752
|
const projectPath = argv.projectPath;
|
|
728
|
-
//
|
|
753
|
+
// recreate the development database
|
|
729
754
|
await this._dbReset(projectPath);
|
|
730
755
|
}
|
|
731
756
|
async _dbReset(projectPath) {
|
|
732
757
|
const {
|
|
733
758
|
argv
|
|
734
759
|
} = this.context;
|
|
735
|
-
const mode = '
|
|
760
|
+
const mode = 'dev';
|
|
736
761
|
const flavor = argv.flavor || 'normal';
|
|
737
762
|
const configMeta = {
|
|
738
763
|
flavor,
|
|
739
764
|
mode
|
|
740
765
|
};
|
|
766
|
+
const paths = resolveVonaLocalPaths(projectPath, mode);
|
|
741
767
|
const configOptions = {
|
|
742
768
|
appDir: projectPath,
|
|
743
|
-
runtimeDir:
|
|
769
|
+
runtimeDir: paths.generatedDir,
|
|
744
770
|
workers: 1
|
|
745
771
|
};
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
772
|
+
try {
|
|
773
|
+
const {
|
|
774
|
+
modulesMeta
|
|
775
|
+
} = await generateVonaMeta(configMeta, configOptions);
|
|
776
|
+
await this._run(projectPath, modulesMeta);
|
|
777
|
+
} finally {
|
|
778
|
+
await rimraf(paths.generatedRoot);
|
|
779
|
+
}
|
|
751
780
|
}
|
|
752
781
|
async _run(projectPath, _modulesMeta) {
|
|
753
782
|
// testFile
|
|
@@ -757,7 +786,7 @@ class CliBinDbReset extends BeanCliBase {
|
|
|
757
786
|
}
|
|
758
787
|
// run
|
|
759
788
|
let args = [];
|
|
760
|
-
args = args.concat([getImportEsm(), testFile, projectPath]);
|
|
789
|
+
args = args.concat([getImportEsm(resolveVonaLocalPaths(projectPath, 'dev').generatedDir), testFile, projectPath]);
|
|
761
790
|
// args = args.concat(['--experimental-transform-types', getImportEsm(), testFile, projectPath]);
|
|
762
791
|
await this.helper.spawnExe({
|
|
763
792
|
cmd: 'node',
|
|
@@ -801,9 +830,10 @@ class CliBinDev extends BeanCliBase {
|
|
|
801
830
|
flavor,
|
|
802
831
|
mode
|
|
803
832
|
};
|
|
833
|
+
const paths = resolveVonaLocalPaths(projectPath, mode);
|
|
804
834
|
const configOptions = {
|
|
805
835
|
appDir: projectPath,
|
|
806
|
-
runtimeDir:
|
|
836
|
+
runtimeDir: paths.generatedDir,
|
|
807
837
|
workers
|
|
808
838
|
};
|
|
809
839
|
try {
|
|
@@ -816,11 +846,12 @@ class CliBinDev extends BeanCliBase {
|
|
|
816
846
|
await this._run(projectPath, modulesMeta);
|
|
817
847
|
}
|
|
818
848
|
} finally {
|
|
819
|
-
await rimraf(
|
|
849
|
+
if (!paths.runId) await rimraf(paths.generatedRoot);
|
|
820
850
|
}
|
|
821
851
|
}
|
|
822
852
|
async _runTest(projectPath) {
|
|
823
|
-
const
|
|
853
|
+
const generatedDir = resolveVonaLocalPaths(projectPath, 'test').generatedDir;
|
|
854
|
+
const child = spawn(process.execPath, [getImportEsm(generatedDir), `${generatedDir}/bootstrap.ts`], {
|
|
824
855
|
cwd: projectPath,
|
|
825
856
|
stdio: 'inherit'
|
|
826
857
|
});
|
|
@@ -843,7 +874,8 @@ class CliBinDev extends BeanCliBase {
|
|
|
843
874
|
}
|
|
844
875
|
async _run(projectPath, _modulesMeta) {
|
|
845
876
|
let closed = false;
|
|
846
|
-
|
|
877
|
+
let crashError;
|
|
878
|
+
return new Promise((resolve, reject) => {
|
|
847
879
|
nodemon({
|
|
848
880
|
script: '.vona/bootstrap.ts',
|
|
849
881
|
cwd: projectPath,
|
|
@@ -855,9 +887,22 @@ class CliBinDev extends BeanCliBase {
|
|
|
855
887
|
watch: ['packages-utils', 'packages-vona', './src'],
|
|
856
888
|
ignore: ['**/node_modules/**', '**/dist/**', '**/test/**/*.test.ts', 'src/backend/play/**', 'src/backend/typing/**', '**/src/config/errors.ts', '**/src/config/locale/*.ts', '**/src/config/config.ts', '**/src/config/constants.ts', '**/src/types/**', '**/src/controller/*.ts(x)?', '**/src/model/*.ts', '**/src/service/*.ts', '**/src/bean/*.*.ts', '**/src/dto/*.ts(x)?', '**/src/entity/*.ts(x)?']
|
|
857
889
|
});
|
|
858
|
-
nodemon.on('
|
|
890
|
+
nodemon.on('crash', () => {
|
|
891
|
+
if (closed) return;
|
|
859
892
|
closed = true;
|
|
860
|
-
|
|
893
|
+
// nodemon emits crash without an error payload; the child already logged the cause.
|
|
894
|
+
crashError = new Error('Development server crashed; see the startup error above');
|
|
895
|
+
// Let nodemon finish processing the child exit before stopping its watchers.
|
|
896
|
+
setImmediate(() => nodemon.emit('quit'));
|
|
897
|
+
}).on('quit', () => {
|
|
898
|
+
closed = true;
|
|
899
|
+
if (crashError) {
|
|
900
|
+
// The programmatic quit event does not close watchers; reset before propagating
|
|
901
|
+
// the failure to the CLI's error handler, which exits the process immediately.
|
|
902
|
+
nodemon.reset(() => reject(crashError));
|
|
903
|
+
} else {
|
|
904
|
+
resolve(undefined);
|
|
905
|
+
}
|
|
861
906
|
}).on('restart', files => {
|
|
862
907
|
if (closed) {
|
|
863
908
|
// force exit
|
|
@@ -913,7 +958,7 @@ class CliBinPlay extends BeanCliBase {
|
|
|
913
958
|
}
|
|
914
959
|
}
|
|
915
960
|
async _runAttach(projectPath) {
|
|
916
|
-
const runtimeFile = path.join(projectPath, '.
|
|
961
|
+
const runtimeFile = path.join(resolveVonaLocalPaths(projectPath, process.env.META_MODE ?? 'dev').runtimeRoot, '-.json');
|
|
917
962
|
if (!fse.existsSync(runtimeFile)) throw new Error('dev server not running');
|
|
918
963
|
// args
|
|
919
964
|
let args = [];
|
|
@@ -993,19 +1038,23 @@ class CliBinTest extends BeanCliBase {
|
|
|
993
1038
|
flavor,
|
|
994
1039
|
mode
|
|
995
1040
|
};
|
|
1041
|
+
const paths = resolveVonaLocalPaths(projectPath, mode);
|
|
996
1042
|
const configOptions = {
|
|
997
1043
|
appDir: projectPath,
|
|
998
|
-
runtimeDir:
|
|
1044
|
+
runtimeDir: paths.generatedDir,
|
|
999
1045
|
workers: 1
|
|
1000
1046
|
};
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1047
|
+
try {
|
|
1048
|
+
const {
|
|
1049
|
+
modulesMeta
|
|
1050
|
+
} = await generateVonaMeta(configMeta, configOptions);
|
|
1051
|
+
await this._run(projectPath, modulesMeta);
|
|
1052
|
+
if (argv.coverage && !argv.ci) {
|
|
1053
|
+
await this._outputCoverageReportViewer(projectPath);
|
|
1054
|
+
}
|
|
1055
|
+
} finally {
|
|
1056
|
+
if (!paths.runId) await rimraf(paths.generatedRoot);
|
|
1007
1057
|
}
|
|
1008
|
-
await rimraf(path.join(projectPath, '.vona'));
|
|
1009
1058
|
}
|
|
1010
1059
|
async _run(projectPath, modulesMeta) {
|
|
1011
1060
|
const {
|
|
@@ -1031,7 +1080,7 @@ class CliBinTest extends BeanCliBase {
|
|
|
1031
1080
|
if (process.env.TEST_WHYISNODERUNNING === 'true') {
|
|
1032
1081
|
args.push('--import=why-is-node-running/include');
|
|
1033
1082
|
}
|
|
1034
|
-
args = args.concat([getImportEsm(), testFile, projectPath, (!!argv.coverage).toString(), patterns.join(',')]);
|
|
1083
|
+
args = args.concat([getImportEsm(resolveVonaLocalPaths(projectPath, 'test').generatedDir), testFile, projectPath, (!!argv.coverage).toString(), patterns.join(',')]);
|
|
1035
1084
|
// args = args.concat(['--experimental-transform-types', getImportEsm(), testFile, projectPath, (!!argv.coverage).toString(), patterns.join(',')]);
|
|
1036
1085
|
await this.helper.spawnExe({
|
|
1037
1086
|
cmd: 'node',
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TestClaimManifest } from 'vona-core';
|
|
2
|
+
import { VonaApplication } from 'vona-core';
|
|
3
|
+
export interface TestCleanupResolvedConfig {
|
|
4
|
+
databaseOptions: Map<string, Record<string, any>>;
|
|
5
|
+
redisOptions: Map<string, Record<string, any>>;
|
|
6
|
+
}
|
|
7
|
+
export interface TestCleanupConfigDependencies {
|
|
8
|
+
loadEnvs(): NodeJS.ProcessEnv;
|
|
9
|
+
files: string[];
|
|
10
|
+
loadConfig(file: string): Promise<{
|
|
11
|
+
default: (app: VonaApplication) => unknown;
|
|
12
|
+
}>;
|
|
13
|
+
createApp(env: NodeJS.ProcessEnv): VonaApplication;
|
|
14
|
+
}
|
|
15
|
+
export declare function resolveTestCleanupConfig(claim: TestClaimManifest, injected?: TestCleanupConfigDependencies): Promise<TestCleanupResolvedConfig>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface CleanupSqlConnection {
|
|
2
|
+
raw(sql: string): Promise<unknown>;
|
|
3
|
+
destroy(): Promise<unknown>;
|
|
4
|
+
}
|
|
5
|
+
export interface CleanupRedisConnection {
|
|
6
|
+
scan(cursor: string, match: 'MATCH', pattern: string, count: 'COUNT', size: number): Promise<[string, string[]]>;
|
|
7
|
+
unlink(...keys: string[]): Promise<unknown>;
|
|
8
|
+
del(...keys: string[]): Promise<unknown>;
|
|
9
|
+
disconnect(): unknown;
|
|
10
|
+
}
|
|
11
|
+
export declare function quoteCleanupDatabase(name: string, dialect: string): string;
|
|
12
|
+
export declare function dropExactCleanupDatabase(connection: CleanupSqlConnection, dialect: string, name: string, validate: (name: string) => void): Promise<void>;
|
|
13
|
+
export declare function escapeRedisCleanupPattern(prefix: string): string;
|
|
14
|
+
export declare function clearExactRedisPrefix(connection: CleanupRedisConnection, prefix: string, validate: (prefix: string) => void, options?: {
|
|
15
|
+
batchSize?: number;
|
|
16
|
+
maxScans?: number;
|
|
17
|
+
}): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -15,4 +15,4 @@ export declare function pathToHref(fileName: string): string;
|
|
|
15
15
|
export declare function getOutDir(): string;
|
|
16
16
|
export declare function getOutReleasesDir(): string;
|
|
17
17
|
export declare function copyTemplateIfNeed(fileSrc: string, fileDest: string): void;
|
|
18
|
-
export declare function getImportEsm(): string;
|
|
18
|
+
export declare function getImportEsm(runtimeDir?: string): string;
|
|
@@ -3,6 +3,23 @@ const argv = process.argv.slice(2);
|
|
|
3
3
|
const projectPath = argv[0];
|
|
4
4
|
await dbResetRun(projectPath);
|
|
5
5
|
async function dbResetRun(projectPath) {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
if (process.env.META_MODE !== 'dev') {
|
|
7
|
+
throw new Error('db:reset requires dev mode');
|
|
8
|
+
}
|
|
9
|
+
const previousReset = process.env.VONA_DB_RESET;
|
|
10
|
+
process.env.VONA_DB_RESET = 'true';
|
|
11
|
+
try {
|
|
12
|
+
await createGeneralApp(projectPath);
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
try {
|
|
16
|
+
await closeApp();
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
if (previousReset === undefined)
|
|
20
|
+
delete process.env.VONA_DB_RESET;
|
|
21
|
+
else
|
|
22
|
+
process.env.VONA_DB_RESET = previousReset;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
8
25
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vona-cli-set-api",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"gitHead": "
|
|
3
|
+
"version": "1.1.159",
|
|
4
|
+
"gitHead": "47e1e55106b7c76f6545c8ba474f23d9be830453",
|
|
5
5
|
"description": "vona cli-set-api",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"framework",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@rollup/plugin-terser": "^1.0.0",
|
|
63
63
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
64
64
|
"babel-plugin-transform-typescript-metadata": "^0.3.2",
|
|
65
|
-
"babel-plugin-vona-bean-module": "^1.1.
|
|
65
|
+
"babel-plugin-vona-bean-module": "^1.1.9",
|
|
66
66
|
"chalk": "^3.0.0",
|
|
67
67
|
"cli-table3": "^0.6.5",
|
|
68
68
|
"compressing": "^1.10.4",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"ts-node-maintained": "^10.9.6",
|
|
78
78
|
"urllib": "^4.9.0",
|
|
79
79
|
"uuid": "^11.1.0",
|
|
80
|
-
"vona-core": "^5.1.
|
|
80
|
+
"vona-core": "^5.1.45",
|
|
81
81
|
"why-is-node-running": "^3.2.2",
|
|
82
82
|
"yargs-parser": "^22.0.0"
|
|
83
83
|
}
|