cabloy 5.1.220 → 5.1.221

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 (49) hide show
  1. package/.cabloy-version +1 -1
  2. package/.github/workflows/agent-governance.yml +2 -2
  3. package/.github/workflows/create-cabloy.yml +2 -2
  4. package/.github/workflows/docs-pages.yml +2 -2
  5. package/.github/workflows/playwright-e2e.yml +4 -4
  6. package/.github/workflows/vona-cov-pg.yml +2 -2
  7. package/.github/workflows/vona-test-crud.yml +2 -2
  8. package/.github/workflows/vona-test-mysql.yml +2 -2
  9. package/.github/workflows/vona-test-pg.yml +2 -2
  10. package/.github/workflows/vona-test-sqlite3.yml +2 -2
  11. package/.github/workflows/vona-tsc.yml +2 -2
  12. package/.github/workflows/zova-ui.yml +2 -2
  13. package/CHANGELOG.md +11 -0
  14. package/package.json +4 -3
  15. package/repo-docs/frontend/openapi-sdk-guide.md +2 -0
  16. package/repo-docs/reference/repo-scripts.md +5 -1
  17. package/scripts/generateOpenapiIsolated.ts +18 -1
  18. package/scripts/runIsolatedTest.test.ts +9 -1
  19. package/scripts/runIsolatedTest.ts +81 -18
  20. package/scripts/strictGenerationDiagnostics.test.ts +1009 -0
  21. package/scripts/strictGenerationDiagnostics.ts +61 -0
  22. package/vona/package.original.json +3 -2
  23. package/vona/packages-cli/cli/package.json +1 -1
  24. package/vona/packages-cli/cli-set-api/package.json +1 -1
  25. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dev.ts +14 -4
  26. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/generateEntryFiles.ts +6 -1
  27. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/generateVonaMeta.ts +2 -10
  28. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/validateGenerationPaths.ts +27 -0
  29. package/vona/packages-cli/cli-set-api/test/binDevLifecycle.test.ts +1 -1
  30. package/vona/packages-cli/cli-set-api/test/strictGenerationPrivacy.test.ts +439 -0
  31. package/vona/packages-vona/vona/package.json +1 -1
  32. package/vona/packages-vona/vona-core/package.json +1 -1
  33. package/vona/packages-vona/vona-core/src/lib/core/logger/appLogger.ts +10 -2
  34. package/vona/packages-vona/vona-core/src/lib/core/logger/diagnosticLogger.test.ts +268 -68
  35. package/vona/packages-vona/vona-core/src/lib/core/testFreshness.ts +3 -9
  36. package/vona/packages-vona/vona-core/src/lib/core/testStrictMode.ts +9 -0
  37. package/vona/packages-vona/vona-mock/package.json +1 -1
  38. package/vona/pnpm-lock.yaml +542 -236
  39. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  40. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
  41. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/index.ts +11 -0
  42. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/lib/protectedSqliteRegistry.ts +356 -0
  43. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  44. package/zova/package.original.json +3 -2
  45. package/zova/packages-cli/cli/package.json +2 -2
  46. package/zova/packages-cli/cli-set-front/package.json +1 -1
  47. package/zova/packages-cli/cli-set-front/src/lib/common/restDependencyVersions.ts +22 -1
  48. package/zova/packages-cli/cli-set-front/test/restDependencies.test.ts +137 -0
  49. package/zova/pnpm-lock.yaml +442 -564
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona",
3
- "version": "5.1.111",
3
+ "version": "5.1.112",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "Vona is an intuitive, elegant and powerful Node.js framework for rapidly developing enterprise applications of any size",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-core",
3
- "version": "5.1.48",
3
+ "version": "5.1.49",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "vona",
6
6
  "keywords": [
@@ -14,6 +14,7 @@ import type {
14
14
  import { BeanSimple } from '../../bean/beanSimple.ts';
15
15
  import { deepExtend } from '../../utils/util.ts';
16
16
  import { getRequestBoundary } from '../requestBoundary.ts';
17
+ import { requiresFreshTestResources } from '../testStrictMode.ts';
17
18
  import { createDiagnosticLogger, getSuppressedDiagnosticLogger } from './diagnosticLogger.ts';
18
19
 
19
20
  const SymbolLoggerInstances = Symbol('SymbolLoggerInstances');
@@ -31,7 +32,9 @@ export class AppLogger extends BeanSimple {
31
32
  }
32
33
 
33
34
  get(clientName?: keyof ILoggerClientRecord) {
34
- if (getRequestBoundary()) return getSuppressedDiagnosticLogger();
35
+ if (requiresFreshTestResources() || getRequestBoundary()) {
36
+ return getSuppressedDiagnosticLogger();
37
+ }
35
38
  clientName = clientName || 'default';
36
39
  if (!this[SymbolLoggerInstances][clientName]) {
37
40
  const raw = this._createClient(clientName);
@@ -42,7 +45,9 @@ export class AppLogger extends BeanSimple {
42
45
  }
43
46
 
44
47
  child(childName?: keyof ILoggerChildRecord, clientName?: keyof ILoggerClientRecord) {
45
- if (getRequestBoundary()) return getSuppressedDiagnosticLogger();
48
+ if (requiresFreshTestResources() || getRequestBoundary()) {
49
+ return getSuppressedDiagnosticLogger();
50
+ }
46
51
  const logger = this.get(clientName);
47
52
  if (!childName) return logger;
48
53
  return logger.child({ name: childName });
@@ -120,6 +125,9 @@ export class AppLogger extends BeanSimple {
120
125
  | Winston.transports.FileTransportOptions
121
126
  | DailyRotateFile.DailyRotateFileTransportOptions,
122
127
  ) {
128
+ if (requiresFreshTestResources()) {
129
+ throw new Error('Strict test file logger transport is disabled');
130
+ }
123
131
  const dirname = this.app.config.logger.baseDir;
124
132
  if (!fse.existsSync(dirname)) {
125
133
  const [_, err] = catchErrorSync(() => {
@@ -1,10 +1,22 @@
1
1
  import assert from 'node:assert/strict';
2
- import { test } from 'node:test';
2
+ import { afterEach, beforeEach, test } from 'node:test';
3
3
  import * as Winston from 'winston';
4
4
  import Transport from 'winston-transport';
5
5
 
6
6
  import { createRequestBoundary, runWithRequestBoundary } from '../requestBoundary.ts';
7
+ import { requiresFreshTestResources, TEST_REQUIRE_FRESH_RESOURCES_ENV } from '../testStrictMode.ts';
7
8
  import { AppLogger } from './appLogger.ts';
9
+ import { getSuppressedDiagnosticLogger } from './diagnosticLogger.ts';
10
+
11
+ let previousStrictFlag: string | undefined;
12
+ beforeEach(() => {
13
+ previousStrictFlag = process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV];
14
+ delete process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV];
15
+ });
16
+ afterEach(() => {
17
+ if (previousStrictFlag === undefined) delete process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV];
18
+ else process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV] = previousStrictFlag;
19
+ });
8
20
 
9
21
  class MemoryTransport extends Transport {
10
22
  count = 0;
@@ -58,87 +70,275 @@ function payloadProbe() {
58
70
  };
59
71
  }
60
72
 
61
- test('cached diagnostic handlers never expose raw Winston to a request boundary', async () => {
73
+ function throwingProbe() {
74
+ let reads = 0;
75
+ const read = () => {
76
+ reads++;
77
+ throw new Error('Synthetic logger input must not be evaluated');
78
+ };
79
+ return {
80
+ value: new Proxy({}, { get: read, ownKeys: read }),
81
+ read,
82
+ reads: () => reads,
83
+ };
84
+ }
85
+
86
+ test(
87
+ 'cached diagnostic handlers never expose raw Winston to a request boundary',
88
+ { concurrency: false },
89
+ async () => {
90
+ const local = fixture();
91
+ const { raw, logger, sink } = local;
92
+ const exceptions = logger.exceptions;
93
+ const rejections = logger.rejections;
94
+ const probe = payloadProbe();
95
+ try {
96
+ assert.equal(local.factory.get(), logger);
97
+ assert.equal(local.creations(), 1);
98
+ assert.equal(logger.exceptions, exceptions);
99
+ assert.equal(logger.rejections, rejections);
100
+ for (const handler of [exceptions, rejections]) {
101
+ assert.equal(handler.logger, logger);
102
+ assert.equal(Reflect.set(handler, 'logger', raw), false);
103
+ }
104
+ assert.equal(raw.exceptions.logger, raw);
105
+ assert.equal(raw.rejections.logger, raw);
106
+ runWithRequestBoundary(createRequestBoundary(), () => {
107
+ assert.equal(local.factory.get(), getSuppressedDiagnosticLogger());
108
+ assert.equal(local.factory.get('unconfigured' as any), getSuppressedDiagnosticLogger());
109
+ assert.equal(local.factory.child('synthetic' as any), getSuppressedDiagnosticLogger());
110
+ logger.error(probe.payload);
111
+ logger.exceptions.logger.error(probe.payload);
112
+ logger.rejections.logger.error(probe.payload);
113
+ exceptions.logger.error(probe.payload);
114
+ rejections.logger.error(probe.payload);
115
+ });
116
+ assert.equal(probe.reads(), 0);
117
+ assert.equal(sink.count, 0);
118
+ for (const handler of [exceptions, rejections]) {
119
+ const before = probe.reads();
120
+ handler.logger.error(probe.payload);
121
+ assert.ok(probe.reads() > before);
122
+ }
123
+ assert.equal(sink.count, 2);
124
+ const before = probe.reads();
125
+ raw.error(probe.payload);
126
+ assert.ok(probe.reads() > before);
127
+ assert.equal(sink.count, 3);
128
+ } finally {
129
+ await local.close();
130
+ }
131
+ },
132
+ );
133
+
134
+ test(
135
+ 'diagnostic handler methods keep their raw receiver and map fluent returns',
136
+ { concurrency: false },
137
+ async () => {
138
+ const local = fixture();
139
+ try {
140
+ for (const key of ['exceptions', 'rejections'] as const) {
141
+ const rawHandler = local.raw[key];
142
+ const handler = local.logger[key];
143
+ const marker = {};
144
+ const original = rawHandler.getAllInfo;
145
+ Object.defineProperty(rawHandler, 'getAllInfo', {
146
+ configurable: true,
147
+ value(this: typeof rawHandler, value: unknown) {
148
+ assert.equal(this, rawHandler);
149
+ assert.equal(value, marker);
150
+ return this;
151
+ },
152
+ });
153
+ try {
154
+ assert.equal(handler.handlers, rawHandler.handlers);
155
+ assert.equal(handler.getAllInfo(marker as any), handler);
156
+ assert.equal(handler.logger, local.logger);
157
+ } finally {
158
+ Object.defineProperty(rawHandler, 'getAllInfo', {
159
+ configurable: true,
160
+ value: original,
161
+ });
162
+ }
163
+ }
164
+ const exceptions = local.logger.exceptions;
165
+ const rejections = local.logger.rejections;
166
+ local.logger.configure({ transports: [local.sink] });
167
+ assert.notEqual(local.logger.exceptions, exceptions);
168
+ assert.notEqual(local.logger.rejections, rejections);
169
+ assert.equal(local.logger.exceptions.logger, local.logger);
170
+ assert.equal(local.logger.rejections.logger, local.logger);
171
+ assert.equal(exceptions.logger, local.logger);
172
+ assert.equal(rejections.logger, local.logger);
173
+ runWithRequestBoundary(createRequestBoundary(), () => {
174
+ exceptions.logger.error('local');
175
+ rejections.logger.error('local');
176
+ });
177
+ assert.equal(local.sink.count, 0);
178
+ } finally {
179
+ await local.close();
180
+ }
181
+ },
182
+ );
183
+
184
+ test('strict logger bypasses cached clients and payloads', { concurrency: false }, async () => {
62
185
  const local = fixture();
63
- const { raw, logger, sink } = local;
64
- const exceptions = logger.exceptions;
65
- const rejections = logger.rejections;
66
- const probe = payloadProbe();
186
+ const probe = throwingProbe();
67
187
  try {
68
- assert.equal(local.factory.get(), logger);
188
+ process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV] = 'true';
189
+ const suppressed = getSuppressedDiagnosticLogger();
190
+ assert.equal(local.factory.get(), suppressed);
191
+ assert.equal(local.factory.get('unconfigured' as any), suppressed);
192
+ assert.equal(local.factory.child('synthetic' as any), suppressed);
193
+ assert.equal(local.factory.child('synthetic' as any, 'unconfigured' as any), suppressed);
194
+ assert.notEqual(suppressed, local.logger);
195
+ assert.equal(suppressed.error(probe.value), suppressed);
196
+ assert.equal(suppressed.info(probe.value), suppressed);
197
+ assert.equal(suppressed.log(probe.value as any), suppressed);
198
+ assert.equal(suppressed.child(probe.value), suppressed);
199
+ assert.equal(suppressed.startTimer().done(probe.value), suppressed);
200
+ let completions = 0;
201
+ assert.equal(
202
+ suppressed.write(probe.value, () => completions++),
203
+ true,
204
+ );
205
+ assert.equal(completions, 1);
206
+ assert.equal(probe.reads(), 0);
69
207
  assert.equal(local.creations(), 1);
70
- assert.equal(logger.exceptions, exceptions);
71
- assert.equal(logger.rejections, rejections);
72
- for (const handler of [exceptions, rejections]) {
73
- assert.equal(handler.logger, logger);
74
- assert.equal(Reflect.set(handler, 'logger', raw), false);
208
+ assert.equal(local.sink.count, 0);
209
+ delete process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV];
210
+ assert.equal(local.factory.get(), local.logger);
211
+ local.factory.child().info('ordinary logging remains available');
212
+ assert.equal(local.sink.count, 1);
213
+ } finally {
214
+ await local.close();
215
+ }
216
+ });
217
+
218
+ test('strict entry guards precede cache and app access', { concurrency: false }, async () => {
219
+ const local = fixture();
220
+ const probe = throwingProbe();
221
+ const descriptors = Object.getOwnPropertyDescriptors(local.factory);
222
+ const cacheKeys = Object.getOwnPropertySymbols(local.factory);
223
+ try {
224
+ assert.equal(cacheKeys.length, 2);
225
+ for (const key of cacheKeys) {
226
+ Object.defineProperty(local.factory, key, { configurable: true, get: probe.read });
75
227
  }
76
- assert.equal(raw.exceptions.logger, raw);
77
- assert.equal(raw.rejections.logger, raw);
78
- runWithRequestBoundary(createRequestBoundary(), () => {
79
- logger.error(probe.payload);
80
- logger.exceptions.logger.error(probe.payload);
81
- logger.rejections.logger.error(probe.payload);
82
- exceptions.logger.error(probe.payload);
83
- rejections.logger.error(probe.payload);
84
- });
228
+ Object.defineProperty(local.factory, 'app', { configurable: true, get: probe.read });
229
+ process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV] = 'true';
230
+ assert.equal(local.factory.get(), getSuppressedDiagnosticLogger());
231
+ assert.equal(local.factory.get(probe.value as any), getSuppressedDiagnosticLogger());
232
+ Object.defineProperty(local.factory, 'get', { configurable: true, get: probe.read });
233
+ assert.equal(local.factory.child(), getSuppressedDiagnosticLogger());
234
+ assert.equal(
235
+ local.factory.child(probe.value as any, probe.value as any),
236
+ getSuppressedDiagnosticLogger(),
237
+ );
238
+ assert.equal(local.creations(), 1);
85
239
  assert.equal(probe.reads(), 0);
86
- assert.equal(sink.count, 0);
87
- for (const handler of [exceptions, rejections]) {
88
- const before = probe.reads();
89
- handler.logger.error(probe.payload);
90
- assert.ok(probe.reads() > before);
91
- }
92
- assert.equal(sink.count, 2);
93
- const before = probe.reads();
94
- raw.error(probe.payload);
95
- assert.ok(probe.reads() > before);
96
- assert.equal(sink.count, 3);
240
+ assert.equal(local.sink.count, 0);
97
241
  } finally {
242
+ delete (local.factory as any).get;
243
+ delete (local.factory as any).app;
244
+ Object.defineProperties(local.factory, descriptors);
98
245
  await local.close();
99
246
  }
100
247
  });
101
248
 
102
- test('diagnostic handler methods keep their raw receiver and map fluent returns', async () => {
249
+ test('strict logger skips real configuration factories', { concurrency: false }, async () => {
250
+ const factory = new AppLogger();
251
+ const probe = throwingProbe();
252
+ let configurations = 0;
253
+ Object.defineProperty(factory, 'app', {
254
+ value: {
255
+ config: {
256
+ logger: {
257
+ base() {
258
+ configurations++;
259
+ return probe.read();
260
+ },
261
+ clients: {
262
+ default() {
263
+ configurations++;
264
+ return probe.read();
265
+ },
266
+ },
267
+ get baseDir() {
268
+ return probe.read();
269
+ },
270
+ get rotate() {
271
+ return probe.read();
272
+ },
273
+ },
274
+ },
275
+ },
276
+ });
277
+ try {
278
+ process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV] = 'true';
279
+ assert.equal(factory.get(), getSuppressedDiagnosticLogger());
280
+ assert.equal(factory.child('synthetic' as any), getSuppressedDiagnosticLogger());
281
+ assert.equal(configurations, 0);
282
+ assert.equal(probe.reads(), 0);
283
+ } finally {
284
+ await factory.dispose();
285
+ }
286
+ });
287
+
288
+ test('strict file transport fails before any input access', { concurrency: false }, () => {
289
+ const factory = new AppLogger();
290
+ const probe = throwingProbe();
291
+ const args = [probe.value, probe.value, probe.value] as unknown as Parameters<
292
+ AppLogger['createTransportFile']
293
+ >;
294
+ Object.defineProperty(factory, 'app', { get: probe.read });
295
+ process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV] = 'true';
296
+ assert.throws(() => factory.createTransportFile(...args), {
297
+ message: 'Strict test file logger transport is disabled',
298
+ });
299
+ runWithRequestBoundary(createRequestBoundary(), () => {
300
+ assert.throws(() => factory.createTransportFile(...args), {
301
+ message: 'Strict test file logger transport is disabled',
302
+ });
303
+ });
304
+ assert.equal(probe.reads(), 0);
305
+ });
306
+
307
+ test('invalid strict flags never fall back to loggers', { concurrency: false }, async () => {
103
308
  const local = fixture();
309
+ const probe = throwingProbe();
310
+ Object.defineProperty(local.factory, 'app', { get: probe.read });
311
+ const args = [probe.value, probe.value, probe.value] as unknown as Parameters<
312
+ AppLogger['createTransportFile']
313
+ >;
104
314
  try {
105
- for (const key of ['exceptions', 'rejections'] as const) {
106
- const rawHandler = local.raw[key];
107
- const handler = local.logger[key];
108
- const marker = {};
109
- const original = rawHandler.getAllInfo;
110
- Object.defineProperty(rawHandler, 'getAllInfo', {
111
- configurable: true,
112
- value(this: typeof rawHandler, value: unknown) {
113
- assert.equal(this, rawHandler);
114
- assert.equal(value, marker);
115
- return this;
116
- },
117
- });
118
- try {
119
- assert.equal(handler.handlers, rawHandler.handlers);
120
- assert.equal(handler.getAllInfo(marker as any), handler);
121
- assert.equal(handler.logger, local.logger);
122
- } finally {
123
- Object.defineProperty(rawHandler, 'getAllInfo', {
124
- configurable: true,
125
- value: original,
126
- });
315
+ const env: NodeJS.ProcessEnv = { NODE_ENV: 'test', META_FLAVOR: 'normal', META_MODE: 'test' };
316
+ assert.equal(requiresFreshTestResources(), false);
317
+ assert.equal(requiresFreshTestResources(env), false);
318
+ assert.equal(
319
+ requiresFreshTestResources({ ...env, [TEST_REQUIRE_FRESH_RESOURCES_ENV]: 'true' }),
320
+ true,
321
+ );
322
+ for (const flag of ['', 'false', 'TRUE', 'synthetic-invalid-flag']) {
323
+ process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV] = flag;
324
+ const expected = { message: 'Invalid strict test resource freshness flag' };
325
+ assert.throws(() => requiresFreshTestResources(), expected);
326
+ assert.throws(
327
+ () => requiresFreshTestResources({ ...env, [TEST_REQUIRE_FRESH_RESOURCES_ENV]: flag }),
328
+ expected,
329
+ );
330
+ const calls = [
331
+ () => local.factory.get(),
332
+ () => local.factory.child('synthetic' as any),
333
+ () => local.factory.createTransportFile(...args),
334
+ ];
335
+ for (const call of calls) {
336
+ assert.throws(call, expected);
337
+ runWithRequestBoundary(createRequestBoundary(), () => assert.throws(call, expected));
127
338
  }
128
339
  }
129
- const exceptions = local.logger.exceptions;
130
- const rejections = local.logger.rejections;
131
- local.logger.configure({ transports: [local.sink] });
132
- assert.notEqual(local.logger.exceptions, exceptions);
133
- assert.notEqual(local.logger.rejections, rejections);
134
- assert.equal(local.logger.exceptions.logger, local.logger);
135
- assert.equal(local.logger.rejections.logger, local.logger);
136
- assert.equal(exceptions.logger, local.logger);
137
- assert.equal(rejections.logger, local.logger);
138
- runWithRequestBoundary(createRequestBoundary(), () => {
139
- exceptions.logger.error('local');
140
- rejections.logger.error('local');
141
- });
340
+ assert.equal(probe.reads(), 0);
341
+ assert.equal(local.creations(), 1);
142
342
  assert.equal(local.sink.count, 0);
143
343
  } finally {
144
344
  await local.close();
@@ -12,17 +12,11 @@ import {
12
12
  mergeTestClaimRedisOptions,
13
13
  } from './testClaim.ts';
14
14
  import { resolveVonaLocalPaths } from './testIsolation.ts';
15
+ import { requiresFreshTestResources } from './testStrictMode.ts';
15
16
 
16
- export const TEST_REQUIRE_FRESH_RESOURCES_ENV = 'VONA_TEST_REQUIRE_FRESH_RESOURCES';
17
- const freshApps = new WeakSet<VonaApplication>();
17
+ export { requiresFreshTestResources, TEST_REQUIRE_FRESH_RESOURCES_ENV } from './testStrictMode.ts';
18
18
 
19
- export function requiresFreshTestResources() {
20
- const value = process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV];
21
- if (value !== undefined && value !== 'true') {
22
- throw new Error('Invalid strict test resource freshness flag');
23
- }
24
- return value === 'true';
25
- }
19
+ const freshApps = new WeakSet<VonaApplication>();
26
20
 
27
21
  export function assertFreshTestResourcesReady(app: VonaApplication) {
28
22
  if (!requiresFreshTestResources()) return;
@@ -0,0 +1,9 @@
1
+ export const TEST_REQUIRE_FRESH_RESOURCES_ENV = 'VONA_TEST_REQUIRE_FRESH_RESOURCES';
2
+
3
+ export function requiresFreshTestResources(env: NodeJS.ProcessEnv = process.env) {
4
+ const value = env[TEST_REQUIRE_FRESH_RESOURCES_ENV];
5
+ if (value !== undefined && value !== 'true') {
6
+ throw new Error('Invalid strict test resource freshness flag');
7
+ }
8
+ return value === 'true';
9
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-mock",
3
- "version": "6.1.48",
3
+ "version": "6.1.49",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "vona mock",
6
6
  "keywords": [