@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,202 @@
|
|
|
1
|
+
// Treenity WatchManager — Layer 5
|
|
2
|
+
// Exact-path + prefix (children) watch/unwatch per user.
|
|
3
|
+
// Supports multiple connections per user (multi-tab).
|
|
4
|
+
// Grace period: on last disconnect, watches survive briefly for SSE auto-reconnect.
|
|
5
|
+
|
|
6
|
+
import { type NodeEvent } from './sub';
|
|
7
|
+
|
|
8
|
+
export type WatchPush = (event: NodeEvent) => void;
|
|
9
|
+
|
|
10
|
+
export type WatchManagerOpts = {
|
|
11
|
+
gracePeriodMs?: number;
|
|
12
|
+
onUserRemoved?: (userId: string) => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type WatchOpts = { children?: boolean; autoWatch?: boolean };
|
|
16
|
+
|
|
17
|
+
export type WatchManager = {
|
|
18
|
+
/** Attach push channel. Returns true if watches were preserved (reconnect within grace). */
|
|
19
|
+
connect(connId: string, userId: string, push: WatchPush): boolean;
|
|
20
|
+
disconnect(connId: string): void;
|
|
21
|
+
watch(userId: string, paths: string[], opts?: WatchOpts): void;
|
|
22
|
+
unwatch(userId: string, paths: string[], opts?: { children?: boolean }): void;
|
|
23
|
+
notify(event: NodeEvent): void;
|
|
24
|
+
clientCount(): number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const DEFAULT_GRACE_MS = 5_000;
|
|
28
|
+
|
|
29
|
+
function addTo(map: Map<string, Set<string>>, key: string, uid: string) {
|
|
30
|
+
let set = map.get(key);
|
|
31
|
+
if (!set) {
|
|
32
|
+
set = new Set();
|
|
33
|
+
map.set(key, set);
|
|
34
|
+
}
|
|
35
|
+
set.add(uid);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function removeFrom(map: Map<string, Set<string>>, key: string, uid: string) {
|
|
39
|
+
const set = map.get(key);
|
|
40
|
+
if (!set) return;
|
|
41
|
+
set.delete(uid);
|
|
42
|
+
if (set.size === 0) map.delete(key);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function createWatchManager(opts?: WatchManagerOpts): WatchManager {
|
|
46
|
+
const gracePeriodMs = opts?.gracePeriodMs ?? DEFAULT_GRACE_MS;
|
|
47
|
+
const pathToUsers = new Map<string, Set<string>>();
|
|
48
|
+
const prefixToUsers = new Map<string, Set<string>>();
|
|
49
|
+
const users = new Map<
|
|
50
|
+
string,
|
|
51
|
+
{ pushes: Map<string, WatchPush>; paths: Set<string>; prefixes: Map<string, boolean> }
|
|
52
|
+
>();
|
|
53
|
+
const graceTimers = new Map<string, ReturnType<typeof setTimeout>>();
|
|
54
|
+
|
|
55
|
+
function removeUser(userId: string) {
|
|
56
|
+
const user = users.get(userId);
|
|
57
|
+
if (!user) return;
|
|
58
|
+
for (const p of user.paths) removeFrom(pathToUsers, p, userId);
|
|
59
|
+
for (const p of user.prefixes.keys()) removeFrom(prefixToUsers, p, userId);
|
|
60
|
+
users.delete(userId);
|
|
61
|
+
opts?.onUserRemoved?.(userId);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function pushToUser(uid: string, event: NodeEvent) {
|
|
65
|
+
const user = users.get(uid);
|
|
66
|
+
if (!user) return;
|
|
67
|
+
for (const push of user.pushes.values()) push(event);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function ensureUser(userId: string) {
|
|
71
|
+
let user = users.get(userId);
|
|
72
|
+
if (!user) {
|
|
73
|
+
user = { pushes: new Map(), paths: new Set(), prefixes: new Map() };
|
|
74
|
+
users.set(userId, user);
|
|
75
|
+
}
|
|
76
|
+
return user;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
connect(connId, userId, push) {
|
|
81
|
+
// Cancel grace timer — user reconnected in time
|
|
82
|
+
const timer = graceTimers.get(userId);
|
|
83
|
+
if (timer) {
|
|
84
|
+
clearTimeout(timer);
|
|
85
|
+
graceTimers.delete(userId);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const preserved = users.has(userId);
|
|
89
|
+
const user = ensureUser(userId);
|
|
90
|
+
user.pushes.set(connId, push);
|
|
91
|
+
return preserved;
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
disconnect(connId) {
|
|
95
|
+
for (const [userId, user] of users) {
|
|
96
|
+
if (!user.pushes.has(connId)) continue;
|
|
97
|
+
user.pushes.delete(connId);
|
|
98
|
+
|
|
99
|
+
if (user.pushes.size === 0) {
|
|
100
|
+
// Start grace period — don't nuke watches yet
|
|
101
|
+
const timer = setTimeout(() => {
|
|
102
|
+
graceTimers.delete(userId);
|
|
103
|
+
const u = users.get(userId);
|
|
104
|
+
if (u && u.pushes.size === 0) removeUser(userId);
|
|
105
|
+
}, gracePeriodMs);
|
|
106
|
+
graceTimers.set(userId, timer);
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
watch(userId, paths, watchOpts) {
|
|
113
|
+
const user = ensureUser(userId);
|
|
114
|
+
|
|
115
|
+
if (watchOpts?.children) {
|
|
116
|
+
for (const p of paths) {
|
|
117
|
+
user.prefixes.set(p, watchOpts.autoWatch ?? false);
|
|
118
|
+
addTo(prefixToUsers, p, userId);
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
for (const p of paths) {
|
|
122
|
+
user.paths.add(p);
|
|
123
|
+
addTo(pathToUsers, p, userId);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
unwatch(userId, paths, unwatchOpts) {
|
|
129
|
+
const user = users.get(userId);
|
|
130
|
+
if (!user) return;
|
|
131
|
+
|
|
132
|
+
if (unwatchOpts?.children) {
|
|
133
|
+
for (const p of paths) {
|
|
134
|
+
user.prefixes.delete(p);
|
|
135
|
+
removeFrom(prefixToUsers, p, userId);
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
for (const p of paths) {
|
|
139
|
+
user.paths.delete(p);
|
|
140
|
+
removeFrom(pathToUsers, p, userId);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
notify(event) {
|
|
146
|
+
if (event.type === 'reconnect') return;
|
|
147
|
+
const notified = new Set<string>();
|
|
148
|
+
|
|
149
|
+
// Exact match
|
|
150
|
+
const exact = pathToUsers.get(event.path);
|
|
151
|
+
if (exact)
|
|
152
|
+
for (const uid of exact) {
|
|
153
|
+
notified.add(uid);
|
|
154
|
+
pushToUser(uid, event);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Prefix match: direct parent only (mirrors getChildren depth=1)
|
|
158
|
+
const idx = event.path.lastIndexOf('/');
|
|
159
|
+
if (idx < 0) return;
|
|
160
|
+
const parent = idx === 0 ? '/' : event.path.slice(0, idx);
|
|
161
|
+
const watchers = prefixToUsers.get(parent);
|
|
162
|
+
if (watchers)
|
|
163
|
+
for (const uid of watchers) {
|
|
164
|
+
if (notified.has(uid)) continue;
|
|
165
|
+
notified.add(uid);
|
|
166
|
+
const user = users.get(uid);
|
|
167
|
+
if (!user) continue;
|
|
168
|
+
pushToUser(uid, event);
|
|
169
|
+
// autoWatch: subscribe to exact path for future updates
|
|
170
|
+
if (user.prefixes.get(parent)) {
|
|
171
|
+
user.paths.add(event.path);
|
|
172
|
+
addTo(pathToUsers, event.path, uid);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Virtual Parent Match (CDC Matrix events)
|
|
177
|
+
const vps = [...('addVps' in event && event.addVps ? event.addVps : []), ...(event.rmVps || [])];
|
|
178
|
+
for (const vp of vps) {
|
|
179
|
+
const vpWatchers = prefixToUsers.get(vp);
|
|
180
|
+
if (vpWatchers) {
|
|
181
|
+
for (const uid of vpWatchers) {
|
|
182
|
+
if (notified.has(uid)) continue;
|
|
183
|
+
notified.add(uid);
|
|
184
|
+
const user = users.get(uid);
|
|
185
|
+
if (!user) continue;
|
|
186
|
+
pushToUser(uid, event);
|
|
187
|
+
if (user.prefixes.get(vp)) {
|
|
188
|
+
user.paths.add(event.path);
|
|
189
|
+
addTo(pathToUsers, event.path, uid);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
clientCount() {
|
|
197
|
+
let count = 0;
|
|
198
|
+
for (const user of users.values()) count += user.pushes.size;
|
|
199
|
+
return count;
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { registerType } from '#comp';
|
|
2
|
+
import { createNode } from '#core';
|
|
3
|
+
import { clearRegistry } from '#core/index.test';
|
|
4
|
+
import { createMemoryTree, type Tree } from '#tree';
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
6
|
+
import { beforeEach, describe, it } from 'node:test';
|
|
7
|
+
import { withMounts } from './mount';
|
|
8
|
+
import { createTreeRouter } from './trpc';
|
|
9
|
+
import { createWatchManager } from './watch';
|
|
10
|
+
|
|
11
|
+
class Order {
|
|
12
|
+
status = 'new';
|
|
13
|
+
|
|
14
|
+
cook() {
|
|
15
|
+
this.status = 'kitchen';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('Workflow & Spatial Gravity', () => {
|
|
20
|
+
let rootStore: Tree;
|
|
21
|
+
let trpcStore: Tree;
|
|
22
|
+
|
|
23
|
+
beforeEach(async () => {
|
|
24
|
+
clearRegistry();
|
|
25
|
+
// We register the query mount manually or import it
|
|
26
|
+
await import('./mount-adapters');
|
|
27
|
+
registerType('order', Order);
|
|
28
|
+
rootStore = createMemoryTree();
|
|
29
|
+
trpcStore = withMounts(rootStore);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('moves order from new to kitchen seamlessly with Immer patch', async () => {
|
|
33
|
+
// 0. Setup root ACL
|
|
34
|
+
await trpcStore.set({
|
|
35
|
+
...createNode('/', 'root'),
|
|
36
|
+
$acl: [{ g: 'public', p: 15 }]
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// 1. Setup flat data folder
|
|
40
|
+
await trpcStore.set(createNode('/entities/orders/1', 'order', { status: 'new' }));
|
|
41
|
+
|
|
42
|
+
// 2. Setup query mounts
|
|
43
|
+
await trpcStore.set(
|
|
44
|
+
createNode('/workflows/new', 'folder', {}, {
|
|
45
|
+
mount: { $type: 't.mount.query' },
|
|
46
|
+
query: { $type: 'query', source: '/entities/orders', match: { status: 'new' } }
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
await trpcStore.set(
|
|
50
|
+
createNode('/workflows/kitchen', 'folder', {}, {
|
|
51
|
+
mount: { $type: 't.mount.query' },
|
|
52
|
+
query: { $type: 'query', source: '/entities/orders', match: { status: 'kitchen' } }
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// Initial check
|
|
57
|
+
let newFolder = await trpcStore.getChildren('/workflows/new');
|
|
58
|
+
let kitchenFolder = await trpcStore.getChildren('/workflows/kitchen');
|
|
59
|
+
assert.equal(newFolder.items.length, 1);
|
|
60
|
+
assert.equal(kitchenFolder.items.length, 0);
|
|
61
|
+
|
|
62
|
+
// Create tRPC router
|
|
63
|
+
const watcher = createWatchManager();
|
|
64
|
+
const router = createTreeRouter(trpcStore as any, watcher);
|
|
65
|
+
const caller = router.createCaller({ session: null, token: null });
|
|
66
|
+
|
|
67
|
+
// Execute the action (should emit patches in console and update DB)
|
|
68
|
+
await caller.execute({
|
|
69
|
+
path: '/entities/orders/1',
|
|
70
|
+
action: 'cook',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Check spatial gravity (moved via query mounts)
|
|
74
|
+
newFolder = await trpcStore.getChildren('/workflows/new');
|
|
75
|
+
kitchenFolder = await trpcStore.getChildren('/workflows/kitchen');
|
|
76
|
+
|
|
77
|
+
assert.equal(newFolder.items.length, 0, 'Order should leave /workflows/new');
|
|
78
|
+
assert.equal(kitchenFolder.items.length, 1, 'Order should appear in /workflows/kitchen');
|
|
79
|
+
assert.equal(kitchenFolder.items[0].$path, '/entities/orders/1', 'Order path remains canonical');
|
|
80
|
+
assert.equal(kitchenFolder.items[0].status, 'kitchen', 'Status is updated');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## store (Tree)
|
|
2
|
+
Tree interface + adapters. Layer 1 — no deps except core types.
|
|
3
|
+
|
|
4
|
+
### Файлы
|
|
5
|
+
- index.ts — Tree interface, paginate, createMemoryTree, createOverlayTree, createFilterTree, resolveRef
|
|
6
|
+
- mongo.ts — MongoDB adapter with $↔_ field mapping, $rev OCC (conditional replaceOne)
|
|
7
|
+
- fs.ts — FS adapter (JSON files on disk), $rev OCC
|
|
8
|
+
- query.ts — Query tree: virtual filtered view via sift (Mongo syntax). Used by t.mount.query
|
|
9
|
+
|
|
10
|
+
### Конвенции
|
|
11
|
+
- $rev: if present on incoming node → OCC check (match stored rev). If absent → blind upsert
|
|
12
|
+
- Mongo: $ prefix → _ prefix transparently (toStorage/fromStorage)
|
|
13
|
+
- Tree composability: overlay(upper, lower), filter(upper, lower, predicate)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import { withCache } from './cache';
|
|
4
|
+
import { createMemoryTree } from './index';
|
|
5
|
+
|
|
6
|
+
function makeNode(path: string, extra?: Record<string, unknown>) {
|
|
7
|
+
return { $path: path, $type: 'test', ...extra };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe('withCache — reads', () => {
|
|
11
|
+
it('miss: delegates to underlying store', async () => {
|
|
12
|
+
const mem = createMemoryTree();
|
|
13
|
+
await mem.set(makeNode('/a'));
|
|
14
|
+
const cached = withCache(mem);
|
|
15
|
+
const node = await cached.get('/a');
|
|
16
|
+
assert.ok(node);
|
|
17
|
+
assert.equal(node.$path, '/a');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('hit: second get does not call underlying store', async () => {
|
|
21
|
+
let calls = 0;
|
|
22
|
+
const mem = createMemoryTree();
|
|
23
|
+
await mem.set(makeNode('/a'));
|
|
24
|
+
|
|
25
|
+
const spied: typeof mem = {
|
|
26
|
+
...mem,
|
|
27
|
+
async get(path, ctx) { calls++; return mem.get(path, ctx); },
|
|
28
|
+
async getChildren(p, o, c) { return mem.getChildren(p, o, c); },
|
|
29
|
+
async set(n, c) { return mem.set(n, c); },
|
|
30
|
+
async remove(p, c) { return mem.remove(p, c); },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const cached = withCache(spied);
|
|
34
|
+
await cached.get('/a'); // miss — calls underlying
|
|
35
|
+
await cached.get('/a'); // hit — should NOT call underlying
|
|
36
|
+
assert.equal(calls, 1);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('get on missing path returns undefined without caching null', async () => {
|
|
40
|
+
const mem = createMemoryTree();
|
|
41
|
+
const cached = withCache(mem);
|
|
42
|
+
const result = await cached.get('/nonexistent');
|
|
43
|
+
assert.equal(result, undefined);
|
|
44
|
+
// After the node is added, it should be fetchable
|
|
45
|
+
await mem.set(makeNode('/nonexistent'));
|
|
46
|
+
const fresh = await cached.get('/nonexistent');
|
|
47
|
+
assert.ok(fresh);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('withCache — writes populate', () => {
|
|
52
|
+
it('set populates cache — next get returns fresh without underlying call', async () => {
|
|
53
|
+
let gets = 0;
|
|
54
|
+
const mem = createMemoryTree();
|
|
55
|
+
|
|
56
|
+
const spied: typeof mem = {
|
|
57
|
+
...mem,
|
|
58
|
+
async get(path, ctx) { gets++; return mem.get(path, ctx); },
|
|
59
|
+
async getChildren(p, o, c) { return mem.getChildren(p, o, c); },
|
|
60
|
+
async set(n, c) { return mem.set(n, c); },
|
|
61
|
+
async remove(p, c) { return mem.remove(p, c); },
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const cached = withCache(spied);
|
|
65
|
+
await cached.set(makeNode('/a', { v: 1 })); // write-populate: 1 get for re-read
|
|
66
|
+
gets = 0;
|
|
67
|
+
|
|
68
|
+
const node = await cached.get('/a'); // should hit cache
|
|
69
|
+
assert.equal(gets, 0);
|
|
70
|
+
assert.equal((node as any).v, 1);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('set captures fresh $rev in cache', async () => {
|
|
74
|
+
const mem = createMemoryTree();
|
|
75
|
+
const cached = withCache(mem);
|
|
76
|
+
|
|
77
|
+
await cached.set(makeNode('/a', { v: 1 }));
|
|
78
|
+
const node = await cached.get('/a');
|
|
79
|
+
assert.equal(node?.$rev, 1, 'cache should have $rev bumped by store');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('set then bypass update then set — cache reflects last write', async () => {
|
|
83
|
+
const mem = createMemoryTree();
|
|
84
|
+
const cached = withCache(mem);
|
|
85
|
+
|
|
86
|
+
await cached.set(makeNode('/a', { v: 1 }));
|
|
87
|
+
await mem.set(makeNode('/a', { v: 2 })); // bypass cache
|
|
88
|
+
await cached.set(makeNode('/a', { v: 3 })); // write-populate
|
|
89
|
+
|
|
90
|
+
const node = await cached.get('/a');
|
|
91
|
+
assert.equal((node as any).v, 3);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('remove invalidates cache entry', async () => {
|
|
95
|
+
const mem = createMemoryTree();
|
|
96
|
+
await mem.set(makeNode('/a'));
|
|
97
|
+
const cached = withCache(mem);
|
|
98
|
+
|
|
99
|
+
await cached.get('/a'); // populate cache
|
|
100
|
+
await cached.remove('/a'); // invalidate
|
|
101
|
+
const node = await cached.get('/a');
|
|
102
|
+
assert.equal(node, undefined);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe('withCache — inflight dedup', () => {
|
|
107
|
+
it('concurrent gets produce single underlying call', async () => {
|
|
108
|
+
let calls = 0;
|
|
109
|
+
const mem = createMemoryTree();
|
|
110
|
+
await mem.set(makeNode('/a', { v: 42 }));
|
|
111
|
+
|
|
112
|
+
const spied: typeof mem = {
|
|
113
|
+
...mem,
|
|
114
|
+
async get(path, ctx) {
|
|
115
|
+
calls++;
|
|
116
|
+
// Simulate async delay
|
|
117
|
+
await new Promise(r => setImmediate(r));
|
|
118
|
+
return mem.get(path, ctx);
|
|
119
|
+
},
|
|
120
|
+
async getChildren(p, o, c) { return mem.getChildren(p, o, c); },
|
|
121
|
+
async set(n, c) { return mem.set(n, c); },
|
|
122
|
+
async remove(p, c) { return mem.remove(p, c); },
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const cached = withCache(spied);
|
|
126
|
+
|
|
127
|
+
// Fire 10 concurrent gets
|
|
128
|
+
const results = await Promise.all(
|
|
129
|
+
Array.from({ length: 10 }, () => cached.get('/a')),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
assert.equal(calls, 1, 'only one underlying get call');
|
|
133
|
+
for (const r of results) {
|
|
134
|
+
assert.equal((r as any).v, 42);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('after inflight settles, next call retries', async () => {
|
|
139
|
+
let calls = 0;
|
|
140
|
+
const mem = createMemoryTree();
|
|
141
|
+
await mem.set(makeNode('/a'));
|
|
142
|
+
|
|
143
|
+
const spied: typeof mem = {
|
|
144
|
+
...mem,
|
|
145
|
+
async get(path, ctx) { calls++; return mem.get(path, ctx); },
|
|
146
|
+
async getChildren(p, o, c) { return mem.getChildren(p, o, c); },
|
|
147
|
+
async set(n, c) { return mem.set(n, c); },
|
|
148
|
+
async remove(p, c) { return mem.remove(p, c); },
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const cached = withCache(spied);
|
|
152
|
+
await cached.get('/a'); // miss → call 1, populates cache
|
|
153
|
+
await cached.remove('/a'); // invalidates
|
|
154
|
+
await mem.set(makeNode('/a')); // restore in underlying
|
|
155
|
+
await cached.get('/a'); // miss again → call 2
|
|
156
|
+
assert.equal(calls, 2);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('withCache — getChildren populates cache', () => {
|
|
161
|
+
it('nodes fetched via getChildren are cached for subsequent get', async () => {
|
|
162
|
+
let gets = 0;
|
|
163
|
+
const mem = createMemoryTree();
|
|
164
|
+
await mem.set(makeNode('/parent'));
|
|
165
|
+
await mem.set(makeNode('/parent/child'));
|
|
166
|
+
|
|
167
|
+
const spied: typeof mem = {
|
|
168
|
+
...mem,
|
|
169
|
+
async get(path, ctx) { gets++; return mem.get(path, ctx); },
|
|
170
|
+
async getChildren(p, o, c) { return mem.getChildren(p, o, c); },
|
|
171
|
+
async set(n, c) { return mem.set(n, c); },
|
|
172
|
+
async remove(p, c) { return mem.remove(p, c); },
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const cached = withCache(spied);
|
|
176
|
+
await cached.getChildren('/parent'); // fetches children, populates cache
|
|
177
|
+
gets = 0; // reset counter
|
|
178
|
+
|
|
179
|
+
await cached.get('/parent/child'); // should hit cache, not call underlying
|
|
180
|
+
assert.equal(gets, 0);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
describe('withCache — tree structure', () => {
|
|
185
|
+
it('caches deep paths independently', async () => {
|
|
186
|
+
const mem = createMemoryTree();
|
|
187
|
+
await mem.set(makeNode('/a/b/c'));
|
|
188
|
+
await mem.set(makeNode('/a/b/d'));
|
|
189
|
+
const cached = withCache(mem);
|
|
190
|
+
|
|
191
|
+
await cached.get('/a/b/c');
|
|
192
|
+
await cached.get('/a/b/d');
|
|
193
|
+
|
|
194
|
+
// Verify both are in cache by checking remove invalidates correctly
|
|
195
|
+
await cached.remove('/a/b/c');
|
|
196
|
+
const c = await cached.get('/a/b/c');
|
|
197
|
+
const d = await cached.get('/a/b/d'); // /d is still cached
|
|
198
|
+
assert.equal(c, undefined);
|
|
199
|
+
assert.ok(d);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('sibling paths do not interfere', async () => {
|
|
203
|
+
const mem = createMemoryTree();
|
|
204
|
+
await mem.set(makeNode('/x/a', { tag: 'a' }));
|
|
205
|
+
await mem.set(makeNode('/x/b', { tag: 'b' }));
|
|
206
|
+
const cached = withCache(mem);
|
|
207
|
+
|
|
208
|
+
const a = await cached.get('/x/a');
|
|
209
|
+
const b = await cached.get('/x/b');
|
|
210
|
+
assert.equal((a as any).tag, 'a');
|
|
211
|
+
assert.equal((b as any).tag, 'b');
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Treenity Cache Tree — Layer 1
|
|
2
|
+
// Write-populate tree cache wrapping any Tree.
|
|
3
|
+
// Tree structure mirrors path hierarchy — O(depth) navigation, O(1) subtree drop.
|
|
4
|
+
// Populate on read AND write. Inflight dedup prevents thundering herd.
|
|
5
|
+
|
|
6
|
+
import type { NodeData } from '#core';
|
|
7
|
+
import { type Tree, treeEnsure, treeNavigate, type TreeNode } from './index';
|
|
8
|
+
import { createInflight } from './inflight';
|
|
9
|
+
|
|
10
|
+
export function withCache(store: Tree): Tree {
|
|
11
|
+
const root: TreeNode<NodeData> = { children: new Map() };
|
|
12
|
+
const dedup = createInflight<NodeData | undefined>();
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
async get(path, ctx) {
|
|
16
|
+
const cached = treeNavigate(root, path);
|
|
17
|
+
if (cached?.data !== undefined) return cached.data;
|
|
18
|
+
return dedup(path, async () => {
|
|
19
|
+
const node = await store.get(path, ctx);
|
|
20
|
+
if (node) treeEnsure(root, node.$path).data = node;
|
|
21
|
+
return node;
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
async getChildren(path, opts, ctx) {
|
|
26
|
+
const result = await store.getChildren(path, opts, ctx);
|
|
27
|
+
for (const node of result.items) treeEnsure(root, node.$path).data = node;
|
|
28
|
+
return result;
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
async set(node, ctx) {
|
|
32
|
+
await store.set(node, ctx);
|
|
33
|
+
// Write-populate: re-read to capture $rev bump, warm cache for subscribers
|
|
34
|
+
const fresh = await store.get(node.$path, ctx);
|
|
35
|
+
treeEnsure(root, node.$path).data = fresh;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async remove(path, ctx) {
|
|
39
|
+
const result = await store.remove(path, ctx);
|
|
40
|
+
const cached = treeNavigate(root, path);
|
|
41
|
+
if (cached) cached.data = undefined;
|
|
42
|
+
return result;
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
async patch(path, ops, ctx) {
|
|
46
|
+
await store.patch(path, ops, ctx);
|
|
47
|
+
const fresh = await store.get(path, ctx);
|
|
48
|
+
treeEnsure(root, path).data = fresh;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|