vona-core 5.1.48 → 5.1.50

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 CHANGED
@@ -2700,6 +2700,191 @@ class VonaAsyncLocalStorage extends AsyncLocalStorage {
2700
2700
  }
2701
2701
  }
2702
2702
 
2703
+ const owners = new WeakMap();
2704
+ const capabilities = new WeakMap();
2705
+ const captures = new WeakSet();
2706
+ const pins = new WeakMap();
2707
+ function createCompletedReadiness(appIdentity) {
2708
+ const state = {
2709
+ app: appIdentity,
2710
+ application: 'starting',
2711
+ applicationAttempt: Object.freeze({}),
2712
+ attempts: new Map(),
2713
+ provisions: new Map(),
2714
+ publications: new Map()
2715
+ };
2716
+ const facade = Object.freeze({
2717
+ snapshot: () => Object.freeze({
2718
+ application: state.application
2719
+ })
2720
+ });
2721
+ owners.set(facade, state);
2722
+ return facade;
2723
+ }
2724
+
2725
+ // Internal framework integration only. None of the issuance/provisioning helpers are barrel exports.
2726
+ function beginCompletedApplication(owner) {
2727
+ const state = owners.get(owner);
2728
+ state.publications.clear();
2729
+ state.attempts.clear();
2730
+ state.applicationAttempt = Object.freeze({});
2731
+ if (state.application !== 'closing') state.application = 'starting';
2732
+ return state.applicationAttempt;
2733
+ }
2734
+ function finishCompletedApplication(owner, attempt, success) {
2735
+ const state = owners.get(owner);
2736
+ if (state.application === 'closing' || state.applicationAttempt !== attempt) return;
2737
+ state.application = success ? 'ready' : 'failed';
2738
+ if (!success) state.publications.clear();
2739
+ }
2740
+ function closeCompletedReadiness(owner) {
2741
+ const state = owners.get(owner);
2742
+ state.application = 'closing';
2743
+ state.publications.clear();
2744
+ state.attempts.clear();
2745
+ }
2746
+ function invalidateCompletedInstance(owner, name) {
2747
+ if (!owner) return;
2748
+ const state = owners.get(owner);
2749
+ state.attempts.set(name, Object.freeze({}));
2750
+ state.publications.delete(name);
2751
+ }
2752
+ function beginCompletedInstance(owner, name) {
2753
+ if (!owner) return;
2754
+ invalidateCompletedInstance(owner, name);
2755
+ return owners.get(owner).attempts.get(name);
2756
+ }
2757
+ function rowCopy(value) {
2758
+ if (!value || typeof value !== 'object') return;
2759
+ const fields = ['id', 'name', 'disabled', 'isolate', 'config'];
2760
+ const data = Object.create(null);
2761
+ for (const key of fields) {
2762
+ const desc = Object.getOwnPropertyDescriptor(value, key);
2763
+ if (!desc || !('value' in desc)) return;
2764
+ data[key] = desc.value;
2765
+ }
2766
+ if (typeof data.id !== 'number' || !Number.isSafeInteger(data.id) || data.id <= 0 || typeof data.name !== 'string' || !data.name.isWellFormed() || data.name.includes('\0') || Buffer.byteLength(data.name) > 256 || data.disabled !== false || typeof data.isolate !== 'boolean' || !(data.config === null || typeof data.config === 'string' && data.config.isWellFormed() && Buffer.byteLength(data.config) <= 65_536)) {
2767
+ return;
2768
+ }
2769
+ return Object.freeze(data);
2770
+ }
2771
+ function detach(value, functions, active = new Set(), depth = 0, budget = {
2772
+ nodes: 0
2773
+ }) {
2774
+ if (++budget.nodes > 100_000 || depth > 64) throw new Error('Unsupported completed configuration');
2775
+ if (value === null || value === undefined || typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' && Number.isFinite(value)) {
2776
+ return value;
2777
+ }
2778
+ if (typeof value === 'function') {
2779
+ if (!functions.has(value) || !Object.isFrozen(value)) throw new Error('Unsupported completed configuration');
2780
+ for (const key of Reflect.ownKeys(value)) {
2781
+ const desc = Object.getOwnPropertyDescriptor(value, key);
2782
+ if (!('value' in desc) || desc.writable || desc.value && (typeof desc.value === 'object' || typeof desc.value === 'function')) {
2783
+ throw new Error('Unsupported completed configuration');
2784
+ }
2785
+ }
2786
+ return value;
2787
+ }
2788
+ if (typeof value !== 'object' || !value || active.has(value)) throw new Error('Unsupported completed configuration');
2789
+ const array = Array.isArray(value);
2790
+ const proto = Object.getPrototypeOf(value);
2791
+ if (!array && proto !== Object.prototype && proto !== null || array && proto !== Array.prototype) {
2792
+ throw new Error('Unsupported completed configuration');
2793
+ }
2794
+ active.add(value);
2795
+ const result = array ? [] : Object.create(null);
2796
+ for (const key of Reflect.ownKeys(value)) {
2797
+ if (array && key === 'length') continue;
2798
+ if (typeof key !== 'string') throw new Error('Unsupported completed configuration');
2799
+ const desc = Object.getOwnPropertyDescriptor(value, key);
2800
+ if (!('value' in desc)) throw new Error('Unsupported completed configuration');
2801
+ Object.defineProperty(result, key, {
2802
+ value: detach(desc.value, functions, active, depth + 1, budget),
2803
+ enumerable: desc.enumerable,
2804
+ configurable: false,
2805
+ writable: false
2806
+ });
2807
+ }
2808
+ if (array) Object.defineProperty(result, 'length', {
2809
+ value: value.length
2810
+ });
2811
+ active.delete(value);
2812
+ return Object.freeze(result);
2813
+ }
2814
+ function captureCompletedInstance(owner, name, attempt, row, config) {
2815
+ if (!owner || !attempt) return;
2816
+ const state = owners.get(owner);
2817
+ const provision = state.provisions.get(name);
2818
+ if (!provision || state.application === 'closing' || state.attempts.get(name) !== attempt) return;
2819
+ try {
2820
+ const capturedRow = rowCopy(row);
2821
+ if (!capturedRow || capturedRow.name !== name || capturedRow.isolate !== provision.isolate) return;
2822
+ const snapshot = detach(config, provision.functions);
2823
+ if (!snapshot || typeof snapshot !== 'object') return;
2824
+ const captured = Object.freeze({
2825
+ attempt,
2826
+ provision,
2827
+ row: capturedRow,
2828
+ config: snapshot
2829
+ });
2830
+ captures.add(captured);
2831
+ return captured;
2832
+ } catch {
2833
+ // Unsupported snapshots leave admission unavailable without inspecting the failure.
2834
+ }
2835
+ }
2836
+ function finishCompletedInstance(owner, name, attempt, captured) {
2837
+ if (!owner || !attempt || !captured || !captures.has(captured)) return;
2838
+ const state = owners.get(owner);
2839
+ const publication = captured;
2840
+ if (state.application !== 'closing' && state.application !== 'failed' && state.attempts.get(name) === attempt && publication.attempt === attempt && state.provisions.get(name) === publication.provision) {
2841
+ state.publications.set(name, publication);
2842
+ }
2843
+ }
2844
+ function resolveExistingReadyCapability(owner, capability, app) {
2845
+ const issued = capabilities.get(capability),
2846
+ state = owners.get(owner);
2847
+ if (!issued || issued.owner !== owner || !state || state.application !== 'ready' || app && app !== state.app) {
2848
+ return;
2849
+ }
2850
+ try {
2851
+ const current = issued.now();
2852
+ if (!Number.isFinite(current) || current >= issued.deadline) return;
2853
+ } catch {
2854
+ return;
2855
+ }
2856
+ const publication = issued.publication;
2857
+ if (state.publications.get(publication.row.name) !== publication || state.attempts.get(publication.row.name) !== publication.attempt) {
2858
+ return;
2859
+ }
2860
+ return Object.freeze({
2861
+ publication,
2862
+ name: publication.row.name,
2863
+ handle: publication.provision.handle
2864
+ });
2865
+ }
2866
+ function pinExistingReadyContext(owner, capability, app, context) {
2867
+ const resolved = resolveExistingReadyCapability(owner, capability, app);
2868
+ if (!resolved || pins.has(context)) return false;
2869
+ const publication = resolved.publication;
2870
+ pins.set(context, publication);
2871
+ for (const [key, value] of [['config', publication.config], ['instance', publication.row], ['instanceName', publication.row.name], ['innerAccess', false]]) {
2872
+ Object.defineProperty(context, key, {
2873
+ value,
2874
+ enumerable: true,
2875
+ configurable: false,
2876
+ writable: false
2877
+ });
2878
+ }
2879
+ return true;
2880
+ }
2881
+ function getExistingReadyContextConfig(context) {
2882
+ return pins.get(context)?.config;
2883
+ }
2884
+ function isExistingReadyContext(context) {
2885
+ return !!context && pins.has(context);
2886
+ }
2887
+
2703
2888
  const BEAN = Symbol.for('Context#__bean');
2704
2889
  const INNERACCESS = Symbol.for('Context#__inneraccess');
2705
2890
  const CTXCALLER = Symbol.for('Context#__ctxcaller');
@@ -2738,6 +2923,8 @@ const contextBase = {
2738
2923
  },
2739
2924
  get config() {
2740
2925
  const self = cast(this);
2926
+ const pinned = getExistingReadyContextConfig(self);
2927
+ if (pinned) return pinned;
2741
2928
  const serviceInstance = cast(self.app.bean._getBean('a-instance.service.instance'));
2742
2929
  return serviceInstance.getConfig(self.instanceName) || self.app.config;
2743
2930
  },
@@ -2872,6 +3059,15 @@ class AppHmr extends BeanSimple {
2872
3059
  }
2873
3060
  }
2874
3061
 
3062
+ const TEST_REQUIRE_FRESH_RESOURCES_ENV = 'VONA_TEST_REQUIRE_FRESH_RESOURCES';
3063
+ function requiresFreshTestResources(env = process.env) {
3064
+ const value = env[TEST_REQUIRE_FRESH_RESOURCES_ENV];
3065
+ if (value !== undefined && value !== 'true') {
3066
+ throw new Error('Invalid strict test resource freshness flag');
3067
+ }
3068
+ return value === 'true';
3069
+ }
3070
+
2875
3071
  const SymbolLoggerInstances = Symbol('SymbolLoggerInstances');
2876
3072
  const SymbolRawLoggerInstances = Symbol('SymbolRawLoggerInstances');
2877
3073
  class AppLogger extends BeanSimple {
@@ -2887,7 +3083,9 @@ class AppLogger extends BeanSimple {
2887
3083
  }
2888
3084
  }
2889
3085
  get(clientName) {
2890
- if (getRequestBoundary()) return getSuppressedDiagnosticLogger();
3086
+ if (requiresFreshTestResources() || getRequestBoundary()) {
3087
+ return getSuppressedDiagnosticLogger();
3088
+ }
2891
3089
  clientName = clientName || 'default';
2892
3090
  if (!this[SymbolLoggerInstances][clientName]) {
2893
3091
  const raw = this._createClient(clientName);
@@ -2897,7 +3095,9 @@ class AppLogger extends BeanSimple {
2897
3095
  return this[SymbolLoggerInstances][clientName];
2898
3096
  }
2899
3097
  child(childName, clientName) {
2900
- if (getRequestBoundary()) return getSuppressedDiagnosticLogger();
3098
+ if (requiresFreshTestResources() || getRequestBoundary()) {
3099
+ return getSuppressedDiagnosticLogger();
3100
+ }
2901
3101
  const logger = this.get(clientName);
2902
3102
  if (!childName) return logger;
2903
3103
  return logger.child({
@@ -2953,6 +3153,9 @@ class AppLogger extends BeanSimple {
2953
3153
  }, Winston);
2954
3154
  }
2955
3155
  createTransportFile(fileName, clientInfo, options) {
3156
+ if (requiresFreshTestResources()) {
3157
+ throw new Error('Strict test file logger transport is disabled');
3158
+ }
2956
3159
  const dirname = this.app.config.logger.baseDir;
2957
3160
  if (!fse.existsSync(dirname)) {
2958
3161
  const [_, err] = catchErrorSync(() => {
@@ -3026,6 +3229,7 @@ class AppMeta extends BeanSimple {
3026
3229
  this.hmrCacheLocaleModules = void 0;
3027
3230
  this.hmrCacheConfigModules = void 0;
3028
3231
  //
3232
+ this.completedReadiness = void 0;
3029
3233
  this.appReady = void 0;
3030
3234
  this.appReadyInstances = void 0;
3031
3235
  //
@@ -3036,6 +3240,7 @@ class AppMeta extends BeanSimple {
3036
3240
  this.appClosed = void 0;
3037
3241
  }
3038
3242
  __init__(env) {
3243
+ this.completedReadiness = createCompletedReadiness(this.app);
3039
3244
  // env
3040
3245
  this.env = env;
3041
3246
  this._prepareEnv();
@@ -3093,6 +3298,7 @@ class AppMeta extends BeanSimple {
3093
3298
  });
3094
3299
  }
3095
3300
  async close() {
3301
+ closeCompletedReadiness(this.completedReadiness);
3096
3302
  if (!this[SymbolClosePromise]) {
3097
3303
  this[SymbolClosePromise] = this._closeInner();
3098
3304
  }
@@ -4482,15 +4688,7 @@ function assertTestClaimRedisClient(app, clientName, options) {
4482
4688
  if (plan.kind === 'client' ? options.keyPrefix !== plan.prefix : options.keyPrefix !== undefined) throw new Error('Unregistered managed Redis key prefix');
4483
4689
  }
4484
4690
 
4485
- const TEST_REQUIRE_FRESH_RESOURCES_ENV = 'VONA_TEST_REQUIRE_FRESH_RESOURCES';
4486
4691
  const freshApps = new WeakSet();
4487
- function requiresFreshTestResources() {
4488
- const value = process.env[TEST_REQUIRE_FRESH_RESOURCES_ENV];
4489
- if (value !== undefined && value !== 'true') {
4490
- throw new Error('Invalid strict test resource freshness flag');
4491
- }
4492
- return value === 'true';
4493
- }
4494
4692
  function assertFreshTestResourcesReady(app) {
4495
4693
  if (!requiresFreshTestResources()) return;
4496
4694
  if (!freshApps.has(app)) throw new Error('Strict test resource freshness was not established');
@@ -4857,6 +5055,8 @@ class Start {
4857
5055
  }
4858
5056
  async start() {
4859
5057
  const app = this.app;
5058
+ const owner = app.meta.completedReadiness;
5059
+ const attempt = beginCompletedApplication(owner);
4860
5060
  try {
4861
5061
  await this._start_appConfig();
4862
5062
  await assertFreshTestResources(app);
@@ -4864,7 +5064,9 @@ class Start {
4864
5064
  await this._start_appStart();
4865
5065
  await this._start_appReady();
4866
5066
  await this._start_appStarted();
5067
+ finishCompletedApplication(owner, attempt, true);
4867
5068
  } catch (err) {
5069
+ finishCompletedApplication(owner, attempt, false);
4868
5070
  // record
4869
5071
  app.meta.appStartError = err;
4870
5072
  // event: appReadyError
@@ -5249,5 +5451,5 @@ async function retry(options, fn) {
5249
5451
 
5250
5452
  zodExtendOpenApi();
5251
5453
 
5252
- export { $Class, $localeScope, $makeLocaleMagic, $protocolKey, AppHmr, AppHmrDeps, AppLocale, AppLogger, AppMeta, AppMetadata, AppResource, AppUtil, BeanAopBase, BeanAopMethodBase, BeanBase, BeanBaseSimple, BeanContainer, BeanInfo, BeanScopeBase, BeanScopeContainer, BeanScopeError, BeanScopeErrorImpl, BeanScopeLocale, BeanScopeScene, BeanScopeUtil, BeanSimple, EnumAppEvent, ErrorClass, Global, LocaleModuleNameSeparator, PickClassInner, ProxyDisable, SymbolBeanContainerInstances, SymbolBeanFullName, SymbolBeanInstanceKey, SymbolBeanInstancePropsLazy, SymbolCacheAopChains, SymbolCacheAopChainsKey, SymbolDecoratorBeanFullName, SymbolDecoratorBeanInfo, SymbolDecoratorGlobal, SymbolDecoratorProxyDisable, SymbolDecoratorUse, SymbolDecoratorVirtual, SymbolHmrStateLoad, SymbolHmrStateSave, SymbolMappedClassMetadataKeys, SymbolModuleBelong, SymbolModuleName, TEST_CLAIM_DIRECTORY, TEST_CLAIM_TOKEN_ENV, TEST_CLAIM_URL_ENV, TEST_CLAIM_WINDOWS_GUARDIAN_ENV, TEST_REQUIRE_FRESH_RESOURCES_ENV, TEST_RUN_ID_ENV, TEST_RUN_OWNER_FILE, Use, Virtual, VonaApplication, __prepareInjectSelectorInfo, appHmrDeps, appMetadata, appResource, assertDisposableDatabaseName, assertFreshTestResources, assertFreshTestResourcesReady, assertIsolatedTestConfig, assertIsolatedTestDatabaseClient, assertIsolatedTestPath, assertTestAppIdentity, assertTestClaimDatabaseClient, assertTestClaimRedisClient, assertTestClaimSafePath, assertTestClaimWindowsJob, assertTestRunOwner, beanFullNameFromOnionName, bootstrap, buildTestClaimResourceInventory, captureRequestBoundary, cast, closeApp, closeProcessWorker, combineConfigDefault, combineFilePathSafe, compose, copyAddon, copyMetadataOfClasses, copyProperties, copyPropertiesOfClasses, createApp, createAppMaster, createBeanDecorator, createDiagnosticLogger, createFreshnessDependencies, createGeneralApp, createHash, createRequestBoundary, createTestClaim, deepExtend, disposeInstance, errorsInternal, filterHeaders, formatLoggerAxiosError, formatLoggerBoundary, formatLoggerConsole, formatLoggerCtx, formatLoggerDummy, formatLoggerErrors, formatLoggerFilter, functionNoop, getDatabaseTestPrefix, getHomeVonaAppDir, getLoggerPathPhysicalRoot, getMappedClassMetadataKeys, getPlatformArch, getPublicPathPhysicalRoot, getRequestBoundary, getRuntimePathPhysicalRoot, getSqlite3DatabaseNameDefault, getSuppressedDiagnosticLogger, getTestAppName, getTestClaimCreatedAt, getTestClaimPaths, getTestClaimRedisPrefix, getTestRunIdFromEnv, hasFreshnessDatabase, hasFreshnessRedis, hasTestClaimTransport, instanceDesp, isLocaleMagic, loadJSONFile, loadTestClaim, mergeTestClaimDatabaseOptions, mergeTestClaimRedisOptions, normalizeTestClaimDatabaseEndpoint, normalizeTestClaimRedisEndpoint, onionNameFromBeanFullName, pathToHref, polyfillDispose, prepareEnv, registerMappedClassMetadataKey, registerTestClaimDatabaseCreation, registerTestClaimResourceInventory, registerTestClaimWindowsJobVerifier, requireAddon, requireDynamic, requiresFreshTestResources, resolveAddon, resolveTestRunId, resolveVonaLocalPaths, resolverSharp, resolverSharpLibvips, resolverSqlite3, retry, runWithRequestBoundary, saveJSONFile, sendTestClaimEvent, setMappedClassMetadataKeys, startTestClaimBroker, text$1 as text, useApp, usePrepareArg, usePrepareArgs, uuidv4, validateTestClaim, withIsolatedTestDatabaseDiscovery, writeTestClaim };
5454
+ export { $Class, $localeScope, $makeLocaleMagic, $protocolKey, AppHmr, AppHmrDeps, AppLocale, AppLogger, AppMeta, AppMetadata, AppResource, AppUtil, BeanAopBase, BeanAopMethodBase, BeanBase, BeanBaseSimple, BeanContainer, BeanInfo, BeanScopeBase, BeanScopeContainer, BeanScopeError, BeanScopeErrorImpl, BeanScopeLocale, BeanScopeScene, BeanScopeUtil, BeanSimple, EnumAppEvent, ErrorClass, Global, LocaleModuleNameSeparator, PickClassInner, ProxyDisable, SymbolBeanContainerInstances, SymbolBeanFullName, SymbolBeanInstanceKey, SymbolBeanInstancePropsLazy, SymbolCacheAopChains, SymbolCacheAopChainsKey, SymbolDecoratorBeanFullName, SymbolDecoratorBeanInfo, SymbolDecoratorGlobal, SymbolDecoratorProxyDisable, SymbolDecoratorUse, SymbolDecoratorVirtual, SymbolHmrStateLoad, SymbolHmrStateSave, SymbolMappedClassMetadataKeys, SymbolModuleBelong, SymbolModuleName, TEST_CLAIM_DIRECTORY, TEST_CLAIM_TOKEN_ENV, TEST_CLAIM_URL_ENV, TEST_CLAIM_WINDOWS_GUARDIAN_ENV, TEST_REQUIRE_FRESH_RESOURCES_ENV, TEST_RUN_ID_ENV, TEST_RUN_OWNER_FILE, Use, Virtual, VonaApplication, __prepareInjectSelectorInfo, appHmrDeps, appMetadata, appResource, assertDisposableDatabaseName, assertFreshTestResources, assertFreshTestResourcesReady, assertIsolatedTestConfig, assertIsolatedTestDatabaseClient, assertIsolatedTestPath, assertTestAppIdentity, assertTestClaimDatabaseClient, assertTestClaimRedisClient, assertTestClaimSafePath, assertTestClaimWindowsJob, assertTestRunOwner, beanFullNameFromOnionName, beginCompletedInstance, bootstrap, buildTestClaimResourceInventory, captureCompletedInstance, captureRequestBoundary, cast, closeApp, closeProcessWorker, combineConfigDefault, combineFilePathSafe, compose, copyAddon, copyMetadataOfClasses, copyProperties, copyPropertiesOfClasses, createApp, createAppMaster, createBeanDecorator, createCompletedReadiness, createDiagnosticLogger, createFreshnessDependencies, createGeneralApp, createHash, createRequestBoundary, createTestClaim, deepExtend, disposeInstance, errorsInternal, filterHeaders, finishCompletedInstance, formatLoggerAxiosError, formatLoggerBoundary, formatLoggerConsole, formatLoggerCtx, formatLoggerDummy, formatLoggerErrors, formatLoggerFilter, functionNoop, getDatabaseTestPrefix, getHomeVonaAppDir, getLoggerPathPhysicalRoot, getMappedClassMetadataKeys, getPlatformArch, getPublicPathPhysicalRoot, getRequestBoundary, getRuntimePathPhysicalRoot, getSqlite3DatabaseNameDefault, getSuppressedDiagnosticLogger, getTestAppName, getTestClaimCreatedAt, getTestClaimPaths, getTestClaimRedisPrefix, getTestRunIdFromEnv, hasFreshnessDatabase, hasFreshnessRedis, hasTestClaimTransport, instanceDesp, invalidateCompletedInstance, isExistingReadyContext, isLocaleMagic, loadJSONFile, loadTestClaim, mergeTestClaimDatabaseOptions, mergeTestClaimRedisOptions, normalizeTestClaimDatabaseEndpoint, normalizeTestClaimRedisEndpoint, onionNameFromBeanFullName, pathToHref, pinExistingReadyContext, polyfillDispose, prepareEnv, registerMappedClassMetadataKey, registerTestClaimDatabaseCreation, registerTestClaimResourceInventory, registerTestClaimWindowsJobVerifier, requireAddon, requireDynamic, requiresFreshTestResources, resolveAddon, resolveExistingReadyCapability, resolveTestRunId, resolveVonaLocalPaths, resolverSharp, resolverSharpLibvips, resolverSqlite3, retry, runWithRequestBoundary, saveJSONFile, sendTestClaimEvent, setMappedClassMetadataKeys, startTestClaimBroker, text$1 as text, useApp, usePrepareArg, usePrepareArgs, uuidv4, validateTestClaim, withIsolatedTestDatabaseDiscovery, writeTestClaim };
5253
5455
  //# sourceMappingURL=index.js.map