@treenity/core 1.0.47 → 3.0.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/dist/chain.d.ts +20 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +59 -0
- package/dist/chain.js.map +1 -0
- package/dist/client/handle.d.ts +13 -0
- package/dist/client/handle.d.ts.map +1 -0
- package/dist/client/handle.js +46 -0
- package/dist/client/handle.js.map +1 -0
- package/dist/client/index.d.ts +21 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +5 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/trpc.d.ts +13 -0
- package/dist/client/trpc.d.ts.map +1 -0
- package/dist/client/trpc.js +78 -0
- package/dist/client/trpc.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -0
- package/dist/comp/handle.d.ts +14 -0
- package/dist/comp/handle.d.ts.map +1 -0
- package/dist/comp/handle.js +21 -0
- package/dist/comp/handle.js.map +1 -0
- package/dist/comp/index.d.ts +42 -0
- package/dist/comp/index.d.ts.map +1 -0
- package/dist/comp/index.js +126 -0
- package/dist/comp/index.js.map +1 -0
- package/dist/comp/needs.d.ts +26 -0
- package/dist/comp/needs.d.ts.map +1 -0
- package/dist/comp/needs.js +101 -0
- package/dist/comp/needs.js.map +1 -0
- package/dist/comp/validate.d.ts +13 -0
- package/dist/comp/validate.d.ts.map +1 -0
- package/dist/comp/validate.js +117 -0
- package/dist/comp/validate.js.map +1 -0
- package/dist/comp.d.ts +2 -0
- package/dist/comp.d.ts.map +1 -0
- package/dist/comp.js +2 -0
- package/dist/comp.js.map +1 -0
- package/dist/contexts/schema/index.d.ts +7 -0
- package/dist/contexts/schema/index.d.ts.map +1 -0
- package/dist/contexts/schema/index.js +2 -0
- package/dist/contexts/schema/index.js.map +1 -0
- package/dist/contexts/schema.d.ts +2 -0
- package/dist/contexts/schema.d.ts.map +1 -0
- package/dist/contexts/schema.js +2 -0
- package/dist/contexts/schema.js.map +1 -0
- package/dist/contexts/service/index.d.ts +31 -0
- package/dist/contexts/service/index.d.ts.map +1 -0
- package/dist/contexts/service/index.js +16 -0
- package/dist/contexts/service/index.js.map +1 -0
- package/dist/contexts/service.d.ts +1 -14
- package/dist/contexts/service.d.ts.map +1 -1
- package/dist/contexts/service.js +2 -0
- package/dist/contexts/service.js.map +1 -0
- package/dist/contexts/telegram/index.d.ts +19 -0
- package/dist/contexts/telegram/index.d.ts.map +1 -0
- package/dist/contexts/telegram/index.js +89 -0
- package/dist/contexts/telegram/index.js.map +1 -0
- package/dist/contexts/text/index.d.ts +7 -0
- package/dist/contexts/text/index.d.ts.map +1 -0
- package/dist/contexts/text/index.js +9 -0
- package/dist/contexts/text/index.js.map +1 -0
- package/dist/contexts/text.d.ts +2 -0
- package/dist/contexts/text.d.ts.map +1 -0
- package/dist/contexts/text.js +2 -0
- package/dist/contexts/text.js.map +1 -0
- package/dist/core/component.d.ts +41 -0
- package/dist/core/component.d.ts.map +1 -0
- package/dist/core/component.js +105 -0
- package/dist/core/component.js.map +1 -0
- package/dist/core/context.d.ts +5 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +3 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/path.d.ts +7 -0
- package/dist/core/path.d.ts.map +1 -0
- package/dist/core/path.js +37 -0
- package/dist/core/path.js.map +1 -0
- package/dist/core/registry.d.ts +16 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +100 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core.d.ts +2 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -0
- package/dist/log.d.ts +8 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +31 -0
- package/dist/log.js.map +1 -0
- package/dist/mod/discover.d.ts +4 -0
- package/dist/mod/discover.d.ts.map +1 -0
- package/dist/mod/discover.js +103 -0
- package/dist/mod/discover.js.map +1 -0
- package/dist/mod/examples/ticker/seed.d.ts +3 -0
- package/dist/mod/examples/ticker/seed.d.ts.map +1 -0
- package/dist/mod/examples/ticker/seed.js +16 -0
- package/dist/mod/examples/ticker/seed.js.map +1 -0
- package/dist/mod/examples/ticker/service.d.ts +2 -0
- package/dist/mod/examples/ticker/service.d.ts.map +1 -0
- package/dist/mod/examples/ticker/service.js +18 -0
- package/dist/mod/examples/ticker/service.js.map +1 -0
- package/dist/mod/examples/ticker/types.d.ts +16 -0
- package/dist/mod/examples/ticker/types.d.ts.map +1 -0
- package/dist/mod/examples/ticker/types.js +20 -0
- package/dist/mod/examples/ticker/types.js.map +1 -0
- package/dist/mod/examples/ticker/view.d.ts +2 -0
- package/dist/mod/examples/ticker/view.d.ts.map +1 -0
- package/dist/mod/examples/ticker/view.js +10 -0
- package/dist/mod/examples/ticker/view.js.map +1 -0
- package/dist/mod/index.d.ts +11 -0
- package/dist/mod/index.d.ts.map +1 -0
- package/dist/mod/index.js +8 -0
- package/dist/mod/index.js.map +1 -0
- package/dist/mod/loader.d.ts +18 -0
- package/dist/mod/loader.d.ts.map +1 -0
- package/dist/mod/loader.js +154 -0
- package/dist/mod/loader.js.map +1 -0
- package/dist/mod/optimistic.d.ts +34 -0
- package/dist/mod/optimistic.d.ts.map +1 -0
- package/dist/mod/optimistic.js +176 -0
- package/dist/mod/optimistic.js.map +1 -0
- package/dist/mod/prefab.d.ts +18 -0
- package/dist/mod/prefab.d.ts.map +1 -0
- package/dist/mod/prefab.js +42 -0
- package/dist/mod/prefab.js.map +1 -0
- package/dist/mod/tracking.d.ts +8 -0
- package/dist/mod/tracking.d.ts.map +1 -0
- package/dist/mod/tracking.js +44 -0
- package/dist/mod/tracking.js.map +1 -0
- package/dist/mod/types.d.ts +31 -0
- package/dist/mod/types.d.ts.map +1 -0
- package/dist/mod/types.js +5 -0
- package/dist/mod/types.js.map +1 -0
- package/dist/mod.d.ts +2 -0
- package/dist/mod.d.ts.map +1 -0
- package/dist/mod.js +2 -0
- package/dist/mod.js.map +1 -0
- package/dist/mods/autostart/server.d.ts +2 -0
- package/dist/mods/autostart/server.d.ts.map +1 -0
- package/dist/mods/autostart/server.js +2 -0
- package/dist/mods/autostart/server.js.map +1 -0
- package/dist/mods/autostart/service.d.ts +14 -0
- package/dist/mods/autostart/service.d.ts.map +1 -0
- package/dist/mods/autostart/service.js +88 -0
- package/dist/mods/autostart/service.js.map +1 -0
- package/dist/mods/llm/index.d.ts +13 -0
- package/dist/mods/llm/index.d.ts.map +1 -0
- package/dist/mods/llm/index.js +43 -0
- package/dist/mods/llm/index.js.map +1 -0
- package/dist/mods/llm/server.d.ts +2 -0
- package/dist/mods/llm/server.d.ts.map +1 -0
- package/dist/mods/llm/server.js +2 -0
- package/dist/mods/llm/server.js.map +1 -0
- package/dist/mods/mcp/server.d.ts +3 -0
- package/dist/mods/mcp/server.d.ts.map +1 -0
- package/dist/mods/mcp/server.js +3 -0
- package/dist/mods/mcp/server.js.map +1 -0
- package/dist/mods/mcp/service.d.ts +2 -0
- package/dist/mods/mcp/service.d.ts.map +1 -0
- package/dist/mods/mcp/service.js +17 -0
- package/dist/mods/mcp/service.js.map +1 -0
- package/dist/mods/mcp/types.d.ts +5 -0
- package/dist/mods/mcp/types.d.ts.map +1 -0
- package/dist/mods/mcp/types.js +7 -0
- package/dist/mods/mcp/types.js.map +1 -0
- package/dist/mods/treenity/agent-port.d.ts +2 -0
- package/dist/mods/treenity/agent-port.d.ts.map +1 -0
- package/dist/mods/treenity/agent-port.js +76 -0
- package/dist/mods/treenity/agent-port.js.map +1 -0
- package/dist/mods/treenity/groups.d.ts +2 -0
- package/dist/mods/treenity/groups.d.ts.map +1 -0
- package/dist/mods/treenity/groups.js +18 -0
- package/dist/mods/treenity/groups.js.map +1 -0
- package/dist/mods/treenity/mod-type.d.ts +2 -0
- package/dist/mods/treenity/mod-type.d.ts.map +1 -0
- package/dist/mods/treenity/mod-type.js +9 -0
- package/dist/mods/treenity/mod-type.js.map +1 -0
- package/dist/mods/treenity/seed.d.ts +2 -0
- package/dist/mods/treenity/seed.d.ts.map +1 -0
- package/dist/mods/treenity/seed.js +53 -0
- package/dist/mods/treenity/seed.js.map +1 -0
- package/dist/mods/treenity/server.d.ts +5 -0
- package/dist/mods/treenity/server.d.ts.map +1 -0
- package/dist/mods/treenity/server.js +5 -0
- package/dist/mods/treenity/server.js.map +1 -0
- package/dist/mods/treenity/system.d.ts +36 -0
- package/dist/mods/treenity/system.d.ts.map +1 -0
- package/dist/mods/treenity/system.js +61 -0
- package/dist/mods/treenity/system.js.map +1 -0
- package/dist/mods/uix/client.d.ts +3 -0
- package/dist/mods/uix/client.d.ts.map +1 -0
- package/dist/mods/uix/client.js +96 -0
- package/dist/mods/uix/client.js.map +1 -0
- package/dist/mods/uix/compile.d.ts +7 -0
- package/dist/mods/uix/compile.d.ts.map +1 -0
- package/dist/mods/uix/compile.js +94 -0
- package/dist/mods/uix/compile.js.map +1 -0
- package/dist/mods/uix/jsx-parser.d.ts +2 -0
- package/dist/mods/uix/jsx-parser.d.ts.map +1 -0
- package/dist/mods/uix/jsx-parser.js +565 -0
- package/dist/mods/uix/jsx-parser.js.map +1 -0
- package/dist/mods/uix/verify.d.ts +7 -0
- package/dist/mods/uix/verify.d.ts.map +1 -0
- package/dist/mods/uix/verify.js +59 -0
- package/dist/mods/uix/verify.js.map +1 -0
- package/dist/schema/catalog.d.ts +23 -0
- package/dist/schema/catalog.d.ts.map +1 -0
- package/dist/schema/catalog.js +82 -0
- package/dist/schema/catalog.js.map +1 -0
- package/dist/schema/extract-schemas.d.ts +5 -0
- package/dist/schema/extract-schemas.d.ts.map +1 -0
- package/dist/schema/extract-schemas.js +444 -0
- package/dist/schema/extract-schemas.js.map +1 -0
- package/dist/schema/load.d.ts +2 -0
- package/dist/schema/load.d.ts.map +1 -0
- package/dist/schema/load.js +23 -0
- package/dist/schema/load.js.map +1 -0
- package/dist/schema/test-fixture.types.d.ts +2 -0
- package/dist/schema/test-fixture.types.d.ts.map +1 -0
- package/dist/schema/test-fixture.types.js +19 -0
- package/dist/schema/test-fixture.types.js.map +1 -0
- package/dist/schema/test-opaque.d.ts +3 -0
- package/dist/schema/test-opaque.d.ts.map +1 -0
- package/dist/schema/test-opaque.js +43 -0
- package/dist/schema/test-opaque.js.map +1 -0
- package/dist/schema/types.d.ts +37 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +3 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/server/actions.d.ts +35 -0
- package/dist/server/actions.d.ts.map +1 -0
- package/dist/server/actions.js +170 -0
- package/dist/server/actions.js.map +1 -0
- package/dist/server/agent.d.ts +6 -0
- package/dist/server/agent.d.ts.map +1 -0
- package/dist/server/agent.js +15 -0
- package/dist/server/agent.js.map +1 -0
- package/dist/server/auth.d.ts +39 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +335 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/client.d.ts +183 -0
- package/dist/server/client.d.ts.map +1 -0
- package/dist/server/client.js +22 -0
- package/dist/server/client.js.map +1 -0
- package/dist/server/cookies.d.ts +5 -0
- package/dist/server/cookies.d.ts.map +1 -0
- package/dist/server/cookies.js +24 -0
- package/dist/server/cookies.js.map +1 -0
- package/dist/server/doc-index.d.ts +38 -0
- package/dist/server/doc-index.d.ts.map +1 -0
- package/dist/server/doc-index.js +244 -0
- package/dist/server/doc-index.js.map +1 -0
- package/dist/server/errors.d.ts +7 -0
- package/dist/server/errors.d.ts.map +1 -0
- package/dist/server/errors.js +11 -0
- package/dist/server/errors.js.map +1 -0
- package/dist/server/factory.d.ts +23 -0
- package/dist/server/factory.d.ts.map +1 -0
- package/dist/server/factory.js +70 -0
- package/dist/server/factory.js.map +1 -0
- package/dist/server/main.d.ts +6 -0
- package/dist/server/main.d.ts.map +1 -0
- package/dist/server/main.js +45 -0
- package/dist/server/main.js.map +1 -0
- package/dist/server/mcp.d.ts +5 -0
- package/dist/server/mcp.d.ts.map +1 -0
- package/dist/server/mcp.js +280 -0
- package/dist/server/mcp.js.map +1 -0
- package/dist/server/migrate.d.ts +3 -0
- package/dist/server/migrate.d.ts.map +1 -0
- package/dist/server/migrate.js +56 -0
- package/dist/server/migrate.js.map +1 -0
- package/dist/server/mod-catalog.d.ts +14 -0
- package/dist/server/mod-catalog.d.ts.map +1 -0
- package/dist/server/mod-catalog.js +40 -0
- package/dist/server/mod-catalog.js.map +1 -0
- package/dist/server/mods-mount.d.ts +4 -0
- package/dist/server/mods-mount.d.ts.map +1 -0
- package/dist/server/mods-mount.js +169 -0
- package/dist/server/mods-mount.js.map +1 -0
- package/dist/server/mount-adapters.d.ts +9 -0
- package/dist/server/mount-adapters.d.ts.map +1 -0
- package/dist/server/mount-adapters.js +75 -0
- package/dist/server/mount-adapters.js.map +1 -0
- package/dist/server/mount.d.ts +3 -0
- package/dist/server/mount.d.ts.map +1 -0
- package/dist/server/mount.js +195 -0
- package/dist/server/mount.js.map +1 -0
- package/dist/server/prefab.d.ts +18 -0
- package/dist/server/prefab.d.ts.map +1 -0
- package/dist/server/prefab.js +70 -0
- package/dist/server/prefab.js.map +1 -0
- package/dist/server/seed/index.d.ts +6 -0
- package/dist/server/seed/index.d.ts.map +1 -0
- package/dist/server/seed/index.js +16 -0
- package/dist/server/seed/index.js.map +1 -0
- package/dist/server/server.d.ts +28 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +117 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/sub.d.ts +34 -0
- package/dist/server/sub.d.ts.map +1 -0
- package/dist/server/sub.js +174 -0
- package/dist/server/sub.js.map +1 -0
- package/dist/server/trpc.d.ts +192 -0
- package/dist/server/trpc.d.ts.map +1 -0
- package/dist/server/trpc.js +319 -0
- package/dist/server/trpc.js.map +1 -0
- package/dist/server/types-mount.d.ts +3 -0
- package/dist/server/types-mount.d.ts.map +1 -0
- package/dist/server/types-mount.js +144 -0
- package/dist/server/types-mount.js.map +1 -0
- package/dist/server/validate.d.ts +3 -0
- package/dist/server/validate.d.ts.map +1 -0
- package/dist/server/validate.js +20 -0
- package/dist/server/validate.js.map +1 -0
- package/dist/server/volatile.d.ts +11 -0
- package/dist/server/volatile.d.ts.map +1 -0
- package/dist/server/volatile.js +26 -0
- package/dist/server/volatile.js.map +1 -0
- package/dist/server/watch.d.ts +23 -0
- package/dist/server/watch.d.ts.map +1 -0
- package/dist/server/watch.js +178 -0
- package/dist/server/watch.js.map +1 -0
- package/dist/tree/cache.d.ts +3 -0
- package/dist/tree/cache.d.ts.map +1 -0
- package/dist/tree/cache.js +48 -0
- package/dist/tree/cache.js.map +1 -0
- package/dist/tree/fs.d.ts +3 -0
- package/dist/tree/fs.d.ts.map +1 -0
- package/dist/tree/fs.js +274 -0
- package/dist/tree/fs.js.map +1 -0
- package/dist/tree/index.d.ts +38 -0
- package/dist/tree/index.d.ts.map +1 -0
- package/dist/tree/index.js +182 -0
- package/dist/tree/index.js.map +1 -0
- package/dist/tree/inflight.d.ts +2 -0
- package/dist/tree/inflight.d.ts.map +1 -0
- package/dist/tree/inflight.js +15 -0
- package/dist/tree/inflight.js.map +1 -0
- package/dist/tree/json-codec.d.ts +2 -0
- package/dist/tree/json-codec.d.ts.map +1 -0
- package/dist/tree/json-codec.js +13 -0
- package/dist/tree/json-codec.js.map +1 -0
- package/dist/tree/mimefs.d.ts +13 -0
- package/dist/tree/mimefs.d.ts.map +1 -0
- package/dist/tree/mimefs.js +124 -0
- package/dist/tree/mimefs.js.map +1 -0
- package/dist/tree/mongo.d.ts +5 -0
- package/dist/tree/mongo.d.ts.map +1 -0
- package/dist/tree/mongo.js +110 -0
- package/dist/tree/mongo.js.map +1 -0
- package/dist/tree/patch.d.ts +30 -0
- package/dist/tree/patch.d.ts.map +1 -0
- package/dist/tree/patch.js +112 -0
- package/dist/tree/patch.js.map +1 -0
- package/dist/tree/query.d.ts +12 -0
- package/dist/tree/query.d.ts.map +1 -0
- package/dist/tree/query.js +61 -0
- package/dist/tree/query.js.map +1 -0
- package/dist/tree/repath.d.ts +3 -0
- package/dist/tree/repath.d.ts.map +1 -0
- package/dist/tree/repath.js +38 -0
- package/dist/tree/repath.js.map +1 -0
- package/dist/tree-chain.d.ts +18 -0
- package/dist/tree-chain.d.ts.map +1 -0
- package/dist/tree-chain.js +109 -0
- package/dist/tree-chain.js.map +1 -0
- package/dist/tree.d.ts +2 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +2 -0
- package/dist/tree.js.map +1 -0
- package/dist/uri.d.ts +11 -0
- package/dist/uri.d.ts.map +1 -0
- package/dist/uri.js +79 -0
- package/dist/uri.js.map +1 -0
- package/package.json +39 -40
- package/src/chain.test.ts +190 -0
- package/src/chain.ts +82 -0
- package/src/client/client.test.ts +192 -0
- package/src/client/handle.ts +53 -0
- package/src/client/index.ts +18 -0
- package/src/client/trpc.ts +91 -0
- package/src/client.ts +1 -0
- package/src/comp/CLAUDE.md +14 -0
- package/src/comp/handle.ts +36 -0
- package/src/comp/index.test.ts +129 -0
- package/src/comp/index.ts +175 -0
- package/src/comp/needs.test.ts +499 -0
- package/src/comp/needs.ts +113 -0
- package/src/comp/validate.test.ts +304 -0
- package/src/comp/validate.ts +125 -0
- package/src/comp.ts +1 -0
- package/src/contexts/schema/index.ts +7 -0
- package/src/contexts/schema.ts +1 -0
- package/src/contexts/service/index.test.ts +323 -0
- package/src/contexts/service/index.ts +43 -0
- package/src/contexts/service.ts +1 -0
- package/src/contexts/telegram/index.ts +115 -0
- package/src/contexts/text/index.test.ts +31 -0
- package/src/contexts/text/index.ts +18 -0
- package/src/contexts/text.ts +1 -0
- package/src/core/component.ts +151 -0
- package/src/core/context.ts +14 -0
- package/src/core/index.test.ts +203 -0
- package/src/core/index.ts +9 -0
- package/src/core/path.ts +35 -0
- package/src/core/registry.ts +115 -0
- package/src/core.ts +1 -0
- package/src/log.test.ts +70 -0
- package/src/log.ts +28 -0
- package/src/mod/discover.test.ts +133 -0
- package/src/mod/discover.ts +100 -0
- package/src/mod/docs/00-index.md +19 -0
- package/src/mod/docs/01-primitives.md +38 -0
- package/src/mod/docs/02-core-api.md +68 -0
- package/src/mod/docs/03-registry.md +30 -0
- package/src/mod/docs/04-store.md +62 -0
- package/src/mod/docs/05-comp.md +111 -0
- package/src/mod/docs/06-actions.md +193 -0
- package/src/mod/docs/07-realtime.md +100 -0
- package/src/mod/docs/08-services.md +33 -0
- package/src/mod/docs/09-mounts.md +43 -0
- package/src/mod/docs/10-acl.md +60 -0
- package/src/mod/docs/11-server.md +62 -0
- package/src/mod/docs/12-conventions.md +65 -0
- package/src/mod/docs/13-example.md +132 -0
- package/src/mod/docs/14-mod-format.md +304 -0
- package/src/mod/docs/15-documenting-types.md +156 -0
- package/src/mod/examples/ticker/seed.ts +19 -0
- package/src/mod/examples/ticker/service.ts +20 -0
- package/src/mod/examples/ticker/ticker.test.ts +18 -0
- package/src/mod/examples/ticker/types.ts +22 -0
- package/src/mod/examples/ticker/view.tsx +19 -0
- package/src/mod/index.ts +12 -0
- package/src/mod/loader.test.ts +168 -0
- package/src/mod/loader.ts +174 -0
- package/src/mod/optimistic.test.ts +446 -0
- package/src/mod/optimistic.ts +210 -0
- package/src/mod/prefab.ts +62 -0
- package/src/mod/tracking.test.ts +59 -0
- package/src/mod/tracking.ts +51 -0
- package/src/mod/types.ts +40 -0
- package/src/mod.ts +1 -0
- package/src/mods/autostart/CLAUDE.md +6 -0
- package/src/mods/autostart/autostart.test.ts +85 -0
- package/src/mods/autostart/server.ts +1 -0
- package/src/mods/autostart/service.ts +98 -0
- package/src/mods/llm/CLAUDE.md +6 -0
- package/src/mods/llm/index.ts +57 -0
- package/src/mods/llm/llm.test.ts +109 -0
- package/src/mods/llm/server.ts +1 -0
- package/src/mods/mcp/CLAUDE.md +6 -0
- package/src/mods/mcp/server.ts +2 -0
- package/src/mods/mcp/service.ts +19 -0
- package/src/mods/mcp/types.ts +7 -0
- package/src/mods/treenity/agent-port.ts +93 -0
- package/src/mods/treenity/groups.ts +19 -0
- package/src/mods/treenity/mod-type.ts +10 -0
- package/src/mods/treenity/seed.ts +56 -0
- package/src/mods/treenity/server.ts +4 -0
- package/src/mods/treenity/system.ts +70 -0
- package/src/mods/uix/CLAUDE.md +7 -0
- package/src/mods/uix/client.ts +117 -0
- package/src/mods/uix/compile.test.ts +228 -0
- package/src/mods/uix/compile.ts +110 -0
- package/src/mods/uix/jsx-parser.test.ts +554 -0
- package/src/mods/uix/jsx-parser.ts +489 -0
- package/src/mods/uix/lazy-load.test.ts +261 -0
- package/src/mods/uix/uix-repomix.md +3509 -0
- package/src/mods/uix/verify.ts +68 -0
- package/src/schema/CLAUDE.md +13 -0
- package/src/schema/catalog.ts +101 -0
- package/src/schema/extract-schemas.test.ts +84 -0
- package/src/schema/extract-schemas.ts +462 -0
- package/src/schema/generated/autostart.json +44 -0
- package/src/schema/generated/board.column.json +25 -0
- package/src/schema/generated/board.task.json +147 -0
- package/src/schema/generated/brahman.action.back.json +12 -0
- package/src/schema/generated/brahman.action.broadcast.json +31 -0
- package/src/schema/generated/brahman.action.call.json +57 -0
- package/src/schema/generated/brahman.action.emittext.json +23 -0
- package/src/schema/generated/brahman.action.eval.json +23 -0
- package/src/schema/generated/brahman.action.file.json +28 -0
- package/src/schema/generated/brahman.action.forward.json +29 -0
- package/src/schema/generated/brahman.action.getvalue.json +28 -0
- package/src/schema/generated/brahman.action.ifelse.json +42 -0
- package/src/schema/generated/brahman.action.keywordselect.json +46 -0
- package/src/schema/generated/brahman.action.message.json +127 -0
- package/src/schema/generated/brahman.action.onerror.json +29 -0
- package/src/schema/generated/brahman.action.page.json +22 -0
- package/src/schema/generated/brahman.action.params.json +36 -0
- package/src/schema/generated/brahman.action.question.json +43 -0
- package/src/schema/generated/brahman.action.remove.json +12 -0
- package/src/schema/generated/brahman.action.resethistory.json +12 -0
- package/src/schema/generated/brahman.action.resetsession.json +12 -0
- package/src/schema/generated/brahman.action.selectlang.json +20 -0
- package/src/schema/generated/brahman.action.setvalue.json +27 -0
- package/src/schema/generated/brahman.action.tag.json +27 -0
- package/src/schema/generated/brahman.bot.json +68 -0
- package/src/schema/generated/brahman.page.json +25 -0
- package/src/schema/generated/brahman.session.json +29 -0
- package/src/schema/generated/brahman.user.json +58 -0
- package/src/schema/generated/cafe.contact.json +56 -0
- package/src/schema/generated/cafe.mail.json +29 -0
- package/src/schema/generated/default.json +15 -0
- package/src/schema/generated/doc.page.json +23 -0
- package/src/schema/generated/examples.demo.generator.json +16 -0
- package/src/schema/generated/examples.demo.sensor.json +35 -0
- package/src/schema/generated/groups.json +20 -0
- package/src/schema/generated/launcher.json +91 -0
- package/src/schema/generated/mcp.server.json +15 -0
- package/src/schema/generated/mindmap.map.json +22 -0
- package/src/schema/generated/sim.agent.json +24 -0
- package/src/schema/generated/sim.ai.json +24 -0
- package/src/schema/generated/sim.config.json +38 -0
- package/src/schema/generated/sim.descriptive.json +26 -0
- package/src/schema/generated/sim.events.json +47 -0
- package/src/schema/generated/sim.item.json +20 -0
- package/src/schema/generated/sim.memory.json +17 -0
- package/src/schema/generated/sim.nearby.json +17 -0
- package/src/schema/generated/sim.position.json +25 -0
- package/src/schema/generated/sim.round.json +64 -0
- package/src/schema/generated/sim.world.json +32 -0
- package/src/schema/generated/t.agent.port.json +74 -0
- package/src/schema/generated/t.llm.json +20 -0
- package/src/schema/generated/t.mod.json +27 -0
- package/src/schema/generated/t3d.animator.json +46 -0
- package/src/schema/generated/t3d.audio.json +58 -0
- package/src/schema/generated/t3d.camera.json +50 -0
- package/src/schema/generated/t3d.collider.json +84 -0
- package/src/schema/generated/t3d.light.json +90 -0
- package/src/schema/generated/t3d.line.json +47 -0
- package/src/schema/generated/t3d.lod.json +28 -0
- package/src/schema/generated/t3d.material.json +131 -0
- package/src/schema/generated/t3d.mesh.json +65 -0
- package/src/schema/generated/t3d.object.json +64 -0
- package/src/schema/generated/t3d.particles.json +109 -0
- package/src/schema/generated/t3d.rigidbody.json +81 -0
- package/src/schema/generated/t3d.scene.json +7 -0
- package/src/schema/generated/t3d.script.json +23 -0
- package/src/schema/generated/t3d.text.json +86 -0
- package/src/schema/generated/t3d.trail.json +45 -0
- package/src/schema/generated/task.json +96 -0
- package/src/schema/generated/test.fixture.json +43 -0
- package/src/schema/generated/ticker.config.json +43 -0
- package/src/schema/generated/ticker.price.json +20 -0
- package/src/schema/generated/todo.item.json +25 -0
- package/src/schema/generated/todo.list.json +33 -0
- package/src/schema/generated/treenity.system.json +259 -0
- package/src/schema/generated/whisper.audio.json +25 -0
- package/src/schema/generated/whisper.checklist.json +17 -0
- package/src/schema/generated/whisper.config.json +30 -0
- package/src/schema/generated/whisper.inbox.json +24 -0
- package/src/schema/generated/whisper.meta.json +35 -0
- package/src/schema/generated/whisper.text.json +16 -0
- package/src/schema/load.ts +24 -0
- package/src/schema/schema.test.ts +86 -0
- package/src/schema/test-fixture.types.ts +21 -0
- package/src/schema/test-opaque.ts +42 -0
- package/src/schema/types.ts +33 -0
- package/src/server/CLAUDE.md +26 -0
- package/src/server/actions.test.ts +272 -0
- package/src/server/actions.ts +274 -0
- package/src/server/agent-sub.test.ts +90 -0
- package/src/server/agent.test.ts +305 -0
- package/src/server/agent.ts +17 -0
- package/src/server/api.test.ts +454 -0
- package/src/server/auth.test.ts +441 -0
- package/src/server/auth.ts +386 -0
- package/src/server/client.ts +24 -0
- package/src/server/conditions.test.ts +128 -0
- package/src/server/cookies.ts +25 -0
- package/src/server/coverage.test.ts +827 -0
- package/src/server/doc-index.ts +286 -0
- package/src/server/e2e.test.ts +966 -0
- package/src/server/errors.ts +11 -0
- package/src/server/factory.ts +99 -0
- package/src/server/main.ts +56 -0
- package/src/server/mcp.ts +326 -0
- package/src/server/migrate.test.ts +123 -0
- package/src/server/migrate.ts +62 -0
- package/src/server/mod-catalog.ts +59 -0
- package/src/server/mods-mount.ts +179 -0
- package/src/server/mount-adapters.ts +82 -0
- package/src/server/mount.parametrized.test.ts +52 -0
- package/src/server/mount.query.test.ts +127 -0
- package/src/server/mount.test.ts +497 -0
- package/src/server/mount.ts +208 -0
- package/src/server/prefab.test.ts +415 -0
- package/src/server/prefab.ts +104 -0
- package/src/server/seed/index.ts +24 -0
- package/src/server/server.ts +153 -0
- package/src/server/stress.test.ts +844 -0
- package/src/server/sub.test.ts +55 -0
- package/src/server/sub.ts +224 -0
- package/src/server/trpc.ts +369 -0
- package/src/server/types-mount.ts +142 -0
- package/src/server/validate.test.ts +91 -0
- package/src/server/validate.ts +22 -0
- package/src/server/volatile.test.ts +140 -0
- package/src/server/volatile.ts +32 -0
- package/src/server/watch.test.ts +594 -0
- package/src/server/watch.ts +202 -0
- package/src/server/workflow.test.ts +82 -0
- package/src/tree/CLAUDE.md +13 -0
- package/src/tree/cache.test.ts +213 -0
- package/src/tree/cache.ts +51 -0
- package/src/tree/fs.test.ts +247 -0
- package/src/tree/fs.ts +251 -0
- package/src/tree/index.test.ts +164 -0
- package/src/tree/index.ts +216 -0
- package/src/tree/inflight.ts +15 -0
- package/src/tree/json-codec.ts +16 -0
- package/src/tree/mimefs.test.ts +289 -0
- package/src/tree/mimefs.ts +142 -0
- package/src/tree/mongo.ts +125 -0
- package/src/tree/patch.test.ts +192 -0
- package/src/tree/patch.ts +133 -0
- package/src/tree/query.test.ts +110 -0
- package/src/tree/query.ts +70 -0
- package/src/tree/repath.test.ts +86 -0
- package/src/tree/repath.ts +53 -0
- package/src/tree-chain.test.ts +723 -0
- package/src/tree-chain.ts +144 -0
- package/src/tree.ts +1 -0
- package/src/uri.test.ts +86 -0
- package/src/uri.ts +82 -0
- package/CHANGELOG.md +0 -305
- package/README.md +0 -18
- package/dist/context.d.ts +0 -41
- package/dist/context.d.ts.map +0 -1
- package/dist/context.mjs +0 -81
- package/dist/context.mjs.map +0 -1
- package/dist/contexts/node-engine.d.ts +0 -12
- package/dist/contexts/node-engine.d.ts.map +0 -1
- package/dist/contexts/node-engine.mjs +0 -7
- package/dist/contexts/node-engine.mjs.map +0 -1
- package/dist/contexts/noflo/types.d.ts +0 -20
- package/dist/contexts/noflo/types.d.ts.map +0 -1
- package/dist/contexts/object.d.ts +0 -11
- package/dist/contexts/object.d.ts.map +0 -1
- package/dist/contexts/object.mjs +0 -15
- package/dist/contexts/object.mjs.map +0 -1
- package/dist/contexts/proto.d.ts +0 -11
- package/dist/contexts/proto.d.ts.map +0 -1
- package/dist/contexts/proto.mjs +0 -7
- package/dist/contexts/proto.mjs.map +0 -1
- package/dist/contexts/react-context.d.ts +0 -21
- package/dist/contexts/react-context.d.ts.map +0 -1
- package/dist/contexts/react-context.mjs +0 -24
- package/dist/contexts/react-context.mjs.map +0 -1
- package/dist/contexts/service.mjs +0 -7
- package/dist/contexts/service.mjs.map +0 -1
- package/dist/get-type-cache.d.ts +0 -2
- package/dist/get-type-cache.d.ts.map +0 -1
- package/dist/get-type-cache.mjs +0 -7
- package/dist/get-type-cache.mjs.map +0 -1
- package/dist/index.d.ts +0 -13
- package/dist/index.d.ts.map +0 -1
- package/dist/index.mjs +0 -10
- package/dist/index.mjs.map +0 -1
- package/dist/link/link.d.ts +0 -25
- package/dist/link/link.d.ts.map +0 -1
- package/dist/link/link.mjs +0 -72
- package/dist/link/link.mjs.map +0 -1
- package/dist/link/link.test.d.ts +0 -2
- package/dist/link/link.test.d.ts.map +0 -1
- package/dist/loading.d.ts +0 -9
- package/dist/loading.d.ts.map +0 -1
- package/dist/meta-type.d.ts +0 -58
- package/dist/meta-type.d.ts.map +0 -1
- package/dist/meta-type.mjs +0 -104
- package/dist/meta-type.mjs.map +0 -1
- package/dist/meta.d.ts +0 -20
- package/dist/meta.d.ts.map +0 -1
- package/dist/meta.mjs +0 -16
- package/dist/meta.mjs.map +0 -1
- package/dist/node/index.d.ts +0 -2
- package/dist/node/index.d.ts.map +0 -1
- package/dist/node/types.d.ts +0 -37
- package/dist/node/types.d.ts.map +0 -1
- package/dist/test/context.test.d.ts +0 -2
- package/dist/test/context.test.d.ts.map +0 -1
- package/dist/types.d.ts +0 -14
- package/dist/types.d.ts.map +0 -1
- package/dist/types.mjs +0 -16
- package/dist/types.mjs.map +0 -1
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { describe, test } from 'node:test'
|
|
3
|
+
import { createMemoryTree } from '#tree'
|
|
4
|
+
import { register } from '#core'
|
|
5
|
+
import { registerType } from '#comp'
|
|
6
|
+
import { type TypedRef, refVal } from '#chain'
|
|
7
|
+
import { isRef } from '#core'
|
|
8
|
+
import type { Tree } from '#tree'
|
|
9
|
+
|
|
10
|
+
// ── Test types ──
|
|
11
|
+
|
|
12
|
+
class Scanner {
|
|
13
|
+
static $type = 'tch.scanner'
|
|
14
|
+
intervalMs = 900_000
|
|
15
|
+
maxRetries = 3
|
|
16
|
+
livePrices: TypedRef<LivePrices> = refVal(LivePrices)
|
|
17
|
+
}
|
|
18
|
+
registerType('tch.scanner', Scanner)
|
|
19
|
+
|
|
20
|
+
class LivePrices {
|
|
21
|
+
static $type = 'tch.live-prices'
|
|
22
|
+
feederUrl = 'ws://localhost:8090'
|
|
23
|
+
}
|
|
24
|
+
registerType('tch.live-prices', LivePrices)
|
|
25
|
+
|
|
26
|
+
class Profile {
|
|
27
|
+
static $type = 'tch.profile'
|
|
28
|
+
name = ''
|
|
29
|
+
balance = 0
|
|
30
|
+
}
|
|
31
|
+
registerType('tch.profile', Profile)
|
|
32
|
+
|
|
33
|
+
class Wallet {
|
|
34
|
+
static $type = 'tch.wallet'
|
|
35
|
+
address = ''
|
|
36
|
+
chain = ''
|
|
37
|
+
}
|
|
38
|
+
registerType('tch.wallet', Wallet)
|
|
39
|
+
|
|
40
|
+
// ── Register actions ──
|
|
41
|
+
|
|
42
|
+
register('tch.scanner', 'action:scan', () => ({ started: true }))
|
|
43
|
+
register('tch.scanner', 'action:configure', (_ctx: any, data: any) => data)
|
|
44
|
+
register('tch.live-prices', 'action:subscribe', (_ctx: any, data: any) =>
|
|
45
|
+
data.slugs.map((s: string) => ({ slug: s, bid: 0.6 })),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
// ── Seed ──
|
|
49
|
+
|
|
50
|
+
async function seed(): Promise<Tree> {
|
|
51
|
+
const tree = createMemoryTree()
|
|
52
|
+
|
|
53
|
+
await tree.set({ $path: '/services', $type: 'dir' })
|
|
54
|
+
await tree.set({
|
|
55
|
+
$path: '/services/scanner',
|
|
56
|
+
$type: 'tch.scanner',
|
|
57
|
+
intervalMs: 900_000,
|
|
58
|
+
maxRetries: 3,
|
|
59
|
+
livePrices: { $type: 'ref', $ref: '/services/live-prices' },
|
|
60
|
+
})
|
|
61
|
+
await tree.set({
|
|
62
|
+
$path: '/services/live-prices',
|
|
63
|
+
$type: 'tch.live-prices',
|
|
64
|
+
feederUrl: 'ws://localhost:8090',
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
// Children of scanner
|
|
68
|
+
await tree.set({ $path: '/services/scanner/s1', $type: 'tch.scan-result', ts: 1000 })
|
|
69
|
+
await tree.set({ $path: '/services/scanner/s2', $type: 'tch.scan-result', ts: 2000 })
|
|
70
|
+
|
|
71
|
+
// Node with named component
|
|
72
|
+
await tree.set({
|
|
73
|
+
$path: '/users/alice',
|
|
74
|
+
$type: 'tch.profile',
|
|
75
|
+
name: 'Alice',
|
|
76
|
+
balance: 100,
|
|
77
|
+
wallet: { $type: 'tch.wallet', address: '0xabc', chain: 'eth' },
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return tree
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
import { treeChain } from './tree-chain'
|
|
84
|
+
|
|
85
|
+
describe('treeChain — path building', () => {
|
|
86
|
+
test('$path from dot navigation', () => {
|
|
87
|
+
const c = treeChain(null as any)
|
|
88
|
+
assert.equal(c.services.scanner.$path, '/services/scanner')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('$path from root', () => {
|
|
92
|
+
const c = treeChain(null as any)
|
|
93
|
+
assert.equal(c.$path, '/')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('$path with basePath', () => {
|
|
97
|
+
const c = treeChain(null as any, '/services')
|
|
98
|
+
assert.equal(c.scanner.$path, '/services/scanner')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('$path with bracket access', () => {
|
|
102
|
+
const c = treeChain(null as any)
|
|
103
|
+
assert.equal(c.services.scanner['s1'].$path, '/services/scanner/s1')
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
describe('treeChain — node materialization (await)', () => {
|
|
108
|
+
test('await returns node data', async () => {
|
|
109
|
+
const tree = await seed()
|
|
110
|
+
const c = treeChain(tree)
|
|
111
|
+
const node = await c.services.scanner
|
|
112
|
+
assert.equal(node.$type, 'tch.scanner')
|
|
113
|
+
assert.equal(node.intervalMs, 900_000)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('await deep path', async () => {
|
|
117
|
+
const tree = await seed()
|
|
118
|
+
const node = await treeChain(tree).services.scanner['s1']
|
|
119
|
+
assert.equal(node.ts, 1000)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('await missing node throws', async () => {
|
|
123
|
+
const tree = await seed()
|
|
124
|
+
await assert.rejects(async () => { await treeChain(tree).nothing.here })
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
describe('treeChain — $get (typed component)', () => {
|
|
129
|
+
test('$get returns typed fields', async () => {
|
|
130
|
+
const tree = await seed()
|
|
131
|
+
const scanner: Scanner = await treeChain(tree).services.scanner.$get(Scanner)
|
|
132
|
+
assert.equal(scanner.intervalMs, 900_000)
|
|
133
|
+
assert.equal(scanner.maxRetries, 3)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
test('$get with named component', async () => {
|
|
137
|
+
const tree = await seed()
|
|
138
|
+
const wallet = await treeChain(tree).users.alice.$get(null, 'wallet')
|
|
139
|
+
assert.equal(wallet.address, '0xabc')
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test('$get wrong type throws', async () => {
|
|
143
|
+
const tree = await seed()
|
|
144
|
+
await assert.rejects(async () => { await treeChain(tree).services.scanner.$get(LivePrices) })
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
describe('treeChain — (Class) bracket access', () => {
|
|
149
|
+
test('(Class) returns typed fields', async () => {
|
|
150
|
+
const tree = await seed()
|
|
151
|
+
const scanner: Scanner = await treeChain(tree).services.scanner(Scanner)
|
|
152
|
+
assert.equal(scanner.intervalMs, 900_000)
|
|
153
|
+
assert.equal(scanner.maxRetries, 3)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('(Class) finds named component by type scan', async () => {
|
|
157
|
+
const tree = await seed()
|
|
158
|
+
const wallet = await treeChain(tree).users.alice(Wallet)
|
|
159
|
+
assert.equal(wallet.address, '0xabc')
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('(Class) wrong type throws', async () => {
|
|
163
|
+
const tree = await seed()
|
|
164
|
+
await assert.rejects(async () => { await treeChain(tree).services.scanner(LivePrices) })
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
test('(Class) then ref follow', async () => {
|
|
168
|
+
const tree = await seed()
|
|
169
|
+
const lp = await treeChain(tree).services.scanner(Scanner).livePrices
|
|
170
|
+
assert.equal(lp.feederUrl, 'ws://localhost:8090')
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test('(Class) → ref → action', async () => {
|
|
174
|
+
const tree = await seed()
|
|
175
|
+
const result = await treeChain(tree)
|
|
176
|
+
.services.scanner(Scanner).livePrices
|
|
177
|
+
.subscribe({ slugs: ['btc'] })
|
|
178
|
+
assert.deepEqual(result, [{ slug: 'btc', bid: 0.6 }])
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
describe('treeChain — ref auto-follow', () => {
|
|
183
|
+
test('TypedRef field resolves to target node', async () => {
|
|
184
|
+
const tree = await seed()
|
|
185
|
+
// scanner.livePrices is { $ref: '/services/live-prices' }
|
|
186
|
+
// chain follows ref automatically
|
|
187
|
+
const lp = await treeChain(tree).services.scanner.$get(Scanner).livePrices
|
|
188
|
+
assert.equal(lp.feederUrl, 'ws://localhost:8090')
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
test('ref field then field access', async () => {
|
|
192
|
+
const tree = await seed()
|
|
193
|
+
const url = await treeChain(tree).services.scanner.$get(Scanner).livePrices.feederUrl
|
|
194
|
+
assert.equal(url, 'ws://localhost:8090')
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
test('missing ref throws', async () => {
|
|
198
|
+
const tree = await seed()
|
|
199
|
+
// Set scanner with broken ref
|
|
200
|
+
await tree.set({
|
|
201
|
+
$path: '/broken',
|
|
202
|
+
$type: 'tch.scanner',
|
|
203
|
+
livePrices: { $type: 'ref', $ref: '/nonexistent' },
|
|
204
|
+
})
|
|
205
|
+
await assert.rejects(async () => { await treeChain(tree).broken.$get(Scanner).livePrices })
|
|
206
|
+
})
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
describe('treeChain — actions', () => {
|
|
210
|
+
test('action call returns result', async () => {
|
|
211
|
+
const tree = await seed()
|
|
212
|
+
const result = await treeChain(tree).services.scanner(Scanner).scan()
|
|
213
|
+
assert.deepEqual(result, { started: true })
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
test('action with data', async () => {
|
|
217
|
+
const tree = await seed()
|
|
218
|
+
const result = await treeChain(tree).services.scanner(Scanner).configure({ interval: 5000 })
|
|
219
|
+
assert.deepEqual(result, { interval: 5000 })
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
test('action on ref target', async () => {
|
|
223
|
+
const tree = await seed()
|
|
224
|
+
const result = await treeChain(tree)
|
|
225
|
+
.services.scanner
|
|
226
|
+
.$get(Scanner).livePrices
|
|
227
|
+
.subscribe({ slugs: ['btc'] })
|
|
228
|
+
assert.deepEqual(result, [{ slug: 'btc', bid: 0.6 }])
|
|
229
|
+
})
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
describe('treeChain — $children', () => {
|
|
233
|
+
test('returns child nodes', async () => {
|
|
234
|
+
const tree = await seed()
|
|
235
|
+
const kids = await treeChain(tree).services.scanner.$children()
|
|
236
|
+
assert.equal(kids.length, 2)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
test('with query filter', async () => {
|
|
240
|
+
const tree = await seed()
|
|
241
|
+
const kids = await treeChain(tree).services.scanner.$children({ ts: 1000 })
|
|
242
|
+
assert.equal(kids.length, 1)
|
|
243
|
+
assert.equal(kids[0].ts, 1000)
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
test('empty children', async () => {
|
|
247
|
+
const tree = await seed()
|
|
248
|
+
const kids = await treeChain(tree).services['live-prices'].$children()
|
|
249
|
+
assert.equal(kids.length, 0)
|
|
250
|
+
})
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
describe('treeChain — composition', () => {
|
|
254
|
+
test('chain is reusable (no state mutation)', async () => {
|
|
255
|
+
const tree = await seed()
|
|
256
|
+
const services = treeChain(tree).services
|
|
257
|
+
const a = await services.scanner
|
|
258
|
+
const b = await services['live-prices']
|
|
259
|
+
assert.equal(a.$type, 'tch.scanner')
|
|
260
|
+
assert.equal(b.$type, 'tch.live-prices')
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
test('chain from basePath', async () => {
|
|
264
|
+
const tree = await seed()
|
|
265
|
+
const scanner = await treeChain(tree, '/services/scanner')
|
|
266
|
+
assert.equal(scanner.$type, 'tch.scanner')
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
test('full pipeline: navigate → type → ref → action', async () => {
|
|
270
|
+
const tree = await seed()
|
|
271
|
+
const result = await treeChain(tree)
|
|
272
|
+
.services // → /services (child nav)
|
|
273
|
+
.scanner // → /services/scanner (child nav)
|
|
274
|
+
.$get(Scanner) // → typed as Scanner
|
|
275
|
+
.livePrices // → follow ref → /services/live-prices
|
|
276
|
+
.subscribe({ slugs: ['eth', 'btc'] }) // → action on LivePrices
|
|
277
|
+
|
|
278
|
+
assert.equal(result.length, 2)
|
|
279
|
+
assert.equal(result[0].slug, 'eth')
|
|
280
|
+
assert.equal(result[1].slug, 'btc')
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
// ── Real-world usage examples ──
|
|
285
|
+
// These show how treeChain would be used on a real Treenity tree.
|
|
286
|
+
// Seed mimics actual /board, /cafe, /agent structure.
|
|
287
|
+
|
|
288
|
+
class BoardTask {
|
|
289
|
+
static $type = 'tch.board.task'
|
|
290
|
+
title = ''
|
|
291
|
+
status = 'backlog'
|
|
292
|
+
priority = 'normal'
|
|
293
|
+
}
|
|
294
|
+
registerType('tch.board.task', BoardTask)
|
|
295
|
+
|
|
296
|
+
class BoardKanban {
|
|
297
|
+
static $type = 'tch.board.kanban'
|
|
298
|
+
}
|
|
299
|
+
registerType('tch.board.kanban', BoardKanban)
|
|
300
|
+
|
|
301
|
+
class CafeContact {
|
|
302
|
+
static $type = 'tch.cafe.contact'
|
|
303
|
+
phone = ''
|
|
304
|
+
address = ''
|
|
305
|
+
}
|
|
306
|
+
registerType('tch.cafe.contact', CafeContact)
|
|
307
|
+
|
|
308
|
+
class AgentConfig {
|
|
309
|
+
static $type = 'tch.agent.config'
|
|
310
|
+
model = ''
|
|
311
|
+
bot: TypedRef<BrahmanBot> = refVal(BrahmanBot)
|
|
312
|
+
}
|
|
313
|
+
registerType('tch.agent.config', AgentConfig)
|
|
314
|
+
|
|
315
|
+
class BrahmanBot {
|
|
316
|
+
static $type = 'tch.brahman.bot'
|
|
317
|
+
alias = ''
|
|
318
|
+
running = false
|
|
319
|
+
}
|
|
320
|
+
registerType('tch.brahman.bot', BrahmanBot)
|
|
321
|
+
|
|
322
|
+
register('tch.board.task', 'action:move', (_ctx: any, data: any) => ({ moved: data.status }))
|
|
323
|
+
register('tch.board.task', 'action:assign', (_ctx: any, data: any) => ({ assigned: data.to }))
|
|
324
|
+
register('tch.brahman.bot', 'action:restart', () => ({ restarted: true }))
|
|
325
|
+
|
|
326
|
+
async function seedRealWorld(): Promise<Tree> {
|
|
327
|
+
const tree = createMemoryTree()
|
|
328
|
+
|
|
329
|
+
// /board — kanban with task children
|
|
330
|
+
await tree.set({ $path: '/board', $type: 'tch.board.kanban' })
|
|
331
|
+
await tree.set({
|
|
332
|
+
$path: '/board/landing',
|
|
333
|
+
$type: 'tch.board.task',
|
|
334
|
+
title: 'Landing treenity.land',
|
|
335
|
+
status: 'doing',
|
|
336
|
+
priority: 'urgent',
|
|
337
|
+
})
|
|
338
|
+
await tree.set({
|
|
339
|
+
$path: '/board/npm-split',
|
|
340
|
+
$type: 'tch.board.task',
|
|
341
|
+
title: 'npm monorepo split',
|
|
342
|
+
status: 'done',
|
|
343
|
+
priority: 'high',
|
|
344
|
+
})
|
|
345
|
+
await tree.set({
|
|
346
|
+
$path: '/board/agent-toolkit',
|
|
347
|
+
$type: 'tch.board.task',
|
|
348
|
+
title: 'Agent Toolkit — MCP tools',
|
|
349
|
+
status: 'backlog',
|
|
350
|
+
priority: 'urgent',
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
// /cafe — contact with nested component
|
|
354
|
+
await tree.set({
|
|
355
|
+
$path: '/cafe/contact',
|
|
356
|
+
$type: 'tch.cafe.contact',
|
|
357
|
+
phone: '+7-999-123-4567',
|
|
358
|
+
address: 'Moscow, Tverskaya 1',
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
// /agent — config with ref to bot
|
|
362
|
+
await tree.set({
|
|
363
|
+
$path: '/agent',
|
|
364
|
+
$type: 'tch.agent.config',
|
|
365
|
+
model: 'claude-opus-4-6',
|
|
366
|
+
bot: { $type: 'ref', $ref: '/brahman' },
|
|
367
|
+
})
|
|
368
|
+
await tree.set({
|
|
369
|
+
$path: '/brahman',
|
|
370
|
+
$type: 'tch.brahman.bot',
|
|
371
|
+
alias: '@treenitybot',
|
|
372
|
+
running: true,
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
return tree
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
describe('real-world: board tasks', () => {
|
|
379
|
+
test('read task title by path', async () => {
|
|
380
|
+
const tree = await seedRealWorld()
|
|
381
|
+
const task = await treeChain(tree).board.landing
|
|
382
|
+
assert.equal(task.title, 'Landing treenity.land')
|
|
383
|
+
assert.equal(task.status, 'doing')
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
test('list all board tasks', async () => {
|
|
387
|
+
const tree = await seedRealWorld()
|
|
388
|
+
const tasks = await treeChain(tree).board.$children()
|
|
389
|
+
assert.equal(tasks.length, 3)
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
test('filter tasks by status', async () => {
|
|
393
|
+
const tree = await seedRealWorld()
|
|
394
|
+
const doing = await treeChain(tree).board.$children({ status: 'doing' })
|
|
395
|
+
assert.equal(doing.length, 1)
|
|
396
|
+
assert.equal(doing[0].title, 'Landing treenity.land')
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
test('move task via action', async () => {
|
|
400
|
+
const tree = await seedRealWorld()
|
|
401
|
+
const result = await treeChain(tree).board.landing(BoardTask).move({ status: 'review' })
|
|
402
|
+
assert.deepEqual(result, { moved: 'review' })
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
test('assign task', async () => {
|
|
406
|
+
const tree = await seedRealWorld()
|
|
407
|
+
const result = await treeChain(tree).board['agent-toolkit'](BoardTask).assign({ to: 'agent' })
|
|
408
|
+
assert.deepEqual(result, { assigned: 'agent' })
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
test('save chain as bookmark, reuse', async () => {
|
|
412
|
+
const tree = await seedRealWorld()
|
|
413
|
+
const board = treeChain(tree).board
|
|
414
|
+
|
|
415
|
+
const t1 = await board.landing
|
|
416
|
+
const t2 = await board['npm-split']
|
|
417
|
+
assert.equal(t1.priority, 'urgent')
|
|
418
|
+
assert.equal(t2.status, 'done')
|
|
419
|
+
})
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
describe('real-world: cross-node refs', () => {
|
|
423
|
+
test('agent → bot ref auto-follow', async () => {
|
|
424
|
+
const tree = await seedRealWorld()
|
|
425
|
+
const bot = await treeChain(tree).agent.$get(AgentConfig).bot
|
|
426
|
+
assert.equal(bot.alias, '@treenitybot')
|
|
427
|
+
assert.equal(bot.running, true)
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
test('action through ref: restart bot via agent', async () => {
|
|
431
|
+
const tree = await seedRealWorld()
|
|
432
|
+
const result = await treeChain(tree)
|
|
433
|
+
.agent
|
|
434
|
+
.$get(AgentConfig).bot
|
|
435
|
+
.restart()
|
|
436
|
+
assert.deepEqual(result, { restarted: true })
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
test('read field through ref', async () => {
|
|
440
|
+
const tree = await seedRealWorld()
|
|
441
|
+
const alias = await treeChain(tree).agent.$get(AgentConfig).bot.alias
|
|
442
|
+
assert.equal(alias, '@treenitybot')
|
|
443
|
+
})
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
describe('real-world: (Class) bracket access', () => {
|
|
447
|
+
test('agent(AgentConfig).bot auto-follows ref', async () => {
|
|
448
|
+
const tree = await seedRealWorld()
|
|
449
|
+
const bot = await treeChain(tree).agent(AgentConfig).bot
|
|
450
|
+
assert.equal(bot.alias, '@treenitybot')
|
|
451
|
+
assert.equal(bot.running, true)
|
|
452
|
+
})
|
|
453
|
+
|
|
454
|
+
test('(Class) → ref → action', async () => {
|
|
455
|
+
const tree = await seedRealWorld()
|
|
456
|
+
const result = await treeChain(tree).agent(AgentConfig).bot.restart()
|
|
457
|
+
assert.deepEqual(result, { restarted: true })
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
test('(Class) → ref → field', async () => {
|
|
461
|
+
const tree = await seedRealWorld()
|
|
462
|
+
const alias = await treeChain(tree).agent(AgentConfig).bot.alias
|
|
463
|
+
assert.equal(alias, '@treenitybot')
|
|
464
|
+
})
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
describe('real-world: ergonomics comparison', () => {
|
|
468
|
+
// These tests show the same operation done via treeChain vs old API
|
|
469
|
+
// to demonstrate the ergonomics gain.
|
|
470
|
+
|
|
471
|
+
test('old way vs new way: read nested data', async () => {
|
|
472
|
+
const tree = await seedRealWorld()
|
|
473
|
+
|
|
474
|
+
// OLD: 3 lines, manual path construction, no types
|
|
475
|
+
const node = await tree.get('/board/landing')
|
|
476
|
+
assert.ok(node)
|
|
477
|
+
const title = node.title
|
|
478
|
+
|
|
479
|
+
// NEW: 1 expression, dot navigation
|
|
480
|
+
const title2 = (await treeChain(tree).board.landing).title
|
|
481
|
+
|
|
482
|
+
assert.equal(title, title2)
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
test('old way vs new way: follow ref + action', async () => {
|
|
486
|
+
const tree = await seedRealWorld()
|
|
487
|
+
|
|
488
|
+
// OLD: manual ref resolution, 4+ lines
|
|
489
|
+
const agentNode = await tree.get('/agent')
|
|
490
|
+
assert.ok(agentNode)
|
|
491
|
+
const botRef = (agentNode as any).bot
|
|
492
|
+
assert.ok(isRef(botRef))
|
|
493
|
+
// would need: const bot = await tree.get(botRef.$ref)
|
|
494
|
+
// then: executeAction(tree, botRef.$ref, ..., 'restart')
|
|
495
|
+
|
|
496
|
+
// NEW: one chain — navigate, follow ref, call action
|
|
497
|
+
const result = await treeChain(tree).agent.$get(AgentConfig).bot.restart()
|
|
498
|
+
assert.deepEqual(result, { restarted: true })
|
|
499
|
+
})
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
describe('treeChain — $set', () => {
|
|
503
|
+
test('creates node with type from class', async () => {
|
|
504
|
+
const tree = createMemoryTree()
|
|
505
|
+
await treeChain(tree).status.$set(LivePrices, { feederUrl: 'ws://example.com' })
|
|
506
|
+
const node = await tree.get('/status')
|
|
507
|
+
assert.ok(node)
|
|
508
|
+
assert.equal(node.$type, 'tch.live-prices')
|
|
509
|
+
assert.equal(node.feederUrl, 'ws://example.com')
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
test('overwrites existing node', async () => {
|
|
513
|
+
const tree = await seed()
|
|
514
|
+
await treeChain(tree).services.scanner.$set(Scanner, { intervalMs: 5000, maxRetries: 1 })
|
|
515
|
+
const node = await tree.get('/services/scanner')
|
|
516
|
+
assert.equal(node!.intervalMs, 5000)
|
|
517
|
+
assert.equal(node!.maxRetries, 1)
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
test('deep path via dot navigation', async () => {
|
|
521
|
+
const tree = createMemoryTree()
|
|
522
|
+
await treeChain(tree).a.b.c.$set(Profile, { name: 'Deep', balance: 42 })
|
|
523
|
+
const node = await tree.get('/a/b/c')
|
|
524
|
+
assert.ok(node)
|
|
525
|
+
assert.equal(node.$type, 'tch.profile')
|
|
526
|
+
assert.equal(node.name, 'Deep')
|
|
527
|
+
assert.equal(node.balance, 42)
|
|
528
|
+
})
|
|
529
|
+
|
|
530
|
+
test('no data — creates node with just type', async () => {
|
|
531
|
+
const tree = createMemoryTree()
|
|
532
|
+
await treeChain(tree).board.$set(BoardKanban)
|
|
533
|
+
const node = await tree.get('/board')
|
|
534
|
+
assert.ok(node)
|
|
535
|
+
assert.equal(node.$type, 'tch.board.kanban')
|
|
536
|
+
})
|
|
537
|
+
|
|
538
|
+
test('$set then read back via chain', async () => {
|
|
539
|
+
const tree = createMemoryTree()
|
|
540
|
+
const t = treeChain(tree)
|
|
541
|
+
await t.users.bob.$set(Profile, { name: 'Bob', balance: 250 })
|
|
542
|
+
const bob = await t.users.bob
|
|
543
|
+
assert.equal(bob.name, 'Bob')
|
|
544
|
+
assert.equal(bob.balance, 250)
|
|
545
|
+
})
|
|
546
|
+
|
|
547
|
+
test('$set with ref field', async () => {
|
|
548
|
+
const tree = createMemoryTree()
|
|
549
|
+
await treeChain(tree).brahman.$set(BrahmanBot, { alias: '@bot', running: true })
|
|
550
|
+
await treeChain(tree).agent.$set(AgentConfig, {
|
|
551
|
+
model: 'opus',
|
|
552
|
+
bot: { $type: 'ref', $ref: '/brahman' },
|
|
553
|
+
})
|
|
554
|
+
const bot = await treeChain(tree).agent(AgentConfig).bot
|
|
555
|
+
assert.equal(bot.alias, '@bot')
|
|
556
|
+
})
|
|
557
|
+
})
|
|
558
|
+
|
|
559
|
+
describe('treeChain — Symbol traps', () => {
|
|
560
|
+
test('Symbol.toPrimitive returns TreeChain(path)', () => {
|
|
561
|
+
const c = treeChain(null as any)
|
|
562
|
+
assert.equal(c.services.scanner[Symbol.toPrimitive], 'TreeChain(/services/scanner)')
|
|
563
|
+
})
|
|
564
|
+
|
|
565
|
+
test('Symbol.toPrimitive on root', () => {
|
|
566
|
+
assert.equal(treeChain(null as any)[Symbol.toPrimitive], 'TreeChain(/)')
|
|
567
|
+
})
|
|
568
|
+
|
|
569
|
+
test('Symbol.toStringTag', () => {
|
|
570
|
+
const c = treeChain(null as any).foo
|
|
571
|
+
assert.equal(c[Symbol.toStringTag], 'TreeChain(/foo)')
|
|
572
|
+
})
|
|
573
|
+
|
|
574
|
+
test('other symbols return undefined', () => {
|
|
575
|
+
const c = treeChain(null as any)
|
|
576
|
+
assert.equal(c[Symbol.iterator], undefined)
|
|
577
|
+
assert.equal(c[Symbol.asyncIterator], undefined)
|
|
578
|
+
})
|
|
579
|
+
})
|
|
580
|
+
|
|
581
|
+
describe('treeChain — basePath edge cases', () => {
|
|
582
|
+
test('basePath without leading slash', () => {
|
|
583
|
+
const c = treeChain(null as any, 'services/scanner')
|
|
584
|
+
assert.equal(c.$path, '/services/scanner')
|
|
585
|
+
})
|
|
586
|
+
|
|
587
|
+
test('basePath await resolves directly', async () => {
|
|
588
|
+
const tree = await seed()
|
|
589
|
+
const node = await treeChain(tree, '/services/scanner')
|
|
590
|
+
assert.equal(node.$type, 'tch.scanner')
|
|
591
|
+
assert.equal(node.intervalMs, 900_000)
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
test('basePath + child nav', async () => {
|
|
595
|
+
const tree = await seed()
|
|
596
|
+
const node = await treeChain(tree, '/services').scanner
|
|
597
|
+
assert.equal(node.$type, 'tch.scanner')
|
|
598
|
+
})
|
|
599
|
+
})
|
|
600
|
+
|
|
601
|
+
describe('treeChain — error paths', () => {
|
|
602
|
+
test('action without (Class) throws', async () => {
|
|
603
|
+
const tree = await seed()
|
|
604
|
+
await assert.rejects(
|
|
605
|
+
async () => { await treeChain(tree).services.scanner.scan() },
|
|
606
|
+
(e: Error) => e.message.includes('Class'),
|
|
607
|
+
)
|
|
608
|
+
})
|
|
609
|
+
|
|
610
|
+
test('unregistered action throws', async () => {
|
|
611
|
+
const tree = await seed()
|
|
612
|
+
await assert.rejects(
|
|
613
|
+
async () => { await treeChain(tree).services.scanner(Scanner).nonexistent() },
|
|
614
|
+
(e: Error) => e.message.includes('action'),
|
|
615
|
+
)
|
|
616
|
+
})
|
|
617
|
+
|
|
618
|
+
test('null field in ops throws', async () => {
|
|
619
|
+
const tree = await seed()
|
|
620
|
+
await assert.rejects(
|
|
621
|
+
async () => { await treeChain(tree).services.scanner.$get(Scanner).noSuchField },
|
|
622
|
+
(e: Error) => e.message.includes('null'),
|
|
623
|
+
)
|
|
624
|
+
})
|
|
625
|
+
|
|
626
|
+
test('$get with missing named component throws', async () => {
|
|
627
|
+
const tree = await seed()
|
|
628
|
+
await assert.rejects(
|
|
629
|
+
async () => { await treeChain(tree).services.scanner.$get(null, 'ghost') },
|
|
630
|
+
(e: Error) => e.message.includes('ghost'),
|
|
631
|
+
)
|
|
632
|
+
})
|
|
633
|
+
|
|
634
|
+
test('await root of empty tree throws', async () => {
|
|
635
|
+
const tree = createMemoryTree()
|
|
636
|
+
await assert.rejects(async () => { await treeChain(tree) })
|
|
637
|
+
})
|
|
638
|
+
})
|
|
639
|
+
|
|
640
|
+
describe('treeChain — (Class) where node.$type matches', () => {
|
|
641
|
+
test('getComp returns node itself when $type matches', async () => {
|
|
642
|
+
const tree = await seed()
|
|
643
|
+
// scanner.$type === 'tch.scanner', Scanner.$type === 'tch.scanner'
|
|
644
|
+
// getComp returns node itself — all fields at node level
|
|
645
|
+
const scanner = await treeChain(tree).services.scanner(Scanner)
|
|
646
|
+
assert.equal(scanner.$type, 'tch.scanner')
|
|
647
|
+
assert.equal(scanner.intervalMs, 900_000)
|
|
648
|
+
assert.equal(scanner.$path, '/services/scanner')
|
|
649
|
+
})
|
|
650
|
+
})
|
|
651
|
+
|
|
652
|
+
describe('treeChain — ref edge cases', () => {
|
|
653
|
+
test('ref without $type field is still followed', async () => {
|
|
654
|
+
const tree = createMemoryTree()
|
|
655
|
+
await tree.set({
|
|
656
|
+
$path: '/target',
|
|
657
|
+
$type: 'tch.live-prices',
|
|
658
|
+
feederUrl: 'ws://bare-ref',
|
|
659
|
+
})
|
|
660
|
+
await tree.set({
|
|
661
|
+
$path: '/source',
|
|
662
|
+
$type: 'tch.scanner',
|
|
663
|
+
intervalMs: 1,
|
|
664
|
+
maxRetries: 1,
|
|
665
|
+
// ref without $type — isRef accepts { $ref: string }
|
|
666
|
+
livePrices: { $ref: '/target' },
|
|
667
|
+
})
|
|
668
|
+
const lp = await treeChain(tree).source.$get(Scanner).livePrices
|
|
669
|
+
assert.equal(lp.feederUrl, 'ws://bare-ref')
|
|
670
|
+
})
|
|
671
|
+
|
|
672
|
+
test('ref field → then read field on resolved target', async () => {
|
|
673
|
+
const tree = await seed()
|
|
674
|
+
const url = await treeChain(tree).services.scanner(Scanner).livePrices.feederUrl
|
|
675
|
+
assert.equal(url, 'ws://localhost:8090')
|
|
676
|
+
})
|
|
677
|
+
})
|
|
678
|
+
|
|
679
|
+
describe('treeChain — multiple ops chain', () => {
|
|
680
|
+
test('field → field reads chain correctly', async () => {
|
|
681
|
+
const tree = createMemoryTree()
|
|
682
|
+
await tree.set({
|
|
683
|
+
$path: '/config',
|
|
684
|
+
$type: 'tch.scanner',
|
|
685
|
+
intervalMs: 1,
|
|
686
|
+
maxRetries: 1,
|
|
687
|
+
livePrices: { $type: 'ref', $ref: '/lp' },
|
|
688
|
+
nested: { $type: 'tch.wallet', address: '0x123', chain: 'polygon' },
|
|
689
|
+
})
|
|
690
|
+
await tree.set({ $path: '/lp', $type: 'tch.live-prices', feederUrl: 'ws://chain' })
|
|
691
|
+
|
|
692
|
+
// $get → field (nested component, not a ref) → field
|
|
693
|
+
const chain = await treeChain(tree).config.$get(null, 'nested').chain
|
|
694
|
+
assert.equal(chain, 'polygon')
|
|
695
|
+
})
|
|
696
|
+
})
|
|
697
|
+
|
|
698
|
+
describe('treeChain — chain isolation', () => {
|
|
699
|
+
test('two chains from same root are independent', async () => {
|
|
700
|
+
const tree = await seed()
|
|
701
|
+
const t = treeChain(tree)
|
|
702
|
+
|
|
703
|
+
const chain1 = t.services.scanner.$get(Scanner)
|
|
704
|
+
const chain2 = t.services['live-prices']
|
|
705
|
+
|
|
706
|
+
const s = await chain1
|
|
707
|
+
const lp = await chain2
|
|
708
|
+
assert.equal(s.$type, 'tch.scanner')
|
|
709
|
+
assert.equal(lp.$type, 'tch.live-prices')
|
|
710
|
+
})
|
|
711
|
+
|
|
712
|
+
test('(Class) on one branch does not affect another', async () => {
|
|
713
|
+
const tree = await seed()
|
|
714
|
+
const services = treeChain(tree).services
|
|
715
|
+
|
|
716
|
+
const typed = await services.scanner(Scanner)
|
|
717
|
+
const raw = await services.scanner
|
|
718
|
+
|
|
719
|
+
assert.equal(typed.intervalMs, 900_000)
|
|
720
|
+
assert.equal(raw.intervalMs, 900_000)
|
|
721
|
+
assert.equal(raw.$type, 'tch.scanner')
|
|
722
|
+
})
|
|
723
|
+
})
|