cabloy 5.1.206 → 5.1.207

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 (31) hide show
  1. package/.cabloy-version +1 -1
  2. package/CHANGELOG.md +14 -0
  3. package/package.json +1 -1
  4. package/repo-agent-governance/managed-assets.json +3 -3
  5. package/repo-agent-governance/policies/repository.md +1 -1
  6. package/repo-docs/backend/migration-and-changes.md +27 -8
  7. package/repo-docs/reference/repo-scripts.md +20 -1
  8. package/scripts/init.ts +15 -0
  9. package/vona/packages-cli/cli/package.json +1 -1
  10. package/vona/packages-cli/cli-set-api/package.json +1 -1
  11. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dev.ts +17 -2
  12. package/vona/packages-cli/cli-set-api/test/binDevLifecycle.test.ts +100 -0
  13. package/vona/packages-vona/vona/package.json +1 -1
  14. package/vona/packages-vona/vona-core/package.json +1 -1
  15. package/vona/packages-vona/vona-core/src/lib/framework/cluster.ts +1 -1
  16. package/vona/packages-vona/vona-core/src/lib/framework/processMaster.test.ts +185 -0
  17. package/vona/packages-vona/vona-core/src/lib/framework/processMaster.ts +18 -7
  18. package/vona/packages-vona/vona-core/src/lib/framework/start.test.ts +127 -0
  19. package/vona/packages-vona/vona-mock/package.json +1 -1
  20. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  21. package/vona/src/suite-vendor/a-vona/modules/a-redis/package.json +1 -1
  22. package/vona/src/suite-vendor/a-vona/modules/a-redis/src/service/redis.ts +77 -42
  23. package/vona/src/suite-vendor/a-vona/modules/a-redis/test/redisCleanup.test.ts +378 -0
  24. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  25. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/service/startup.ts +56 -9
  26. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/types/startup.ts +1 -0
  27. package/vona/src/suite-vendor/a-vona/modules/a-startup/test/devSeed.test.ts +104 -0
  28. package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
  29. package/vona/src/suite-vendor/a-vona/modules/a-version/src/service/database.ts +183 -51
  30. package/vona/src/suite-vendor/a-vona/modules/a-version/test/devDatabasePreparation.test.ts +221 -0
  31. package/vona/src/suite-vendor/a-vona/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-startup",
3
- "version": "5.1.18",
3
+ "version": "5.1.19",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "keywords": [
@@ -28,17 +28,22 @@ export class ServiceStartup extends BeanBase {
28
28
  }
29
29
  // clear keys
30
30
  await this._clearResources();
31
+ if (this.app.meta.isDev) {
32
+ await this.bean.executor.newCtx(
33
+ () => this.$scope.version.service.database.prepareDevDatabases(),
34
+ { dbInfo: { level: 1 }, instanceName: null },
35
+ );
36
+ }
31
37
 
32
38
  // run startups: not after
33
39
  for (const startup of this._startups) {
34
40
  const startupOptions = startup.beanOptions.options;
35
41
  if (!startupOptions?.instance && startupOptions?.after !== true) {
36
- // A previous dev startup may have left databaseInit's debounce key in Redis.
37
- // Only the explicit reset must bypass that key to guarantee recreation.
38
42
  const force =
39
43
  this.app.meta.isDev &&
40
- process.env.VONA_DB_RESET === 'true' &&
41
- startup.name === 'a-version:databaseInit';
44
+ startup.name === 'a-version:databaseInit' &&
45
+ (process.env.VONA_DB_RESET === 'true' ||
46
+ this.$scope.version.service.database.createdInstanceNames.length > 0);
42
47
  const run = () => this.runStartup(startup.name, null, force ? { force: true } : undefined);
43
48
  if (this.app.meta.env.VONA_TEST_RUN_ID && startup.name === 'a-version:databaseInit') {
44
49
  const defaultClient = this.app.config.database.defaultClient;
@@ -55,6 +60,25 @@ export class ServiceStartup extends BeanBase {
55
60
  }
56
61
 
57
62
  async appReady() {
63
+ const createdInstances = this.$scope.version.service.database.createdInstanceNames;
64
+ const preparingDev = this.app.meta.isDev && createdInstances.length > 0;
65
+ if (preparingDev) {
66
+ // Initialize and seed fresh instances before listeners or queue workers start.
67
+ const instanceNames = [
68
+ '',
69
+ ...createdInstances.filter(name => name !== ''),
70
+ ] as (keyof IInstanceRecord)[];
71
+ for (const instanceName of instanceNames) {
72
+ await this._appReadyInstanceStartup(instanceName, true, true);
73
+ }
74
+ for (const instanceName of instanceNames) {
75
+ await this.bean.executor.newCtx(() => this.runStartupInstanceAfter(instanceName), {
76
+ dbInfo: { level: 1 },
77
+ instanceName,
78
+ });
79
+ }
80
+ }
81
+
58
82
  // run startups: after
59
83
  for (const startup of this._startups) {
60
84
  const startupOptions = startup.beanOptions.options;
@@ -65,7 +89,7 @@ export class ServiceStartup extends BeanBase {
65
89
 
66
90
  // version init : force: should be false
67
91
  if (this.app.meta.isTest || this.app.meta.isDev) {
68
- await this._appReadyInstanceStartup('', true);
92
+ if (!preparingDev) await this._appReadyInstanceStartup('', true);
69
93
  } else {
70
94
  // only start static instances (defined in config)
71
95
  for (const key in this.app.config.instance.instances) {
@@ -78,8 +102,8 @@ export class ServiceStartup extends BeanBase {
78
102
  }
79
103
  }
80
104
 
81
- // Seed test runs and explicit development resets only, after instance initialization.
82
- if (this.app.meta.isTest || (this.app.meta.isDev && process.env.VONA_DB_RESET === 'true')) {
105
+ // Test seeding retains its existing lifecycle; dev seeding belongs to fresh instances.
106
+ if (this.app.meta.isTest) {
83
107
  await this.seedDefaultInstance();
84
108
  }
85
109
  }
@@ -94,9 +118,17 @@ export class ServiceStartup extends BeanBase {
94
118
  );
95
119
  }
96
120
 
97
- private async _appReadyInstanceStartup(instanceName: keyof IInstanceRecord, wait: boolean) {
121
+ private async _appReadyInstanceStartup(
122
+ instanceName: keyof IInstanceRecord,
123
+ wait: boolean,
124
+ deferAfter?: boolean,
125
+ ) {
98
126
  const res = this.$scope.instance.service.instance.instanceStartupIsolate(instanceName, {
99
- force: this.app.meta.isDev && process.env.VONA_DB_RESET === 'true',
127
+ force:
128
+ this.app.meta.isDev &&
129
+ (process.env.VONA_DB_RESET === 'true' ||
130
+ this.$scope.version.service.database.createdInstanceNames.includes(instanceName)),
131
+ deferAfter,
100
132
  });
101
133
  if (wait) {
102
134
  await res;
@@ -182,6 +214,21 @@ export class ServiceStartup extends BeanBase {
182
214
  await this.runStartup(startup.name, instanceName, options);
183
215
  }
184
216
  }
217
+ if (
218
+ this.app.meta.isDev &&
219
+ this.$scope.version.service.database.createdInstanceNames.includes(instanceName)
220
+ ) {
221
+ await this.$scope.version.service.version.__instanceSeed(instanceName);
222
+ this.$scope.version.service.database.consumeCreatedInstance(instanceName);
223
+ }
224
+ if (options?.deferAfter) return;
225
+ await this.runStartupInstanceAfter(instanceName, options);
226
+ }
227
+
228
+ async runStartupInstanceAfter(
229
+ instanceName: keyof IInstanceRecord,
230
+ options?: IInstanceStartupOptions,
231
+ ) {
185
232
  // set flag
186
233
  this.app.meta.appReadyInstances[instanceName] = true;
187
234
  // run startups: after
@@ -22,6 +22,7 @@ export interface IDecoratorStartupOptions
22
22
 
23
23
  export interface IInstanceStartupOptions {
24
24
  force?: boolean;
25
+ deferAfter?: boolean;
25
26
  configInstanceBase?: ConfigInstanceBase;
26
27
  }
27
28
 
@@ -0,0 +1,104 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+
4
+ import { ServiceStartup } from '../src/service/startup.ts';
5
+
6
+ function fixture(created: string[] = []) {
7
+ const calls: string[] = [];
8
+ const pending = new Set(created);
9
+ const app = {
10
+ meta: { isDev: true, isTest: false, appReadyInstances: {} as Record<string, boolean> },
11
+ config: { server: { listen: { disable: false } } },
12
+ };
13
+ const service = Object.create(ServiceStartup.prototype) as ServiceStartup;
14
+ const startups = [
15
+ { name: 'a-version:instanceInit', beanOptions: { options: { instance: true } } },
16
+ { name: 'a-runtime:runtime', beanOptions: { options: { instance: true, after: true } } },
17
+ { name: 'a-queue:loadQueueWorkers', beanOptions: { options: { instance: true, after: true } } },
18
+ { name: 'a-web:listen', beanOptions: { options: { after: true } } },
19
+ ];
20
+ Object.defineProperties(service, {
21
+ app: { value: app },
22
+ _startups: { value: startups },
23
+ bean: { value: { executor: { newCtx: async (fn: () => Promise<unknown>) => fn() } } },
24
+ $scope: {
25
+ value: {
26
+ version: {
27
+ service: {
28
+ database: {
29
+ get createdInstanceNames() {
30
+ return [...pending];
31
+ },
32
+ consumeCreatedInstance: (name: string) => pending.delete(name),
33
+ },
34
+ version: {
35
+ __instanceSeed: async (name: string) => {
36
+ calls.push(`seed:${name}`);
37
+ },
38
+ },
39
+ },
40
+ },
41
+ instance: {
42
+ service: {
43
+ instance: {
44
+ instanceStartupIsolate: async (name: string, options: any) =>
45
+ service.runStartupInstance(name as never, options),
46
+ },
47
+ },
48
+ },
49
+ },
50
+ },
51
+ runStartup: {
52
+ value: async (name: string, instance: string) => {
53
+ calls.push(`${name}:${instance}`);
54
+ },
55
+ },
56
+ });
57
+ return { service, app, calls, pending };
58
+ }
59
+
60
+ describe('creation-driven dev seed', { concurrency: false }, () => {
61
+ it('seeds fresh instances before runtime, queues, and listening', async () => {
62
+ const { service, calls, pending, app } = fixture(['', 'isolateTest']);
63
+ await service.appReady();
64
+ assert.equal(pending.size, 0);
65
+ const lastSeed = calls.indexOf('seed:isolateTest');
66
+ assert.ok(lastSeed > calls.indexOf('seed:'));
67
+ for (const call of ['a-runtime:runtime:', 'a-queue:loadQueueWorkers:', 'a-web:listen:null']) {
68
+ assert.ok(calls.indexOf(call) > lastSeed, `${call} must follow all seeds`);
69
+ }
70
+ assert.equal(app.meta.appReadyInstances[''], true);
71
+ assert.equal(app.meta.appReadyInstances.isolateTest, true);
72
+ await service.runStartupInstance('' as never);
73
+ assert.equal(calls.filter(call => call === 'seed:').length, 1);
74
+ });
75
+
76
+ it('does not seed existing default when only an isolated database is new', async () => {
77
+ const { service, calls } = fixture(['isolateTest']);
78
+ await service.appReady();
79
+ assert.ok(calls.includes('seed:isolateTest'));
80
+ assert.ok(!calls.includes('seed:'));
81
+ });
82
+
83
+ it('does not seed when all databases are reused', async () => {
84
+ const { service, calls } = fixture();
85
+ await service.appReady();
86
+ assert.ok(!calls.some(call => call.startsWith('seed:')));
87
+ });
88
+
89
+ it('fails before after-startups and readiness if seeding fails', async () => {
90
+ const { service, app, calls, pending } = fixture(['']);
91
+ (service as any).$scope.version.service.version.__instanceSeed = async () => {
92
+ throw new Error('seed failed');
93
+ };
94
+ await assert.rejects(service.appReady(), /seed failed/);
95
+ assert.ok(pending.has(''));
96
+ assert.deepEqual(app.meta.appReadyInstances, {});
97
+ assert.ok(
98
+ !calls.some(
99
+ call =>
100
+ call.includes('runtime') || call.includes('listen') || call.includes('loadQueueWorkers'),
101
+ ),
102
+ );
103
+ });
104
+ });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-version",
3
- "version": "5.1.19",
3
+ "version": "5.1.20",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "vona-module-a-version",
6
6
  "keywords": [
@@ -1,4 +1,4 @@
1
- import type { IInstanceRecord } from 'vona';
1
+ import type { IInstanceRecord, VonaApplication } from 'vona';
2
2
  import type { ConfigInstanceBase } from 'vona-module-a-instance';
3
3
  import type { IDatabaseClientRecord, ServiceDatabaseClient } from 'vona-module-a-orm';
4
4
 
@@ -20,6 +20,26 @@ import { createDatabaseTestName, getDatabaseTestPrefix } from '../lib/databaseTe
20
20
  const __separator = '-';
21
21
  const __timeFormat = `yyyyMMdd${__separator}HHmmss`;
22
22
 
23
+ interface IDevDatabaseTarget {
24
+ clientName: keyof IDatabaseClientRecord;
25
+ instanceName?: keyof IInstanceRecord;
26
+ configInstanceBase?: ConfigInstanceBase;
27
+ }
28
+
29
+ interface IDevDatabasePlan extends IDevDatabaseTarget {
30
+ databasePrefix: string;
31
+ sqliteRoot?: string;
32
+ databases: string[];
33
+ create: boolean;
34
+ }
35
+
36
+ interface IDevDatabasePreparation {
37
+ prepared: boolean;
38
+ createdInstances: Set<keyof IInstanceRecord>;
39
+ }
40
+
41
+ const devDatabasePreparations = new WeakMap<VonaApplication, IDevDatabasePreparation>();
42
+
23
43
  export function assertDisposableDatabaseName(
24
44
  databaseName: string,
25
45
  databasePrefix: string,
@@ -49,6 +69,110 @@ export class ServiceDatabase extends BeanBase {
49
69
  return getDatabaseTestPrefix(this.app.name, scope);
50
70
  }
51
71
 
72
+ get createdInstanceNames(): (keyof IInstanceRecord)[] {
73
+ return [...(devDatabasePreparations.get(this.app)?.createdInstances ?? [])];
74
+ }
75
+
76
+ consumeCreatedInstance(instanceName: keyof IInstanceRecord) {
77
+ devDatabasePreparations.get(this.app)?.createdInstances.delete(instanceName);
78
+ }
79
+
80
+ public async prepareDevDatabases(reset = process.env.VONA_DB_RESET === 'true') {
81
+ if (!this.app.meta.isDev) return;
82
+ if (!this.configDatabase.testDatabase) {
83
+ if (reset) {
84
+ throw new Error('db:reset requires database.testDatabase=true in the dev configuration');
85
+ }
86
+ return;
87
+ }
88
+ if (devDatabasePreparations.get(this.app)?.prepared) return;
89
+
90
+ if (typeof this.configDatabase.defaultClient !== 'string') {
91
+ throw new TypeError('Disposable dev database preparation requires a static default client');
92
+ }
93
+ // Validate every target before clearing any application resources.
94
+ const plans: IDevDatabasePlan[] = [];
95
+ const clientNames = new Set<keyof IDatabaseClientRecord>();
96
+ for (const target of this.__databaseTargets()) {
97
+ if (target.configInstanceBase?.isolate && !target.configInstanceBase.id) {
98
+ throw new Error(`should specify id for isolate instance: ${target.instanceName}`);
99
+ }
100
+ const clientName = this.$scope.orm.service.database.prepareClientNameReal(target.clientName);
101
+ if (clientNames.has(clientName)) {
102
+ throw new Error(`Disposable database targets must use distinct clients: ${clientName}`);
103
+ }
104
+ clientNames.add(clientName);
105
+ plans.push(
106
+ await this.bean.database.switchDb(async () => {
107
+ const client = this.bean.database.current.client;
108
+ const databasePrefix = this.getDatabasePrefix(
109
+ target.instanceName,
110
+ target.configInstanceBase,
111
+ );
112
+ const sqliteRoot = this.__sqliteRoot(client);
113
+ const currentName = client.getDatabaseName();
114
+ const currentFilename = sqliteRoot ? path.basename(currentName, '.db') : currentName;
115
+ if (currentFilename.startsWith(databasePrefix)) {
116
+ assertDisposableDatabaseName(currentName, databasePrefix, sqliteRoot);
117
+ if (reset) {
118
+ throw new Error('db:reset requires a connection outside the disposable database');
119
+ }
120
+ }
121
+ const dbs = await this.__fetchDatabases(
122
+ client,
123
+ target.instanceName,
124
+ target.configInstanceBase,
125
+ );
126
+ for (const db of dbs) {
127
+ assertDisposableDatabaseName(db.name, databasePrefix, sqliteRoot);
128
+ }
129
+ return {
130
+ ...target,
131
+ databasePrefix,
132
+ sqliteRoot,
133
+ databases: dbs.map(db => db.name),
134
+ create: reset,
135
+ };
136
+ }, target.clientName),
137
+ );
138
+ }
139
+
140
+ if (!reset) {
141
+ const missing = plans.find(plan => plan.databases.length === 0);
142
+ if (missing) this.__missingDevDatabase(missing.instanceName);
143
+ }
144
+
145
+ if (reset) {
146
+ await this.$scope.redis.service.redis.clearAllData();
147
+ await this.bean.worker.setAlive();
148
+ }
149
+ const preparation: IDevDatabasePreparation = {
150
+ prepared: false,
151
+ createdInstances: new Set(),
152
+ };
153
+ for (const plan of plans) {
154
+ await this.bean.database.switchDb(async () => {
155
+ const client = this.bean.database.current.client;
156
+ if (reset) {
157
+ for (const databaseName of plan.databases) {
158
+ assertDisposableDatabaseName(databaseName, plan.databasePrefix, plan.sqliteRoot);
159
+ await client.connection.schema.dropDatabase(databaseName);
160
+ }
161
+ }
162
+ const databaseName = plan.create
163
+ ? await this.__createDatabase(client, plan.instanceName, plan.configInstanceBase)
164
+ : plan.databases[0];
165
+ assertDisposableDatabaseName(databaseName, plan.databasePrefix, plan.sqliteRoot);
166
+ await client.changeConfigConnectionAndReloadWorker(databaseName);
167
+ if (plan.create) preparation.createdInstances.add(plan.instanceName ?? '');
168
+ this.$logger.silly(chalk.cyan(`dialect: ${client.db.dialectName}`));
169
+ this.$logger.silly(chalk.cyan(`database: ${databaseName}, pid: ${process.pid}`));
170
+ }, plan.clientName);
171
+ }
172
+ preparation.prepared = true;
173
+ devDatabasePreparations.set(this.app, preparation);
174
+ }
175
+
52
176
  public async databaseInitStartup() {
53
177
  // database
54
178
  await this.__prepareDatabases(true);
@@ -97,22 +221,41 @@ export class ServiceDatabase extends BeanBase {
97
221
  return await client.connection.schema.createDatabase(databaseName);
98
222
  }
99
223
 
100
- private async __prepareDatabases(versionStart: boolean) {
101
- // default
102
- await this.prepareDatabase('default', versionStart);
103
- // isolate
224
+ private __databaseTargets(): IDevDatabaseTarget[] {
225
+ const targets: IDevDatabaseTarget[] = [{ clientName: 'default' }];
104
226
  for (const key in this.app.config.instance.instances) {
105
227
  const instanceName = key as keyof IInstanceRecord;
106
228
  const configInstanceBase = this.app.config.instance.instances[instanceName];
107
- if (configInstanceBase === false) continue;
108
- if (!configInstanceBase.isolate) continue;
109
- if (!configInstanceBase.isolateClient)
229
+ if (configInstanceBase === false || !configInstanceBase.isolate) continue;
230
+ if (!configInstanceBase.isolateClient) {
110
231
  throw new Error(`should specify isolateClient for isolate instance: ${instanceName}`);
111
- await this.prepareDatabase(
112
- configInstanceBase.isolateClient,
113
- versionStart,
232
+ }
233
+ targets.push({
234
+ clientName: configInstanceBase.isolateClient,
114
235
  instanceName,
115
236
  configInstanceBase,
237
+ });
238
+ }
239
+ return targets;
240
+ }
241
+
242
+ private __sqliteRoot(client: ServiceDatabaseClient) {
243
+ return client.db.dialectName === 'better-sqlite3'
244
+ ? resolveVonaLocalPaths(
245
+ this.app.projectPath,
246
+ this.app.meta.env.META_MODE,
247
+ this.app.meta.env.VONA_TEST_RUN_ID,
248
+ ).sqliteRoot
249
+ : undefined;
250
+ }
251
+
252
+ private async __prepareDatabases(versionStart: boolean) {
253
+ for (const target of this.__databaseTargets()) {
254
+ await this.prepareDatabase(
255
+ target.clientName,
256
+ versionStart,
257
+ target.instanceName,
258
+ target.configInstanceBase,
116
259
  );
117
260
  }
118
261
  }
@@ -122,14 +265,36 @@ export class ServiceDatabase extends BeanBase {
122
265
  instanceName?: keyof IInstanceRecord,
123
266
  configInstanceBase?: ConfigInstanceBase,
124
267
  ) {
125
- await this.__prepareDatabaseInner(versionStart, instanceName, configInstanceBase);
268
+ await this.__prepareDatabaseInner(instanceName, configInstanceBase);
126
269
  if (versionStart) {
127
270
  await this.scope.service.version.__start();
128
271
  }
129
272
  }
130
273
 
274
+ private __missingDevDatabase(instanceName?: keyof IInstanceRecord): never {
275
+ // eslint-disable-next-line
276
+ console.error(
277
+ [
278
+ '',
279
+ chalk.bgRed.white.bold(' DEVELOPMENT DATABASE MISSING '),
280
+ chalk.yellow(`Instance: ${instanceName || 'default'}`),
281
+ '',
282
+ chalk.bold.yellow('Run this command before starting the development server:'),
283
+ '',
284
+ chalk.bold.cyan(' npm run db:reset'),
285
+ '',
286
+ chalk.yellow('Warning: db:reset deletes managed development data.'),
287
+ chalk.yellow('Stop processes using the same database and Redis namespace first.'),
288
+ '',
289
+ ].join('\n'),
290
+ );
291
+ throw new Error(
292
+ `Development database is missing for instance "${instanceName || 'default'}". ` +
293
+ 'Run "npm run db:reset" before starting the development server.',
294
+ );
295
+ }
296
+
131
297
  private async __prepareDatabaseInner(
132
- versionStart: boolean,
133
298
  instanceName?: keyof IInstanceRecord,
134
299
  configInstanceBase?: ConfigInstanceBase,
135
300
  ) {
@@ -137,6 +302,10 @@ export class ServiceDatabase extends BeanBase {
137
302
  // donothing
138
303
  return;
139
304
  }
305
+ if (this.app.meta.isDev) {
306
+ await this.prepareDevDatabases();
307
+ return;
308
+ }
140
309
  const databasePrefix = this.getDatabasePrefix(instanceName, configInstanceBase);
141
310
  if (this.app.meta.env.VONA_TEST_RUN_ID) {
142
311
  const paths = resolveVonaLocalPaths(
@@ -149,16 +318,7 @@ export class ServiceDatabase extends BeanBase {
149
318
  // client
150
319
  const client = this.bean.database.current.client;
151
320
  // get current database name
152
- let databaseName = client.getDatabaseName();
153
- // dev/debug db
154
- if (this.app.meta.isDev) {
155
- const reset = versionStart && process.env.VONA_DB_RESET === 'true';
156
- // Never drop a configured, non-disposable development database.
157
- if (reset && !this.configDatabase.testDatabase) {
158
- throw new Error('db:reset requires database.testDatabase=true in the dev configuration');
159
- }
160
- if (!this.configDatabase.testDatabase) return;
161
- }
321
+ const databaseName = client.getDatabaseName();
162
322
  const sqliteRoot =
163
323
  client.db.dialectName === 'better-sqlite3'
164
324
  ? resolveVonaLocalPaths(
@@ -180,34 +340,6 @@ export class ServiceDatabase extends BeanBase {
180
340
  `Isolated test database is outside its disposable namespace: ${databaseName}`,
181
341
  );
182
342
  }
183
- // dev/debug db
184
- if (this.app.meta.isDev) {
185
- const reset = versionStart && process.env.VONA_DB_RESET === 'true';
186
- // The database used to enumerate/drop databases must not itself be dropped.
187
- if (isTestDatabase) {
188
- if (reset)
189
- throw new Error('db:reset requires a connection outside the disposable database');
190
- return;
191
- }
192
- const dbs = await this.__fetchDatabases(client, instanceName, configInstanceBase);
193
- for (const db of dbs) {
194
- assertDisposableDatabaseName(db.name, databasePrefix, sqliteRoot);
195
- }
196
- if (reset) {
197
- for (const db of dbs) {
198
- await client.connection.schema.dropDatabase(db.name);
199
- }
200
- }
201
- databaseName =
202
- reset || dbs.length === 0
203
- ? await this.__createDatabase(client, instanceName, configInstanceBase)
204
- : dbs[0].name;
205
- assertDisposableDatabaseName(databaseName, databasePrefix, sqliteRoot);
206
- // set config and reload client
207
- await client.changeConfigConnectionAndReloadWorker(databaseName);
208
- this.$logger.silly(chalk.cyan(`dialect: ${client.db.dialectName}`));
209
- this.$logger.silly(chalk.cyan(`database: ${databaseName}, pid: ${process.pid}`));
210
- }
211
343
  // test db
212
344
  if (this.app.meta.isTest) {
213
345
  // check