@aigne/aos 0.2.0-beta
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/CHANGELOG.md +49 -0
- package/LICENSE.md +26 -0
- package/dist/agent-dsl.cjs +116 -0
- package/dist/agent-dsl.d.cts +31 -0
- package/dist/agent-dsl.d.cts.map +1 -0
- package/dist/agent-dsl.d.mts +31 -0
- package/dist/agent-dsl.d.mts.map +1 -0
- package/dist/agent-dsl.mjs +115 -0
- package/dist/agent-dsl.mjs.map +1 -0
- package/dist/arc-compat.cjs +125 -0
- package/dist/arc-compat.d.cts +17 -0
- package/dist/arc-compat.d.cts.map +1 -0
- package/dist/arc-compat.d.mts +17 -0
- package/dist/arc-compat.d.mts.map +1 -0
- package/dist/arc-compat.mjs +123 -0
- package/dist/arc-compat.mjs.map +1 -0
- package/dist/auto-surface/compiler.cjs +36 -0
- package/dist/auto-surface/compiler.d.cts +7 -0
- package/dist/auto-surface/compiler.d.cts.map +1 -0
- package/dist/auto-surface/compiler.d.mts +7 -0
- package/dist/auto-surface/compiler.d.mts.map +1 -0
- package/dist/auto-surface/compiler.mjs +37 -0
- package/dist/auto-surface/compiler.mjs.map +1 -0
- package/dist/auto-surface/definition-dsl.cjs +333 -0
- package/dist/auto-surface/definition-dsl.d.cts +41 -0
- package/dist/auto-surface/definition-dsl.d.cts.map +1 -0
- package/dist/auto-surface/definition-dsl.d.mts +41 -0
- package/dist/auto-surface/definition-dsl.d.mts.map +1 -0
- package/dist/auto-surface/definition-dsl.mjs +332 -0
- package/dist/auto-surface/definition-dsl.mjs.map +1 -0
- package/dist/auto-surface/fragments.cjs +177 -0
- package/dist/auto-surface/fragments.d.cts +23 -0
- package/dist/auto-surface/fragments.d.cts.map +1 -0
- package/dist/auto-surface/fragments.d.mts +23 -0
- package/dist/auto-surface/fragments.d.mts.map +1 -0
- package/dist/auto-surface/fragments.mjs +175 -0
- package/dist/auto-surface/fragments.mjs.map +1 -0
- package/dist/auto-surface/index.d.mts +9 -0
- package/dist/auto-surface/layering.cjs +43 -0
- package/dist/auto-surface/layering.d.cts +7 -0
- package/dist/auto-surface/layering.d.cts.map +1 -0
- package/dist/auto-surface/layering.d.mts +7 -0
- package/dist/auto-surface/layering.d.mts.map +1 -0
- package/dist/auto-surface/layering.mjs +43 -0
- package/dist/auto-surface/layering.mjs.map +1 -0
- package/dist/auto-surface/projection.cjs +11 -0
- package/dist/auto-surface/projection.d.cts +11 -0
- package/dist/auto-surface/projection.d.cts.map +1 -0
- package/dist/auto-surface/projection.d.mts +11 -0
- package/dist/auto-surface/projection.d.mts.map +1 -0
- package/dist/auto-surface/projection.mjs +12 -0
- package/dist/auto-surface/projection.mjs.map +1 -0
- package/dist/auto-surface/projectors/settings-shell.cjs +114 -0
- package/dist/auto-surface/projectors/settings-shell.d.cts +10 -0
- package/dist/auto-surface/projectors/settings-shell.d.cts.map +1 -0
- package/dist/auto-surface/projectors/settings-shell.d.mts +10 -0
- package/dist/auto-surface/projectors/settings-shell.d.mts.map +1 -0
- package/dist/auto-surface/projectors/settings-shell.mjs +114 -0
- package/dist/auto-surface/projectors/settings-shell.mjs.map +1 -0
- package/dist/auto-surface/scenario.cjs +38 -0
- package/dist/auto-surface/scenario.d.cts +31 -0
- package/dist/auto-surface/scenario.d.cts.map +1 -0
- package/dist/auto-surface/scenario.d.mts +31 -0
- package/dist/auto-surface/scenario.d.mts.map +1 -0
- package/dist/auto-surface/scenario.mjs +37 -0
- package/dist/auto-surface/scenario.mjs.map +1 -0
- package/dist/auto-surface/types.cjs +9 -0
- package/dist/auto-surface/types.d.cts +153 -0
- package/dist/auto-surface/types.d.cts.map +1 -0
- package/dist/auto-surface/types.d.mts +153 -0
- package/dist/auto-surface/types.d.mts.map +1 -0
- package/dist/auto-surface/types.mjs +9 -0
- package/dist/auto-surface/types.mjs.map +1 -0
- package/dist/auto-surface/value-dsl.cjs +80 -0
- package/dist/auto-surface/value-dsl.d.cts +24 -0
- package/dist/auto-surface/value-dsl.d.cts.map +1 -0
- package/dist/auto-surface/value-dsl.d.mts +24 -0
- package/dist/auto-surface/value-dsl.d.mts.map +1 -0
- package/dist/auto-surface/value-dsl.mjs +79 -0
- package/dist/auto-surface/value-dsl.mjs.map +1 -0
- package/dist/blocklet/activation.cjs +94 -0
- package/dist/blocklet/activation.d.cts +30 -0
- package/dist/blocklet/activation.d.cts.map +1 -0
- package/dist/blocklet/activation.d.mts +30 -0
- package/dist/blocklet/activation.d.mts.map +1 -0
- package/dist/blocklet/activation.mjs +94 -0
- package/dist/blocklet/activation.mjs.map +1 -0
- package/dist/blocklet/did-space-registry.cjs +282 -0
- package/dist/blocklet/did-space-registry.d.cts +82 -0
- package/dist/blocklet/did-space-registry.d.cts.map +1 -0
- package/dist/blocklet/did-space-registry.d.mts +82 -0
- package/dist/blocklet/did-space-registry.d.mts.map +1 -0
- package/dist/blocklet/did-space-registry.mjs +281 -0
- package/dist/blocklet/did-space-registry.mjs.map +1 -0
- package/dist/blocklet/handlers.cjs +66 -0
- package/dist/blocklet/handlers.d.cts +16 -0
- package/dist/blocklet/handlers.d.cts.map +1 -0
- package/dist/blocklet/handlers.d.mts +16 -0
- package/dist/blocklet/handlers.d.mts.map +1 -0
- package/dist/blocklet/handlers.mjs +65 -0
- package/dist/blocklet/handlers.mjs.map +1 -0
- package/dist/blocklet/index.d.mts +7 -0
- package/dist/blocklet/manifest.d.cts +2 -0
- package/dist/blocklet/manifest.d.mts +2 -0
- package/dist/blocklet/manifest.mjs +3 -0
- package/dist/blocklet/registry.cjs +447 -0
- package/dist/blocklet/registry.d.cts +197 -0
- package/dist/blocklet/registry.d.cts.map +1 -0
- package/dist/blocklet/registry.d.mts +197 -0
- package/dist/blocklet/registry.d.mts.map +1 -0
- package/dist/blocklet/registry.mjs +441 -0
- package/dist/blocklet/registry.mjs.map +1 -0
- package/dist/blocklet/static-render.cjs +183 -0
- package/dist/blocklet/static-render.d.cts +55 -0
- package/dist/blocklet/static-render.d.cts.map +1 -0
- package/dist/blocklet/static-render.d.mts +55 -0
- package/dist/blocklet/static-render.d.mts.map +1 -0
- package/dist/blocklet/static-render.mjs +181 -0
- package/dist/blocklet/static-render.mjs.map +1 -0
- package/dist/blocklet/types.d.cts +70 -0
- package/dist/blocklet/types.d.cts.map +1 -0
- package/dist/blocklet/types.d.mts +70 -0
- package/dist/blocklet/types.d.mts.map +1 -0
- package/dist/devices/chain.cjs +127 -0
- package/dist/devices/chain.d.cts +48 -0
- package/dist/devices/chain.d.cts.map +1 -0
- package/dist/devices/chain.d.mts +48 -0
- package/dist/devices/chain.d.mts.map +1 -0
- package/dist/devices/chain.mjs +125 -0
- package/dist/devices/chain.mjs.map +1 -0
- package/dist/dsl-shared.cjs +290 -0
- package/dist/dsl-shared.d.cts +54 -0
- package/dist/dsl-shared.d.cts.map +1 -0
- package/dist/dsl-shared.d.mts +54 -0
- package/dist/dsl-shared.d.mts.map +1 -0
- package/dist/dsl-shared.mjs +287 -0
- package/dist/dsl-shared.mjs.map +1 -0
- package/dist/http/afs-mcp.cjs +85 -0
- package/dist/http/afs-mcp.d.cts +14 -0
- package/dist/http/afs-mcp.d.cts.map +1 -0
- package/dist/http/afs-mcp.d.mts +14 -0
- package/dist/http/afs-mcp.d.mts.map +1 -0
- package/dist/http/afs-mcp.mjs +86 -0
- package/dist/http/afs-mcp.mjs.map +1 -0
- package/dist/http/afs-raw.cjs +264 -0
- package/dist/http/afs-raw.d.cts +31 -0
- package/dist/http/afs-raw.d.cts.map +1 -0
- package/dist/http/afs-raw.d.mts +31 -0
- package/dist/http/afs-raw.d.mts.map +1 -0
- package/dist/http/afs-raw.mjs +264 -0
- package/dist/http/afs-raw.mjs.map +1 -0
- package/dist/http/afs-rest.cjs +30 -0
- package/dist/http/afs-rest.d.cts +21 -0
- package/dist/http/afs-rest.d.cts.map +1 -0
- package/dist/http/afs-rest.d.mts +21 -0
- package/dist/http/afs-rest.d.mts.map +1 -0
- package/dist/http/afs-rest.mjs +31 -0
- package/dist/http/afs-rest.mjs.map +1 -0
- package/dist/http/afs-rpc-wire.cjs +271 -0
- package/dist/http/afs-rpc-wire.d.cts +195 -0
- package/dist/http/afs-rpc-wire.d.cts.map +1 -0
- package/dist/http/afs-rpc-wire.d.mts +195 -0
- package/dist/http/afs-rpc-wire.d.mts.map +1 -0
- package/dist/http/afs-rpc-wire.mjs +262 -0
- package/dist/http/afs-rpc-wire.mjs.map +1 -0
- package/dist/http/afs-rpc.cjs +729 -0
- package/dist/http/afs-rpc.d.cts +103 -0
- package/dist/http/afs-rpc.d.cts.map +1 -0
- package/dist/http/afs-rpc.d.mts +103 -0
- package/dist/http/afs-rpc.d.mts.map +1 -0
- package/dist/http/afs-rpc.mjs +729 -0
- package/dist/http/afs-rpc.mjs.map +1 -0
- package/dist/http/afs-upload.cjs +116 -0
- package/dist/http/afs-upload.d.cts +40 -0
- package/dist/http/afs-upload.d.cts.map +1 -0
- package/dist/http/afs-upload.d.mts +40 -0
- package/dist/http/afs-upload.d.mts.map +1 -0
- package/dist/http/afs-upload.mjs +116 -0
- package/dist/http/afs-upload.mjs.map +1 -0
- package/dist/http/aup-client.cjs +60 -0
- package/dist/http/aup-client.d.cts +22 -0
- package/dist/http/aup-client.d.cts.map +1 -0
- package/dist/http/aup-client.d.mts +22 -0
- package/dist/http/aup-client.d.mts.map +1 -0
- package/dist/http/aup-client.mjs +59 -0
- package/dist/http/aup-client.mjs.map +1 -0
- package/dist/http/aup-event.cjs +100 -0
- package/dist/http/aup-event.d.cts +38 -0
- package/dist/http/aup-event.d.cts.map +1 -0
- package/dist/http/aup-event.d.mts +38 -0
- package/dist/http/aup-event.d.mts.map +1 -0
- package/dist/http/aup-event.mjs +101 -0
- package/dist/http/aup-event.mjs.map +1 -0
- package/dist/http/auth-context.cjs +66 -0
- package/dist/http/auth-context.d.cts +64 -0
- package/dist/http/auth-context.d.cts.map +1 -0
- package/dist/http/auth-context.d.mts +64 -0
- package/dist/http/auth-context.d.mts.map +1 -0
- package/dist/http/auth-context.mjs +66 -0
- package/dist/http/auth-context.mjs.map +1 -0
- package/dist/http/csrf.cjs +50 -0
- package/dist/http/csrf.d.cts +8 -0
- package/dist/http/csrf.d.cts.map +1 -0
- package/dist/http/csrf.d.mts +8 -0
- package/dist/http/csrf.d.mts.map +1 -0
- package/dist/http/csrf.mjs +49 -0
- package/dist/http/csrf.mjs.map +1 -0
- package/dist/http/handlers.cjs +106 -0
- package/dist/http/handlers.d.cts +39 -0
- package/dist/http/handlers.d.cts.map +1 -0
- package/dist/http/handlers.d.mts +39 -0
- package/dist/http/handlers.d.mts.map +1 -0
- package/dist/http/handlers.mjs +104 -0
- package/dist/http/handlers.mjs.map +1 -0
- package/dist/http/index.d.mts +1 -0
- package/dist/http/ingest-facade.cjs +315 -0
- package/dist/http/ingest-facade.mjs +314 -0
- package/dist/http/ingest-facade.mjs.map +1 -0
- package/dist/http/raw-url.cjs +136 -0
- package/dist/http/raw-url.d.cts +54 -0
- package/dist/http/raw-url.d.cts.map +1 -0
- package/dist/http/raw-url.d.mts +54 -0
- package/dist/http/raw-url.d.mts.map +1 -0
- package/dist/http/raw-url.mjs +136 -0
- package/dist/http/raw-url.mjs.map +1 -0
- package/dist/http/request-context.cjs +178 -0
- package/dist/http/request-context.d.cts +76 -0
- package/dist/http/request-context.d.cts.map +1 -0
- package/dist/http/request-context.d.mts +76 -0
- package/dist/http/request-context.d.mts.map +1 -0
- package/dist/http/request-context.mjs +179 -0
- package/dist/http/request-context.mjs.map +1 -0
- package/dist/index.cjs +197 -0
- package/dist/index.d.cts +63 -0
- package/dist/index.d.mts +68 -0
- package/dist/index.mjs +61 -0
- package/dist/mcp/index.cjs +9 -0
- package/dist/mcp/index.d.cts +5 -0
- package/dist/mcp/index.d.mts +5 -0
- package/dist/mcp/index.mjs +6 -0
- package/dist/mcp/prompts.cjs +17 -0
- package/dist/mcp/prompts.d.cts +8 -0
- package/dist/mcp/prompts.d.cts.map +1 -0
- package/dist/mcp/prompts.d.mts +8 -0
- package/dist/mcp/prompts.d.mts.map +1 -0
- package/dist/mcp/prompts.mjs +17 -0
- package/dist/mcp/prompts.mjs.map +1 -0
- package/dist/mcp/resources.cjs +22 -0
- package/dist/mcp/resources.d.cts +8 -0
- package/dist/mcp/resources.d.cts.map +1 -0
- package/dist/mcp/resources.d.mts +8 -0
- package/dist/mcp/resources.d.mts.map +1 -0
- package/dist/mcp/resources.mjs +22 -0
- package/dist/mcp/resources.mjs.map +1 -0
- package/dist/mcp/server.cjs +51 -0
- package/dist/mcp/server.d.cts +20 -0
- package/dist/mcp/server.d.cts.map +1 -0
- package/dist/mcp/server.d.mts +20 -0
- package/dist/mcp/server.d.mts.map +1 -0
- package/dist/mcp/server.mjs +52 -0
- package/dist/mcp/server.mjs.map +1 -0
- package/dist/mcp/tools.cjs +218 -0
- package/dist/mcp/tools.d.cts +8 -0
- package/dist/mcp/tools.d.cts.map +1 -0
- package/dist/mcp/tools.d.mts +8 -0
- package/dist/mcp/tools.d.mts.map +1 -0
- package/dist/mcp/tools.mjs +219 -0
- package/dist/mcp/tools.mjs.map +1 -0
- package/dist/mcp/utils.cjs +75 -0
- package/dist/mcp/utils.mjs +69 -0
- package/dist/mcp/utils.mjs.map +1 -0
- package/dist/mount/index.cjs +4 -0
- package/dist/mount/index.d.cts +3 -0
- package/dist/mount/index.d.mts +3 -0
- package/dist/mount/index.mjs +3 -0
- package/dist/mount/materializer.cjs +167 -0
- package/dist/mount/materializer.d.cts +97 -0
- package/dist/mount/materializer.d.cts.map +1 -0
- package/dist/mount/materializer.d.mts +97 -0
- package/dist/mount/materializer.d.mts.map +1 -0
- package/dist/mount/materializer.mjs +167 -0
- package/dist/mount/materializer.mjs.map +1 -0
- package/dist/mount/types.d.cts +90 -0
- package/dist/mount/types.d.cts.map +1 -0
- package/dist/mount/types.d.mts +90 -0
- package/dist/mount/types.d.mts.map +1 -0
- package/dist/mount-config.cjs +61 -0
- package/dist/mount-config.d.cts +19 -0
- package/dist/mount-config.d.cts.map +1 -0
- package/dist/mount-config.d.mts +19 -0
- package/dist/mount-config.d.mts.map +1 -0
- package/dist/mount-config.mjs +61 -0
- package/dist/mount-config.mjs.map +1 -0
- package/dist/projectors/aup-projector.cjs +190 -0
- package/dist/projectors/aup-projector.d.cts +59 -0
- package/dist/projectors/aup-projector.d.cts.map +1 -0
- package/dist/projectors/aup-projector.d.mts +59 -0
- package/dist/projectors/aup-projector.d.mts.map +1 -0
- package/dist/projectors/aup-projector.mjs +188 -0
- package/dist/projectors/aup-projector.mjs.map +1 -0
- package/dist/projectors/index.cjs +6 -0
- package/dist/projectors/index.d.cts +2 -0
- package/dist/projectors/index.d.mts +2 -0
- package/dist/projectors/index.mjs +3 -0
- package/dist/scaffold/afs.cjs +195 -0
- package/dist/scaffold/afs.d.cts +16 -0
- package/dist/scaffold/afs.d.cts.map +1 -0
- package/dist/scaffold/afs.d.mts +16 -0
- package/dist/scaffold/afs.d.mts.map +1 -0
- package/dist/scaffold/afs.mjs +195 -0
- package/dist/scaffold/afs.mjs.map +1 -0
- package/dist/scaffold/composition.cjs +92 -0
- package/dist/scaffold/composition.d.cts +10 -0
- package/dist/scaffold/composition.d.cts.map +1 -0
- package/dist/scaffold/composition.d.mts +10 -0
- package/dist/scaffold/composition.d.mts.map +1 -0
- package/dist/scaffold/composition.mjs +92 -0
- package/dist/scaffold/composition.mjs.map +1 -0
- package/dist/scaffold/dsl-error.cjs +21 -0
- package/dist/scaffold/dsl-error.d.cts +11 -0
- package/dist/scaffold/dsl-error.d.cts.map +1 -0
- package/dist/scaffold/dsl-error.d.mts +11 -0
- package/dist/scaffold/dsl-error.d.mts.map +1 -0
- package/dist/scaffold/dsl-error.mjs +20 -0
- package/dist/scaffold/dsl-error.mjs.map +1 -0
- package/dist/scaffold/index.d.mts +12 -0
- package/dist/scaffold/manifest-dsl.cjs +188 -0
- package/dist/scaffold/manifest-dsl.d.cts +8 -0
- package/dist/scaffold/manifest-dsl.d.cts.map +1 -0
- package/dist/scaffold/manifest-dsl.d.mts +8 -0
- package/dist/scaffold/manifest-dsl.d.mts.map +1 -0
- package/dist/scaffold/manifest-dsl.mjs +188 -0
- package/dist/scaffold/manifest-dsl.mjs.map +1 -0
- package/dist/scaffold/module-dsl.cjs +284 -0
- package/dist/scaffold/module-dsl.d.cts +8 -0
- package/dist/scaffold/module-dsl.d.cts.map +1 -0
- package/dist/scaffold/module-dsl.d.mts +8 -0
- package/dist/scaffold/module-dsl.d.mts.map +1 -0
- package/dist/scaffold/module-dsl.mjs +284 -0
- package/dist/scaffold/module-dsl.mjs.map +1 -0
- package/dist/scaffold/resolver.cjs +156 -0
- package/dist/scaffold/resolver.d.cts +7 -0
- package/dist/scaffold/resolver.d.cts.map +1 -0
- package/dist/scaffold/resolver.d.mts +7 -0
- package/dist/scaffold/resolver.d.mts.map +1 -0
- package/dist/scaffold/resolver.mjs +156 -0
- package/dist/scaffold/resolver.mjs.map +1 -0
- package/dist/scaffold/runtime.cjs +24 -0
- package/dist/scaffold/runtime.d.cts +19 -0
- package/dist/scaffold/runtime.d.cts.map +1 -0
- package/dist/scaffold/runtime.d.mts +19 -0
- package/dist/scaffold/runtime.d.mts.map +1 -0
- package/dist/scaffold/runtime.mjs +25 -0
- package/dist/scaffold/runtime.mjs.map +1 -0
- package/dist/scaffold/shell-dsl.cjs +279 -0
- package/dist/scaffold/shell-dsl.d.cts +8 -0
- package/dist/scaffold/shell-dsl.d.cts.map +1 -0
- package/dist/scaffold/shell-dsl.d.mts +8 -0
- package/dist/scaffold/shell-dsl.d.mts.map +1 -0
- package/dist/scaffold/shell-dsl.mjs +279 -0
- package/dist/scaffold/shell-dsl.mjs.map +1 -0
- package/dist/scaffold/surface-dsl.cjs +182 -0
- package/dist/scaffold/surface-dsl.d.cts +8 -0
- package/dist/scaffold/surface-dsl.d.cts.map +1 -0
- package/dist/scaffold/surface-dsl.d.mts +8 -0
- package/dist/scaffold/surface-dsl.d.mts.map +1 -0
- package/dist/scaffold/surface-dsl.mjs +182 -0
- package/dist/scaffold/surface-dsl.mjs.map +1 -0
- package/dist/scaffold/surfaces.cjs +84 -0
- package/dist/scaffold/surfaces.d.cts +23 -0
- package/dist/scaffold/surfaces.d.cts.map +1 -0
- package/dist/scaffold/surfaces.d.mts +24 -0
- package/dist/scaffold/surfaces.d.mts.map +1 -0
- package/dist/scaffold/surfaces.mjs +84 -0
- package/dist/scaffold/surfaces.mjs.map +1 -0
- package/dist/scaffold/types.d.cts +264 -0
- package/dist/scaffold/types.d.cts.map +1 -0
- package/dist/scaffold/types.d.mts +265 -0
- package/dist/scaffold/types.d.mts.map +1 -0
- package/dist/scaffold/workspace-dsl.cjs +339 -0
- package/dist/scaffold/workspace-dsl.d.cts +49 -0
- package/dist/scaffold/workspace-dsl.d.cts.map +1 -0
- package/dist/scaffold/workspace-dsl.d.mts +49 -0
- package/dist/scaffold/workspace-dsl.d.mts.map +1 -0
- package/dist/scaffold/workspace-dsl.mjs +337 -0
- package/dist/scaffold/workspace-dsl.mjs.map +1 -0
- package/dist/scope/index.d.mts +3 -0
- package/dist/scope/read-blocklet-scope.cjs +29 -0
- package/dist/scope/read-blocklet-scope.d.cts +8 -0
- package/dist/scope/read-blocklet-scope.d.cts.map +1 -0
- package/dist/scope/read-blocklet-scope.d.mts +8 -0
- package/dist/scope/read-blocklet-scope.d.mts.map +1 -0
- package/dist/scope/read-blocklet-scope.mjs +30 -0
- package/dist/scope/read-blocklet-scope.mjs.map +1 -0
- package/dist/scope/resolve-scoped-afs.cjs +87 -0
- package/dist/scope/resolve-scoped-afs.d.cts +7 -0
- package/dist/scope/resolve-scoped-afs.d.cts.map +1 -0
- package/dist/scope/resolve-scoped-afs.d.mts +7 -0
- package/dist/scope/resolve-scoped-afs.d.mts.map +1 -0
- package/dist/scope/resolve-scoped-afs.mjs +88 -0
- package/dist/scope/resolve-scoped-afs.mjs.map +1 -0
- package/dist/scope/types.d.cts +25 -0
- package/dist/scope/types.d.cts.map +1 -0
- package/dist/scope/types.d.mts +25 -0
- package/dist/scope/types.d.mts.map +1 -0
- package/dist/session/backends.cjs +90 -0
- package/dist/session/backends.d.cts +35 -0
- package/dist/session/backends.d.cts.map +1 -0
- package/dist/session/backends.d.mts +35 -0
- package/dist/session/backends.d.mts.map +1 -0
- package/dist/session/backends.mjs +89 -0
- package/dist/session/backends.mjs.map +1 -0
- package/dist/session/replication-resolver.cjs +323 -0
- package/dist/session/replication-resolver.d.cts +71 -0
- package/dist/session/replication-resolver.d.cts.map +1 -0
- package/dist/session/replication-resolver.d.mts +71 -0
- package/dist/session/replication-resolver.d.mts.map +1 -0
- package/dist/session/replication-resolver.mjs +323 -0
- package/dist/session/replication-resolver.mjs.map +1 -0
- package/dist/session/role-level.cjs +36 -0
- package/dist/session/role-level.d.cts +24 -0
- package/dist/session/role-level.d.cts.map +1 -0
- package/dist/session/role-level.d.mts +24 -0
- package/dist/session/role-level.d.mts.map +1 -0
- package/dist/session/role-level.mjs +35 -0
- package/dist/session/role-level.mjs.map +1 -0
- package/dist/session/session-dir-providers.cjs +254 -0
- package/dist/session/session-dir-providers.d.cts +32 -0
- package/dist/session/session-dir-providers.d.cts.map +1 -0
- package/dist/session/session-dir-providers.d.mts +32 -0
- package/dist/session/session-dir-providers.d.mts.map +1 -0
- package/dist/session/session-dir-providers.mjs +252 -0
- package/dist/session/session-dir-providers.mjs.map +1 -0
- package/dist/session/session-id.cjs +20 -0
- package/dist/session/session-id.d.cts +15 -0
- package/dist/session/session-id.d.cts.map +1 -0
- package/dist/session/session-id.d.mts +15 -0
- package/dist/session/session-id.d.mts.map +1 -0
- package/dist/session/session-id.mjs +20 -0
- package/dist/session/session-id.mjs.map +1 -0
- package/dist/session/session-user-afs.cjs +899 -0
- package/dist/session/session-user-afs.d.cts +296 -0
- package/dist/session/session-user-afs.d.cts.map +1 -0
- package/dist/session/session-user-afs.d.mts +296 -0
- package/dist/session/session-user-afs.d.mts.map +1 -0
- package/dist/session/session-user-afs.mjs +896 -0
- package/dist/session/session-user-afs.mjs.map +1 -0
- package/dist/session/settings-cascade.cjs +69 -0
- package/dist/session/settings-cascade.d.cts +81 -0
- package/dist/session/settings-cascade.d.cts.map +1 -0
- package/dist/session/settings-cascade.d.mts +81 -0
- package/dist/session/settings-cascade.d.mts.map +1 -0
- package/dist/session/settings-cascade.mjs +69 -0
- package/dist/session/settings-cascade.mjs.map +1 -0
- package/dist/session/settings-resolver.cjs +770 -0
- package/dist/session/settings-resolver.d.cts +177 -0
- package/dist/session/settings-resolver.d.cts.map +1 -0
- package/dist/session/settings-resolver.d.mts +177 -0
- package/dist/session/settings-resolver.d.mts.map +1 -0
- package/dist/session/settings-resolver.mjs +771 -0
- package/dist/session/settings-resolver.mjs.map +1 -0
- package/dist/session/settings-schema-store.cjs +0 -0
- package/dist/session/settings-schema-store.d.cts +72 -0
- package/dist/session/settings-schema-store.d.cts.map +1 -0
- package/dist/session/settings-schema-store.d.mts +72 -0
- package/dist/session/settings-schema-store.d.mts.map +1 -0
- package/dist/session/settings-schema-store.mjs +0 -0
- package/dist/session/settings-schema-store.mjs.map +1 -0
- package/dist/system-mounts/index.cjs +14 -0
- package/dist/system-mounts/index.d.cts +6 -0
- package/dist/system-mounts/index.d.mts +6 -0
- package/dist/system-mounts/index.mjs +6 -0
- package/dist/system-mounts/install.cjs +101 -0
- package/dist/system-mounts/install.d.cts +36 -0
- package/dist/system-mounts/install.d.cts.map +1 -0
- package/dist/system-mounts/install.d.mts +37 -0
- package/dist/system-mounts/install.d.mts.map +1 -0
- package/dist/system-mounts/install.mjs +102 -0
- package/dist/system-mounts/install.mjs.map +1 -0
- package/dist/system-mounts/installers.cjs +247 -0
- package/dist/system-mounts/installers.d.cts +13 -0
- package/dist/system-mounts/installers.d.cts.map +1 -0
- package/dist/system-mounts/installers.d.mts +14 -0
- package/dist/system-mounts/installers.d.mts.map +1 -0
- package/dist/system-mounts/installers.mjs +244 -0
- package/dist/system-mounts/installers.mjs.map +1 -0
- package/dist/system-mounts/lists.cjs +122 -0
- package/dist/system-mounts/lists.d.cts +34 -0
- package/dist/system-mounts/lists.d.cts.map +1 -0
- package/dist/system-mounts/lists.d.mts +34 -0
- package/dist/system-mounts/lists.d.mts.map +1 -0
- package/dist/system-mounts/lists.mjs +122 -0
- package/dist/system-mounts/lists.mjs.map +1 -0
- package/dist/system-mounts/types.d.cts +124 -0
- package/dist/system-mounts/types.d.cts.map +1 -0
- package/dist/system-mounts/types.d.mts +125 -0
- package/dist/system-mounts/types.d.mts.map +1 -0
- package/dist/system-mounts/validate.cjs +56 -0
- package/dist/system-mounts/validate.d.cts +34 -0
- package/dist/system-mounts/validate.d.cts.map +1 -0
- package/dist/system-mounts/validate.d.mts +34 -0
- package/dist/system-mounts/validate.d.mts.map +1 -0
- package/dist/system-mounts/validate.mjs +56 -0
- package/dist/system-mounts/validate.mjs.map +1 -0
- package/dist/terminal-llm.cjs +90 -0
- package/dist/terminal-llm.d.cts +50 -0
- package/dist/terminal-llm.d.cts.map +1 -0
- package/dist/terminal-llm.d.mts +50 -0
- package/dist/terminal-llm.d.mts.map +1 -0
- package/dist/terminal-llm.mjs +90 -0
- package/dist/terminal-llm.mjs.map +1 -0
- package/dist/terminal-repl.cjs +371 -0
- package/dist/terminal-repl.d.cts +69 -0
- package/dist/terminal-repl.d.cts.map +1 -0
- package/dist/terminal-repl.d.mts +69 -0
- package/dist/terminal-repl.d.mts.map +1 -0
- package/dist/terminal-repl.mjs +370 -0
- package/dist/terminal-repl.mjs.map +1 -0
- package/dist/transport/idle-timer.cjs +136 -0
- package/dist/transport/idle-timer.d.cts +92 -0
- package/dist/transport/idle-timer.d.cts.map +1 -0
- package/dist/transport/idle-timer.d.mts +92 -0
- package/dist/transport/idle-timer.d.mts.map +1 -0
- package/dist/transport/idle-timer.mjs +132 -0
- package/dist/transport/idle-timer.mjs.map +1 -0
- package/dist/web-component-dsl.cjs +153 -0
- package/dist/web-component-dsl.d.cts +27 -0
- package/dist/web-component-dsl.d.cts.map +1 -0
- package/dist/web-component-dsl.d.mts +27 -0
- package/dist/web-component-dsl.d.mts.map +1 -0
- package/dist/web-component-dsl.mjs +152 -0
- package/dist/web-component-dsl.mjs.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
//#region src/transport/idle-timer.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Per-WebSocket idle timer — runtime-neutral.
|
|
4
|
+
*
|
|
5
|
+
* Why: long-lived WebSockets that sit idle still consume runtime resources.
|
|
6
|
+
* On Cloudflare Durable Objects this is direct billing (`server.accept()`
|
|
7
|
+
* keeps the DO active for the full WS lifetime); on Node it's memory and
|
|
8
|
+
* file descriptors. Both runtimes benefit from closing WebSockets that
|
|
9
|
+
* haven't seen a client message in a configurable window.
|
|
10
|
+
*
|
|
11
|
+
* What: arm a timer per connection, reset on every inbound message; on
|
|
12
|
+
* expiry, close the WS with a close code ≥ 4000 so the AUP client suppresses
|
|
13
|
+
* its auto-reconnect loop (see `web-page/core.ts` — code ≥ 4000 means
|
|
14
|
+
* "server rejected, do not reconnect"). The user reconnects on next
|
|
15
|
+
* interaction; the existing `sessionId`-based handshake restores per-session
|
|
16
|
+
* state.
|
|
17
|
+
*
|
|
18
|
+
* On Cloudflare, once all WebSockets close, the DO is auto-evicted by the
|
|
19
|
+
* Workers runtime and duration billing stops. On Node, the WS object is GC'd
|
|
20
|
+
* and the file descriptor returned to the OS.
|
|
21
|
+
*/
|
|
22
|
+
/** Close code used for intentional idle close (must be ≥ 4000). */
|
|
23
|
+
declare const IDLE_CLOSE_CODE = 4001;
|
|
24
|
+
/** Short ASCII reason — CF caps reason at 123 bytes. */
|
|
25
|
+
declare const IDLE_CLOSE_REASON = "idle-timeout";
|
|
26
|
+
interface IdleTimerOptions {
|
|
27
|
+
/** Idle window in ms. `0` disables the timer (useful for tests / opt-out). */
|
|
28
|
+
timeoutMs: number;
|
|
29
|
+
/** Invoked when the idle window elapses without a `rearm()`. */
|
|
30
|
+
onIdle: () => void;
|
|
31
|
+
/** Test seam — defaults to `globalThis.setTimeout`. */
|
|
32
|
+
setTimeout?: typeof setTimeout;
|
|
33
|
+
/** Test seam — defaults to `globalThis.clearTimeout`. */
|
|
34
|
+
clearTimeout?: typeof clearTimeout;
|
|
35
|
+
}
|
|
36
|
+
interface IdleTimer {
|
|
37
|
+
/** Reset (or start) the idle countdown. Safe to call repeatedly. */
|
|
38
|
+
rearm(): void;
|
|
39
|
+
/** Stop the timer. After cancel, `rearm()` resumes it. */
|
|
40
|
+
cancel(): void;
|
|
41
|
+
}
|
|
42
|
+
declare function createIdleTimer(opts: IdleTimerOptions): IdleTimer;
|
|
43
|
+
/**
|
|
44
|
+
* Minimal WebSocket surface used by `attachIdleClose`. Both the CF Workers
|
|
45
|
+
* `WebSocket` and the Node `ws` library satisfy this shape.
|
|
46
|
+
*/
|
|
47
|
+
interface IdleCloseTarget {
|
|
48
|
+
readyState: number;
|
|
49
|
+
close(code?: number, reason?: string): void;
|
|
50
|
+
send?: (data: any) => void;
|
|
51
|
+
addEventListener(type: "message" | "close" | "error", listener: (event: unknown) => void): void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Wire an idle timer to a WebSocket-like object: arm immediately, rearm on
|
|
55
|
+
* every inbound message, cancel on close/error. On expiry, close the socket
|
|
56
|
+
* with `IDLE_CLOSE_CODE` and `IDLE_CLOSE_REASON`.
|
|
57
|
+
*
|
|
58
|
+
* Returns the timer so callers can `cancel()` it during external teardown.
|
|
59
|
+
*/
|
|
60
|
+
declare function attachIdleClose(server: IdleCloseTarget, timeoutMs: number, options?: {
|
|
61
|
+
/**
|
|
62
|
+
* When true, wraps `server.send` so that every outbound server push also
|
|
63
|
+
* rearms the idle timer. Without this, a session receiving only passive
|
|
64
|
+
* live-update pushes (no client→server traffic) is considered "idle" and
|
|
65
|
+
* closed after `timeoutMs` even though it has ongoing server activity.
|
|
66
|
+
*/
|
|
67
|
+
rearmOnOutbound?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Inbound message `type` values that must NOT rearm the idle timer.
|
|
70
|
+
* Exists for synthetic client keepalive frames (e.g. the AUP web client's
|
|
71
|
+
* `{type:"ping"}`, sent purely to defeat CF-edge / mobile-NAT idle-drop
|
|
72
|
+
* of an otherwise-unused connection — see WS_KEEPALIVE_MESSAGE_TYPE in
|
|
73
|
+
* `@aigne/afs-ui`). Without this, a keepalive ping would itself count as
|
|
74
|
+
* "activity" and the idle-close timer — whose entire purpose is evicting
|
|
75
|
+
* genuinely-unused connections to stop Durable Object duration billing —
|
|
76
|
+
* would never fire for as long as the tab merely sits open (arc#1243).
|
|
77
|
+
* Messages that fail to parse as `{type: string}` JSON are never treated
|
|
78
|
+
* as ignorable, so this can only narrow rearm triggers, never widen them.
|
|
79
|
+
*/
|
|
80
|
+
ignoreMessageTypes?: string[];
|
|
81
|
+
setTimeout?: typeof setTimeout;
|
|
82
|
+
clearTimeout?: typeof clearTimeout;
|
|
83
|
+
}): IdleTimer;
|
|
84
|
+
/**
|
|
85
|
+
* Parse an env-supplied idle timeout. Accepts undefined / empty / non-numeric
|
|
86
|
+
* (returns `defaultMs`), `0` (returns `0` — disabled), and clamps to
|
|
87
|
+
* [MIN_TIMEOUT_MS, MAX_TIMEOUT_MS] for any positive value.
|
|
88
|
+
*/
|
|
89
|
+
declare function resolveIdleTimeoutMs(value: string | undefined, defaultMs: number): number;
|
|
90
|
+
//#endregion
|
|
91
|
+
export { IDLE_CLOSE_CODE, IDLE_CLOSE_REASON, IdleCloseTarget, IdleTimer, IdleTimerOptions, attachIdleClose, createIdleTimer, resolveIdleTimeoutMs };
|
|
92
|
+
//# sourceMappingURL=idle-timer.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle-timer.d.mts","names":[],"sources":["../../src/transport/idle-timer.ts"],"mappings":";;AAsBA;;;;;AAGA;;;;;AAOA;;;;;;;;;;cAVa,eAAA;;cAGA,iBAAA;AAAA,UAOI,gBAAA;;EAEf,SAAA;EAaM;EAXN,MAAA;EAc6B;EAZ7B,UAAA,UAAoB,UAAA;EAY4C;EAVhE,YAAA,UAAsB,YAAA;AAAA;AAAA,UAGP,SAAA;EAOiD;EALhE,KAAA;EA2Ce;EAzCf,MAAA;AAAA;AAAA,iBAGc,eAAA,CAAgB,IAAA,EAAM,gBAAA,GAAmB,SAAA;;;;;UAsCxC,eAAA;EACf,UAAA;EACA,KAAA,CAAM,IAAA,WAAe,MAAA;EACrB,IAAA,IAAQ,IAAA;EACR,gBAAA,CAAiB,IAAA,iCAAqC,QAAA,GAAW,KAAA;AAAA;;;AA6BnE;;;;;iBAAgB,eAAA,CACd,MAAA,EAAQ,eAAA,EACR,SAAA,UACA,OAAA;EAwBC;;;;;;EAjBC,eAAA;EAaA;;;;;;;;;AAgDJ;;;EAhDI,kBAAA;EACA,UAAA,UAAoB,UAAA;EACpB,YAAA,UAAsB,YAAA;AAAA,IAEvB,SAAA;;;;;;iBA4Ca,oBAAA,CAAqB,KAAA,sBAA2B,SAAA"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
//#region src/transport/idle-timer.ts
|
|
2
|
+
/**
|
|
3
|
+
* Per-WebSocket idle timer — runtime-neutral.
|
|
4
|
+
*
|
|
5
|
+
* Why: long-lived WebSockets that sit idle still consume runtime resources.
|
|
6
|
+
* On Cloudflare Durable Objects this is direct billing (`server.accept()`
|
|
7
|
+
* keeps the DO active for the full WS lifetime); on Node it's memory and
|
|
8
|
+
* file descriptors. Both runtimes benefit from closing WebSockets that
|
|
9
|
+
* haven't seen a client message in a configurable window.
|
|
10
|
+
*
|
|
11
|
+
* What: arm a timer per connection, reset on every inbound message; on
|
|
12
|
+
* expiry, close the WS with a close code ≥ 4000 so the AUP client suppresses
|
|
13
|
+
* its auto-reconnect loop (see `web-page/core.ts` — code ≥ 4000 means
|
|
14
|
+
* "server rejected, do not reconnect"). The user reconnects on next
|
|
15
|
+
* interaction; the existing `sessionId`-based handshake restores per-session
|
|
16
|
+
* state.
|
|
17
|
+
*
|
|
18
|
+
* On Cloudflare, once all WebSockets close, the DO is auto-evicted by the
|
|
19
|
+
* Workers runtime and duration billing stops. On Node, the WS object is GC'd
|
|
20
|
+
* and the file descriptor returned to the OS.
|
|
21
|
+
*/
|
|
22
|
+
/** Close code used for intentional idle close (must be ≥ 4000). */
|
|
23
|
+
const IDLE_CLOSE_CODE = 4001;
|
|
24
|
+
/** Short ASCII reason — CF caps reason at 123 bytes. */
|
|
25
|
+
const IDLE_CLOSE_REASON = "idle-timeout";
|
|
26
|
+
/** Lower bound — under 1s is almost certainly a misconfiguration. */
|
|
27
|
+
const MIN_TIMEOUT_MS = 1e3;
|
|
28
|
+
/** Upper bound — keep one connection alive at most 24h on a single client. */
|
|
29
|
+
const MAX_TIMEOUT_MS = 1440 * 6e4;
|
|
30
|
+
function createIdleTimer(opts) {
|
|
31
|
+
const { timeoutMs, onIdle } = opts;
|
|
32
|
+
const setT = opts.setTimeout ?? globalThis.setTimeout;
|
|
33
|
+
const clearT = opts.clearTimeout ?? globalThis.clearTimeout;
|
|
34
|
+
if (timeoutMs <= 0) return {
|
|
35
|
+
rearm() {},
|
|
36
|
+
cancel() {}
|
|
37
|
+
};
|
|
38
|
+
let handle = null;
|
|
39
|
+
const fire = () => {
|
|
40
|
+
handle = null;
|
|
41
|
+
try {
|
|
42
|
+
onIdle();
|
|
43
|
+
} catch {}
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
rearm() {
|
|
47
|
+
if (handle !== null) clearT(handle);
|
|
48
|
+
handle = setT(fire, timeoutMs);
|
|
49
|
+
},
|
|
50
|
+
cancel() {
|
|
51
|
+
if (handle !== null) {
|
|
52
|
+
clearT(handle);
|
|
53
|
+
handle = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Best-effort `{ type: string }` sniff of an inbound WS message event, used
|
|
60
|
+
* only to decide whether it should rearm the idle timer. Any parse failure
|
|
61
|
+
* (binary frame, non-JSON text, missing `.data`) is treated as "not a
|
|
62
|
+
* recognized synthetic type" — i.e. it still counts as real activity. This
|
|
63
|
+
* keeps `ignoreMessageTypes` strictly opt-in and never silently swallows a
|
|
64
|
+
* message the caller didn't ask to ignore.
|
|
65
|
+
*/
|
|
66
|
+
function messageTypeOf(event) {
|
|
67
|
+
try {
|
|
68
|
+
const data = event?.data;
|
|
69
|
+
if (typeof data !== "string") return void 0;
|
|
70
|
+
const parsed = JSON.parse(data);
|
|
71
|
+
return typeof parsed?.type === "string" ? parsed.type : void 0;
|
|
72
|
+
} catch {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Wire an idle timer to a WebSocket-like object: arm immediately, rearm on
|
|
78
|
+
* every inbound message, cancel on close/error. On expiry, close the socket
|
|
79
|
+
* with `IDLE_CLOSE_CODE` and `IDLE_CLOSE_REASON`.
|
|
80
|
+
*
|
|
81
|
+
* Returns the timer so callers can `cancel()` it during external teardown.
|
|
82
|
+
*/
|
|
83
|
+
function attachIdleClose(server, timeoutMs, options) {
|
|
84
|
+
const timer = createIdleTimer({
|
|
85
|
+
timeoutMs,
|
|
86
|
+
onIdle: () => {
|
|
87
|
+
try {
|
|
88
|
+
if (server.readyState === 1) server.close(IDLE_CLOSE_CODE, IDLE_CLOSE_REASON);
|
|
89
|
+
} catch {}
|
|
90
|
+
},
|
|
91
|
+
setTimeout: options?.setTimeout,
|
|
92
|
+
clearTimeout: options?.clearTimeout
|
|
93
|
+
});
|
|
94
|
+
timer.rearm();
|
|
95
|
+
const ignoreTypes = options?.ignoreMessageTypes;
|
|
96
|
+
server.addEventListener("message", (event) => {
|
|
97
|
+
if (ignoreTypes?.length) {
|
|
98
|
+
const type = messageTypeOf(event);
|
|
99
|
+
if (type !== void 0 && ignoreTypes.includes(type)) return;
|
|
100
|
+
}
|
|
101
|
+
timer.rearm();
|
|
102
|
+
});
|
|
103
|
+
server.addEventListener("close", () => timer.cancel());
|
|
104
|
+
server.addEventListener("error", () => timer.cancel());
|
|
105
|
+
if (options?.rearmOnOutbound && server.send) {
|
|
106
|
+
const orig = server.send.bind(server);
|
|
107
|
+
server.send = (data) => {
|
|
108
|
+
timer.rearm();
|
|
109
|
+
orig(data);
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return timer;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse an env-supplied idle timeout. Accepts undefined / empty / non-numeric
|
|
116
|
+
* (returns `defaultMs`), `0` (returns `0` — disabled), and clamps to
|
|
117
|
+
* [MIN_TIMEOUT_MS, MAX_TIMEOUT_MS] for any positive value.
|
|
118
|
+
*/
|
|
119
|
+
function resolveIdleTimeoutMs(value, defaultMs) {
|
|
120
|
+
if (value === void 0 || value === "") return defaultMs;
|
|
121
|
+
if (!/^-?\d+$/.test(value.trim())) return defaultMs;
|
|
122
|
+
const n = Number.parseInt(value, 10);
|
|
123
|
+
if (Number.isNaN(n)) return defaultMs;
|
|
124
|
+
if (n <= 0) return 0;
|
|
125
|
+
if (n < MIN_TIMEOUT_MS) return MIN_TIMEOUT_MS;
|
|
126
|
+
if (n > MAX_TIMEOUT_MS) return MAX_TIMEOUT_MS;
|
|
127
|
+
return n;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
export { IDLE_CLOSE_CODE, IDLE_CLOSE_REASON, attachIdleClose, createIdleTimer, resolveIdleTimeoutMs };
|
|
132
|
+
//# sourceMappingURL=idle-timer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle-timer.mjs","names":[],"sources":["../../src/transport/idle-timer.ts"],"sourcesContent":["/**\n * Per-WebSocket idle timer — runtime-neutral.\n *\n * Why: long-lived WebSockets that sit idle still consume runtime resources.\n * On Cloudflare Durable Objects this is direct billing (`server.accept()`\n * keeps the DO active for the full WS lifetime); on Node it's memory and\n * file descriptors. Both runtimes benefit from closing WebSockets that\n * haven't seen a client message in a configurable window.\n *\n * What: arm a timer per connection, reset on every inbound message; on\n * expiry, close the WS with a close code ≥ 4000 so the AUP client suppresses\n * its auto-reconnect loop (see `web-page/core.ts` — code ≥ 4000 means\n * \"server rejected, do not reconnect\"). The user reconnects on next\n * interaction; the existing `sessionId`-based handshake restores per-session\n * state.\n *\n * On Cloudflare, once all WebSockets close, the DO is auto-evicted by the\n * Workers runtime and duration billing stops. On Node, the WS object is GC'd\n * and the file descriptor returned to the OS.\n */\n\n/** Close code used for intentional idle close (must be ≥ 4000). */\nexport const IDLE_CLOSE_CODE = 4001;\n\n/** Short ASCII reason — CF caps reason at 123 bytes. */\nexport const IDLE_CLOSE_REASON = \"idle-timeout\";\n\n/** Lower bound — under 1s is almost certainly a misconfiguration. */\nconst MIN_TIMEOUT_MS = 1_000;\n/** Upper bound — keep one connection alive at most 24h on a single client. */\nconst MAX_TIMEOUT_MS = 24 * 60 * 60_000;\n\nexport interface IdleTimerOptions {\n /** Idle window in ms. `0` disables the timer (useful for tests / opt-out). */\n timeoutMs: number;\n /** Invoked when the idle window elapses without a `rearm()`. */\n onIdle: () => void;\n /** Test seam — defaults to `globalThis.setTimeout`. */\n setTimeout?: typeof setTimeout;\n /** Test seam — defaults to `globalThis.clearTimeout`. */\n clearTimeout?: typeof clearTimeout;\n}\n\nexport interface IdleTimer {\n /** Reset (or start) the idle countdown. Safe to call repeatedly. */\n rearm(): void;\n /** Stop the timer. After cancel, `rearm()` resumes it. */\n cancel(): void;\n}\n\nexport function createIdleTimer(opts: IdleTimerOptions): IdleTimer {\n const { timeoutMs, onIdle } = opts;\n const setT = opts.setTimeout ?? globalThis.setTimeout;\n const clearT = opts.clearTimeout ?? globalThis.clearTimeout;\n\n if (timeoutMs <= 0) {\n return { rearm() {}, cancel() {} };\n }\n\n let handle: ReturnType<typeof setTimeout> | null = null;\n\n const fire = () => {\n handle = null;\n try {\n onIdle();\n } catch {\n // Swallow — a misbehaving callback must never take down the runtime.\n }\n };\n\n return {\n rearm() {\n if (handle !== null) clearT(handle);\n handle = setT(fire, timeoutMs);\n },\n cancel() {\n if (handle !== null) {\n clearT(handle);\n handle = null;\n }\n },\n };\n}\n\n/**\n * Minimal WebSocket surface used by `attachIdleClose`. Both the CF Workers\n * `WebSocket` and the Node `ws` library satisfy this shape.\n */\nexport interface IdleCloseTarget {\n readyState: number;\n close(code?: number, reason?: string): void;\n send?: (data: any) => void;\n addEventListener(type: \"message\" | \"close\" | \"error\", listener: (event: unknown) => void): void;\n}\n\n/**\n * Best-effort `{ type: string }` sniff of an inbound WS message event, used\n * only to decide whether it should rearm the idle timer. Any parse failure\n * (binary frame, non-JSON text, missing `.data`) is treated as \"not a\n * recognized synthetic type\" — i.e. it still counts as real activity. This\n * keeps `ignoreMessageTypes` strictly opt-in and never silently swallows a\n * message the caller didn't ask to ignore.\n */\nfunction messageTypeOf(event: unknown): string | undefined {\n try {\n const data = (event as { data?: unknown })?.data;\n if (typeof data !== \"string\") return undefined;\n const parsed = JSON.parse(data);\n return typeof parsed?.type === \"string\" ? parsed.type : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Wire an idle timer to a WebSocket-like object: arm immediately, rearm on\n * every inbound message, cancel on close/error. On expiry, close the socket\n * with `IDLE_CLOSE_CODE` and `IDLE_CLOSE_REASON`.\n *\n * Returns the timer so callers can `cancel()` it during external teardown.\n */\nexport function attachIdleClose(\n server: IdleCloseTarget,\n timeoutMs: number,\n options?: {\n /**\n * When true, wraps `server.send` so that every outbound server push also\n * rearms the idle timer. Without this, a session receiving only passive\n * live-update pushes (no client→server traffic) is considered \"idle\" and\n * closed after `timeoutMs` even though it has ongoing server activity.\n */\n rearmOnOutbound?: boolean;\n /**\n * Inbound message `type` values that must NOT rearm the idle timer.\n * Exists for synthetic client keepalive frames (e.g. the AUP web client's\n * `{type:\"ping\"}`, sent purely to defeat CF-edge / mobile-NAT idle-drop\n * of an otherwise-unused connection — see WS_KEEPALIVE_MESSAGE_TYPE in\n * `@aigne/afs-ui`). Without this, a keepalive ping would itself count as\n * \"activity\" and the idle-close timer — whose entire purpose is evicting\n * genuinely-unused connections to stop Durable Object duration billing —\n * would never fire for as long as the tab merely sits open (arc#1243).\n * Messages that fail to parse as `{type: string}` JSON are never treated\n * as ignorable, so this can only narrow rearm triggers, never widen them.\n */\n ignoreMessageTypes?: string[];\n setTimeout?: typeof setTimeout;\n clearTimeout?: typeof clearTimeout;\n },\n): IdleTimer {\n const timer = createIdleTimer({\n timeoutMs,\n onIdle: () => {\n try {\n // Compare the numeric value directly (CF / browser / `ws` all agree\n // on `OPEN === 1`). Avoiding `WebSocket.READY_STATE_OPEN` makes the\n // helper trivially mockable and keeps the file runtime-neutral.\n if (server.readyState === 1) {\n server.close(IDLE_CLOSE_CODE, IDLE_CLOSE_REASON);\n }\n } catch {\n // Closing a closing socket throws on some runtimes — ignore.\n }\n },\n setTimeout: options?.setTimeout,\n clearTimeout: options?.clearTimeout,\n });\n timer.rearm();\n const ignoreTypes = options?.ignoreMessageTypes;\n server.addEventListener(\"message\", (event) => {\n if (ignoreTypes?.length) {\n const type = messageTypeOf(event);\n if (type !== undefined && ignoreTypes.includes(type)) return;\n }\n timer.rearm();\n });\n server.addEventListener(\"close\", () => timer.cancel());\n server.addEventListener(\"error\", () => timer.cancel());\n if (options?.rearmOnOutbound && server.send) {\n const orig = server.send.bind(server);\n server.send = (data: any) => {\n timer.rearm();\n orig(data);\n };\n }\n return timer;\n}\n\n/**\n * Parse an env-supplied idle timeout. Accepts undefined / empty / non-numeric\n * (returns `defaultMs`), `0` (returns `0` — disabled), and clamps to\n * [MIN_TIMEOUT_MS, MAX_TIMEOUT_MS] for any positive value.\n */\nexport function resolveIdleTimeoutMs(value: string | undefined, defaultMs: number): number {\n if (value === undefined || value === \"\") return defaultMs;\n if (!/^-?\\d+$/.test(value.trim())) return defaultMs;\n const n = Number.parseInt(value, 10);\n if (Number.isNaN(n)) return defaultMs;\n if (n <= 0) return 0;\n if (n < MIN_TIMEOUT_MS) return MIN_TIMEOUT_MS;\n if (n > MAX_TIMEOUT_MS) return MAX_TIMEOUT_MS;\n return n;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,kBAAkB;;AAG/B,MAAa,oBAAoB;;AAGjC,MAAM,iBAAiB;;AAEvB,MAAM,iBAAiB,OAAU;AAoBjC,SAAgB,gBAAgB,MAAmC;CACjE,MAAM,EAAE,WAAW,WAAW;CAC9B,MAAM,OAAO,KAAK,cAAc,WAAW;CAC3C,MAAM,SAAS,KAAK,gBAAgB,WAAW;AAE/C,KAAI,aAAa,EACf,QAAO;EAAE,QAAQ;EAAI,SAAS;EAAI;CAGpC,IAAI,SAA+C;CAEnD,MAAM,aAAa;AACjB,WAAS;AACT,MAAI;AACF,WAAQ;UACF;;AAKV,QAAO;EACL,QAAQ;AACN,OAAI,WAAW,KAAM,QAAO,OAAO;AACnC,YAAS,KAAK,MAAM,UAAU;;EAEhC,SAAS;AACP,OAAI,WAAW,MAAM;AACnB,WAAO,OAAO;AACd,aAAS;;;EAGd;;;;;;;;;;AAsBH,SAAS,cAAc,OAAoC;AACzD,KAAI;EACF,MAAM,OAAQ,OAA8B;AAC5C,MAAI,OAAO,SAAS,SAAU,QAAO;EACrC,MAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,OAAO,QAAQ,SAAS,WAAW,OAAO,OAAO;SAClD;AACN;;;;;;;;;;AAWJ,SAAgB,gBACd,QACA,WACA,SAwBW;CACX,MAAM,QAAQ,gBAAgB;EAC5B;EACA,cAAc;AACZ,OAAI;AAIF,QAAI,OAAO,eAAe,EACxB,QAAO,MAAM,iBAAiB,kBAAkB;WAE5C;;EAIV,YAAY,SAAS;EACrB,cAAc,SAAS;EACxB,CAAC;AACF,OAAM,OAAO;CACb,MAAM,cAAc,SAAS;AAC7B,QAAO,iBAAiB,YAAY,UAAU;AAC5C,MAAI,aAAa,QAAQ;GACvB,MAAM,OAAO,cAAc,MAAM;AACjC,OAAI,SAAS,UAAa,YAAY,SAAS,KAAK,CAAE;;AAExD,QAAM,OAAO;GACb;AACF,QAAO,iBAAiB,eAAe,MAAM,QAAQ,CAAC;AACtD,QAAO,iBAAiB,eAAe,MAAM,QAAQ,CAAC;AACtD,KAAI,SAAS,mBAAmB,OAAO,MAAM;EAC3C,MAAM,OAAO,OAAO,KAAK,KAAK,OAAO;AACrC,SAAO,QAAQ,SAAc;AAC3B,SAAM,OAAO;AACb,QAAK,KAAK;;;AAGd,QAAO;;;;;;;AAQT,SAAgB,qBAAqB,OAA2B,WAA2B;AACzF,KAAI,UAAU,UAAa,UAAU,GAAI,QAAO;AAChD,KAAI,CAAC,UAAU,KAAK,MAAM,MAAM,CAAC,CAAE,QAAO;CAC1C,MAAM,IAAI,OAAO,SAAS,OAAO,GAAG;AACpC,KAAI,OAAO,MAAM,EAAE,CAAE,QAAO;AAC5B,KAAI,KAAK,EAAG,QAAO;AACnB,KAAI,IAAI,eAAgB,QAAO;AAC/B,KAAI,IAAI,eAAgB,QAAO;AAC/B,QAAO"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const require_dsl_shared = require('./dsl-shared.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/web-component-dsl.ts
|
|
4
|
+
var WebComponentDslCompileError = class extends Error {
|
|
5
|
+
constructor(message, line, column = 1) {
|
|
6
|
+
super(`${line}:${column} ${message}`);
|
|
7
|
+
this.line = line;
|
|
8
|
+
this.column = column;
|
|
9
|
+
this.name = "WebComponentDslCompileError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function compileWebComponentDsl(source) {
|
|
13
|
+
const component = require_dsl_shared.parseDeclaration(source, {
|
|
14
|
+
kind: "component",
|
|
15
|
+
allowQuotedId: true,
|
|
16
|
+
allowShorthandString: true,
|
|
17
|
+
expected: "Expected component \"<name>\" {",
|
|
18
|
+
fieldContinuationPreceders: ["default", "description"],
|
|
19
|
+
fieldKeywords: [
|
|
20
|
+
"description",
|
|
21
|
+
"seo",
|
|
22
|
+
"script",
|
|
23
|
+
"prop"
|
|
24
|
+
],
|
|
25
|
+
error: parseError
|
|
26
|
+
});
|
|
27
|
+
const manifest = {
|
|
28
|
+
name: component.id,
|
|
29
|
+
props: {}
|
|
30
|
+
};
|
|
31
|
+
if (component.shorthand) {
|
|
32
|
+
manifest.description = require_dsl_shared.parseDslStringToken(component.shorthand, parseError);
|
|
33
|
+
manifest.seoStrategy = "full";
|
|
34
|
+
return { manifest };
|
|
35
|
+
}
|
|
36
|
+
for (const field of component.fields) {
|
|
37
|
+
if (field.name.value === "description") {
|
|
38
|
+
manifest.description = expectSingleString(field, "Expected description \"<text>\"");
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (field.name.value === "seo") {
|
|
42
|
+
const value = expectSingleWord(field, "Expected seo full|partial|none");
|
|
43
|
+
if (![
|
|
44
|
+
"full",
|
|
45
|
+
"partial",
|
|
46
|
+
"none"
|
|
47
|
+
].includes(value.value)) throw new WebComponentDslCompileError("Expected seo full|partial|none", value.token.line, value.token.column);
|
|
48
|
+
manifest.seoStrategy = value.value;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (field.name.value === "script") {
|
|
52
|
+
manifest.hasScript = parseScriptField(field);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (field.name.value === "prop") {
|
|
56
|
+
const parsed = parseProp(field);
|
|
57
|
+
manifest.props[parsed.name] = parsed.prop;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { manifest };
|
|
61
|
+
}
|
|
62
|
+
function formatWebComponentDsl(source) {
|
|
63
|
+
const { manifest } = compileWebComponentDsl(source);
|
|
64
|
+
if (manifest.description && manifest.seoStrategy === "full" && manifest.hasScript === void 0 && Object.keys(manifest.props).length === 0) return `component ${formatName(manifest.name)} ${JSON.stringify(manifest.description)}\n`;
|
|
65
|
+
const lines = [`component ${formatName(manifest.name)} {`];
|
|
66
|
+
if (manifest.description) lines.push(` description ${JSON.stringify(manifest.description)}`);
|
|
67
|
+
if (manifest.seoStrategy) lines.push(` seo ${manifest.seoStrategy}`);
|
|
68
|
+
if (manifest.hasScript !== void 0) lines.push(manifest.hasScript ? " script" : " script false");
|
|
69
|
+
for (const [name, prop] of Object.entries(manifest.props)) {
|
|
70
|
+
const parts = [` prop ${name}`];
|
|
71
|
+
if (prop.type) parts.push(prop.type);
|
|
72
|
+
if (prop.default !== void 0) parts.push("default", JSON.stringify(prop.default));
|
|
73
|
+
if (prop.required) parts.push("required");
|
|
74
|
+
if (prop.description) parts.push("description", JSON.stringify(prop.description));
|
|
75
|
+
lines.push(parts.join(" "));
|
|
76
|
+
}
|
|
77
|
+
lines.push("}");
|
|
78
|
+
return `${lines.join("\n")}\n`;
|
|
79
|
+
}
|
|
80
|
+
function parseProp(field) {
|
|
81
|
+
const name = field.values[0];
|
|
82
|
+
if (name?.type !== "word") throw new WebComponentDslCompileError("Expected prop <name> <type>", name?.line ?? field.name.line, name?.column ?? field.name.column);
|
|
83
|
+
let index = 1;
|
|
84
|
+
const prop = {};
|
|
85
|
+
const type = field.values[index];
|
|
86
|
+
if (type?.type === "word" && ![
|
|
87
|
+
"default",
|
|
88
|
+
"description",
|
|
89
|
+
"required"
|
|
90
|
+
].includes(type.value)) {
|
|
91
|
+
prop.type = type.value;
|
|
92
|
+
index += 1;
|
|
93
|
+
}
|
|
94
|
+
while (index < field.values.length) {
|
|
95
|
+
const token = field.values[index];
|
|
96
|
+
if (!token) break;
|
|
97
|
+
if (token.type !== "word") throw new WebComponentDslCompileError("Expected prop option", token.line, token.column);
|
|
98
|
+
if (token.value === "default") {
|
|
99
|
+
const value = field.values[index + 1];
|
|
100
|
+
if (!value) throw new WebComponentDslCompileError("Expected default <value>", token.line, token.column);
|
|
101
|
+
prop.default = require_dsl_shared.parseDslScalarToken(value, parseError);
|
|
102
|
+
index += 2;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (token.value === "description") {
|
|
106
|
+
const value = field.values[index + 1];
|
|
107
|
+
if (!value) throw new WebComponentDslCompileError("Expected description \"<text>\"", token.line, token.column);
|
|
108
|
+
prop.description = require_dsl_shared.parseDslStringToken(value, parseError);
|
|
109
|
+
index += 2;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (token.value === "required") {
|
|
113
|
+
prop.required = true;
|
|
114
|
+
index += 1;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
throw new WebComponentDslCompileError(`Unknown prop option: ${token.value}`, token.line, token.column);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
name: name.value,
|
|
121
|
+
prop
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function parseScriptField(field) {
|
|
125
|
+
if (field.values.length === 0) return true;
|
|
126
|
+
const value = field.values[0];
|
|
127
|
+
if (field.values.length === 1 && value?.type === "word" && ["true", "false"].includes(value.value)) return value.value === "true";
|
|
128
|
+
throw new WebComponentDslCompileError("Expected script [true|false]", value?.line ?? field.name.line, value?.column ?? field.name.column);
|
|
129
|
+
}
|
|
130
|
+
function expectSingleString(field, message) {
|
|
131
|
+
const token = field.values[0];
|
|
132
|
+
if (field.values.length !== 1 || token?.type !== "string") throw new WebComponentDslCompileError(message, token?.line ?? field.name.line, token?.column ?? field.name.column);
|
|
133
|
+
return require_dsl_shared.parseDslStringToken(token, parseError);
|
|
134
|
+
}
|
|
135
|
+
function expectSingleWord(field, message) {
|
|
136
|
+
const token = field.values[0];
|
|
137
|
+
if (field.values.length !== 1 || token?.type !== "word") throw new WebComponentDslCompileError(message, token?.line ?? field.name.line, token?.column ?? field.name.column);
|
|
138
|
+
return {
|
|
139
|
+
value: token.value,
|
|
140
|
+
token
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function parseError(message, line, column = 1) {
|
|
144
|
+
return new WebComponentDslCompileError(message, line, column);
|
|
145
|
+
}
|
|
146
|
+
function formatName(name) {
|
|
147
|
+
return /^[A-Za-z0-9_-]+$/.test(name) ? name : JSON.stringify(name);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
//#endregion
|
|
151
|
+
exports.WebComponentDslCompileError = WebComponentDslCompileError;
|
|
152
|
+
exports.compileWebComponentDsl = compileWebComponentDsl;
|
|
153
|
+
exports.formatWebComponentDsl = formatWebComponentDsl;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/web-component-dsl.d.ts
|
|
2
|
+
interface WebComponentDslCompileResult {
|
|
3
|
+
manifest: WebComponentManifest;
|
|
4
|
+
}
|
|
5
|
+
interface WebComponentManifest {
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
seoStrategy?: "full" | "partial" | "none";
|
|
9
|
+
hasScript?: boolean;
|
|
10
|
+
props: Record<string, WebComponentPropManifest>;
|
|
11
|
+
}
|
|
12
|
+
interface WebComponentPropManifest {
|
|
13
|
+
type?: string;
|
|
14
|
+
default?: unknown;
|
|
15
|
+
description?: string;
|
|
16
|
+
required?: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare class WebComponentDslCompileError extends Error {
|
|
19
|
+
readonly line: number;
|
|
20
|
+
readonly column: number;
|
|
21
|
+
constructor(message: string, line: number, column?: number);
|
|
22
|
+
}
|
|
23
|
+
declare function compileWebComponentDsl(source: string): WebComponentDslCompileResult;
|
|
24
|
+
declare function formatWebComponentDsl(source: string): string;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { WebComponentDslCompileError, WebComponentDslCompileResult, WebComponentManifest, WebComponentPropManifest, compileWebComponentDsl, formatWebComponentDsl };
|
|
27
|
+
//# sourceMappingURL=web-component-dsl.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-component-dsl.d.cts","names":[],"sources":["../src/web-component-dsl.ts"],"mappings":";UAQiB,4BAAA;EACf,QAAA,EAAU,oBAAA;AAAA;AAAA,UAGK,oBAAA;EACf,IAAA;EACA,WAAA;EACA,WAAA;EACA,SAAA;EACA,KAAA,EAAO,MAAA,SAAe,wBAAA;AAAA;AAAA,UAGP,wBAAA;EACf,IAAA;EACA,OAAA;EACA,WAAA;EACA,QAAA;AAAA;AAAA,cAGW,2BAAA,SAAoC,KAAA;EAAA,SAGpC,IAAA;EAAA,SACA,MAAA;cAFT,OAAA,UACS,IAAA,UACA,MAAA;AAAA;AAAA,iBAOG,sBAAA,CAAuB,MAAA,WAAiB,4BAAA;AAAA,iBAuDxC,qBAAA,CAAsB,MAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/web-component-dsl.d.ts
|
|
2
|
+
interface WebComponentDslCompileResult {
|
|
3
|
+
manifest: WebComponentManifest;
|
|
4
|
+
}
|
|
5
|
+
interface WebComponentManifest {
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
seoStrategy?: "full" | "partial" | "none";
|
|
9
|
+
hasScript?: boolean;
|
|
10
|
+
props: Record<string, WebComponentPropManifest>;
|
|
11
|
+
}
|
|
12
|
+
interface WebComponentPropManifest {
|
|
13
|
+
type?: string;
|
|
14
|
+
default?: unknown;
|
|
15
|
+
description?: string;
|
|
16
|
+
required?: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare class WebComponentDslCompileError extends Error {
|
|
19
|
+
readonly line: number;
|
|
20
|
+
readonly column: number;
|
|
21
|
+
constructor(message: string, line: number, column?: number);
|
|
22
|
+
}
|
|
23
|
+
declare function compileWebComponentDsl(source: string): WebComponentDslCompileResult;
|
|
24
|
+
declare function formatWebComponentDsl(source: string): string;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { WebComponentDslCompileError, WebComponentDslCompileResult, WebComponentManifest, WebComponentPropManifest, compileWebComponentDsl, formatWebComponentDsl };
|
|
27
|
+
//# sourceMappingURL=web-component-dsl.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-component-dsl.d.mts","names":[],"sources":["../src/web-component-dsl.ts"],"mappings":";UAQiB,4BAAA;EACf,QAAA,EAAU,oBAAA;AAAA;AAAA,UAGK,oBAAA;EACf,IAAA;EACA,WAAA;EACA,WAAA;EACA,SAAA;EACA,KAAA,EAAO,MAAA,SAAe,wBAAA;AAAA;AAAA,UAGP,wBAAA;EACf,IAAA;EACA,OAAA;EACA,WAAA;EACA,QAAA;AAAA;AAAA,cAGW,2BAAA,SAAoC,KAAA;EAAA,SAGpC,IAAA;EAAA,SACA,MAAA;cAFT,OAAA,UACS,IAAA,UACA,MAAA;AAAA;AAAA,iBAOG,sBAAA,CAAuB,MAAA,WAAiB,4BAAA;AAAA,iBAuDxC,qBAAA,CAAsB,MAAA"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { parseDeclaration, parseDslScalarToken, parseDslStringToken } from "./dsl-shared.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/web-component-dsl.ts
|
|
4
|
+
var WebComponentDslCompileError = class extends Error {
|
|
5
|
+
constructor(message, line, column = 1) {
|
|
6
|
+
super(`${line}:${column} ${message}`);
|
|
7
|
+
this.line = line;
|
|
8
|
+
this.column = column;
|
|
9
|
+
this.name = "WebComponentDslCompileError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function compileWebComponentDsl(source) {
|
|
13
|
+
const component = parseDeclaration(source, {
|
|
14
|
+
kind: "component",
|
|
15
|
+
allowQuotedId: true,
|
|
16
|
+
allowShorthandString: true,
|
|
17
|
+
expected: "Expected component \"<name>\" {",
|
|
18
|
+
fieldContinuationPreceders: ["default", "description"],
|
|
19
|
+
fieldKeywords: [
|
|
20
|
+
"description",
|
|
21
|
+
"seo",
|
|
22
|
+
"script",
|
|
23
|
+
"prop"
|
|
24
|
+
],
|
|
25
|
+
error: parseError
|
|
26
|
+
});
|
|
27
|
+
const manifest = {
|
|
28
|
+
name: component.id,
|
|
29
|
+
props: {}
|
|
30
|
+
};
|
|
31
|
+
if (component.shorthand) {
|
|
32
|
+
manifest.description = parseDslStringToken(component.shorthand, parseError);
|
|
33
|
+
manifest.seoStrategy = "full";
|
|
34
|
+
return { manifest };
|
|
35
|
+
}
|
|
36
|
+
for (const field of component.fields) {
|
|
37
|
+
if (field.name.value === "description") {
|
|
38
|
+
manifest.description = expectSingleString(field, "Expected description \"<text>\"");
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (field.name.value === "seo") {
|
|
42
|
+
const value = expectSingleWord(field, "Expected seo full|partial|none");
|
|
43
|
+
if (![
|
|
44
|
+
"full",
|
|
45
|
+
"partial",
|
|
46
|
+
"none"
|
|
47
|
+
].includes(value.value)) throw new WebComponentDslCompileError("Expected seo full|partial|none", value.token.line, value.token.column);
|
|
48
|
+
manifest.seoStrategy = value.value;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (field.name.value === "script") {
|
|
52
|
+
manifest.hasScript = parseScriptField(field);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (field.name.value === "prop") {
|
|
56
|
+
const parsed = parseProp(field);
|
|
57
|
+
manifest.props[parsed.name] = parsed.prop;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { manifest };
|
|
61
|
+
}
|
|
62
|
+
function formatWebComponentDsl(source) {
|
|
63
|
+
const { manifest } = compileWebComponentDsl(source);
|
|
64
|
+
if (manifest.description && manifest.seoStrategy === "full" && manifest.hasScript === void 0 && Object.keys(manifest.props).length === 0) return `component ${formatName(manifest.name)} ${JSON.stringify(manifest.description)}\n`;
|
|
65
|
+
const lines = [`component ${formatName(manifest.name)} {`];
|
|
66
|
+
if (manifest.description) lines.push(` description ${JSON.stringify(manifest.description)}`);
|
|
67
|
+
if (manifest.seoStrategy) lines.push(` seo ${manifest.seoStrategy}`);
|
|
68
|
+
if (manifest.hasScript !== void 0) lines.push(manifest.hasScript ? " script" : " script false");
|
|
69
|
+
for (const [name, prop] of Object.entries(manifest.props)) {
|
|
70
|
+
const parts = [` prop ${name}`];
|
|
71
|
+
if (prop.type) parts.push(prop.type);
|
|
72
|
+
if (prop.default !== void 0) parts.push("default", JSON.stringify(prop.default));
|
|
73
|
+
if (prop.required) parts.push("required");
|
|
74
|
+
if (prop.description) parts.push("description", JSON.stringify(prop.description));
|
|
75
|
+
lines.push(parts.join(" "));
|
|
76
|
+
}
|
|
77
|
+
lines.push("}");
|
|
78
|
+
return `${lines.join("\n")}\n`;
|
|
79
|
+
}
|
|
80
|
+
function parseProp(field) {
|
|
81
|
+
const name = field.values[0];
|
|
82
|
+
if (name?.type !== "word") throw new WebComponentDslCompileError("Expected prop <name> <type>", name?.line ?? field.name.line, name?.column ?? field.name.column);
|
|
83
|
+
let index = 1;
|
|
84
|
+
const prop = {};
|
|
85
|
+
const type = field.values[index];
|
|
86
|
+
if (type?.type === "word" && ![
|
|
87
|
+
"default",
|
|
88
|
+
"description",
|
|
89
|
+
"required"
|
|
90
|
+
].includes(type.value)) {
|
|
91
|
+
prop.type = type.value;
|
|
92
|
+
index += 1;
|
|
93
|
+
}
|
|
94
|
+
while (index < field.values.length) {
|
|
95
|
+
const token = field.values[index];
|
|
96
|
+
if (!token) break;
|
|
97
|
+
if (token.type !== "word") throw new WebComponentDslCompileError("Expected prop option", token.line, token.column);
|
|
98
|
+
if (token.value === "default") {
|
|
99
|
+
const value = field.values[index + 1];
|
|
100
|
+
if (!value) throw new WebComponentDslCompileError("Expected default <value>", token.line, token.column);
|
|
101
|
+
prop.default = parseDslScalarToken(value, parseError);
|
|
102
|
+
index += 2;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (token.value === "description") {
|
|
106
|
+
const value = field.values[index + 1];
|
|
107
|
+
if (!value) throw new WebComponentDslCompileError("Expected description \"<text>\"", token.line, token.column);
|
|
108
|
+
prop.description = parseDslStringToken(value, parseError);
|
|
109
|
+
index += 2;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (token.value === "required") {
|
|
113
|
+
prop.required = true;
|
|
114
|
+
index += 1;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
throw new WebComponentDslCompileError(`Unknown prop option: ${token.value}`, token.line, token.column);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
name: name.value,
|
|
121
|
+
prop
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function parseScriptField(field) {
|
|
125
|
+
if (field.values.length === 0) return true;
|
|
126
|
+
const value = field.values[0];
|
|
127
|
+
if (field.values.length === 1 && value?.type === "word" && ["true", "false"].includes(value.value)) return value.value === "true";
|
|
128
|
+
throw new WebComponentDslCompileError("Expected script [true|false]", value?.line ?? field.name.line, value?.column ?? field.name.column);
|
|
129
|
+
}
|
|
130
|
+
function expectSingleString(field, message) {
|
|
131
|
+
const token = field.values[0];
|
|
132
|
+
if (field.values.length !== 1 || token?.type !== "string") throw new WebComponentDslCompileError(message, token?.line ?? field.name.line, token?.column ?? field.name.column);
|
|
133
|
+
return parseDslStringToken(token, parseError);
|
|
134
|
+
}
|
|
135
|
+
function expectSingleWord(field, message) {
|
|
136
|
+
const token = field.values[0];
|
|
137
|
+
if (field.values.length !== 1 || token?.type !== "word") throw new WebComponentDslCompileError(message, token?.line ?? field.name.line, token?.column ?? field.name.column);
|
|
138
|
+
return {
|
|
139
|
+
value: token.value,
|
|
140
|
+
token
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function parseError(message, line, column = 1) {
|
|
144
|
+
return new WebComponentDslCompileError(message, line, column);
|
|
145
|
+
}
|
|
146
|
+
function formatName(name) {
|
|
147
|
+
return /^[A-Za-z0-9_-]+$/.test(name) ? name : JSON.stringify(name);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
//#endregion
|
|
151
|
+
export { WebComponentDslCompileError, compileWebComponentDsl, formatWebComponentDsl };
|
|
152
|
+
//# sourceMappingURL=web-component-dsl.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-component-dsl.mjs","names":[],"sources":["../src/web-component-dsl.ts"],"sourcesContent":["import {\n type DslField,\n type DslToken,\n parseDeclaration,\n parseDslScalarToken,\n parseDslStringToken,\n} from \"./dsl-shared.js\";\n\nexport interface WebComponentDslCompileResult {\n manifest: WebComponentManifest;\n}\n\nexport interface WebComponentManifest {\n name: string;\n description?: string;\n seoStrategy?: \"full\" | \"partial\" | \"none\";\n hasScript?: boolean;\n props: Record<string, WebComponentPropManifest>;\n}\n\nexport interface WebComponentPropManifest {\n type?: string;\n default?: unknown;\n description?: string;\n required?: boolean;\n}\n\nexport class WebComponentDslCompileError extends Error {\n constructor(\n message: string,\n readonly line: number,\n readonly column = 1,\n ) {\n super(`${line}:${column} ${message}`);\n this.name = \"WebComponentDslCompileError\";\n }\n}\n\nexport function compileWebComponentDsl(source: string): WebComponentDslCompileResult {\n const component = parseDeclaration(source, {\n kind: \"component\",\n allowQuotedId: true,\n allowShorthandString: true,\n expected: 'Expected component \"<name>\" {',\n fieldContinuationPreceders: [\"default\", \"description\"],\n fieldKeywords: [\"description\", \"seo\", \"script\", \"prop\"],\n error: parseError,\n });\n\n const manifest: WebComponentManifest = {\n name: component.id,\n props: {},\n };\n\n if (component.shorthand) {\n manifest.description = parseDslStringToken(component.shorthand, parseError);\n manifest.seoStrategy = \"full\";\n return { manifest };\n }\n\n for (const field of component.fields) {\n if (field.name.value === \"description\") {\n manifest.description = expectSingleString(field, 'Expected description \"<text>\"');\n continue;\n }\n\n if (field.name.value === \"seo\") {\n const value = expectSingleWord(field, \"Expected seo full|partial|none\");\n if (![\"full\", \"partial\", \"none\"].includes(value.value)) {\n throw new WebComponentDslCompileError(\n \"Expected seo full|partial|none\",\n value.token.line,\n value.token.column,\n );\n }\n manifest.seoStrategy = value.value as WebComponentManifest[\"seoStrategy\"];\n continue;\n }\n\n if (field.name.value === \"script\") {\n manifest.hasScript = parseScriptField(field);\n continue;\n }\n\n if (field.name.value === \"prop\") {\n const parsed = parseProp(field);\n manifest.props[parsed.name] = parsed.prop;\n }\n }\n\n return { manifest };\n}\n\nexport function formatWebComponentDsl(source: string): string {\n const { manifest } = compileWebComponentDsl(source);\n if (\n manifest.description &&\n manifest.seoStrategy === \"full\" &&\n manifest.hasScript === undefined &&\n Object.keys(manifest.props).length === 0\n ) {\n return `component ${formatName(manifest.name)} ${JSON.stringify(manifest.description)}\\n`;\n }\n\n const lines = [`component ${formatName(manifest.name)} {`];\n if (manifest.description) lines.push(` description ${JSON.stringify(manifest.description)}`);\n if (manifest.seoStrategy) lines.push(` seo ${manifest.seoStrategy}`);\n if (manifest.hasScript !== undefined) {\n lines.push(manifest.hasScript ? \" script\" : \" script false\");\n }\n for (const [name, prop] of Object.entries(manifest.props)) {\n const parts = [` prop ${name}`];\n if (prop.type) parts.push(prop.type);\n if (prop.default !== undefined) parts.push(\"default\", JSON.stringify(prop.default));\n if (prop.required) parts.push(\"required\");\n if (prop.description) parts.push(\"description\", JSON.stringify(prop.description));\n lines.push(parts.join(\" \"));\n }\n lines.push(\"}\");\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction parseProp(field: DslField): { name: string; prop: WebComponentPropManifest } {\n const name = field.values[0];\n if (name?.type !== \"word\") {\n throw new WebComponentDslCompileError(\n \"Expected prop <name> <type>\",\n name?.line ?? field.name.line,\n name?.column ?? field.name.column,\n );\n }\n\n let index = 1;\n const prop: WebComponentPropManifest = {};\n const type = field.values[index];\n if (type?.type === \"word\" && ![\"default\", \"description\", \"required\"].includes(type.value)) {\n prop.type = type.value;\n index += 1;\n }\n\n while (index < field.values.length) {\n const token = field.values[index];\n if (!token) break;\n if (token.type !== \"word\") {\n throw new WebComponentDslCompileError(\"Expected prop option\", token.line, token.column);\n }\n\n if (token.value === \"default\") {\n const value = field.values[index + 1];\n if (!value) {\n throw new WebComponentDslCompileError(\"Expected default <value>\", token.line, token.column);\n }\n prop.default = parseDslScalarToken(value, parseError);\n index += 2;\n continue;\n }\n\n if (token.value === \"description\") {\n const value = field.values[index + 1];\n if (!value) {\n throw new WebComponentDslCompileError(\n 'Expected description \"<text>\"',\n token.line,\n token.column,\n );\n }\n prop.description = parseDslStringToken(value, parseError);\n index += 2;\n continue;\n }\n\n if (token.value === \"required\") {\n prop.required = true;\n index += 1;\n continue;\n }\n\n throw new WebComponentDslCompileError(\n `Unknown prop option: ${token.value}`,\n token.line,\n token.column,\n );\n }\n\n return { name: name.value, prop };\n}\n\nfunction parseScriptField(field: DslField): boolean {\n if (field.values.length === 0) return true;\n const value = field.values[0];\n if (\n field.values.length === 1 &&\n value?.type === \"word\" &&\n [\"true\", \"false\"].includes(value.value)\n ) {\n return value.value === \"true\";\n }\n throw new WebComponentDslCompileError(\n \"Expected script [true|false]\",\n value?.line ?? field.name.line,\n value?.column ?? field.name.column,\n );\n}\n\nfunction expectSingleString(field: DslField, message: string): string {\n const token = field.values[0];\n if (field.values.length !== 1 || token?.type !== \"string\") {\n throw new WebComponentDslCompileError(\n message,\n token?.line ?? field.name.line,\n token?.column ?? field.name.column,\n );\n }\n return parseDslStringToken(token, parseError);\n}\n\nfunction expectSingleWord(field: DslField, message: string): { value: string; token: DslToken } {\n const token = field.values[0];\n if (field.values.length !== 1 || token?.type !== \"word\") {\n throw new WebComponentDslCompileError(\n message,\n token?.line ?? field.name.line,\n token?.column ?? field.name.column,\n );\n }\n return { value: token.value, token };\n}\n\nfunction parseError(message: string, line: number, column = 1): WebComponentDslCompileError {\n return new WebComponentDslCompileError(message, line, column);\n}\n\nfunction formatName(name: string): string {\n return /^[A-Za-z0-9_-]+$/.test(name) ? name : JSON.stringify(name);\n}\n"],"mappings":"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"}
|