@cldmv/slothlet 3.15.3 → 3.16.0
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/README.md +7 -5
- package/dist/lib/builders/api-assignment.mjs +1 -1
- package/dist/lib/builders/api_builder.mjs +1 -1
- package/dist/lib/builders/builder.mjs +1 -1
- package/dist/lib/builders/modes-processor.mjs +1 -1
- package/dist/lib/handlers/api-cache-manager.mjs +1 -1
- package/dist/lib/handlers/api-manager.mjs +1 -1
- package/dist/lib/handlers/module-manager.mjs +1 -1
- package/dist/lib/handlers/ownership.mjs +1 -1
- package/dist/lib/handlers/routine-manager.mjs +17 -0
- package/dist/lib/handlers/unified-wrapper.mjs +1 -1
- package/dist/lib/helpers/config.mjs +1 -1
- package/dist/lib/helpers/defaults.mjs +1 -1
- package/dist/lib/helpers/eventtarget-property-context.mjs +17 -0
- package/dist/lib/helpers/observer-context.mjs +17 -0
- package/dist/lib/helpers/scheduler-context.mjs +1 -1
- package/dist/lib/i18n/languages/en-us.json +2 -0
- package/dist/lib/modes/eager.mjs +1 -1
- package/dist/lib/processors/flatten.mjs +1 -1
- package/dist/slothlet.mjs +1 -1
- package/index.cjs +20 -0
- package/index.mjs +14 -0
- package/package.json +8 -7
- package/types/stub/devcheck.d.mts +1 -1
- package/types/stub/lib/builders/api-assignment.d.mts +130 -2
- package/types/stub/lib/builders/api_builder.d.mts +109 -2
- package/types/stub/lib/builders/builder.d.mts +87 -2
- package/types/stub/lib/builders/modes-processor.d.mts +71 -2
- package/types/stub/lib/factories/component-base.d.mts +177 -0
- package/types/stub/lib/helpers/caller-pinning.d.mts +22 -2
- package/types/stub/lib/helpers/class-instance-wrapper.d.mts +58 -2
- package/types/stub/lib/helpers/config.d.mts +321 -2
- package/types/stub/lib/helpers/defaults.d.mts +41 -2
- package/types/stub/lib/helpers/eventemitter-context.d.mts +31 -2
- package/types/stub/lib/helpers/eventtarget-context.d.mts +21 -2
- package/types/stub/lib/helpers/eventtarget-property-context.d.mts +23 -0
- package/types/stub/lib/helpers/generate-manifest.d.mts +180 -2
- package/types/stub/lib/helpers/hint-detector.d.mts +27 -2
- package/types/stub/lib/helpers/manifest-resolver.d.mts +101 -2
- package/types/stub/lib/helpers/modes-utils.d.mts +35 -2
- package/types/stub/lib/helpers/module-discovery.d.mts +81 -2
- package/types/stub/lib/helpers/module-manifest-validator.d.mts +37 -2
- package/types/stub/lib/helpers/module-sort.d.mts +65 -2
- package/types/stub/lib/helpers/observer-context.d.mts +23 -0
- package/types/stub/lib/helpers/pattern-matcher.d.mts +44 -2
- package/types/stub/lib/helpers/platform.d.mts +111 -2
- package/types/stub/lib/helpers/resolve-from-caller.d.mts +33 -2
- package/types/stub/lib/helpers/scheduler-context.d.mts +23 -2
- package/types/stub/lib/helpers/utilities.d.mts +57 -2
- package/types/stub/lib/i18n/translations.d.mts +52 -2
- package/types/stub/lib/modes/eager.d.mts +56 -2
- package/types/stub/lib/modes/lazy.d.mts +67 -2
- package/types/stub/lib/processors/flatten.d.mts +123 -2
- package/types/stub/lib/processors/loader.d.mts +83 -2
- package/types/stub/lib/processors/type-generator.d.mts +19 -2
- package/types/stub/lib/processors/typescript.d.mts +174 -2
- package/types/stub/lib/runtime/runtime-asynclocalstorage.d.mts +72 -2
- package/types/stub/lib/runtime/runtime-livebindings.d.mts +38 -2
package/README.md
CHANGED
|
@@ -43,17 +43,19 @@ Every feature has been hardened with a comprehensive test suite - over **5,300 t
|
|
|
43
43
|
|
|
44
44
|
## ✨ What's New
|
|
45
45
|
|
|
46
|
-
### Latest: v3.
|
|
46
|
+
### Latest: v3.16.0 (September 2026)
|
|
47
47
|
|
|
48
|
-
- **
|
|
49
|
-
-
|
|
48
|
+
- **Stackable lifecycle routines** — a `routines` config option stacks every module's contribution to a named lifecycle-hook-style export (`initialize`, `shutdown`, or any custom name) into one callable at its composed api path, plus a root cascade (`self.<name>()` ≡ `api.slothlet.<name>()`) that runs every matching contribution anywhere in the tree; replaces the deprecated `collectLifecycleHooks` option with bare/dotted, recursive, and root-anchored glob name matching, `manual`/`startup`/`shutdown`/`destroy` modes, and best-effort aggregated error reporting (#341). A new `stackRoutines` flag — decoupled entirely from `collisionMode` — controls whether same-path contributors that lost an ordinary collision still participate in the stack (#365). All opt-in; no breaking API changes.
|
|
49
|
+
- **Collision, ownership & routine-stacking correctness pass** — the per-path routine stack now self-heals reactively instead of going stale after a late reassignment or a second colliding contributor (#362, #374); `assignToApiPath` awaits the now-async collision reconciliation it was firing unawaited (#369, #376); and collision-mode overrides, speculative-registration revert, and lazy-collision materialization are threaded correctly throughout `api.add()` (#366, #367, #372). Minimum Node is raised to `>=22.12.0` to match the toolchain floor.
|
|
50
|
+
- **Remaining live-runtime deferred-callback boundaries pinned** — `requestAnimationFrame`/`requestIdleCallback`, IDL `on*` handler properties (`EventSource`, `WebSocket`, `Worker`/`MessagePort`, `FileReader`, `XMLHttpRequest`), and the `MutationObserver`/`ResizeObserver`/`IntersectionObserver` constructors now correctly pin `self`/context identity for a browser-mode live-runtime instance, closing out the gaps left after `setTimeout`/`EventTarget.addEventListener` (#349, #350, #352, #353).
|
|
51
|
+
- [View full v3.16.0 Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v3/v3.16.0.md)
|
|
50
52
|
|
|
51
53
|
### Recent Releases
|
|
52
54
|
|
|
55
|
+
- **v3.15.3** (September 2026) — Wrap-on-set / `api.add()` live Proxy delegation, plus hook-lifecycle default fixes: `self.X = obj` and `api.slothlet.api.add()` now give a genuinely live, two-way view onto the underlying object instead of a frozen snapshot, including `EventEmitter`-derived values (#340, #342); hook-subset default `||` bug fixed to `??` (#343, #344) ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v3/v3.15.3.md))
|
|
53
56
|
- **v3.15.2** (September 2026) — Core context/composition bug-fix release: async-leaf class-instance context propagation, wrap-on-set context/permission parity with `add()`, `add()` no longer hangs on a socket or circular value, and an EventEmitter context-patch memory leak fix ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v3/v3.15.2.md))
|
|
54
57
|
- **v3.15.1** (August 2026) — Maintenance & supply-chain hardening, no runtime changes: least-privilege GitHub Actions token permissions (#319), two high-severity dev-only toolchain advisories cleared (#322), and an OpenSSF Scorecard badge (#320) ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v3/v3.15.1.md))
|
|
55
58
|
- **v3.15.0** (August 2026) — Character-safe `moduleID`s and scoped `remove(moduleID, apiPath)`: a `moduleID` may contain any character and round-trips through `add`/`leaves`/`remove`/`reload`; scoped removals and synthetic adds now survive `reload()`; plus a prototype-pollution guard on mount paths (#303, #302, #304) ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v3/v3.15.0.md))
|
|
56
|
-
- **v3.14.0** (August 2026) — Browser importmap resolves consumer-graph package `exports` subpaths (not just slothlet's own surface), so a redirected dependency subpath no longer 404s in the browser and consumers can drop hand-maintained allowlists (#297) ([Changelog](https://github.com/CLDMV/slothlet/blob/master/docs/changelog/v3/v3.14.0.md))
|
|
57
59
|
|
|
58
60
|
📚 **For complete version history and detailed release notes, see [docs/changelog/](https://github.com/CLDMV/slothlet/tree/master/docs/changelog/) folder.**
|
|
59
61
|
|
|
@@ -167,7 +169,7 @@ Run slothlet in the browser, web workers, and Electron renderers — anywhere th
|
|
|
167
169
|
|
|
168
170
|
### Requirements
|
|
169
171
|
|
|
170
|
-
- **Node.js v22.
|
|
172
|
+
- **Node.js v22.12.0 or higher**
|
|
171
173
|
|
|
172
174
|
### Install
|
|
173
175
|
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import{ComponentBase}from"#factories/component-base";import{resolveWrapper,UnifiedWrapper,isFrameworkReservedKey}from"#handlers/unified-wrapper";import{isFrameworkInternal,markFrameworkInternal}from"#handlers/framework-internals";class ApiAssignment extends ComponentBase{static slothletProperty="apiAssignment";constructor(slothlet){super(slothlet)}isWrapperProxy(value){return!!(value&&resolveWrapper(value))}mergeOffSlotCollisionFolder(keptWrapper){const offSlotFolder=keptWrapper?.____slothletInternal?.offSlotCollisionFolder;if(!offSlotFolder)return;delete keptWrapper.____slothletInternal.offSlotCollisionFolder;const folderChildren=new Map;for(const childKey of Object.keys(offSlotFolder)){if(isFrameworkReservedKey(childKey))continue;folderChildren.set(childKey,offSlotFolder[childKey])}const folderProduct=UnifiedWrapper._extractFullImpl(offSlotFolder);if(!folderProduct||typeof folderProduct!=="object"&&typeof folderProduct!=="function")return;const keptImpl=keptWrapper.____slothletInternal.impl;for(const folderKey of Object.keys(folderProduct)){if(isFrameworkReservedKey(folderKey))continue;const alreadyPresent=Object.prototype.hasOwnProperty.call(keptWrapper,folderKey)||!!keptImpl&&Object.prototype.hasOwnProperty.call(keptImpl,folderKey);if(alreadyPresent)continue;Object.defineProperty(keptWrapper,folderKey,{value:folderChildren.has(folderKey)?folderChildren.get(folderKey):folderProduct[folderKey],writable:false,enumerable:true,configurable:true})}}assignToApiPath(targetApi,key,value,options={}){const valueIsWrapper=this.isWrapperProxy(value);const valueId=valueIsWrapper?resolveWrapper(value)?.____slothletInternal?.id??"no-id":"not-wrapper";this.slothlet.debug("api",{key:"DEBUG_MODE_ASSIGN_TO_API",propKey:key,valueId,typeOf:typeof value});const{allowOverwrite=false,mutateExisting=false,useCollisionDetection=false,config=null,collisionContext="initial",syncWrapper=null,collisionMode="merge",moduleID=null}=options;const existing=targetApi[key];if(existing!==void 0&&this.isWrapperProxy(existing)&&this.isWrapperProxy(value)){if(mutateExisting&&syncWrapper){syncWrapper(existing,value,config,collisionMode,moduleID);return true}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_CHECK",propKey:key,useCollisionDetection,hasConfig:!!config,hasExisting:existing!==void 0,existingType:typeof existing});if(useCollisionDetection&&config&&existing!==void 0){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_DETECT",propKey:key,context:collisionContext,existingType:typeof existing,valueType:typeof value});const collisionMode2=config.collision?.[collisionContext]||"merge";if(collisionMode2==="error"){const SlothletError=this.slothlet?.SlothletError||Error;throw new SlothletError("COLLISION_ERROR",{key:String(key),collisionMode:collisionMode2,collisionContext})}if(collisionMode2==="skip"){return false}let effectiveMode=collisionMode2;if(collisionMode2==="warn"){new this.slothlet.SlothletWarning("WARNING_COLLISION_FILE_FOLDER_MERGE",{key:String(key)});effectiveMode="merge"}const existingIsWrapper=this.isWrapperProxy(existing);const valueIsWrapper2=this.isWrapperProxy(value);this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_WRAPPER_DETECTION",propKey:key,existingIsWrapper,valueIsWrapper:valueIsWrapper2,hasExistingWrapper:resolveWrapper(existing)?"yes":"no",hasValueWrapper:resolveWrapper(value)?"yes":"no"});if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_LAZY_DETECTION",propKey:key,effectiveMode,existingLazy:existingIsLazyUnmaterialized,valueLazy:valueIsLazyUnmaterialized});if(existingIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_SET_MODE_EXISTING_WRAPPER",effectiveMode,apiPath:existingWrapper.____slothletInternal.apiPath});existingWrapper.____slothletInternal.state.collisionMode=effectiveMode;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_VERIFIED_EXISTING_WRAPPER_MODE",collisionMode:existingWrapper.____slothletInternal.state.collisionMode})}if(valueIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_SET_MODE_VALUE_WRAPPER",effectiveMode,apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper.____slothletInternal.state.collisionMode=effectiveMode;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_VERIFIED_VALUE_WRAPPER_MODE",collisionMode:valueWrapper.____slothletInternal.state.collisionMode});if(effectiveMode==="replace"){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_MATERIALIZE",apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper._materialize()}}}if(effectiveMode==="replace"){if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;if(valueIsLazyUnmaterialized&&!existingIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_NO_COPY"});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_BEFORE",propKey:key,currentWrapperId:resolveWrapper(existing)?.____slothletInternal.id});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_ASSIGN_REPLACING_WITH_LAZY",propKey:key,collisionMode:valueWrapper.____slothletInternal.state.collisionMode});targetApi[key]=value;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_AFTER",propKey:key,newWrapperId:resolveWrapper(targetApi[key])?.____slothletInternal.id});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_VERIFY",expectedId:valueWrapper.____slothletInternal.id,actualId:resolveWrapper(targetApi[key])?.____slothletInternal.id});return true}}targetApi[key]=value;return true}if(effectiveMode==="merge"||effectiveMode==="merge-replace"){const isMergeReplace=effectiveMode==="merge-replace";if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;if(existingIsLazyUnmaterialized&&!valueIsLazyUnmaterialized){const valueMetadata=this.slothlet.handlers?.metadata?.getMetadata(value);const valueFilePath=valueMetadata?.filePath;if(!existingWrapper.____slothletInternal.childFilePathsPreMaterialize){existingWrapper.____slothletInternal.childFilePathsPreMaterialize={}}const valueChildKeys=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const key2 of valueChildKeys){Object.defineProperty(existingWrapper,key2,{configurable:true});if(valueFilePath){existingWrapper.____slothletInternal.childFilePathsPreMaterialize[key2]=valueFilePath}}return true}else if(valueIsLazyUnmaterialized&&!existingIsLazyUnmaterialized){if(!isMergeReplace&&existingWrapper.____slothletInternal.isCallable){valueWrapper.____slothletInternal.state.collisionMode=effectiveMode;existingWrapper.____slothletInternal.offSlotCollisionFolder=valueWrapper;valueWrapper.____slothletInternal.needsImmediateChildAdoption=true;if(valueWrapper.____slothletInternal.materializeFunc&&!valueWrapper.____slothletInternal.state?.materialized&&!valueWrapper.____slothletInternal.state?.inFlight){valueWrapper._materialize().catch(()=>{})}targetApi[key]=existing;return true}if(!isMergeReplace){const existingMetadata=this.slothlet.handlers?.metadata?.getMetadata(existing);const existingFilePath=existingMetadata?.filePath;if(!valueWrapper.____slothletInternal.childFilePathsPreMaterialize){valueWrapper.____slothletInternal.childFilePathsPreMaterialize={}}const existingChildKeys=Object.keys(existingWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_COPY_CHILD_KEYS",existingChildKeys:existingChildKeys.join(","),fromApiPath:existingWrapper.____slothletInternal.apiPath,toApiPath:valueWrapper.____slothletInternal.apiPath,valueWrapperId:valueWrapper.____slothletInternal.id||"no-id"});if(!valueWrapper.____slothletInternal.collisionMergedKeys){valueWrapper.____slothletInternal.collisionMergedKeys=new Set}for(const key2 of existingChildKeys){const child=existingWrapper[key2];this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_COPY_INDIVIDUAL_KEY",propKey:key2,childName:child?.name,typeOf:typeof child,valueWrapperId:valueWrapper.____slothletInternal.id||"no-id"});Object.defineProperty(valueWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true});valueWrapper.____slothletInternal.collisionMergedKeys.add(key2);if(existingFilePath){valueWrapper.____slothletInternal.childFilePathsPreMaterialize[key2]=existingFilePath}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_TRIGGER_EARLY_MAT",apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper.____slothletInternal.needsImmediateChildAdoption=true;if(valueWrapper.____slothletInternal.materializeFunc&&!valueWrapper.____slothletInternal.state?.materialized&&!valueWrapper.____slothletInternal.state?.inFlight){valueWrapper._materialize().catch(err=>{new this.slothlet.SlothletWarning("WARNING_COLLISION_TRIGGER_MATERIALIZE_ERROR",{apiPath:valueWrapper.____slothletInternal.apiPath},err)})}}else{valueWrapper._mergeAfterMaterialize={existingWrapper,isMergeReplace:true}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_ASSIGN_REPLACING_WITH_LAZY",propKey:key,collisionMode:valueWrapper.____slothletInternal.state.collisionMode});targetApi[key]=value;return true}const existingChildCount=Object.keys(existingWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;const valueChildCount=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;if(existingWrapper.____slothletInternal.impl&&existingChildCount===0){existingWrapper.___adoptImplChildren()}if(valueWrapper.____slothletInternal.impl&&valueChildCount===0){valueWrapper.___adoptImplChildren()}const existingIsCallable=!!existingWrapper.____slothletInternal.isCallable;const valueIsCallable=!!valueWrapper.____slothletInternal.isCallable;if(!existingIsCallable&&valueIsCallable){const existingChildKeys2=Object.keys(existingWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const key2 of existingChildKeys2){const existingChild2=existingWrapper[key2];const keyOnValue=Object.prototype.hasOwnProperty.call(valueWrapper,key2);if(keyOnValue&&isMergeReplace){continue}if(keyOnValue){const desc2=Object.getOwnPropertyDescriptor(valueWrapper,key2);if(!desc2?.configurable)continue;delete valueWrapper[key2]}Object.defineProperty(valueWrapper,key2,{value:existingChild2,writable:false,enumerable:true,configurable:true})}targetApi[key]=value;return true}const valueChildKeys2=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const key2 of valueChildKeys2){const child=valueWrapper[key2];const isInternal=typeof key2==="string"&&(key2.startsWith("_")||key2.startsWith("__"));const keyExists=!isInternal&&Object.prototype.hasOwnProperty.call(existingWrapper,key2);if(!keyExists){Object.defineProperty(existingWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true})}else if(isMergeReplace){const descriptor=Object.getOwnPropertyDescriptor(existingWrapper,key2);if(descriptor?.configurable){delete existingWrapper[key2]}Object.defineProperty(existingWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true})}else{const existingChild=existingWrapper[key2];const existingChildWrapper=resolveWrapper(existingChild);const newChildWrapper=resolveWrapper(child);if(existingChildWrapper&&newChildWrapper){const newChildChildCount=Object.keys(newChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;if(newChildWrapper.____slothletInternal.impl&&newChildChildCount===0){newChildWrapper.___adoptImplChildren()}const newChildKeys=Object.keys(newChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));const ____existingChildKeys=Object.keys(existingChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const childKey of newChildKeys){const childKeyExists=Object.prototype.hasOwnProperty.call(existingChildWrapper,childKey);if(!childKeyExists){Object.defineProperty(existingChildWrapper,childKey,{value:newChildWrapper[childKey],writable:false,enumerable:true,configurable:true})}}}}}if(valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized&&valueWrapper.____slothletInternal.materializeFunc){return false}return true}else if(existingIsWrapper&&!valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const existingImpl=existingWrapper.__impl;const mergedImpl={...existingImpl||{},...value};existingWrapper.___setImpl(mergedImpl);return true}else if(!existingIsWrapper&&valueIsWrapper2){}else{if(typeof existing==="object"&&existing!==null&&typeof value==="object"&&value!==null){Object.assign(existing,value);return true}}}}if(existing!==void 0&&!allowOverwrite&&!mutateExisting&&!useCollisionDetection){return false}targetApi[key]=value;return true}async mergeApiObjects(targetApi,sourceApi,options={}){const config=options.config;if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_ENTRY",targetApiType:typeof targetApi,sourceApiType:typeof sourceApi});this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_SOURCE_KEYS",sourceApiKeys:sourceApi?Object.keys(sourceApi):[]})}if(!sourceApi||typeof sourceApi!=="object"&&typeof sourceApi!=="function"){if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_EXIT_INVALID_SOURCE"})}return}const{removeMissing=false,moduleID=null,...assignOptions}=options;if(isFrameworkInternal(sourceApi)){markFrameworkInternal(resolveWrapper(targetApi))}const sourceKeys=new Set(Object.keys(sourceApi));for(const key of sourceKeys){const sourceValue=sourceApi[key];const targetValue=targetApi[key];if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_PROCESSING_KEY",propKey:key,targetValueType:typeof targetValue,sourceValueType:typeof sourceValue})}if(targetValue&&typeof targetValue==="object"&&!this.isWrapperProxy(targetValue)&&sourceValue&&typeof sourceValue==="object"&&!this.isWrapperProxy(sourceValue)){if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_RECURSING",propKey:key})}await this.mergeApiObjects(targetValue,sourceValue,options)}else{if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_CALLING_ASSIGN",propKey:key})}this.assignToApiPath(targetApi,key,sourceValue,{...assignOptions,moduleID})}}if(removeMissing){for(const key of Object.keys(targetApi)){if(!sourceKeys.has(key)){delete targetApi[key]}}}}}export{ApiAssignment};
|
|
17
|
+
import{ComponentBase}from"#factories/component-base";import{resolveWrapper,UnifiedWrapper,isFrameworkReservedKey}from"#handlers/unified-wrapper";import{isFrameworkInternal,markFrameworkInternal}from"#handlers/framework-internals";class ApiAssignment extends ComponentBase{static slothletProperty="apiAssignment";constructor(slothlet){super(slothlet)}isWrapperProxy(value){return!!(value&&resolveWrapper(value))}mergeOffSlotCollisionFolder(keptWrapper){const offSlotFolder=keptWrapper?.____slothletInternal?.offSlotCollisionFolder;if(!offSlotFolder)return;delete keptWrapper.____slothletInternal.offSlotCollisionFolder;const folderChildren=new Map;for(const childKey of Object.keys(offSlotFolder)){if(isFrameworkReservedKey(childKey))continue;folderChildren.set(childKey,offSlotFolder[childKey])}const folderProduct=UnifiedWrapper._extractFullImpl(offSlotFolder);if(!folderProduct||typeof folderProduct!=="object"&&typeof folderProduct!=="function")return;const keptImpl=keptWrapper.____slothletInternal.impl;for(const folderKey of Object.keys(folderProduct)){if(isFrameworkReservedKey(folderKey))continue;const alreadyPresent=Object.prototype.hasOwnProperty.call(keptWrapper,folderKey)||!!keptImpl&&Object.prototype.hasOwnProperty.call(keptImpl,folderKey);if(alreadyPresent)continue;Object.defineProperty(keptWrapper,folderKey,{value:folderChildren.has(folderKey)?folderChildren.get(folderKey):folderProduct[folderKey],writable:false,enumerable:true,configurable:true})}}async assignToApiPath(targetApi,key,value,options={}){const valueIsWrapper=this.isWrapperProxy(value);const valueId=valueIsWrapper?resolveWrapper(value)?.____slothletInternal?.id??"no-id":"not-wrapper";this.slothlet.debug("api",{key:"DEBUG_MODE_ASSIGN_TO_API",propKey:key,valueId,typeOf:typeof value});const{allowOverwrite=false,mutateExisting=false,useCollisionDetection=false,config=null,collisionContext="initial",syncWrapper=null,collisionMode="merge",collisionModeOverride=null,moduleID=null}=options;const existing=targetApi[key];if(existing!==void 0&&this.isWrapperProxy(existing)&&this.isWrapperProxy(value)){if(mutateExisting&&syncWrapper){await syncWrapper(existing,value,config,collisionMode,moduleID);return true}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_CHECK",propKey:key,useCollisionDetection,hasConfig:!!config,hasExisting:existing!==void 0,existingType:typeof existing});if(useCollisionDetection&&config&&existing!==void 0){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_DETECT",propKey:key,context:collisionContext,existingType:typeof existing,valueType:typeof value});const collisionMode2=collisionModeOverride||config.collision?.[collisionContext]||"merge";if(collisionMode2==="error"){const SlothletError=this.slothlet?.SlothletError||Error;throw new SlothletError("COLLISION_ERROR",{key:String(key),collisionMode:collisionMode2,collisionContext})}if(collisionMode2==="skip"){return false}let effectiveMode=collisionMode2;if(collisionMode2==="warn"){new this.slothlet.SlothletWarning("WARNING_COLLISION_FILE_FOLDER_MERGE",{key:String(key)});effectiveMode="merge"}const existingIsWrapper=this.isWrapperProxy(existing);const valueIsWrapper2=this.isWrapperProxy(value);this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_WRAPPER_DETECTION",propKey:key,existingIsWrapper,valueIsWrapper:valueIsWrapper2,hasExistingWrapper:resolveWrapper(existing)?"yes":"no",hasValueWrapper:resolveWrapper(value)?"yes":"no"});if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_LAZY_DETECTION",propKey:key,effectiveMode,existingLazy:existingIsLazyUnmaterialized,valueLazy:valueIsLazyUnmaterialized});if(existingIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_SET_MODE_EXISTING_WRAPPER",effectiveMode,apiPath:existingWrapper.____slothletInternal.apiPath});existingWrapper.____slothletInternal.state.collisionMode=effectiveMode;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_VERIFIED_EXISTING_WRAPPER_MODE",collisionMode:existingWrapper.____slothletInternal.state.collisionMode})}if(valueIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_SET_MODE_VALUE_WRAPPER",effectiveMode,apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper.____slothletInternal.state.collisionMode=effectiveMode;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_VERIFIED_VALUE_WRAPPER_MODE",collisionMode:valueWrapper.____slothletInternal.state.collisionMode});if(effectiveMode==="replace"){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_MATERIALIZE",apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper._materialize()}}}if(effectiveMode==="replace"){if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;if(valueIsLazyUnmaterialized&&!existingIsLazyUnmaterialized){this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_NO_COPY"});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_BEFORE",propKey:key,currentWrapperId:resolveWrapper(existing)?.____slothletInternal.id});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_ASSIGN_REPLACING_WITH_LAZY",propKey:key,collisionMode:valueWrapper.____slothletInternal.state.collisionMode});targetApi[key]=value;this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_AFTER",propKey:key,newWrapperId:resolveWrapper(targetApi[key])?.____slothletInternal.id});this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_REPLACE_VERIFY",expectedId:valueWrapper.____slothletInternal.id,actualId:resolveWrapper(targetApi[key])?.____slothletInternal.id});return true}}targetApi[key]=value;return true}if(effectiveMode==="merge"||effectiveMode==="merge-replace"){const isMergeReplace=effectiveMode==="merge-replace";if(existingIsWrapper&&valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const valueWrapper=resolveWrapper(value);const existingIsLazyUnmaterialized=existingWrapper.____slothletInternal.mode==="lazy"&&!existingWrapper.____slothletInternal.state.materialized;const valueIsLazyUnmaterialized=valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized;if(existingIsLazyUnmaterialized&&!valueIsLazyUnmaterialized){const valueMetadata=this.slothlet.handlers?.metadata?.getMetadata(value);const valueFilePath=valueMetadata?.filePath;if(!existingWrapper.____slothletInternal.childFilePathsPreMaterialize){existingWrapper.____slothletInternal.childFilePathsPreMaterialize={}}const valueChildKeys=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const key2 of valueChildKeys){Object.defineProperty(existingWrapper,key2,{configurable:true});if(valueFilePath){existingWrapper.____slothletInternal.childFilePathsPreMaterialize[key2]=valueFilePath}}return true}else if(valueIsLazyUnmaterialized&&!existingIsLazyUnmaterialized){if(!isMergeReplace&&existingWrapper.____slothletInternal.isCallable){valueWrapper.____slothletInternal.state.collisionMode=effectiveMode;existingWrapper.____slothletInternal.offSlotCollisionFolder=valueWrapper;valueWrapper.____slothletInternal.needsImmediateChildAdoption=true;if(valueWrapper.____slothletInternal.materializeFunc&&!valueWrapper.____slothletInternal.state?.materialized&&!valueWrapper.____slothletInternal.state?.inFlight){valueWrapper._materialize().catch(()=>{})}targetApi[key]=existing;return true}if(!isMergeReplace){const existingMetadata=this.slothlet.handlers?.metadata?.getMetadata(existing);const existingFilePath=existingMetadata?.filePath;if(!valueWrapper.____slothletInternal.childFilePathsPreMaterialize){valueWrapper.____slothletInternal.childFilePathsPreMaterialize={}}const existingChildKeys=Object.keys(existingWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_COPY_CHILD_KEYS",existingChildKeys:existingChildKeys.join(","),fromApiPath:existingWrapper.____slothletInternal.apiPath,toApiPath:valueWrapper.____slothletInternal.apiPath,valueWrapperId:valueWrapper.____slothletInternal.id||"no-id"});if(!valueWrapper.____slothletInternal.collisionMergedKeys){valueWrapper.____slothletInternal.collisionMergedKeys=new Set}for(const key2 of existingChildKeys){const child=existingWrapper[key2];this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_COPY_INDIVIDUAL_KEY",propKey:key2,childName:child?.name,typeOf:typeof child,valueWrapperId:valueWrapper.____slothletInternal.id||"no-id"});Object.defineProperty(valueWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true});valueWrapper.____slothletInternal.collisionMergedKeys.add(key2);if(existingFilePath){valueWrapper.____slothletInternal.childFilePathsPreMaterialize[key2]=existingFilePath}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_TRIGGER_EARLY_MAT",apiPath:valueWrapper.____slothletInternal.apiPath});valueWrapper.____slothletInternal.needsImmediateChildAdoption=true;if(valueWrapper.____slothletInternal.materializeFunc&&!valueWrapper.____slothletInternal.state?.materialized&&!valueWrapper.____slothletInternal.state?.inFlight){valueWrapper._materialize().catch(err=>{new this.slothlet.SlothletWarning("WARNING_COLLISION_TRIGGER_MATERIALIZE_ERROR",{apiPath:valueWrapper.____slothletInternal.apiPath},err)})}}else{valueWrapper._mergeAfterMaterialize={existingWrapper,isMergeReplace:true}}this.slothlet.debug("api",{key:"DEBUG_MODE_COLLISION_ASSIGN_REPLACING_WITH_LAZY",propKey:key,collisionMode:valueWrapper.____slothletInternal.state.collisionMode});targetApi[key]=value;return true}const existingChildCount=Object.keys(existingWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;const valueChildCount=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;if(existingWrapper.____slothletInternal.impl&&existingChildCount===0){existingWrapper.___adoptImplChildren()}if(valueWrapper.____slothletInternal.impl&&valueChildCount===0){valueWrapper.___adoptImplChildren()}const existingIsCallable=!!existingWrapper.____slothletInternal.isCallable;const valueIsCallable=!!valueWrapper.____slothletInternal.isCallable;if(!existingIsCallable&&valueIsCallable){const existingChildKeys2=Object.keys(existingWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const key2 of existingChildKeys2){const existingChild2=existingWrapper[key2];const keyOnValue=Object.prototype.hasOwnProperty.call(valueWrapper,key2);if(keyOnValue&&isMergeReplace){continue}if(keyOnValue){const desc2=Object.getOwnPropertyDescriptor(valueWrapper,key2);if(!desc2?.configurable)continue;delete valueWrapper[key2]}Object.defineProperty(valueWrapper,key2,{value:existingChild2,writable:false,enumerable:true,configurable:true})}targetApi[key]=value;return true}const valueChildKeys2=Object.keys(valueWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const key2 of valueChildKeys2){const child=valueWrapper[key2];const isInternal=typeof key2==="string"&&(key2.startsWith("_")||key2.startsWith("__"));const keyExists=!isInternal&&Object.prototype.hasOwnProperty.call(existingWrapper,key2);if(!keyExists){Object.defineProperty(existingWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true})}else if(isMergeReplace){const descriptor=Object.getOwnPropertyDescriptor(existingWrapper,key2);if(descriptor?.configurable){delete existingWrapper[key2]}Object.defineProperty(existingWrapper,key2,{value:child,writable:false,enumerable:true,configurable:true})}else{const existingChild=existingWrapper[key2];const existingChildWrapper=resolveWrapper(existingChild);const newChildWrapper=resolveWrapper(child);if(existingChildWrapper&&newChildWrapper){const newChildChildCount=Object.keys(newChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__")).length;if(newChildWrapper.____slothletInternal.impl&&newChildChildCount===0){newChildWrapper.___adoptImplChildren()}const newChildKeys=Object.keys(newChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));const ____existingChildKeys=Object.keys(existingChildWrapper).filter(k=>!k.startsWith("_")&&!k.startsWith("__"));for(const childKey of newChildKeys){const childKeyExists=Object.prototype.hasOwnProperty.call(existingChildWrapper,childKey);if(!childKeyExists){Object.defineProperty(existingChildWrapper,childKey,{value:newChildWrapper[childKey],writable:false,enumerable:true,configurable:true})}}}}}if(valueWrapper.____slothletInternal.mode==="lazy"&&!valueWrapper.____slothletInternal.state.materialized&&valueWrapper.____slothletInternal.materializeFunc){return false}return true}else if(existingIsWrapper&&!valueIsWrapper2){const existingWrapper=resolveWrapper(existing);const existingImpl=existingWrapper.__impl;const mergedImpl={...existingImpl||{},...value};existingWrapper.___setImpl(mergedImpl);return true}else if(!existingIsWrapper&&valueIsWrapper2){}else{if(typeof existing==="object"&&existing!==null&&typeof value==="object"&&value!==null){Object.assign(existing,value);return true}}}}if(existing!==void 0&&!allowOverwrite&&!mutateExisting&&!useCollisionDetection){return false}targetApi[key]=value;return true}async mergeApiObjects(targetApi,sourceApi,options={}){const config=options.config;if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_ENTRY",targetApiType:typeof targetApi,sourceApiType:typeof sourceApi});this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_SOURCE_KEYS",sourceApiKeys:sourceApi?Object.keys(sourceApi):[]})}if(!sourceApi||typeof sourceApi!=="object"&&typeof sourceApi!=="function"){if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_EXIT_INVALID_SOURCE"})}return}const{removeMissing=false,moduleID=null,...assignOptions}=options;if(isFrameworkInternal(sourceApi)){markFrameworkInternal(resolveWrapper(targetApi))}const sourceKeys=new Set(Object.keys(sourceApi));for(const key of sourceKeys){const sourceValue=sourceApi[key];const targetValue=targetApi[key];if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_PROCESSING_KEY",propKey:key,targetValueType:typeof targetValue,sourceValueType:typeof sourceValue})}if(targetValue&&typeof targetValue==="object"&&!this.isWrapperProxy(targetValue)&&sourceValue&&typeof sourceValue==="object"&&!this.isWrapperProxy(sourceValue)){if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_RECURSING",propKey:key})}await this.mergeApiObjects(targetValue,sourceValue,options)}else{if(config?.debug?.api){this.slothlet.debug("api",{key:"DEBUG_MODE_MERGE_API_OBJECTS_CALLING_ASSIGN",propKey:key})}await this.assignToApiPath(targetApi,key,sourceValue,{...assignOptions,moduleID})}}if(removeMissing){for(const key of Object.keys(targetApi)){if(!sourceKeys.has(key)){delete targetApi[key]}}}}}export{ApiAssignment};
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import{isNode,AsyncResource,loadJson}from"@cldmv/slothlet/helpers/platform";import{ComponentBase}from"#factories/component-base";import{TYPE_STATES,resolveWrapper}from"#handlers/unified-wrapper";import{TRUSTED_ROOT,PROTECT_SENTINEL}from"#handlers/trusted-root";import{getLanguage,initI18n,setLanguage,setLanguageAsync,t,translate}from"@cldmv/slothlet/i18n";function _resolvePathOrModuleId(slothlet,pathOrModuleId){const history=slothlet.handlers?.apiManager?.state?.addHistory;if(history){let match=null;for(let i=history.length-1;i>=0;i--){const entry=history[i];if(entry?.moduleID===pathOrModuleId){match=entry;break}}if(match)return match.apiPath}return pathOrModuleId}function describeScopeReceived(value){if(Array.isArray(value)){const badIndex=value.findIndex(entry=>typeof entry!=="string");if(badIndex!==-1){return`array with non-string entry (${typeof value[badIndex]} at index ${badIndex})`}return"array"}return typeof value}function makeCopyOnWriteSelf(parentSelf){const overlay=new Map;const childViews=new Map;return new Proxy({},{get(_t,prop){if(overlay.has(prop))return overlay.get(prop);const real=parentSelf[prop];if(real!==null&&typeof real==="object"){let view=childViews.get(prop);if(view===void 0){view=makeCopyOnWriteSelf(real);childViews.set(prop,view)}return view}return real},set(_t,prop,value){overlay.set(prop,value);childViews.delete(prop);return true},has(_t,prop){return overlay.has(prop)||prop in parentSelf},deleteProperty(_t,prop){overlay.delete(prop);childViews.delete(prop);return true},ownKeys(){const keys=new Set(Reflect.ownKeys(parentSelf));for(const k of overlay.keys())keys.add(k);return[...keys]},getOwnPropertyDescriptor(_t,prop){if(overlay.has(prop)){return{value:overlay.get(prop),writable:true,enumerable:true,configurable:true}}const desc=Reflect.getOwnPropertyDescriptor(parentSelf,prop);return desc?{...desc,configurable:true}:void 0}})}class ApiBuilder extends ComponentBase{static slothletProperty="apiBuilder";constructor(slothlet){super(slothlet)}async buildFinalAPI(userApi){this.slothlet.debug("api",{key:"DEBUG_MODE_BUILD_FINAL_API_CALLED",diagnostics:this.____config.diagnostics,userApiKeys:Object.keys(userApi)});if(this.slothlet._ownBuiltins){for(const[key,ref]of Object.entries(this.slothlet._ownBuiltins)){if(ref&&Object.prototype.hasOwnProperty.call(userApi,key)&&userApi[key]===ref){try{delete userApi[key]}catch(_){}}}}this.slothlet.userHooks={shutdown:typeof userApi.shutdown==="function"?userApi.shutdown:null,destroy:typeof userApi.destroy==="function"?userApi.destroy:null};if(userApi.slothlet){if(!this.____config?.silent){new this.SlothletWarning("WARNING_RESERVED_PROPERTY_CONFLICT",{properties:"slothlet"})}await this.emitImplDiagnostic("warning",{apiPath:"slothlet",code:"WARNING_RESERVED_PROPERTY_CONFLICT",context:{properties:"slothlet"},source:"buildAPI"})}const slothletNamespace=await this.createSlothletNamespace(userApi);this.slothlet.debug("api",{key:"DEBUG_MODE_SLOTHLET_NAMESPACE_CREATED",namespaceKeys:Object.keys(slothletNamespace),hasDiag:!!slothletNamespace.diag});const shutdownFn=this.createShutdownFunction();this.attachBuiltins(userApi,{slothlet:slothletNamespace,shutdown:shutdownFn,destroy:null});this.slothlet.debug("api",{key:"DEBUG_MODE_BUILT_INS_ATTACHED",userApiKeys:Object.keys(userApi),hasSlothlet:!!userApi.slothlet,hasDiag:!!userApi.slothlet?.diag});const destroyWithApi=this.createDestroyFunction(userApi);Object.defineProperty(userApi,"destroy",{value:destroyWithApi,enumerable:true,writable:false,configurable:true});this.slothlet._ownBuiltins={shutdown:shutdownFn,slothlet:slothletNamespace,destroy:destroyWithApi};return userApi}async createSlothletNamespace(userApi){const slothlet=this.slothlet;const config=this.____config;const enforceInternalPermission=targetPath=>{const ctx=slothlet.contextManager?.tryGetContext?.(slothlet.instanceID);const identity=slothlet.contextManager?.getCallerIdentity?.(slothlet.instanceID);if(identity?.unresolved){throw new slothlet.SlothletError("PERMISSION_DENIED",{caller:null,target:targetPath})}const callerWrapper=identity?.currentWrapper;if(!callerWrapper)return;const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.enforceAccess){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const callerPath=callerWrapper.____slothletInternal?.apiPath??"";const callerFilePath=callerWrapper.____slothletInternal?.filePath??null;const runtimeContext=ctx?.context??null;if(!permissionManager.enforceAccess(callerPath,targetPath,callerFilePath,null,runtimeContext)){throw new slothlet.SlothletError("PERMISSION_DENIED",{caller:callerPath,target:targetPath})}};const canTraverseInternalNamespace=targetPath=>{const ctx=slothlet.contextManager?.tryGetContext?.(slothlet.instanceID);const identity=slothlet.contextManager?.getCallerIdentity?.(slothlet.instanceID);if(identity?.unresolved)return false;const callerWrapper=identity?.currentWrapper;if(!callerWrapper)return false;const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesForCaller||!permissionManager?.checkAccess){return false}const callerPath=callerWrapper.____slothletInternal?.apiPath??"";const callerFilePath=callerWrapper.____slothletInternal?.filePath??null;const runtimeContext=ctx?.context??null;const callerRules=permissionManager.getRulesForCaller(callerPath);const conditionMatches=condition=>typeof permissionManager.matchesCondition==="function"?permissionManager.matchesCondition(condition,runtimeContext):false;const prefix=`${targetPath}.`;for(const rule of callerRules){if(!rule||rule.effect!=="allow"||typeof rule.target!=="string")continue;const couldMatchDescendant=rule.target.startsWith(prefix)||rule.target==="**"||rule.target==="*";if(!couldMatchDescendant)continue;if(rule.target.startsWith(prefix)&&conditionMatches(rule.condition)){return true}const probePaths=[`${targetPath}.__probe__`];if(rule.target.startsWith(prefix)){const suffix=rule.target.slice(prefix.length);const firstSegment=suffix.split(".")[0];if(firstSegment&&!/[*!?{}]/u.test(firstSegment)){probePaths.unshift(`${targetPath}.${firstSegment}`);probePaths.push(`${targetPath}.${firstSegment}.__probe__`)}}for(const probePath of probePaths){if(permissionManager.checkAccess(callerPath,probePath,callerFilePath,null,runtimeContext,{useCache:false})){return true}}}return false};const createInternalRouteProxy=(value,routePath,seen=new WeakMap)=>{if(!value||typeof value!=="object"&&typeof value!=="function")return value;const isMetaProperty=prop=>prop==="__proto__"||prop==="prototype"||prop==="constructor"||prop==="caller"||prop==="arguments";let routeCache=seen.get(value);if(!routeCache){routeCache=new Map;seen.set(value,routeCache)}if(routeCache.has(routePath)){return routeCache.get(routePath)}const proxy=new Proxy(value,{get(target,prop,receiver){if(typeof prop!=="string"){const result2=Reflect.get(target,prop,receiver);return createInternalRouteProxy(result2,routePath,seen)}const childRoutePath=`${routePath}.${prop}`;let deniedError=null;try{enforceInternalPermission(childRoutePath)}catch(error){deniedError=error}if(deniedError){if(canTraverseInternalNamespace(childRoutePath)){const result2=Reflect.get(target,prop,receiver);if(result2&&(typeof result2==="object"||typeof result2==="function")){return createInternalRouteProxy(result2,childRoutePath,seen)}}throw deniedError}const result=Reflect.get(target,prop,receiver);if(isMetaProperty(prop)){return result}const descriptor=Object.getOwnPropertyDescriptor(target,prop);if(descriptor&&"value"in descriptor&&descriptor.configurable===false&&descriptor.writable===false){return descriptor.value}return createInternalRouteProxy(result,childRoutePath,seen)},getOwnPropertyDescriptor(target,prop){const descriptor=Reflect.getOwnPropertyDescriptor(target,prop);if(!descriptor)return void 0;if(typeof prop!=="string"){return descriptor}const childRoutePath=`${routePath}.${prop}`;if(isMetaProperty(prop)){enforceInternalPermission(childRoutePath);return descriptor}if("get"in descriptor||"set"in descriptor){enforceInternalPermission(childRoutePath);if(descriptor.configurable===true){return{...descriptor,get:typeof descriptor.get==="function"?function slothlet_internal_descriptor_getter(...args){enforceInternalPermission(childRoutePath);return Reflect.apply(descriptor.get,this,args)}:descriptor.get,set:typeof descriptor.set==="function"?function slothlet_internal_descriptor_setter(...args){enforceInternalPermission(childRoutePath);return Reflect.apply(descriptor.set,this,args)}:descriptor.set}}return descriptor}if(!("value"in descriptor)){return descriptor}const descriptorValue=descriptor.value;if(descriptor.configurable===false&&descriptor.writable===false){enforceInternalPermission(childRoutePath);return descriptor}if(!descriptorValue||typeof descriptorValue!=="object"&&typeof descriptorValue!=="function"||typeof descriptorValue==="function"){enforceInternalPermission(childRoutePath);if(typeof descriptorValue==="function"&&descriptor.configurable===true){return{...descriptor,value:createInternalRouteProxy(descriptorValue,childRoutePath,seen)}}return descriptor}return{...descriptor,value:createInternalRouteProxy(descriptorValue,childRoutePath,seen)}},set(target,prop,newValue,receiver){if(typeof prop!=="string"){return Reflect.set(target,prop,newValue,receiver)}const childRoutePath=`${routePath}.${prop}`;enforceInternalPermission(childRoutePath);return Reflect.set(target,prop,newValue,receiver)},defineProperty(target,prop,descriptor){if(typeof prop!=="string"){return Reflect.defineProperty(target,prop,descriptor)}const childRoutePath=`${routePath}.${prop}`;enforceInternalPermission(childRoutePath);return Reflect.defineProperty(target,prop,descriptor)},deleteProperty(target,prop){if(typeof prop!=="string"){return Reflect.deleteProperty(target,prop)}const childRoutePath=`${routePath}.${prop}`;enforceInternalPermission(childRoutePath);return Reflect.deleteProperty(target,prop)},ownKeys(target){return Reflect.ownKeys(target)},apply(target,thisArg,argArray){enforceInternalPermission(routePath);return Reflect.apply(target,thisArg,argArray)},construct(target,argArray,newTarget){enforceInternalPermission(routePath);return Reflect.construct(target,argArray,newTarget)}});routeCache.set(routePath,proxy);return proxy};let version="unknown";if(isNode){const pkg=loadJson(new URL("../../../package.json",import.meta.url));if(pkg?.version)version=pkg?.version}const namespace={i18n:{setLanguage,setLanguageAsync,getLanguage,translate,t,initI18n},version,instanceID:slothlet.instanceID,types:TYPE_STATES,api:{add:async function slothlet_api_add(apiPath,folderPath,options={},versionConfig=null){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.add",validationError:true})}const{recordHistory:____recordHistory,collisionMode:____collisionMode,mutateExisting:____mutateExisting,...filteredOptions}=options;return slothlet.handlers.apiManager.addApiComponent({apiPath,folderPath,options:filteredOptions,versionConfig:versionConfig||null})},remove:async function slothlet_api_remove(pathOrModuleId,apiPath){if(!config.api?.mutations?.remove){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.remove",validationError:true})}if(typeof pathOrModuleId!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"pathOrModuleId",expected:"string",received:typeof pathOrModuleId,validationError:true})}if(apiPath!==void 0&&typeof apiPath!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"apiPath",expected:"string",received:typeof apiPath,validationError:true})}return slothlet.handlers.apiManager.removeApiComponent(pathOrModuleId,{scopedApiPath:apiPath})},leaves:async function slothlet_api_leaves(key,options={}){enforceInternalPermission("slothlet.api.leaves");if(typeof key!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"key",expected:"string",received:typeof key,validationError:true})}const normalizedOptions=options==null?{}:options;if(typeof normalizedOptions!=="object"||Array.isArray(normalizedOptions)){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"options",expected:"object with optional boolean details/includePrivate",received:Array.isArray(normalizedOptions)?"array":typeof normalizedOptions,validationError:true})}const{details=false,includePrivate=false}=normalizedOptions;for(const[name,value]of[["details",details],["includePrivate",includePrivate]]){if(typeof value!=="boolean"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:`options.${name}`,expected:"boolean",received:typeof value,validationError:true})}}const ownership=slothlet.handlers.ownership;const leavesIdentity=slothlet.contextManager?.getCallerIdentity?.();const leavesCaller=leavesIdentity?.currentWrapper??null;if(includePrivate&&leavesCaller){throw new slothlet.SlothletError("PERMISSION_DENIED",{caller:leavesCaller.____slothletInternal?.apiPath??"",target:"slothlet.api.leaves:includePrivate"})}let moduleID=null;if(key==="."||key===""){moduleID=[...ownership.moduleEndpoints.entries()].find(([,endpoint2])=>endpoint2===".")?.[0]}else if(ownership.moduleToPath.has(key)){moduleID=key}else{moduleID=ownership.getCurrentOwner(key)?.moduleID??null;if(!moduleID){moduleID=[...ownership.moduleEndpoints.entries()].find(([,endpoint2])=>endpoint2===key)?.[0]??null}}if(!moduleID||!ownership.moduleToPath.has(moduleID)){throw new slothlet.SlothletError("API_LEAVES_UNKNOWN_MODULE",{key},null,{validationError:true})}const endpoint=ownership.moduleEndpoints.get(moduleID);const boundApi=slothlet.boundApi;if(config.mode==="lazy"&&boundApi){const seen=new WeakSet;let root=boundApi;if(endpoint!=="."){for(const segment of endpoint.split("."))root=root[segment]}const pending=[{node:root,path:endpoint==="."?"":endpoint}];while(pending.length>0){const{node,path}=pending.pop();if(node===null||typeof node!=="object"&&typeof node!=="function")continue;if(seen.has(node))continue;seen.add(node);if(typeof node._materialize==="function"&&node.__materialized===false){await node._materialize()}const childKeys=new Set(Object.keys(node));const records=ownership.moduleToPath.get(moduleID);if(path!==null&&records){const prefix=path===""?"":`${path}.`;for(const ownedPath of records){if(ownedPath===""||prefix!==""&&!ownedPath.startsWith(prefix))continue;const rest=ownedPath.slice(prefix.length);const segmentEnd=rest.indexOf(".");childKeys.add(segmentEnd===-1?rest:rest.slice(0,segmentEnd))}}for(const childKey of childKeys){if(path===""&&(childKey==="slothlet"||childKey==="shutdown"||childKey==="destroy"))continue;let child;try{child=node[childKey]}catch{continue}const childWrapper=child?resolveWrapper(child):null;if(childWrapper?.____slothletInternal?.userAssigned)continue;const childPath=path===null?null:path===""?childKey:`${path}.${childKey}`;pending.push({node:child,path:records?.has(childPath)?childPath:null})}}}if(!ownership.moduleToPath.has(moduleID)){throw new slothlet.SlothletError("API_LEAVES_UNKNOWN_MODULE",{key},null,{validationError:true})}const ownedPaths=[...ownership.moduleToPath.get(moduleID)].filter(path=>{if(path==="")return false;if(endpoint==="."&&(path==="slothlet"||path.startsWith("slothlet.")||path==="shutdown"||path==="destroy"))return false;const currentOwner=ownership.getCurrentOwner(path);return!currentOwner||currentOwner.moduleID===moduleID});ownedPaths.sort();const namespaces=new Set;for(const owned of ownedPaths){let cut=owned.lastIndexOf(".");while(cut>0){namespaces.add(owned.slice(0,cut));cut=owned.lastIndexOf(".",cut-1)}}const kindOf=path=>{if(namespaces.has(path))return"namespace";const entry=ownership.pathToModule.get(path)?.find(candidate=>candidate.moduleID===moduleID);return typeof entry?.value==="function"?"function":"data"};const permissionManager=slothlet.handlers?.permissionManager;let visiblePaths=ownedPaths;if(!includePrivate&&permissionManager?.isEnabled?.()){const callerPath=leavesCaller?.____slothletInternal?.apiPath??"";const callerFilePath=leavesCaller?.____slothletInternal?.filePath??null;const runtimeContext=slothlet.contextManager?.tryGetContext?.()?.context??null;visiblePaths=ownedPaths.filter(path=>{if(!permissionManager.isPrivateTarget(path))return true;const entry=ownership.pathToModule.get(path)?.find(candidate=>candidate.moduleID===moduleID);return permissionManager.checkAccess(callerPath,path,callerFilePath,entry?.filePath,runtimeContext)})}if(details){return visiblePaths.map(path=>({path,kind:kindOf(path)}))}return visiblePaths.filter(path=>kindOf(path)==="function")},reload:async function slothlet_api_reload(pathOrModuleId,options){if(!config.api?.mutations?.reload){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.reload",validationError:true})}if(pathOrModuleId==null||pathOrModuleId===""||pathOrModuleId==="."){return slothlet.handlers.apiManager.reloadApiComponent({apiPath:".",options})}if(typeof pathOrModuleId!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"pathOrModuleId",expected:"string, null, undefined, or '.'",received:typeof pathOrModuleId,validationError:true})}const isModuleId=slothlet.handlers.apiManager.state.addHistory.some(entry=>entry.moduleID===pathOrModuleId);if(isModuleId){return slothlet.handlers.apiManager.reloadApiComponent({moduleID:pathOrModuleId,options})}const normalizedPath=slothlet.handlers.apiManager.normalizeApiPath(pathOrModuleId).apiPath;const pathParts=normalizedPath.split(".");let current=slothlet.api;for(const part of pathParts){if(!current||typeof current!=="object"&&typeof current!=="function"){throw new slothlet.SlothletError("INVALID_API_PATH",{apiPath:pathOrModuleId,validationError:true})}current=current[part]}if(current===void 0){throw new slothlet.SlothletError("INVALID_API_PATH",{apiPath:pathOrModuleId,validationError:true})}return slothlet.handlers.apiManager.reloadApiComponent({apiPath:normalizedPath,options})},modules:{discover:function slothlet_modules_discover(options){return slothlet.handlers.moduleManager.discover(options)},sort:function slothlet_modules_sort(results,comparator){return slothlet.handlers.moduleManager.sort(results,comparator)},addModule:async function slothlet_modules_addModule(nameOrResult,options){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.modules.addModule",validationError:true})}return slothlet.handlers.moduleManager.addModule(nameOrResult,options)},addModules:async function slothlet_modules_addModules(items,options){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.modules.addModules",validationError:true})}return slothlet.handlers.moduleManager.addModules(items,options)},removeModule:async function slothlet_modules_removeModule(name,opts){if(!config.api?.mutations?.remove){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.modules.removeModule",validationError:true})}return slothlet.handlers.moduleManager.removeModule(name,opts)},addDiscovered:async function slothlet_modules_addDiscovered(options={}){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.modules.addDiscovered",validationError:true})}const{sort:comparator,collisionMode,onFailure,concurrency,...discoverOptions}=options;const found=await slothlet.handlers.moduleManager.discover(discoverOptions);const ordered=slothlet.handlers.moduleManager.sort(found,comparator);return slothlet.handlers.moduleManager.addModules(ordered,{collisionMode,onFailure,concurrency})},getDiscoveryCache:function slothlet_modules_getDiscoveryCache(){return slothlet.handlers.moduleManager.getDiscoveryCache()},clearDiscoveryCache:function slothlet_modules_clearDiscoveryCache(){return slothlet.handlers.moduleManager.clearDiscoveryCache()},getStaleMounts:function slothlet_modules_getStaleMounts(){return slothlet.handlers.moduleManager.getStaleMounts()}}},sanitize:function slothlet_sanitize(str){if(typeof str!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"str",expected:"string",received:typeof str,validationError:true})}return slothlet.helpers.sanitize.sanitizePropertyName(str,slothlet.config.sanitize||{})},lockCaller:function slothlet_lockCaller(fn){if(typeof fn!=="function"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"fn",expected:"function",received:typeof fn,validationError:true})}const capturedWrapper=slothlet.contextManager?.getCallerIdentity?.()?.currentWrapper??null;if(!capturedWrapper)return fn;const locked=function slothlet_lockedCaller(...args){return slothlet.contextManager.runInContext(slothlet.instanceID,fn,this,args,capturedWrapper,true)};locked._slothletOriginal=fn;return locked},bind:function slothlet_bind(fn){if(typeof fn!=="function"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"fn",expected:"function",received:typeof fn,validationError:true})}return AsyncResource?AsyncResource.bind(fn,"slothlet-bound"):fn},context:{get:key=>{if(slothlet.contextManager.constructor.name==="LiveContextManager"){const currentID=slothlet.contextManager.currentInstanceID;if(currentID){const activeStore=slothlet.contextManager.instances.get(currentID);const isOurInstance=currentID===slothlet.instanceID||currentID?.startsWith(slothlet.instanceID+"__run_")||activeStore?.parentInstanceID===slothlet.instanceID;if(isOurInstance&&activeStore){return key?activeStore.context[key]:{...activeStore.context}}}const store=slothlet.contextManager.instances.get(slothlet.instanceID);if(!store){const baseContext2=slothlet.context||{};return key?baseContext2[key]:{...baseContext2}}return key?store.context[key]:{...store.context}}if(slothlet.contextManager.constructor.name==="AsyncContextManager"){let currentStore=slothlet.contextManager.tryGetContext();if(!currentStore){const baseStore2=slothlet.contextManager.instances.get(slothlet.instanceID);const baseContext3=baseStore2?.context||{};return key?baseContext3[key]:{...baseContext3}}const isOurInstance=currentStore.instanceID===slothlet.instanceID||currentStore.parentInstanceID===slothlet.instanceID||currentStore.instanceID.startsWith(slothlet.instanceID+"__run_");if(isOurInstance){return key?currentStore.context[key]:{...currentStore.context}}const baseStore=slothlet.contextManager.instances.get(slothlet.instanceID);const baseContext2=baseStore?.context||{};return key?baseContext2[key]:{...baseContext2}}const baseContext=slothlet.context||{};return key?baseContext[key]:{...baseContext}},diagnostics:()=>{if(!slothlet.config?.diagnostics)return void 0;const managerType=slothlet.contextManager.constructor.name;const result={instanceID:slothlet.instanceID,managerType,instancesMapSize:slothlet.contextManager.instances.size,instancesMapKeys:Array.from(slothlet.contextManager.instances.keys()),baseContext:slothlet.context};const store=slothlet.contextManager.instances.get(slothlet.instanceID);result.storeFromInstancesMap=store?{instanceID:store.instanceID,context:store.context,createdAt:store.createdAt}:null;if(managerType==="AsyncContextManager"){try{const currentCtx=slothlet.contextManager.tryGetContext();result.currentALSContext=currentCtx?{instanceID:currentCtx.instanceID,context:currentCtx.context,hasParent:!!currentCtx.parentContext,parentInstanceID:currentCtx.parentInstanceID}:null}catch(____error){result.currentALSContext=null}}if(managerType==="LiveContextManager"){result.currentInstanceID=slothlet.contextManager.currentInstanceID}return result},run:this.createRunFunction(),scope:this.createScopeFunction()},hook:{on:function slothlet_hook_on(typePattern,handler,options={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.on(typePattern,handler,options)},remove:function slothlet_hook_remove(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.remove(filter)},clear:function slothlet_hook_clear(filter={}){return this.remove(filter)},off:function slothlet_hook_off(idOrFilter){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}const filter=typeof idOrFilter==="string"?{id:idOrFilter}:idOrFilter;return slothlet.handlers.hookManager.remove(filter)},enable:function slothlet_hook_enable(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.enable(filter)},disable:function slothlet_hook_disable(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.disable(filter)},enablePattern:function slothlet_hook_enablePattern(pattern){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.enablePattern(pattern)},disablePattern:function slothlet_hook_disablePattern(pattern){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.disablePattern(pattern)},resetPatternFilter:function slothlet_hook_resetPatternFilter(){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.resetPatternFilter()},list:function slothlet_hook_list(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.list(filter)},pin:{get enabled(){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.pinEnforced},enable:function slothlet_hook_pin_enable(){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.setPinEnforced(true)},disable:function slothlet_hook_pin_disable(){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.setPinEnforced(false)}}},metadata:{setGlobal:function slothlet_metadata_setGlobal(keyOrObj,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}const validateGlobalMetadataKeyPath=keyPath=>{const blocked=new Set(["__proto__","prototype","constructor"]);if(typeof keyPath!=="string"||keyPath.length===0){throw new slothlet.SlothletError("INVALID_METADATA_KEY",{key:keyPath,type:typeof keyPath,expected:"non-empty string"})}const segments=keyPath.split(".");for(const segment of segments){if(!segment||blocked.has(segment)){throw new slothlet.SlothletError("INVALID_METADATA_KEY",{key:keyPath,type:typeof keyPath,expected:"safe dot-notation key without reserved segments"})}}};const normalizeGlobalMetadataObject=(source,prefix="",ancestors=new WeakSet)=>{if(ancestors.has(source)){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"keyOrObj",expected:"acyclic object",received:"circular reference",validationError:true})}ancestors.add(source);try{const normalized={};for(const[key,nestedValue]of Object.entries(source)){const fullKey=prefix?`${prefix}.${key}`:key;validateGlobalMetadataKeyPath(fullKey);const nestedProto=nestedValue&&typeof nestedValue==="object"?Object.getPrototypeOf(nestedValue):null;const isPlainNested=nestedProto===Object.prototype||nestedProto===null;if(nestedValue&&typeof nestedValue==="object"&&!Array.isArray(nestedValue)&&isPlainNested){normalized[key]=normalizeGlobalMetadataObject(nestedValue,fullKey,ancestors);continue}normalized[key]=nestedValue}return normalized}finally{ancestors.delete(source)}};if(keyOrObj&&typeof keyOrObj==="object"&&!Array.isArray(keyOrObj)){const normalizedMetadata=normalizeGlobalMetadataObject(keyOrObj);for(const[key,nestedValue]of Object.entries(normalizedMetadata)){slothlet.handlers.metadata.setGlobalMetadata(key,nestedValue)}return}if(typeof keyOrObj!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"keyOrObj",expected:"string or object",received:typeof keyOrObj,validationError:true})}validateGlobalMetadataKeyPath(keyOrObj);return slothlet.handlers.metadata.setGlobalMetadata(keyOrObj,value)},set:function slothlet_metadata_set(fn,key,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}return slothlet.handlers.metadata.setUserMetadata(fn,key,value)},remove:function slothlet_metadata_remove(fn,key){return slothlet.handlers.metadata.removeUserMetadata(fn,key)},setFor:function slothlet_metadata_setFor(pathOrModuleId,keyOrObj,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}const resolvedPath=_resolvePathOrModuleId(slothlet,pathOrModuleId);return slothlet.handlers.metadata.setPathMetadata(resolvedPath,keyOrObj,value)},removeFor:function slothlet_metadata_removeFor(pathOrModuleId,key){if(!slothlet.handlers?.metadata)return;const resolvedPath=_resolvePathOrModuleId(slothlet,pathOrModuleId);return slothlet.handlers.metadata.removePathMetadata(resolvedPath,key)},getFor:function slothlet_metadata_getFor(pathOrModuleId){if(!slothlet.handlers?.metadata)return{};const resolvedPath=_resolvePathOrModuleId(slothlet,pathOrModuleId);return slothlet.handlers.metadata.getPathMetadata(resolvedPath)},setForVersion:function slothlet_metadata_setForVersion(logicalPath,versionTag,keyOrObj,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}const info=slothlet.handlers?.versionManager?.list(logicalPath);if(!info||!info.versions?.[versionTag]){throw new slothlet.SlothletError("VERSION_NOT_FOUND",{version:versionTag,apiPath:logicalPath})}const{moduleID}=info.versions[versionTag];const resolvedPath=_resolvePathOrModuleId(slothlet,moduleID);return slothlet.handlers.metadata.setPathMetadata(resolvedPath,keyOrObj,value)},getForVersion:function slothlet_metadata_getForVersion(logicalPath,versionTag){if(!slothlet.handlers?.metadata)return{};const info=slothlet.handlers?.versionManager?.list(logicalPath);if(!info||!info.versions?.[versionTag])return{};const{moduleID}=info.versions[versionTag];const resolvedPath=_resolvePathOrModuleId(slothlet,moduleID);return slothlet.handlers.metadata.getPathMetadata(resolvedPath)}},scope:this.createScopeFunction(),run:this.createRunFunction(),reload:async(options={})=>{if(!config.api?.mutations?.reload){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"reload",validationError:true})}return slothlet.reload(options)},shutdown:async()=>{return slothlet.shutdown()},owner:{get:apiPath=>{if(slothlet.handlers?.ownership){return slothlet.handlers.ownership.getPathOwnership(apiPath)}return null}},materialize:(()=>{const mgr=slothlet.handlers?.materialize;const getMaterializedState=()=>{enforceInternalPermission("slothlet.materialize.materialized");return mgr?.materialized??false};const getMaterializeStats=()=>{enforceInternalPermission("slothlet.materialize.get");return mgr?mgr.get():{total:0,materialized:0,remaining:0,percentage:100}};const waitForMaterialization=async()=>{enforceInternalPermission("slothlet.materialize.wait");if(!mgr)return;return mgr.wait()};if(!mgr){return Object.freeze({get materialized(){return getMaterializedState()},get:getMaterializeStats,wait:waitForMaterialization})}return Object.freeze({get materialized(){return getMaterializedState()},get:getMaterializeStats,wait:waitForMaterialization})})(),lifecycle:(()=>{const handler=slothlet.handlers?.lifecycle;const noop=()=>{};if(!handler)return{on:noop,off:noop};return{on:handler.on.bind(handler),off:handler.off.bind(handler)}})(),env:slothlet.envSnapshot,versioning:{list:function slothlet_version_list(logicalPath){if(!slothlet.handlers?.versionManager)return void 0;return slothlet.handlers.versionManager.list(logicalPath)},setDefault:function slothlet_version_setDefault(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return;return slothlet.handlers.versionManager.setDefault(logicalPath,versionTag)},unregister:async function slothlet_version_unregister(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return false;const info=slothlet.handlers.versionManager.list(logicalPath);if(!info||!info.versions?.[versionTag])return false;const{moduleID:versionedModuleID}=info.versions[versionTag];await slothlet.handlers.apiManager.removeApiComponent(versionedModuleID);return true},getVersionMetadata:function slothlet_version_getVersionMetadata(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return void 0;return slothlet.handlers.versionManager.getVersionMetadataByPath(logicalPath,versionTag)},setVersionMetadata:function slothlet_version_setVersionMetadata(logicalPath,versionTag,patch){if(!slothlet.handlers?.versionManager)return;return slothlet.handlers.versionManager.setVersionMetadataByPath(logicalPath,versionTag,patch)}},permissions:{addRule:function slothlet_permissions_addRule(rule){if(!config.api?.mutations?.permissions){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.slothlet.permissions.addRule",validationError:true})}const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.addRule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const ruleId=permissionManager.addRule(rule,null);if(slothlet.handlers?.apiManager?.state?.operationHistory){slothlet.handlers.apiManager.state.operationHistory.push({type:"addPermissionRule",rule,ownerModuleID:null,ruleId,timestamp:Date.now()})}return ruleId},removeRule:function slothlet_permissions_removeRule(ruleId){if(!config.api?.mutations?.permissions){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.slothlet.permissions.removeRule",validationError:true})}const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.removeRule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const currentWrapper=slothlet.contextManager?.getCallerIdentity?.()?.currentWrapper;const callerModuleID=currentWrapper?.____slothletInternal?.moduleID??null;const result=slothlet.handlers.permissionManager.removeRule(ruleId,callerModuleID);if(result&&slothlet.handlers?.apiManager?.state?.operationHistory){slothlet.handlers.apiManager.state.operationHistory.push({type:"removePermissionRule",ruleId,callerModuleID,timestamp:Date.now()})}return result},self:{access:function slothlet_permissions_self_access(target){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.checkAccess){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const ctx=slothlet.contextManager?.tryGetContext?.();const currentWrapper=slothlet.contextManager?.getCallerIdentity?.()?.currentWrapper;const callerPath=currentWrapper?.____slothletInternal?.apiPath??"";const callerFilePath=currentWrapper?.____slothletInternal?.filePath??null;const runtimeContext=ctx?.context??null;return slothlet.handlers.permissionManager.checkAccess(callerPath,target,callerFilePath,null,runtimeContext)},rules:function slothlet_permissions_self_rules(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesForCaller){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const currentWrapper=slothlet.contextManager?.getCallerIdentity?.()?.currentWrapper;const callerPath=currentWrapper?.____slothletInternal?.apiPath??"";return slothlet.handlers.permissionManager.getRulesForCaller(callerPath)}},global:{checkAccess:function slothlet_permissions_global_checkAccess(caller,target){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.checkAccess){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const runtimeContext=slothlet.contextManager?.tryGetContext?.()?.context??null;return slothlet.handlers.permissionManager.checkAccess(caller,target,null,null,runtimeContext)},rulesForPath:function slothlet_permissions_global_rulesForPath(path){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesForPath){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return slothlet.handlers.permissionManager.getRulesForPath(path)},rulesByModule:function slothlet_permissions_global_rulesByModule(moduleID){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesByModule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return slothlet.handlers.permissionManager.getRulesByModule(moduleID)}},control:{get enabled(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.isEnabled){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return permissionManager.isEnabled()},enable:function slothlet_permissions_control_enable(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.enable){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}slothlet.handlers.permissionManager.enable()},disable:function slothlet_permissions_control_disable(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.disable){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}slothlet.handlers.permissionManager.disable()},get readGatingEnabled(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.isReadGatingEnabled){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return permissionManager.isReadGatingEnabled()},readGating:function slothlet_permissions_control_readGating(value){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.setReadGating){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}slothlet.handlers.permissionManager.setReadGating(value)},seal:function slothlet_permissions_control_seal(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.seal){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}slothlet.handlers.permissionManager.seal()},get sealed(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.isSealed){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return permissionManager.isSealed()}}}};if(!config.hook?.enabled&&config.diagnostics!==true){delete namespace.hooks}if(config.diagnostics===true){namespace.diag={describe:(showAll=false)=>{if(showAll){return{...userApi}}return Reflect.ownKeys(userApi)},reference:slothlet.reference||null,context:slothlet.context||{},inspect:()=>{return slothlet.getDiagnostics()},getAPI:()=>{return slothlet.getAPI()},getOwnership:()=>{return slothlet.getOwnership()},owner:{get:apiPath=>{if(slothlet.handlers?.ownership){return slothlet.handlers.ownership.getPathOwnership(apiPath)}return null}},caches:{get:()=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.getCacheDiagnostics()}return{totalCaches:0,caches:[]}},getAllModuleIDs:()=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.getAllModuleIDs()}return[]},has:moduleID=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.has(moduleID)}return false}},SlothletWarning:slothlet.SlothletWarning,hook:slothlet.handlers?.hookManager?{get enabled(){return slothlet.handlers.hookManager.enabled},compilePattern:pattern=>{return slothlet.handlers.hookManager.getCompilePatternForDiagnostics()(pattern)}}:void 0}}return createInternalRouteProxy(namespace,"slothlet")}createShutdownFunction(){const slothlet=this.slothlet;const shutdownFunction={shutdown:async()=>{if(slothlet.config.collectLifecycleHooks){const nestedHooks=(await slothlet._collectLifecycleHooks("shutdown")).reverse();for(const{fn,receiver}of nestedHooks){try{await Reflect.apply(fn,receiver,[])}catch{}}}if(slothlet.userHooks?.shutdown&&typeof slothlet.userHooks.shutdown==="function"){await slothlet.userHooks.shutdown()}return slothlet.shutdown()}}.shutdown;return shutdownFunction}createRunFunction(){const slothlet=this.slothlet;const scopeFunc=this.createScopeFunction();const runFunction={run:async(contextData,callback,...args)=>{if(slothlet.config.scope===false){throw new slothlet.SlothletError("SCOPE_DISABLED",{},null,{validationError:true})}if(!contextData||typeof contextData!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_CONTEXT",{received:typeof contextData},null,{validationError:true})}if(typeof callback!=="function"){throw new slothlet.SlothletError("SCOPE_INVALID_CALLBACK",{received:typeof callback},null,{validationError:true})}return scopeFunc({context:contextData,fn:callback,args,merge:slothlet.config.scope?.merge||"shallow",isolation:slothlet.config.scope?.isolation||"partial"})}}.run;return runFunction}createScopeFunction(){const slothlet=this.slothlet;const scopeFunction={scope:async options=>{if(slothlet.config.scope===false){throw new slothlet.SlothletError("SCOPE_DISABLED",{},null,{validationError:true})}if(!options||typeof options!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_OPTIONS",{received:typeof options},null,{validationError:true})}if(!options.fn||typeof options.fn!=="function"){throw new slothlet.SlothletError("SCOPE_INVALID_FN",{received:typeof options?.fn},null,{validationError:true})}if(!options.context||typeof options.context!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_CONTEXT_OBJECT",{received:typeof options?.context},null,{validationError:true})}const{context:contextData,fn,args=[],merge="shallow",isolation,protect,owners}=options;if(merge!=="shallow"&&merge!=="deep"){throw new slothlet.SlothletError("SCOPE_INVALID_MERGE_STRATEGY",{merge},null,{validationError:true})}const isolationMode=isolation||slothlet.config.scope?.isolation||"partial";if(isolationMode!=="partial"&&isolationMode!=="full"){throw new slothlet.SlothletError("SCOPE_INVALID_ISOLATION_MODE",{isolationMode},null,{validationError:true})}if(protect!==void 0&&(!Array.isArray(protect)||protect.some(k=>typeof k!=="string"))){throw new slothlet.SlothletError("SCOPE_INVALID_PROTECT",{received:describeScopeReceived(protect)},null,{validationError:true})}if(owners!==void 0){if(typeof owners!=="object"||owners===null||Array.isArray(owners)){throw new slothlet.SlothletError("SCOPE_INVALID_OWNERS",{received:describeScopeReceived(owners)},null,{validationError:true})}for(const[key,owner]of Object.entries(owners)){if(typeof owner!=="string"||owner.length===0){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:`owners.${key}`,expected:"non-empty string",received:typeof owner==="string"?"empty string":typeof owner,validationError:true})}}}const buildContextOwners=parentOwners=>{const base=parentOwners??null;let child=base;const claim=(key,owner)=>{const existing=child&&Object.prototype.hasOwnProperty.call(child,key)?child[key]:void 0;if(existing!==void 0&&existing!==owner){throw new slothlet.SlothletError("CONTEXT_KEY_OWNED",{key:String(key)},null,{validationError:true})}if(child===base)child=base?Object.assign(Object.create(null),base):Object.create(null);child[key]=owner};if(Array.isArray(protect))for(const k of protect)claim(k,PROTECT_SENTINEL);if(owners&&typeof owners==="object")for(const[k,o]of Object.entries(owners))claim(k,o);return child};const contextManager=slothlet.contextManager;if(!contextManager){throw new slothlet.SlothletError("NO_CONTEXT_MANAGER",{validationError:true})}const{utilities}=slothlet.helpers;if(contextManager.constructor.name==="LiveContextManager"){let currentStore=null;const currentID=contextManager.currentInstanceID;if(currentID){const activeStore=contextManager.instances.get(currentID);const isOurContext=currentID===slothlet.instanceID||activeStore?.parentInstanceID===slothlet.instanceID||currentID.startsWith(slothlet.instanceID+"__run_");if(isOurContext){currentStore=activeStore}}if(!currentStore){currentStore=contextManager.instances.get(slothlet.instanceID)}if(!currentStore){throw new slothlet.SlothletError("CONTEXT_NOT_FOUND",{instanceID:slothlet.instanceID,availableInstances:[...contextManager.instances.keys()].join(", ")||"none",validationError:true})}let mergedContext;if(merge==="deep"){mergedContext=utilities.deepMerge(currentStore.context,contextData);mergedContext=structuredClone(mergedContext)}else{const clonedParent=structuredClone(currentStore.context);mergedContext={...clonedParent,...contextData}}const childInstanceID=`${slothlet.instanceID}__run_${Date.now()}_${Math.random().toString(36).slice(2,9)}`;const childStore={instanceID:childInstanceID,context:mergedContext,self:isolationMode==="full"?makeCopyOnWriteSelf(currentStore.self):currentStore.self,config:currentStore.config,createdAt:currentStore.createdAt,parentInstanceID:slothlet.instanceID,currentWrapper:currentStore.currentWrapper,callerWrapper:currentStore.callerWrapper,slothlet:currentStore.slothlet,__contextOwners:buildContextOwners(currentStore.__contextOwners)};if(currentStore[TRUSTED_ROOT]===true){Object.defineProperty(childStore,TRUSTED_ROOT,{value:true,configurable:true})}contextManager.instances.set(childInstanceID,childStore);const previousInstanceID=contextManager.currentInstanceID;try{contextManager.currentInstanceID=childInstanceID;return await fn(...args)}finally{contextManager.currentInstanceID=previousInstanceID;contextManager.instances.delete(childInstanceID)}}if(contextManager.constructor.name==="AsyncContextManager"){let currentStore=null;const activeStore=contextManager.tryGetContext();if(activeStore){const isOurContext=activeStore.instanceID===slothlet.instanceID||activeStore.parentInstanceID===slothlet.instanceID||activeStore.instanceID.startsWith(slothlet.instanceID+"__run_");if(isOurContext){currentStore=activeStore}}if(!currentStore){const baseStore=contextManager.instances.get(slothlet.instanceID);if(!baseStore){throw new slothlet.SlothletError("CONTEXT_NOT_FOUND",{instanceID:slothlet.instanceID,availableInstances:[...contextManager.instances.keys()].join(", ")||"none",validationError:true})}currentStore=baseStore}let mergedContext;if(merge==="deep"){mergedContext=utilities.deepMerge(currentStore.context,contextData);mergedContext=structuredClone(mergedContext)}else{const clonedParent=structuredClone(currentStore.context);mergedContext={...clonedParent,...contextData}}const childInstanceID=`${slothlet.instanceID}__run_${Date.now()}_${Math.random().toString(36).slice(2,9)}`;const childStore={instanceID:childInstanceID,context:mergedContext,self:isolationMode==="full"?makeCopyOnWriteSelf(currentStore.self):currentStore.self,config:currentStore.config,createdAt:currentStore.createdAt,parentInstanceID:slothlet.instanceID,currentWrapper:currentStore.currentWrapper,callerWrapper:currentStore.callerWrapper,slothlet:currentStore.slothlet,__contextOwners:buildContextOwners(currentStore.__contextOwners)};if(currentStore[TRUSTED_ROOT]===true){Object.defineProperty(childStore,TRUSTED_ROOT,{value:true,configurable:true})}contextManager.instances.set(childInstanceID,childStore);try{return await contextManager.als.run(childStore,async()=>{return await fn(...args)})}finally{contextManager.instances.delete(childInstanceID)}}throw new slothlet.SlothletError("UNSUPPORTED_CONTEXT_MANAGER",{manager:contextManager.constructor.name,validationError:true})}}.scope;return scopeFunction}createDestroyFunction(api){const slothlet=this.slothlet;const destroyFunction={destroy:async()=>{if(slothlet.config.collectLifecycleHooks){const nestedHooks=(await slothlet._collectLifecycleHooks("destroy")).reverse();for(const{fn,receiver}of nestedHooks){try{await Reflect.apply(fn,receiver,[])}catch{}}}if(slothlet.userHooks?.destroy&&typeof slothlet.userHooks.destroy==="function"){await slothlet.userHooks.destroy()}if(api&&typeof api.shutdown==="function"){await api.shutdown()}else{await slothlet.shutdown()}slothlet.isDestroyed=true;const objectsToClear=[api,slothlet.api].filter(obj=>obj&&typeof obj==="object");for(const obj of objectsToClear){const keys=Object.keys(obj);for(const key of keys){try{delete obj[key]}catch(_){}}}slothlet.api=null}}.destroy;return destroyFunction}attachBuiltins(userApi,builtins){Object.defineProperty(userApi,"slothlet",{value:builtins.slothlet,enumerable:true,writable:false,configurable:true});Object.defineProperty(userApi,"shutdown",{value:builtins.shutdown,enumerable:true,writable:false,configurable:true});if(builtins.destroy!==null){Object.defineProperty(userApi,"destroy",{value:builtins.destroy,enumerable:true,writable:false,configurable:true})}}}export{ApiBuilder};
|
|
17
|
+
import{isNode,AsyncResource,loadJson}from"@cldmv/slothlet/helpers/platform";import{ComponentBase}from"#factories/component-base";import{TYPE_STATES,resolveWrapper}from"#handlers/unified-wrapper";import{TRUSTED_ROOT,PROTECT_SENTINEL}from"#handlers/trusted-root";import{getLanguage,initI18n,setLanguage,setLanguageAsync,t,translate}from"@cldmv/slothlet/i18n";function _resolvePathOrModuleId(slothlet,pathOrModuleId){const history=slothlet.handlers?.apiManager?.state?.addHistory;if(history){let match=null;for(let i=history.length-1;i>=0;i--){const entry=history[i];if(entry?.moduleID===pathOrModuleId){match=entry;break}}if(match)return match.apiPath}return pathOrModuleId}function describeScopeReceived(value){if(Array.isArray(value)){const badIndex=value.findIndex(entry=>typeof entry!=="string");if(badIndex!==-1){return`array with non-string entry (${typeof value[badIndex]} at index ${badIndex})`}return"array"}return typeof value}function makeCopyOnWriteSelf(parentSelf){const overlay=new Map;const childViews=new Map;return new Proxy({},{get(_t,prop){if(overlay.has(prop))return overlay.get(prop);const real=parentSelf[prop];if(real!==null&&typeof real==="object"){let view=childViews.get(prop);if(view===void 0){view=makeCopyOnWriteSelf(real);childViews.set(prop,view)}return view}return real},set(_t,prop,value){overlay.set(prop,value);childViews.delete(prop);return true},has(_t,prop){return overlay.has(prop)||prop in parentSelf},deleteProperty(_t,prop){overlay.delete(prop);childViews.delete(prop);return true},ownKeys(){const keys=new Set(Reflect.ownKeys(parentSelf));for(const k of overlay.keys())keys.add(k);return[...keys]},getOwnPropertyDescriptor(_t,prop){if(overlay.has(prop)){return{value:overlay.get(prop),writable:true,enumerable:true,configurable:true}}const desc=Reflect.getOwnPropertyDescriptor(parentSelf,prop);return desc?{...desc,configurable:true}:void 0}})}class ApiBuilder extends ComponentBase{static slothletProperty="apiBuilder";constructor(slothlet){super(slothlet)}async buildFinalAPI(userApi){this.slothlet.debug("api",{key:"DEBUG_MODE_BUILD_FINAL_API_CALLED",diagnostics:this.____config.diagnostics,userApiKeys:Object.keys(userApi)});if(this.slothlet._ownBuiltins){for(const[key,ref]of Object.entries(this.slothlet._ownBuiltins)){if(ref&&Object.prototype.hasOwnProperty.call(userApi,key)&&userApi[key]===ref){try{delete userApi[key]}catch(_){}}}}this.slothlet.userHooks={shutdown:typeof userApi.shutdown==="function"?userApi.shutdown:null,destroy:typeof userApi.destroy==="function"?userApi.destroy:null};if(userApi.slothlet){if(!this.____config?.silent){new this.SlothletWarning("WARNING_RESERVED_PROPERTY_CONFLICT",{properties:"slothlet"})}await this.emitImplDiagnostic("warning",{apiPath:"slothlet",code:"WARNING_RESERVED_PROPERTY_CONFLICT",context:{properties:"slothlet"},source:"buildAPI"})}const slothletNamespace=await this.createSlothletNamespace(userApi);this.slothlet.debug("api",{key:"DEBUG_MODE_SLOTHLET_NAMESPACE_CREATED",namespaceKeys:Object.keys(slothletNamespace),hasDiag:!!slothletNamespace.diag});const shutdownFn=this.createShutdownFunction();this.attachBuiltins(userApi,{slothlet:slothletNamespace,shutdown:shutdownFn,destroy:null});this.slothlet.debug("api",{key:"DEBUG_MODE_BUILT_INS_ATTACHED",userApiKeys:Object.keys(userApi),hasSlothlet:!!userApi.slothlet,hasDiag:!!userApi.slothlet?.diag});const destroyWithApi=this.createDestroyFunction(userApi);Object.defineProperty(userApi,"destroy",{value:destroyWithApi,enumerable:true,writable:false,configurable:true});this.slothlet._ownBuiltins={shutdown:shutdownFn,slothlet:slothletNamespace,destroy:destroyWithApi};return userApi}async createSlothletNamespace(userApi){const slothlet=this.slothlet;const config=this.____config;const enforceInternalPermission=targetPath=>{const ctx=slothlet.contextManager?.tryGetContext?.(slothlet.instanceID);const identity=slothlet.contextManager?.getCallerIdentity?.(slothlet.instanceID);if(identity?.unresolved){throw new slothlet.SlothletError("PERMISSION_DENIED",{caller:null,target:targetPath})}const callerWrapper=identity?.currentWrapper;if(!callerWrapper)return;const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.enforceAccess){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const callerPath=callerWrapper.____slothletInternal?.apiPath??"";const callerFilePath=callerWrapper.____slothletInternal?.filePath??null;const runtimeContext=ctx?.context??null;if(!permissionManager.enforceAccess(callerPath,targetPath,callerFilePath,null,runtimeContext)){throw new slothlet.SlothletError("PERMISSION_DENIED",{caller:callerPath,target:targetPath})}};const canTraverseInternalNamespace=targetPath=>{const ctx=slothlet.contextManager?.tryGetContext?.(slothlet.instanceID);const identity=slothlet.contextManager?.getCallerIdentity?.(slothlet.instanceID);if(identity?.unresolved)return false;const callerWrapper=identity?.currentWrapper;if(!callerWrapper)return false;const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesForCaller||!permissionManager?.checkAccess){return false}const callerPath=callerWrapper.____slothletInternal?.apiPath??"";const callerFilePath=callerWrapper.____slothletInternal?.filePath??null;const runtimeContext=ctx?.context??null;const callerRules=permissionManager.getRulesForCaller(callerPath);const conditionMatches=condition=>typeof permissionManager.matchesCondition==="function"?permissionManager.matchesCondition(condition,runtimeContext):false;const prefix=`${targetPath}.`;for(const rule of callerRules){if(!rule||rule.effect!=="allow"||typeof rule.target!=="string")continue;const couldMatchDescendant=rule.target.startsWith(prefix)||rule.target==="**"||rule.target==="*";if(!couldMatchDescendant)continue;if(rule.target.startsWith(prefix)&&conditionMatches(rule.condition)){return true}const probePaths=[`${targetPath}.__probe__`];if(rule.target.startsWith(prefix)){const suffix=rule.target.slice(prefix.length);const firstSegment=suffix.split(".")[0];if(firstSegment&&!/[*!?{}]/u.test(firstSegment)){probePaths.unshift(`${targetPath}.${firstSegment}`);probePaths.push(`${targetPath}.${firstSegment}.__probe__`)}}for(const probePath of probePaths){if(permissionManager.checkAccess(callerPath,probePath,callerFilePath,null,runtimeContext,{useCache:false})){return true}}}return false};const createInternalRouteProxy=(value,routePath,seen=new WeakMap)=>{if(!value||typeof value!=="object"&&typeof value!=="function")return value;const isMetaProperty=prop=>prop==="__proto__"||prop==="prototype"||prop==="constructor"||prop==="caller"||prop==="arguments";let routeCache=seen.get(value);if(!routeCache){routeCache=new Map;seen.set(value,routeCache)}if(routeCache.has(routePath)){return routeCache.get(routePath)}const proxy=new Proxy(value,{get(target,prop,receiver){if(typeof prop!=="string"){const result2=Reflect.get(target,prop,receiver);return createInternalRouteProxy(result2,routePath,seen)}const childRoutePath=`${routePath}.${prop}`;let deniedError=null;try{enforceInternalPermission(childRoutePath)}catch(error){deniedError=error}if(deniedError){if(canTraverseInternalNamespace(childRoutePath)){const result2=Reflect.get(target,prop,receiver);if(result2&&(typeof result2==="object"||typeof result2==="function")){return createInternalRouteProxy(result2,childRoutePath,seen)}}throw deniedError}const result=Reflect.get(target,prop,receiver);if(isMetaProperty(prop)){return result}const descriptor=Object.getOwnPropertyDescriptor(target,prop);if(descriptor&&"value"in descriptor&&descriptor.configurable===false&&descriptor.writable===false){return descriptor.value}return createInternalRouteProxy(result,childRoutePath,seen)},getOwnPropertyDescriptor(target,prop){const descriptor=Reflect.getOwnPropertyDescriptor(target,prop);if(!descriptor)return void 0;if(typeof prop!=="string"){return descriptor}const childRoutePath=`${routePath}.${prop}`;if(isMetaProperty(prop)){enforceInternalPermission(childRoutePath);return descriptor}if("get"in descriptor||"set"in descriptor){enforceInternalPermission(childRoutePath);if(descriptor.configurable===true){return{...descriptor,get:typeof descriptor.get==="function"?function slothlet_internal_descriptor_getter(...args){enforceInternalPermission(childRoutePath);return Reflect.apply(descriptor.get,this,args)}:descriptor.get,set:typeof descriptor.set==="function"?function slothlet_internal_descriptor_setter(...args){enforceInternalPermission(childRoutePath);return Reflect.apply(descriptor.set,this,args)}:descriptor.set}}return descriptor}if(!("value"in descriptor)){return descriptor}const descriptorValue=descriptor.value;if(descriptor.configurable===false&&descriptor.writable===false){enforceInternalPermission(childRoutePath);return descriptor}if(!descriptorValue||typeof descriptorValue!=="object"&&typeof descriptorValue!=="function"||typeof descriptorValue==="function"){enforceInternalPermission(childRoutePath);if(typeof descriptorValue==="function"&&descriptor.configurable===true){return{...descriptor,value:createInternalRouteProxy(descriptorValue,childRoutePath,seen)}}return descriptor}return{...descriptor,value:createInternalRouteProxy(descriptorValue,childRoutePath,seen)}},set(target,prop,newValue,receiver){if(typeof prop!=="string"){return Reflect.set(target,prop,newValue,receiver)}const childRoutePath=`${routePath}.${prop}`;enforceInternalPermission(childRoutePath);return Reflect.set(target,prop,newValue,receiver)},defineProperty(target,prop,descriptor){if(typeof prop!=="string"){return Reflect.defineProperty(target,prop,descriptor)}const childRoutePath=`${routePath}.${prop}`;enforceInternalPermission(childRoutePath);return Reflect.defineProperty(target,prop,descriptor)},deleteProperty(target,prop){if(typeof prop!=="string"){return Reflect.deleteProperty(target,prop)}const childRoutePath=`${routePath}.${prop}`;enforceInternalPermission(childRoutePath);return Reflect.deleteProperty(target,prop)},ownKeys(target){return Reflect.ownKeys(target)},apply(target,thisArg,argArray){enforceInternalPermission(routePath);return Reflect.apply(target,thisArg,argArray)},construct(target,argArray,newTarget){enforceInternalPermission(routePath);return Reflect.construct(target,argArray,newTarget)}});routeCache.set(routePath,proxy);return proxy};let version="unknown";if(isNode){const pkg=loadJson(new URL("../../../package.json",import.meta.url));if(pkg?.version)version=pkg?.version}const namespace={i18n:{setLanguage,setLanguageAsync,getLanguage,translate,t,initI18n},version,instanceID:slothlet.instanceID,types:TYPE_STATES,api:{add:async function slothlet_api_add(apiPath,folderPath,options={},versionConfig=null){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.add",validationError:true})}const{recordHistory:____recordHistory,collisionMode:____collisionMode,mutateExisting:____mutateExisting,...filteredOptions}=options;const addResult=await slothlet.handlers.apiManager.addApiComponent({apiPath,folderPath,options:filteredOptions,versionConfig:versionConfig||null});if(slothlet.handlers.routineManager){await slothlet.handlers.routineManager.rebuildStacks(userApi)}return addResult},remove:async function slothlet_api_remove(pathOrModuleId,apiPath){if(!config.api?.mutations?.remove){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.remove",validationError:true})}if(typeof pathOrModuleId!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"pathOrModuleId",expected:"string",received:typeof pathOrModuleId,validationError:true})}if(apiPath!==void 0&&typeof apiPath!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"apiPath",expected:"string",received:typeof apiPath,validationError:true})}const removeResult=await slothlet.handlers.apiManager.removeApiComponent(pathOrModuleId,{scopedApiPath:apiPath});if(slothlet.handlers.routineManager){await slothlet.handlers.routineManager.rebuildStacks(userApi)}return removeResult},leaves:async function slothlet_api_leaves(key,options={}){enforceInternalPermission("slothlet.api.leaves");if(typeof key!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"key",expected:"string",received:typeof key,validationError:true})}const normalizedOptions=options==null?{}:options;if(typeof normalizedOptions!=="object"||Array.isArray(normalizedOptions)){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"options",expected:"object with optional boolean details/includePrivate",received:Array.isArray(normalizedOptions)?"array":typeof normalizedOptions,validationError:true})}const{details=false,includePrivate=false}=normalizedOptions;for(const[name,value]of[["details",details],["includePrivate",includePrivate]]){if(typeof value!=="boolean"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:`options.${name}`,expected:"boolean",received:typeof value,validationError:true})}}const ownership=slothlet.handlers.ownership;const leavesIdentity=slothlet.contextManager?.getCallerIdentity?.();const leavesCaller=leavesIdentity?.currentWrapper??null;if(includePrivate&&leavesCaller){throw new slothlet.SlothletError("PERMISSION_DENIED",{caller:leavesCaller.____slothletInternal?.apiPath??"",target:"slothlet.api.leaves:includePrivate"})}let moduleID=null;if(key==="."||key===""){moduleID=[...ownership.moduleEndpoints.entries()].find(([,endpoint2])=>endpoint2===".")?.[0]}else if(ownership.moduleToPath.has(key)){moduleID=key}else{moduleID=ownership.getCurrentOwner(key)?.moduleID??null;if(!moduleID){moduleID=[...ownership.moduleEndpoints.entries()].find(([,endpoint2])=>endpoint2===key)?.[0]??null}}if(!moduleID||!ownership.moduleToPath.has(moduleID)){throw new slothlet.SlothletError("API_LEAVES_UNKNOWN_MODULE",{key},null,{validationError:true})}const endpoint=ownership.moduleEndpoints.get(moduleID);const boundApi=slothlet.boundApi;if(config.mode==="lazy"&&boundApi){const seen=new WeakSet;let root=boundApi;if(endpoint!=="."){for(const segment of endpoint.split("."))root=root[segment]}const pending=[{node:root,path:endpoint==="."?"":endpoint}];while(pending.length>0){const{node,path}=pending.pop();if(node===null||typeof node!=="object"&&typeof node!=="function")continue;if(seen.has(node))continue;seen.add(node);if(typeof node._materialize==="function"&&node.__materialized===false){await node._materialize()}const childKeys=new Set(Object.keys(node));const records=ownership.moduleToPath.get(moduleID);if(path!==null&&records){const prefix=path===""?"":`${path}.`;for(const ownedPath of records){if(ownedPath===""||prefix!==""&&!ownedPath.startsWith(prefix))continue;const rest=ownedPath.slice(prefix.length);const segmentEnd=rest.indexOf(".");childKeys.add(segmentEnd===-1?rest:rest.slice(0,segmentEnd))}}for(const childKey of childKeys){if(path===""&&(childKey==="slothlet"||childKey==="shutdown"||childKey==="destroy"))continue;let child;try{child=node[childKey]}catch{continue}const childWrapper=child?resolveWrapper(child):null;if(childWrapper?.____slothletInternal?.userAssigned)continue;const childPath=path===null?null:path===""?childKey:`${path}.${childKey}`;pending.push({node:child,path:records?.has(childPath)?childPath:null})}}}if(!ownership.moduleToPath.has(moduleID)){throw new slothlet.SlothletError("API_LEAVES_UNKNOWN_MODULE",{key},null,{validationError:true})}const ownedPaths=[...ownership.moduleToPath.get(moduleID)].filter(path=>{if(path==="")return false;if(endpoint==="."&&(path==="slothlet"||path.startsWith("slothlet.")||path==="shutdown"||path==="destroy"))return false;const currentOwner=ownership.getCurrentOwner(path);return!currentOwner||currentOwner.moduleID===moduleID});ownedPaths.sort();const namespaces=new Set;for(const owned of ownedPaths){let cut=owned.lastIndexOf(".");while(cut>0){namespaces.add(owned.slice(0,cut));cut=owned.lastIndexOf(".",cut-1)}}const kindOf=path=>{if(namespaces.has(path))return"namespace";const entry=ownership.pathToModule.get(path)?.find(candidate=>candidate.moduleID===moduleID);return typeof entry?.value==="function"?"function":"data"};const permissionManager=slothlet.handlers?.permissionManager;let visiblePaths=ownedPaths;if(!includePrivate&&permissionManager?.isEnabled?.()){const callerPath=leavesCaller?.____slothletInternal?.apiPath??"";const callerFilePath=leavesCaller?.____slothletInternal?.filePath??null;const runtimeContext=slothlet.contextManager?.tryGetContext?.()?.context??null;visiblePaths=ownedPaths.filter(path=>{if(!permissionManager.isPrivateTarget(path))return true;const entry=ownership.pathToModule.get(path)?.find(candidate=>candidate.moduleID===moduleID);return permissionManager.checkAccess(callerPath,path,callerFilePath,entry?.filePath,runtimeContext)})}if(details){return visiblePaths.map(path=>({path,kind:kindOf(path)}))}return visiblePaths.filter(path=>kindOf(path)==="function")},reload:async function slothlet_api_reload(pathOrModuleId,options){if(!config.api?.mutations?.reload){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.reload",validationError:true})}if(pathOrModuleId==null||pathOrModuleId===""||pathOrModuleId==="."){return slothlet.handlers.apiManager.reloadApiComponent({apiPath:".",options})}if(typeof pathOrModuleId!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"pathOrModuleId",expected:"string, null, undefined, or '.'",received:typeof pathOrModuleId,validationError:true})}const isModuleId=slothlet.handlers.apiManager.state.addHistory.some(entry=>entry.moduleID===pathOrModuleId);if(isModuleId){return slothlet.handlers.apiManager.reloadApiComponent({moduleID:pathOrModuleId,options})}const normalizedPath=slothlet.handlers.apiManager.normalizeApiPath(pathOrModuleId).apiPath;const pathParts=normalizedPath.split(".");let current=slothlet.api;for(const part of pathParts){if(!current||typeof current!=="object"&&typeof current!=="function"){throw new slothlet.SlothletError("INVALID_API_PATH",{apiPath:pathOrModuleId,validationError:true})}current=current[part]}if(current===void 0){throw new slothlet.SlothletError("INVALID_API_PATH",{apiPath:pathOrModuleId,validationError:true})}return slothlet.handlers.apiManager.reloadApiComponent({apiPath:normalizedPath,options})},modules:{discover:function slothlet_modules_discover(options){return slothlet.handlers.moduleManager.discover(options)},sort:function slothlet_modules_sort(results,comparator){return slothlet.handlers.moduleManager.sort(results,comparator)},addModule:async function slothlet_modules_addModule(nameOrResult,options){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.modules.addModule",validationError:true})}return slothlet.handlers.moduleManager.addModule(nameOrResult,options)},addModules:async function slothlet_modules_addModules(items,options){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.modules.addModules",validationError:true})}return slothlet.handlers.moduleManager.addModules(items,options)},removeModule:async function slothlet_modules_removeModule(name,opts){if(!config.api?.mutations?.remove){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.modules.removeModule",validationError:true})}return slothlet.handlers.moduleManager.removeModule(name,opts)},addDiscovered:async function slothlet_modules_addDiscovered(options={}){if(!config.api?.mutations?.add){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.modules.addDiscovered",validationError:true})}const{sort:comparator,collisionMode,onFailure,concurrency,...discoverOptions}=options;const found=await slothlet.handlers.moduleManager.discover(discoverOptions);const ordered=slothlet.handlers.moduleManager.sort(found,comparator);return slothlet.handlers.moduleManager.addModules(ordered,{collisionMode,onFailure,concurrency})},getDiscoveryCache:function slothlet_modules_getDiscoveryCache(){return slothlet.handlers.moduleManager.getDiscoveryCache()},clearDiscoveryCache:function slothlet_modules_clearDiscoveryCache(){return slothlet.handlers.moduleManager.clearDiscoveryCache()},getStaleMounts:function slothlet_modules_getStaleMounts(){return slothlet.handlers.moduleManager.getStaleMounts()}}},sanitize:function slothlet_sanitize(str){if(typeof str!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"str",expected:"string",received:typeof str,validationError:true})}return slothlet.helpers.sanitize.sanitizePropertyName(str,slothlet.config.sanitize||{})},lockCaller:function slothlet_lockCaller(fn){if(typeof fn!=="function"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"fn",expected:"function",received:typeof fn,validationError:true})}const capturedWrapper=slothlet.contextManager?.getCallerIdentity?.()?.currentWrapper??null;if(!capturedWrapper)return fn;const locked=function slothlet_lockedCaller(...args){return slothlet.contextManager.runInContext(slothlet.instanceID,fn,this,args,capturedWrapper,true)};locked._slothletOriginal=fn;return locked},bind:function slothlet_bind(fn){if(typeof fn!=="function"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"fn",expected:"function",received:typeof fn,validationError:true})}return AsyncResource?AsyncResource.bind(fn,"slothlet-bound"):fn},context:{get:key=>{if(slothlet.contextManager.constructor.name==="LiveContextManager"){const currentID=slothlet.contextManager.currentInstanceID;if(currentID){const activeStore=slothlet.contextManager.instances.get(currentID);const isOurInstance=currentID===slothlet.instanceID||currentID?.startsWith(slothlet.instanceID+"__run_")||activeStore?.parentInstanceID===slothlet.instanceID;if(isOurInstance&&activeStore){return key?activeStore.context[key]:{...activeStore.context}}}const store=slothlet.contextManager.instances.get(slothlet.instanceID);if(!store){const baseContext2=slothlet.context||{};return key?baseContext2[key]:{...baseContext2}}return key?store.context[key]:{...store.context}}if(slothlet.contextManager.constructor.name==="AsyncContextManager"){let currentStore=slothlet.contextManager.tryGetContext();if(!currentStore){const baseStore2=slothlet.contextManager.instances.get(slothlet.instanceID);const baseContext3=baseStore2?.context||{};return key?baseContext3[key]:{...baseContext3}}const isOurInstance=currentStore.instanceID===slothlet.instanceID||currentStore.parentInstanceID===slothlet.instanceID||currentStore.instanceID.startsWith(slothlet.instanceID+"__run_");if(isOurInstance){return key?currentStore.context[key]:{...currentStore.context}}const baseStore=slothlet.contextManager.instances.get(slothlet.instanceID);const baseContext2=baseStore?.context||{};return key?baseContext2[key]:{...baseContext2}}const baseContext=slothlet.context||{};return key?baseContext[key]:{...baseContext}},diagnostics:()=>{if(!slothlet.config?.diagnostics)return void 0;const managerType=slothlet.contextManager.constructor.name;const result={instanceID:slothlet.instanceID,managerType,instancesMapSize:slothlet.contextManager.instances.size,instancesMapKeys:Array.from(slothlet.contextManager.instances.keys()),baseContext:slothlet.context};const store=slothlet.contextManager.instances.get(slothlet.instanceID);result.storeFromInstancesMap=store?{instanceID:store.instanceID,context:store.context,createdAt:store.createdAt}:null;if(managerType==="AsyncContextManager"){try{const currentCtx=slothlet.contextManager.tryGetContext();result.currentALSContext=currentCtx?{instanceID:currentCtx.instanceID,context:currentCtx.context,hasParent:!!currentCtx.parentContext,parentInstanceID:currentCtx.parentInstanceID}:null}catch(____error){result.currentALSContext=null}}if(managerType==="LiveContextManager"){result.currentInstanceID=slothlet.contextManager.currentInstanceID}return result},run:this.createRunFunction(),scope:this.createScopeFunction()},hook:{on:function slothlet_hook_on(typePattern,handler,options={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.on(typePattern,handler,options)},remove:function slothlet_hook_remove(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.remove(filter)},clear:function slothlet_hook_clear(filter={}){return this.remove(filter)},off:function slothlet_hook_off(idOrFilter){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}const filter=typeof idOrFilter==="string"?{id:idOrFilter}:idOrFilter;return slothlet.handlers.hookManager.remove(filter)},enable:function slothlet_hook_enable(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.enable(filter)},disable:function slothlet_hook_disable(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.disable(filter)},enablePattern:function slothlet_hook_enablePattern(pattern){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.enablePattern(pattern)},disablePattern:function slothlet_hook_disablePattern(pattern){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.disablePattern(pattern)},resetPatternFilter:function slothlet_hook_resetPatternFilter(){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.resetPatternFilter()},list:function slothlet_hook_list(filter={}){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.list(filter)},pin:{get enabled(){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.pinEnforced},enable:function slothlet_hook_pin_enable(){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.setPinEnforced(true)},disable:function slothlet_hook_pin_disable(){if(!slothlet.handlers?.hookManager){throw new slothlet.SlothletError("HOOKS_NOT_INITIALIZED",{validationError:true})}return slothlet.handlers.hookManager.setPinEnforced(false)}}},metadata:{setGlobal:function slothlet_metadata_setGlobal(keyOrObj,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}const validateGlobalMetadataKeyPath=keyPath=>{const blocked=new Set(["__proto__","prototype","constructor"]);if(typeof keyPath!=="string"||keyPath.length===0){throw new slothlet.SlothletError("INVALID_METADATA_KEY",{key:keyPath,type:typeof keyPath,expected:"non-empty string"})}const segments=keyPath.split(".");for(const segment of segments){if(!segment||blocked.has(segment)){throw new slothlet.SlothletError("INVALID_METADATA_KEY",{key:keyPath,type:typeof keyPath,expected:"safe dot-notation key without reserved segments"})}}};const normalizeGlobalMetadataObject=(source,prefix="",ancestors=new WeakSet)=>{if(ancestors.has(source)){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"keyOrObj",expected:"acyclic object",received:"circular reference",validationError:true})}ancestors.add(source);try{const normalized={};for(const[key,nestedValue]of Object.entries(source)){const fullKey=prefix?`${prefix}.${key}`:key;validateGlobalMetadataKeyPath(fullKey);const nestedProto=nestedValue&&typeof nestedValue==="object"?Object.getPrototypeOf(nestedValue):null;const isPlainNested=nestedProto===Object.prototype||nestedProto===null;if(nestedValue&&typeof nestedValue==="object"&&!Array.isArray(nestedValue)&&isPlainNested){normalized[key]=normalizeGlobalMetadataObject(nestedValue,fullKey,ancestors);continue}normalized[key]=nestedValue}return normalized}finally{ancestors.delete(source)}};if(keyOrObj&&typeof keyOrObj==="object"&&!Array.isArray(keyOrObj)){const normalizedMetadata=normalizeGlobalMetadataObject(keyOrObj);for(const[key,nestedValue]of Object.entries(normalizedMetadata)){slothlet.handlers.metadata.setGlobalMetadata(key,nestedValue)}return}if(typeof keyOrObj!=="string"){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:"keyOrObj",expected:"string or object",received:typeof keyOrObj,validationError:true})}validateGlobalMetadataKeyPath(keyOrObj);return slothlet.handlers.metadata.setGlobalMetadata(keyOrObj,value)},set:function slothlet_metadata_set(fn,key,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}return slothlet.handlers.metadata.setUserMetadata(fn,key,value)},remove:function slothlet_metadata_remove(fn,key){return slothlet.handlers.metadata.removeUserMetadata(fn,key)},setFor:function slothlet_metadata_setFor(pathOrModuleId,keyOrObj,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}const resolvedPath=_resolvePathOrModuleId(slothlet,pathOrModuleId);return slothlet.handlers.metadata.setPathMetadata(resolvedPath,keyOrObj,value)},removeFor:function slothlet_metadata_removeFor(pathOrModuleId,key){if(!slothlet.handlers?.metadata)return;const resolvedPath=_resolvePathOrModuleId(slothlet,pathOrModuleId);return slothlet.handlers.metadata.removePathMetadata(resolvedPath,key)},getFor:function slothlet_metadata_getFor(pathOrModuleId){if(!slothlet.handlers?.metadata)return{};const resolvedPath=_resolvePathOrModuleId(slothlet,pathOrModuleId);return slothlet.handlers.metadata.getPathMetadata(resolvedPath)},setForVersion:function slothlet_metadata_setForVersion(logicalPath,versionTag,keyOrObj,value){if(!slothlet.handlers?.metadata){throw new slothlet.SlothletError("METADATA_NOT_AVAILABLE",{handlersKeys:slothlet.handlers?Object.keys(slothlet.handlers).join(", "):"undefined",validationError:true})}const info=slothlet.handlers?.versionManager?.list(logicalPath);if(!info||!info.versions?.[versionTag]){throw new slothlet.SlothletError("VERSION_NOT_FOUND",{version:versionTag,apiPath:logicalPath})}const{moduleID}=info.versions[versionTag];const resolvedPath=_resolvePathOrModuleId(slothlet,moduleID);return slothlet.handlers.metadata.setPathMetadata(resolvedPath,keyOrObj,value)},getForVersion:function slothlet_metadata_getForVersion(logicalPath,versionTag){if(!slothlet.handlers?.metadata)return{};const info=slothlet.handlers?.versionManager?.list(logicalPath);if(!info||!info.versions?.[versionTag])return{};const{moduleID}=info.versions[versionTag];const resolvedPath=_resolvePathOrModuleId(slothlet,moduleID);return slothlet.handlers.metadata.getPathMetadata(resolvedPath)}},scope:this.createScopeFunction(),run:this.createRunFunction(),reload:async(options={})=>{if(!config.api?.mutations?.reload){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"reload",validationError:true})}return slothlet.reload(options)},shutdown:async()=>{let routineError=null;try{await slothlet.handlers.routineManager?.runShutdownModeRoutines()}catch(error){routineError=error}const result=await slothlet.shutdown();if(routineError)throw routineError;return result},owner:{get:apiPath=>{if(slothlet.handlers?.ownership){return slothlet.handlers.ownership.getPathOwnership(apiPath)}return null}},materialize:(()=>{const mgr=slothlet.handlers?.materialize;const getMaterializedState=()=>{enforceInternalPermission("slothlet.materialize.materialized");return mgr?.materialized??false};const getMaterializeStats=()=>{enforceInternalPermission("slothlet.materialize.get");return mgr?mgr.get():{total:0,materialized:0,remaining:0,percentage:100}};const waitForMaterialization=async()=>{enforceInternalPermission("slothlet.materialize.wait");if(!mgr)return;return mgr.wait()};if(!mgr){return Object.freeze({get materialized(){return getMaterializedState()},get:getMaterializeStats,wait:waitForMaterialization})}return Object.freeze({get materialized(){return getMaterializedState()},get:getMaterializeStats,wait:waitForMaterialization})})(),lifecycle:(()=>{const handler=slothlet.handlers?.lifecycle;const noop=()=>{};if(!handler)return{on:noop,off:noop};return{on:handler.on.bind(handler),off:handler.off.bind(handler)}})(),env:slothlet.envSnapshot,versioning:{list:function slothlet_version_list(logicalPath){if(!slothlet.handlers?.versionManager)return void 0;return slothlet.handlers.versionManager.list(logicalPath)},setDefault:function slothlet_version_setDefault(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return;return slothlet.handlers.versionManager.setDefault(logicalPath,versionTag)},unregister:async function slothlet_version_unregister(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return false;const info=slothlet.handlers.versionManager.list(logicalPath);if(!info||!info.versions?.[versionTag])return false;const{moduleID:versionedModuleID}=info.versions[versionTag];await slothlet.handlers.apiManager.removeApiComponent(versionedModuleID);return true},getVersionMetadata:function slothlet_version_getVersionMetadata(logicalPath,versionTag){if(!slothlet.handlers?.versionManager)return void 0;return slothlet.handlers.versionManager.getVersionMetadataByPath(logicalPath,versionTag)},setVersionMetadata:function slothlet_version_setVersionMetadata(logicalPath,versionTag,patch){if(!slothlet.handlers?.versionManager)return;return slothlet.handlers.versionManager.setVersionMetadataByPath(logicalPath,versionTag,patch)}},permissions:{addRule:function slothlet_permissions_addRule(rule){if(!config.api?.mutations?.permissions){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.slothlet.permissions.addRule",validationError:true})}const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.addRule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const ruleId=permissionManager.addRule(rule,null);if(slothlet.handlers?.apiManager?.state?.operationHistory){slothlet.handlers.apiManager.state.operationHistory.push({type:"addPermissionRule",rule,ownerModuleID:null,ruleId,timestamp:Date.now()})}return ruleId},removeRule:function slothlet_permissions_removeRule(ruleId){if(!config.api?.mutations?.permissions){throw new slothlet.SlothletError("INVALID_CONFIG_MUTATIONS_DISABLED",{operation:"api.slothlet.permissions.removeRule",validationError:true})}const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.removeRule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const currentWrapper=slothlet.contextManager?.getCallerIdentity?.()?.currentWrapper;const callerModuleID=currentWrapper?.____slothletInternal?.moduleID??null;const result=slothlet.handlers.permissionManager.removeRule(ruleId,callerModuleID);if(result&&slothlet.handlers?.apiManager?.state?.operationHistory){slothlet.handlers.apiManager.state.operationHistory.push({type:"removePermissionRule",ruleId,callerModuleID,timestamp:Date.now()})}return result},self:{access:function slothlet_permissions_self_access(target){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.checkAccess){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const ctx=slothlet.contextManager?.tryGetContext?.();const currentWrapper=slothlet.contextManager?.getCallerIdentity?.()?.currentWrapper;const callerPath=currentWrapper?.____slothletInternal?.apiPath??"";const callerFilePath=currentWrapper?.____slothletInternal?.filePath??null;const runtimeContext=ctx?.context??null;return slothlet.handlers.permissionManager.checkAccess(callerPath,target,callerFilePath,null,runtimeContext)},rules:function slothlet_permissions_self_rules(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesForCaller){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const currentWrapper=slothlet.contextManager?.getCallerIdentity?.()?.currentWrapper;const callerPath=currentWrapper?.____slothletInternal?.apiPath??"";return slothlet.handlers.permissionManager.getRulesForCaller(callerPath)}},global:{checkAccess:function slothlet_permissions_global_checkAccess(caller,target){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.checkAccess){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}const runtimeContext=slothlet.contextManager?.tryGetContext?.()?.context??null;return slothlet.handlers.permissionManager.checkAccess(caller,target,null,null,runtimeContext)},rulesForPath:function slothlet_permissions_global_rulesForPath(path){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesForPath){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return slothlet.handlers.permissionManager.getRulesForPath(path)},rulesByModule:function slothlet_permissions_global_rulesByModule(moduleID){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.getRulesByModule){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return slothlet.handlers.permissionManager.getRulesByModule(moduleID)}},control:{get enabled(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.isEnabled){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return permissionManager.isEnabled()},enable:function slothlet_permissions_control_enable(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.enable){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}slothlet.handlers.permissionManager.enable()},disable:function slothlet_permissions_control_disable(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.disable){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}slothlet.handlers.permissionManager.disable()},get readGatingEnabled(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.isReadGatingEnabled){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return permissionManager.isReadGatingEnabled()},readGating:function slothlet_permissions_control_readGating(value){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.setReadGating){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}slothlet.handlers.permissionManager.setReadGating(value)},seal:function slothlet_permissions_control_seal(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.seal){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}slothlet.handlers.permissionManager.seal()},get sealed(){const permissionManager=slothlet.handlers?.permissionManager;if(!permissionManager?.isSealed){throw new slothlet.SlothletError("PERMISSION_MANAGER_NOT_AVAILABLE",{validationError:true})}return permissionManager.isSealed()}}}};if(!config.hook?.enabled&&config.diagnostics!==true){delete namespace.hooks}if(config.diagnostics===true){namespace.diag={describe:(showAll=false)=>{if(showAll){return{...userApi}}return Reflect.ownKeys(userApi)},reference:slothlet.reference||null,context:slothlet.context||{},inspect:()=>{return slothlet.getDiagnostics()},getAPI:()=>{return slothlet.getAPI()},getOwnership:()=>{return slothlet.getOwnership()},owner:{get:apiPath=>{if(slothlet.handlers?.ownership){return slothlet.handlers.ownership.getPathOwnership(apiPath)}return null}},caches:{get:()=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.getCacheDiagnostics()}return{totalCaches:0,caches:[]}},getAllModuleIDs:()=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.getAllModuleIDs()}return[]},has:moduleID=>{if(slothlet.handlers?.apiCacheManager){return slothlet.handlers.apiCacheManager.has(moduleID)}return false}},SlothletWarning:slothlet.SlothletWarning,hook:slothlet.handlers?.hookManager?{get enabled(){return slothlet.handlers.hookManager.enabled},compilePattern:pattern=>{return slothlet.handlers.hookManager.getCompilePatternForDiagnostics()(pattern)}}:void 0}}return createInternalRouteProxy(namespace,"slothlet")}createShutdownFunction(){const slothlet=this.slothlet;const shutdownFunction={shutdown:async()=>{let routineError=null;try{await slothlet.handlers.routineManager?.runShutdownModeRoutines()}catch(error){routineError=error}if(slothlet.userHooks?.shutdown&&typeof slothlet.userHooks.shutdown==="function"){await slothlet.userHooks.shutdown()}const result=await slothlet.shutdown();if(routineError)throw routineError;return result}}.shutdown;return shutdownFunction}createRunFunction(){const slothlet=this.slothlet;const scopeFunc=this.createScopeFunction();const runFunction={run:async(contextData,callback,...args)=>{if(slothlet.config.scope===false){throw new slothlet.SlothletError("SCOPE_DISABLED",{},null,{validationError:true})}if(!contextData||typeof contextData!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_CONTEXT",{received:typeof contextData},null,{validationError:true})}if(typeof callback!=="function"){throw new slothlet.SlothletError("SCOPE_INVALID_CALLBACK",{received:typeof callback},null,{validationError:true})}return scopeFunc({context:contextData,fn:callback,args,merge:slothlet.config.scope?.merge||"shallow",isolation:slothlet.config.scope?.isolation||"partial"})}}.run;return runFunction}createScopeFunction(){const slothlet=this.slothlet;const scopeFunction={scope:async options=>{if(slothlet.config.scope===false){throw new slothlet.SlothletError("SCOPE_DISABLED",{},null,{validationError:true})}if(!options||typeof options!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_OPTIONS",{received:typeof options},null,{validationError:true})}if(!options.fn||typeof options.fn!=="function"){throw new slothlet.SlothletError("SCOPE_INVALID_FN",{received:typeof options?.fn},null,{validationError:true})}if(!options.context||typeof options.context!=="object"){throw new slothlet.SlothletError("SCOPE_INVALID_CONTEXT_OBJECT",{received:typeof options?.context},null,{validationError:true})}const{context:contextData,fn,args=[],merge="shallow",isolation,protect,owners}=options;if(merge!=="shallow"&&merge!=="deep"){throw new slothlet.SlothletError("SCOPE_INVALID_MERGE_STRATEGY",{merge},null,{validationError:true})}const isolationMode=isolation||slothlet.config.scope?.isolation||"partial";if(isolationMode!=="partial"&&isolationMode!=="full"){throw new slothlet.SlothletError("SCOPE_INVALID_ISOLATION_MODE",{isolationMode},null,{validationError:true})}if(protect!==void 0&&(!Array.isArray(protect)||protect.some(k=>typeof k!=="string"))){throw new slothlet.SlothletError("SCOPE_INVALID_PROTECT",{received:describeScopeReceived(protect)},null,{validationError:true})}if(owners!==void 0){if(typeof owners!=="object"||owners===null||Array.isArray(owners)){throw new slothlet.SlothletError("SCOPE_INVALID_OWNERS",{received:describeScopeReceived(owners)},null,{validationError:true})}for(const[key,owner]of Object.entries(owners)){if(typeof owner!=="string"||owner.length===0){throw new slothlet.SlothletError("INVALID_ARGUMENT",{argument:`owners.${key}`,expected:"non-empty string",received:typeof owner==="string"?"empty string":typeof owner,validationError:true})}}}const buildContextOwners=parentOwners=>{const base=parentOwners??null;let child=base;const claim=(key,owner)=>{const existing=child&&Object.prototype.hasOwnProperty.call(child,key)?child[key]:void 0;if(existing!==void 0&&existing!==owner){throw new slothlet.SlothletError("CONTEXT_KEY_OWNED",{key:String(key)},null,{validationError:true})}if(child===base)child=base?Object.assign(Object.create(null),base):Object.create(null);child[key]=owner};if(Array.isArray(protect))for(const k of protect)claim(k,PROTECT_SENTINEL);if(owners&&typeof owners==="object")for(const[k,o]of Object.entries(owners))claim(k,o);return child};const contextManager=slothlet.contextManager;if(!contextManager){throw new slothlet.SlothletError("NO_CONTEXT_MANAGER",{validationError:true})}const{utilities}=slothlet.helpers;if(contextManager.constructor.name==="LiveContextManager"){let currentStore=null;const currentID=contextManager.currentInstanceID;if(currentID){const activeStore=contextManager.instances.get(currentID);const isOurContext=currentID===slothlet.instanceID||activeStore?.parentInstanceID===slothlet.instanceID||currentID.startsWith(slothlet.instanceID+"__run_");if(isOurContext){currentStore=activeStore}}if(!currentStore){currentStore=contextManager.instances.get(slothlet.instanceID)}if(!currentStore){throw new slothlet.SlothletError("CONTEXT_NOT_FOUND",{instanceID:slothlet.instanceID,availableInstances:[...contextManager.instances.keys()].join(", ")||"none",validationError:true})}let mergedContext;if(merge==="deep"){mergedContext=utilities.deepMerge(currentStore.context,contextData);mergedContext=structuredClone(mergedContext)}else{const clonedParent=structuredClone(currentStore.context);mergedContext={...clonedParent,...contextData}}const childInstanceID=`${slothlet.instanceID}__run_${Date.now()}_${Math.random().toString(36).slice(2,9)}`;const childStore={instanceID:childInstanceID,context:mergedContext,self:isolationMode==="full"?makeCopyOnWriteSelf(currentStore.self):currentStore.self,config:currentStore.config,createdAt:currentStore.createdAt,parentInstanceID:slothlet.instanceID,currentWrapper:currentStore.currentWrapper,callerWrapper:currentStore.callerWrapper,slothlet:currentStore.slothlet,__contextOwners:buildContextOwners(currentStore.__contextOwners)};if(currentStore[TRUSTED_ROOT]===true){Object.defineProperty(childStore,TRUSTED_ROOT,{value:true,configurable:true})}contextManager.instances.set(childInstanceID,childStore);const previousInstanceID=contextManager.currentInstanceID;try{contextManager.currentInstanceID=childInstanceID;return await fn(...args)}finally{contextManager.currentInstanceID=previousInstanceID;contextManager.instances.delete(childInstanceID)}}if(contextManager.constructor.name==="AsyncContextManager"){let currentStore=null;const activeStore=contextManager.tryGetContext();if(activeStore){const isOurContext=activeStore.instanceID===slothlet.instanceID||activeStore.parentInstanceID===slothlet.instanceID||activeStore.instanceID.startsWith(slothlet.instanceID+"__run_");if(isOurContext){currentStore=activeStore}}if(!currentStore){const baseStore=contextManager.instances.get(slothlet.instanceID);if(!baseStore){throw new slothlet.SlothletError("CONTEXT_NOT_FOUND",{instanceID:slothlet.instanceID,availableInstances:[...contextManager.instances.keys()].join(", ")||"none",validationError:true})}currentStore=baseStore}let mergedContext;if(merge==="deep"){mergedContext=utilities.deepMerge(currentStore.context,contextData);mergedContext=structuredClone(mergedContext)}else{const clonedParent=structuredClone(currentStore.context);mergedContext={...clonedParent,...contextData}}const childInstanceID=`${slothlet.instanceID}__run_${Date.now()}_${Math.random().toString(36).slice(2,9)}`;const childStore={instanceID:childInstanceID,context:mergedContext,self:isolationMode==="full"?makeCopyOnWriteSelf(currentStore.self):currentStore.self,config:currentStore.config,createdAt:currentStore.createdAt,parentInstanceID:slothlet.instanceID,currentWrapper:currentStore.currentWrapper,callerWrapper:currentStore.callerWrapper,slothlet:currentStore.slothlet,__contextOwners:buildContextOwners(currentStore.__contextOwners)};if(currentStore[TRUSTED_ROOT]===true){Object.defineProperty(childStore,TRUSTED_ROOT,{value:true,configurable:true})}contextManager.instances.set(childInstanceID,childStore);try{return await contextManager.als.run(childStore,async()=>{return await fn(...args)})}finally{contextManager.instances.delete(childInstanceID)}}throw new slothlet.SlothletError("UNSUPPORTED_CONTEXT_MANAGER",{manager:contextManager.constructor.name,validationError:true})}}.scope;return scopeFunction}createDestroyFunction(api){const slothlet=this.slothlet;const destroyFunction={destroy:async()=>{let routineError=null;try{await slothlet.handlers.routineManager?.runDestroyModeRoutines()}catch(error){routineError=error}if(slothlet.userHooks?.destroy&&typeof slothlet.userHooks.destroy==="function"){await slothlet.userHooks.destroy()}try{if(api&&typeof api.shutdown==="function"){await api.shutdown()}else{await slothlet.shutdown()}}catch(error){if(!routineError)routineError=error}slothlet.isDestroyed=true;const objectsToClear=[api,slothlet.api].filter(obj=>obj&&typeof obj==="object");for(const obj of objectsToClear){const keys=Object.keys(obj);for(const key of keys){try{delete obj[key]}catch(_){}}}slothlet.api=null;if(routineError)throw routineError}}.destroy;return destroyFunction}attachBuiltins(userApi,builtins){Object.defineProperty(userApi,"slothlet",{value:builtins.slothlet,enumerable:true,writable:false,configurable:true});Object.defineProperty(userApi,"shutdown",{value:builtins.shutdown,enumerable:true,writable:false,configurable:true});if(builtins.destroy!==null){Object.defineProperty(userApi,"destroy",{value:builtins.destroy,enumerable:true,writable:false,configurable:true})}}}export{ApiBuilder};
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import{ComponentBase}from"#factories/component-base";class Builder extends ComponentBase{static slothletProperty="builder";constructor(slothlet){super(slothlet)}async buildAPI(options){const{dir,mode="eager",apiPathPrefix="",collisionContext="initial",moduleID,cacheBust=null,fileFilter=null,hidden=null,scanHiddenFolders=false,collisionMode=null,syntheticExports=null,syntheticName="synthetic",rootUnwrap=false}=options;let preloadedStructure=null;let effectiveDir=dir;if(syntheticExports!=null){const isPlainObject=value=>{if(value===null||typeof value!=="object")return false;const proto=Object.getPrototypeOf(value);return proto===Object.prototype||proto===null};if(!isPlainObject(syntheticExports)){throw new this.SlothletError("INVALID_CONFIG_SYNTHETIC_EXPORTS_SHAPE",{received:Array.isArray(syntheticExports)?"array":typeof syntheticExports==="object"?`${syntheticExports.constructor?.name??"non-plain object"} instance`:typeof syntheticExports,validationError:true})}if(typeof syntheticName!=="string"||!syntheticName){throw new this.SlothletError("INVALID_CONFIG_SYNTHETIC_NAME",{received:typeof syntheticName==="string"?"<empty>":typeof syntheticName,validationError:true})}const sentinel=`synthetic:${syntheticName}`;effectiveDir=sentinel;preloadedStructure={files:[{path:sentinel,name:syntheticName,fullName:`${syntheticName}.mjs`,moduleID,synthetic:true,exports:syntheticExports}],directories:[]}}else if(!dir||typeof dir!=="string"){throw new this.SlothletError("INVALID_CONFIG_DIR_INVALID",{dir},null,{validationError:true})}if(mode!=="eager"&&mode!=="lazy"){throw new this.SlothletError("INVALID_CONFIG_MODE_INVALID",{value:mode},null,{validationError:true})}let rawAPI;this.slothlet.____buildDepth=(this.slothlet.____buildDepth||0)+1;try{if(mode==="eager"){rawAPI=await this.slothlet.modes.eager.buildAPI({dir:effectiveDir,apiPathPrefix,collisionContext,moduleID,apiDepth:this.slothlet.config.apiDepth,cacheBust,fileFilter,hidden,scanHiddenFolders,preloadedStructure,rootUnwrap})}else{rawAPI=await this.slothlet.modes.lazy.buildAPI({dir:effectiveDir,apiPathPrefix,collisionContext,collisionMode,moduleID,apiDepth:this.slothlet.config.apiDepth,cacheBust,fileFilter,hidden,scanHiddenFolders,preloadedStructure,rootUnwrap})}}finally{this.slothlet.____buildDepth--}return rawAPI}}export{Builder};
|
|
17
|
+
import{ComponentBase}from"#factories/component-base";class Builder extends ComponentBase{static slothletProperty="builder";constructor(slothlet){super(slothlet)}async buildAPI(options){const{dir,mode="eager",apiPathPrefix="",collisionContext="initial",moduleID,cacheBust=null,fileFilter=null,hidden=null,scanHiddenFolders=false,collisionMode=null,syntheticExports=null,syntheticName="synthetic",rootUnwrap=false}=options;let preloadedStructure=null;let effectiveDir=dir;if(syntheticExports!=null){const isPlainObject=value=>{if(value===null||typeof value!=="object")return false;const proto=Object.getPrototypeOf(value);return proto===Object.prototype||proto===null};if(!isPlainObject(syntheticExports)){throw new this.SlothletError("INVALID_CONFIG_SYNTHETIC_EXPORTS_SHAPE",{received:Array.isArray(syntheticExports)?"array":typeof syntheticExports==="object"?`${syntheticExports.constructor?.name??"non-plain object"} instance`:typeof syntheticExports,validationError:true})}if(typeof syntheticName!=="string"||!syntheticName){throw new this.SlothletError("INVALID_CONFIG_SYNTHETIC_NAME",{received:typeof syntheticName==="string"?"<empty>":typeof syntheticName,validationError:true})}const sentinel=`synthetic:${syntheticName}`;effectiveDir=sentinel;preloadedStructure={files:[{path:sentinel,name:syntheticName,fullName:`${syntheticName}.mjs`,moduleID,synthetic:true,exports:syntheticExports}],directories:[]}}else if(!dir||typeof dir!=="string"){throw new this.SlothletError("INVALID_CONFIG_DIR_INVALID",{dir},null,{validationError:true})}if(mode!=="eager"&&mode!=="lazy"){throw new this.SlothletError("INVALID_CONFIG_MODE_INVALID",{value:mode},null,{validationError:true})}let rawAPI;this.slothlet.____buildDepth=(this.slothlet.____buildDepth||0)+1;try{if(mode==="eager"){rawAPI=await this.slothlet.modes.eager.buildAPI({dir:effectiveDir,apiPathPrefix,collisionContext,collisionMode,moduleID,apiDepth:this.slothlet.config.apiDepth,cacheBust,fileFilter,hidden,scanHiddenFolders,preloadedStructure,rootUnwrap})}else{rawAPI=await this.slothlet.modes.lazy.buildAPI({dir:effectiveDir,apiPathPrefix,collisionContext,collisionMode,moduleID,apiDepth:this.slothlet.config.apiDepth,cacheBust,fileFilter,hidden,scanHiddenFolders,preloadedStructure,rootUnwrap})}}finally{this.slothlet.____buildDepth--}return rawAPI}}export{Builder};
|