@treenity/core 1.0.48 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -12
- package/dist/chain.d.ts +19 -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 +79 -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 +41 -0
- package/dist/comp/index.d.ts.map +1 -0
- package/dist/comp/index.js +127 -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 +43 -0
- package/dist/core/component.d.ts.map +1 -0
- package/dist/core/component.js +101 -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 +41 -0
- package/dist/core/path.js.map +1 -0
- package/dist/core/registry.d.ts +17 -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/index.d.ts +1 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts +38 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +150 -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 +17 -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 +19 -0
- package/dist/mod/loader.d.ts.map +1 -0
- package/dist/mod/loader.js +180 -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/clients.d.ts +2 -0
- package/dist/mods/clients.d.ts.map +1 -0
- package/dist/mods/clients.js +3 -0
- package/dist/mods/clients.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 +2 -0
- package/dist/mods/mcp/server.js +2 -0
- package/dist/mods/mcp/service.d.ts +1 -0
- package/dist/mods/mcp/service.js +16 -0
- package/dist/mods/mcp/types.d.ts +4 -0
- package/dist/mods/mcp/types.js +6 -0
- package/dist/mods/servers.d.ts +4 -0
- package/dist/mods/servers.d.ts.map +1 -0
- package/dist/mods/servers.js +5 -0
- package/dist/mods/servers.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/builtins.d.ts +2 -0
- package/dist/mods/treenity/builtins.d.ts.map +1 -0
- package/dist/mods/treenity/builtins.js +18 -0
- package/dist/mods/treenity/builtins.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/logs.d.ts +18 -0
- package/dist/mods/treenity/logs.d.ts.map +1 -0
- package/dist/mods/treenity/logs.js +17 -0
- package/dist/mods/treenity/logs.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 +55 -0
- package/dist/mods/treenity/seed.js.map +1 -0
- package/dist/mods/treenity/server.d.ts +7 -0
- package/dist/mods/treenity/server.d.ts.map +1 -0
- package/dist/mods/treenity/server.js +7 -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 +96 -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/_test-fixture.d.ts +11 -0
- package/dist/schema/_test-fixture.d.ts.map +1 -0
- package/dist/schema/_test-fixture.js +8 -0
- package/dist/schema/_test-fixture.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/types.d.ts +38 -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 +336 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/client.d.ts +190 -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 +245 -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 +29 -0
- package/dist/server/factory.d.ts.map +1 -0
- package/dist/server/factory.js +89 -0
- package/dist/server/factory.js.map +1 -0
- package/dist/server/main.d.ts +2 -0
- package/dist/server/main.d.ts.map +1 -0
- package/dist/server/main.js +19 -0
- package/dist/server/main.js.map +1 -0
- package/dist/server/mcp.d.ts +4 -0
- package/dist/server/mcp.js +279 -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 +3 -0
- package/dist/server/mods-mount.d.ts.map +1 -0
- package/dist/server/mods-mount.js +168 -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 +80 -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 +72 -0
- package/dist/server/prefab.js.map +1 -0
- package/dist/server/refs.d.ts +3 -0
- package/dist/server/refs.d.ts.map +1 -0
- package/dist/server/refs.js +59 -0
- package/dist/server/refs.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 +127 -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 +199 -0
- package/dist/server/trpc.d.ts.map +1 -0
- package/dist/server/trpc.js +323 -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 +276 -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 +183 -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 +19 -0
- package/dist/tree-chain.d.ts.map +1 -0
- package/dist/tree-chain.js +111 -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 +84 -0
- package/dist/uri.js.map +1 -0
- package/package.json +78 -37
- package/src/chain.test.ts +190 -0
- package/src/chain.ts +84 -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 +92 -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 +165 -0
- package/src/comp/index.ts +186 -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 +153 -0
- package/src/core/context.ts +14 -0
- package/src/core/index.test.ts +224 -0
- package/src/core/index.ts +9 -0
- package/src/core/path.ts +38 -0
- package/src/core/registry.ts +112 -0
- package/src/core.ts +1 -0
- package/src/index.ts +1 -0
- package/src/log.test.ts +70 -0
- package/src/log.ts +199 -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 +108 -0
- package/src/mod/docs/08-services.md +35 -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 +108 -0
- package/src/mod/docs/13-example.md +142 -0
- package/src/mod/docs/14-mod-format.md +377 -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 +19 -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 +220 -0
- package/src/mod/loader.ts +207 -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/clients.ts +2 -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/servers.ts +4 -0
- package/src/mods/treenity/agent-port.ts +93 -0
- package/src/mods/treenity/builtins.ts +21 -0
- package/src/mods/treenity/groups.ts +19 -0
- package/src/mods/treenity/logs.ts +26 -0
- package/src/mods/treenity/mod-type.ts +10 -0
- package/src/mods/treenity/seed.ts +58 -0
- package/src/mods/treenity/server.ts +6 -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 +112 -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/_test-fixture.ts +12 -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/ai.agent.json +133 -0
- package/src/schema/generated/ai.approval.json +105 -0
- package/src/schema/generated/ai.approvals.json +24 -0
- package/src/schema/generated/ai.assignment.json +28 -0
- package/src/schema/generated/ai.plan.json +84 -0
- package/src/schema/generated/ai.policy.json +105 -0
- package/src/schema/generated/ai.pool.json +37 -0
- package/src/schema/generated/ai.thread.json +64 -0
- package/src/schema/generated/autostart.json +44 -0
- package/src/schema/generated/board.column.json +25 -0
- package/src/schema/generated/board.kanban.json +7 -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/canary.item.json +40 -0
- package/src/schema/generated/claude-search.json +20 -0
- package/src/schema/generated/craft.product.json +47 -0
- package/src/schema/generated/craft.shop.json +94 -0
- package/src/schema/generated/craft.subscription.json +27 -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/examples.demo.sensor.reading.json +25 -0
- package/src/schema/generated/flow.node.action.json +61 -0
- package/src/schema/generated/flow.node.code.json +43 -0
- package/src/schema/generated/flow.node.condition.json +37 -0
- package/src/schema/generated/flow.node.end.json +35 -0
- package/src/schema/generated/flow.node.http.json +65 -0
- package/src/schema/generated/flow.node.llm.json +67 -0
- package/src/schema/generated/flow.node.loop.json +49 -0
- package/src/schema/generated/flow.node.start.json +39 -0
- package/src/schema/generated/flow.scenario.json +118 -0
- package/src/schema/generated/groups.json +20 -0
- package/src/schema/generated/grove.attempt.json +199 -0
- package/src/schema/generated/grove.path.json +93 -0
- package/src/schema/generated/grove.review.json +27 -0
- package/src/schema/generated/grove.task.json +164 -0
- package/src/schema/generated/intel.scenario.json +58 -0
- package/src/schema/generated/intel.signal.json +113 -0
- package/src/schema/generated/intel.world.json +15 -0
- package/src/schema/generated/landing.block.json +201 -0
- package/src/schema/generated/landing.page.json +84 -0
- package/src/schema/generated/launcher.json +91 -0
- package/src/schema/generated/mcp.server.json +15 -0
- package/src/schema/generated/metatron.config.json +119 -0
- package/src/schema/generated/metatron.permission.json +36 -0
- package/src/schema/generated/metatron.skill.json +36 -0
- package/src/schema/generated/metatron.task.json +114 -0
- package/src/schema/generated/metatron.template.json +26 -0
- package/src/schema/generated/metatron.workspace.json +60 -0
- package/src/schema/generated/mindmap.map.json +22 -0
- package/src/schema/generated/order.status.json +21 -0
- package/src/schema/generated/polyhope.backtest.json +161 -0
- package/src/schema/generated/polyhope.feed.json +33 -0
- package/src/schema/generated/polyhope.run.json +94 -0
- package/src/schema/generated/polyhope.strategy.json +152 -0
- package/src/schema/generated/polymax.activity.json +65 -0
- package/src/schema/generated/polymax.aggr-feed.json +28 -0
- package/src/schema/generated/polymax.aggr.json +20 -0
- package/src/schema/generated/polymax.alert.json +56 -0
- package/src/schema/generated/polymax.bot-config.json +14 -0
- package/src/schema/generated/polymax.bot-status.json +35 -0
- package/src/schema/generated/polymax.classification.json +55 -0
- package/src/schema/generated/polymax.deposits.json +45 -0
- package/src/schema/generated/polymax.holding.json +55 -0
- package/src/schema/generated/polymax.identity.json +71 -0
- package/src/schema/generated/polymax.lb-entry.json +75 -0
- package/src/schema/generated/polymax.leaderboard.json +37 -0
- package/src/schema/generated/polymax.market-ref.json +25 -0
- package/src/schema/generated/polymax.performance.json +65 -0
- package/src/schema/generated/polymax.profile.json +16 -0
- package/src/schema/generated/polymax.scan-result.json +50 -0
- package/src/schema/generated/polymax.status.json +40 -0
- package/src/schema/generated/polymax.tags.json +53 -0
- package/src/schema/generated/polymax.trader.json +16 -0
- package/src/schema/generated/polymax.wallet-market.json +50 -0
- package/src/schema/generated/polymax.wallet-pnl.json +35 -0
- package/src/schema/generated/pult.concept.json +53 -0
- package/src/schema/generated/pult.config.json +227 -0
- package/src/schema/generated/pult.connector.json +72 -0
- package/src/schema/generated/pult.market.json +113 -0
- package/src/schema/generated/pult.order.json +113 -0
- package/src/schema/generated/pult.rete.json +68 -0
- package/src/schema/generated/pult.sensor.json +74 -0
- package/src/schema/generated/pult.signal.json +54 -0
- package/src/schema/generated/pult.synapse.json +93 -0
- package/src/schema/generated/pult.trade.json +93 -0
- package/src/schema/generated/resim.config.json +34 -0
- package/src/schema/generated/resim.function.json +62 -0
- package/src/schema/generated/resim.goal.json +22 -0
- package/src/schema/generated/resim.resource.json +40 -0
- package/src/schema/generated/resim.state.json +48 -0
- package/src/schema/generated/resim.world.json +40 -0
- package/src/schema/generated/saveme.action.save.json +29 -0
- package/src/schema/generated/saveme.message.json +36 -0
- package/src/schema/generated/saveme.router.json +31 -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.coolify.json +50 -0
- package/src/schema/generated/t.event.json +46 -0
- package/src/schema/generated/t.llm.json +20 -0
- package/src/schema/generated/t.logs.json +155 -0
- package/src/schema/generated/t.mod.json +27 -0
- package/src/schema/generated/t.note.json +31 -0
- package/src/schema/generated/t.person.json +36 -0
- package/src/schema/generated/t.tenant.json +57 -0
- package/src/schema/generated/t.tenant.status.json +42 -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/tagger.config.json +115 -0
- package/src/schema/generated/tagger.result.json +57 -0
- package/src/schema/generated/tagger.tree.json +36 -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/ui.table.json +46 -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/types.ts +34 -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 +463 -0
- package/src/server/auth.test.ts +441 -0
- package/src/server/auth.ts +387 -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 +287 -0
- package/src/server/e2e.test.ts +967 -0
- package/src/server/errors.ts +11 -0
- package/src/server/factory.ts +121 -0
- package/src/server/main.ts +24 -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 +177 -0
- package/src/server/mount-adapters.ts +87 -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 +565 -0
- package/src/server/mount.ts +208 -0
- package/src/server/prefab.test.ts +415 -0
- package/src/server/prefab.ts +105 -0
- package/src/server/refs.test.ts +82 -0
- package/src/server/refs.ts +64 -0
- package/src/server/seed/index.ts +24 -0
- package/src/server/server.ts +164 -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 +375 -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 +257 -0
- package/src/tree/index.test.ts +190 -0
- package/src/tree/index.ts +217 -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 +716 -0
- package/src/tree-chain.ts +150 -0
- package/src/tree.ts +1 -0
- package/src/uri.test.ts +113 -0
- package/src/uri.ts +84 -0
- package/CHANGELOG.md +0 -314
- 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.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,193 @@
|
|
|
1
|
+
# 06 — Экшены
|
|
2
|
+
|
|
3
|
+
Экшен — метод класса компонента. Сервер исполняет его через Immer draft, патчи
|
|
4
|
+
автоматически сохраняются. Если данные не менялись — store.set() не вызывается.
|
|
5
|
+
|
|
6
|
+
## Шаг 1: определи экшены как методы класса
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import { registerComp } from '#comp';
|
|
10
|
+
|
|
11
|
+
export class OrderStatus {
|
|
12
|
+
value: 'incoming' | 'kitchen' | 'ready' = 'incoming';
|
|
13
|
+
|
|
14
|
+
advance() {
|
|
15
|
+
// this — Immer draft компонента
|
|
16
|
+
if (this.value === 'incoming') this.value = 'kitchen';
|
|
17
|
+
else if (this.value === 'kitchen') this.value = 'ready';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
registerComp('order.status', OrderStatus);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Всё. `registerComp` автоматически регистрирует `action:advance` из метода.
|
|
25
|
+
|
|
26
|
+
## Шаг 2: вызов из React-вьюшки
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { useComp } from '#front/hooks';
|
|
30
|
+
import { OrderStatus } from './types';
|
|
31
|
+
|
|
32
|
+
function OrderCard({ path }: { path: string }) {
|
|
33
|
+
const status = useComp(path, OrderStatus);
|
|
34
|
+
// status.value — live данные из кэша (реактивно)
|
|
35
|
+
// status.advance() — вызывает trpc.execute, получает ответ
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<button onClick={() => status.advance()}>
|
|
39
|
+
{status.value} →
|
|
40
|
+
</button>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`useComp(path, Class, key?)` — одна точка для данных и действий.
|
|
46
|
+
- `key` нужен только если на ноде несколько компонентов одного `$type`.
|
|
47
|
+
|
|
48
|
+
## Шаг 3: вызов из сервиса / серверного кода
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { createServerNodeClient } from '#server/actions';
|
|
52
|
+
import { OrderStatus } from '../orders/types';
|
|
53
|
+
|
|
54
|
+
register('my.service', 'service', async (node, ctx) => {
|
|
55
|
+
const nc = createServerNodeClient(ctx.store);
|
|
56
|
+
|
|
57
|
+
await nc('/orders/123').get(OrderStatus).advance();
|
|
58
|
+
// Typed: IDE подсказывает методы и аргументы
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`key` можно опустить: если ключ поля совпадает с последним сегментом `$type`
|
|
63
|
+
(`'order.status'` → `'status'`), сканирование находит компонент автоматически.
|
|
64
|
+
|
|
65
|
+
## Методы с аргументами
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
export class PultConfig {
|
|
69
|
+
risk = 0.5;
|
|
70
|
+
|
|
71
|
+
setRisk(data: { value: number }) {
|
|
72
|
+
this.risk = Math.max(0, Math.min(1, data.value));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
// React:
|
|
79
|
+
const cfg = useComp(path, PultConfig);
|
|
80
|
+
<Fader onChange={v => cfg.setRisk({ value: v })} />
|
|
81
|
+
|
|
82
|
+
// Сервис:
|
|
83
|
+
await nc(path).get(PultConfig).setRisk({ value: 0.1 });
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Сигнатура = порты + параметры
|
|
87
|
+
|
|
88
|
+
Тип `data`-аргумента метода — единый источник правды для двух контекстов:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
class Invoice {
|
|
92
|
+
static $type = 'billing.invoice'
|
|
93
|
+
|
|
94
|
+
async charge(data: { amount: number, account: Account, user?: User }) {
|
|
95
|
+
data.account.debit(data.amount)
|
|
96
|
+
data.user?.notify('charged')
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
| В коде | В визуальном редакторе |
|
|
102
|
+
|--------|----------------------|
|
|
103
|
+
| `amount: number` — параметр, передаётся при вызове | Поле ввода на кубике |
|
|
104
|
+
| `account: Account` — typed значение | **Порт** — входной разъём типа Account, тянешь провод |
|
|
105
|
+
| `user?: User` — optional параметр | **Опциональный порт** — можно не подключать |
|
|
106
|
+
|
|
107
|
+
**Вызов из кода** — обычный typed call:
|
|
108
|
+
```ts
|
|
109
|
+
invoice.charge({ amount: 10, account: user.account })
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Компиляция графа** — визуальный редактор собирает значения с подключённых портов:
|
|
113
|
+
```ts
|
|
114
|
+
// wired connections → data object:
|
|
115
|
+
invoice.charge({
|
|
116
|
+
amount: amountNode.value,
|
|
117
|
+
account: getComp(acmeNode, Account),
|
|
118
|
+
})
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Одна TypeScript-сигнатура, два мира. TypeScript проверяет типы при компиляции,
|
|
122
|
+
JSON Schema генерируется для AI/валидации. Без отдельного DSL для портов.
|
|
123
|
+
|
|
124
|
+
## Async-методы и доступ к store
|
|
125
|
+
|
|
126
|
+
> **Правило:** `getCtx()` вызывай только синхронно на первой строке метода — до первого `await`/`yield`.
|
|
127
|
+
> После `await` контекст уже не валиден (async stack ушёл).
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { getCtx } from '#comp';
|
|
133
|
+
|
|
134
|
+
export class PultConfig {
|
|
135
|
+
async rebalance() {
|
|
136
|
+
const { node, store } = getCtx(); // ТОЛЬКО на первой строке — до первого await
|
|
137
|
+
|
|
138
|
+
const { items: markets } = await store.getChildren(`${node.$path}/markets`);
|
|
139
|
+
for (const m of markets) {
|
|
140
|
+
// ...
|
|
141
|
+
}
|
|
142
|
+
return { rebalanced: markets.length };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Generator-экшены — стримят результаты клиенту
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
export class Builder {
|
|
151
|
+
async *build(data: { count: number }) {
|
|
152
|
+
const { node, store, signal } = getCtx(); // ТОЛЬКО здесь — до любого await/yield
|
|
153
|
+
|
|
154
|
+
for (let i = 0; i < data.count; i++) {
|
|
155
|
+
if (signal.aborted) return;
|
|
156
|
+
const item = await buildItem(i);
|
|
157
|
+
await store.set(item);
|
|
158
|
+
yield item; // нода → клиент кладёт в кэш
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
// Подписка на стрим:
|
|
166
|
+
trpc.streamAction.subscribe({ path, action: 'build', data: { count: 10 } }, {
|
|
167
|
+
onData(item) { /* nodes → cache */ },
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Справка: низкоуровневые вызовы
|
|
174
|
+
|
|
175
|
+
Используй только если `useComp`/`createServerNodeClient` не подходят
|
|
176
|
+
(generic Inspector, MCP, внешние интеграции).
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// Прямой вызов (type scan без key):
|
|
180
|
+
await executeAction(store, path, 'order.status', undefined, 'advance');
|
|
181
|
+
|
|
182
|
+
// С конкретным key:
|
|
183
|
+
await executeAction(store, path, 'order.status', 'status', 'advance');
|
|
184
|
+
|
|
185
|
+
// Node-level (без компонента):
|
|
186
|
+
await executeAction(store, path, undefined, undefined, 'doStuff');
|
|
187
|
+
|
|
188
|
+
// tRPC напрямую:
|
|
189
|
+
trpc.execute.mutate({ path, type: 'order.status', action: 'advance' });
|
|
190
|
+
trpc.execute.mutate({ path, type: 'order.status', key: 'status', action: 'advance' });
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Resolution: key → node[key] + verify $type; type only → findCompByType scan; neither → node.$type scan.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# 07 — Подписки и React
|
|
2
|
+
|
|
3
|
+
## Серверная сторона
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { withSubscriptions, type ReactivStore, type NodeEvent } from '#server/sub';
|
|
7
|
+
|
|
8
|
+
type NodeEvent =
|
|
9
|
+
| { type: 'set'; path: string; node: NodeData; patches?: Patch[] }
|
|
10
|
+
| { type: 'patch'; path: string; patches: Patch[] }
|
|
11
|
+
| { type: 'remove'; path: string };
|
|
12
|
+
|
|
13
|
+
const reactive: ReactivStore = withSubscriptions(store);
|
|
14
|
+
|
|
15
|
+
const unsub = reactive.subscribe('/tasks', (event: NodeEvent) => {
|
|
16
|
+
// срабатывает на /tasks, /tasks/1, /tasks/1/sub, ...
|
|
17
|
+
});
|
|
18
|
+
unsub();
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
В сервисе store уже реактивный. `store.set()` / `store.remove()` автоматически нотифицируют подписчиков.
|
|
22
|
+
|
|
23
|
+
## CDC Matrix (Query Mounts)
|
|
24
|
+
|
|
25
|
+
При store.set() подписки автоматически проверяют все активные query mount-ы. Если нода вошла/вышла из фильтра — генерируются `addVps` / `rmVps` в событии. Клиентский кэш автоматически добавляет/убирает ноду из виртуальных папок.
|
|
26
|
+
|
|
27
|
+
## React хуки
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { useNode, useChildren, useComponent, useAction, useNodeCount } from '#front/hooks';
|
|
31
|
+
|
|
32
|
+
const [node, setNode] = useNode('/tasks/1');
|
|
33
|
+
await setNode({ ...node, title: 'Updated' }); // optimistic → server → refetch
|
|
34
|
+
|
|
35
|
+
const children = useChildren('/tasks', {
|
|
36
|
+
watch: true, // подписаться на изменения существующих
|
|
37
|
+
watchNew: true, // подписаться на появление новых
|
|
38
|
+
limit: 50,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const [comp, setComp] = useComponent('/tasks/1', 'status');
|
|
42
|
+
await setComp({ $type: 'status', value: 'done' });
|
|
43
|
+
|
|
44
|
+
const results = useAction('/dashboard', 'stats');
|
|
45
|
+
const count = useNodeCount();
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Рендер через контекст
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import { Render, RenderContext, NodeProvider, useCurrentNode, useTreeContext } from '#contexts/react';
|
|
52
|
+
|
|
53
|
+
<Render value={component} onChange={handler} />
|
|
54
|
+
|
|
55
|
+
<RenderContext name="react:compact">
|
|
56
|
+
<Render value={component} /> {/* ищет react:compact → react → default */}
|
|
57
|
+
</RenderContext>
|
|
58
|
+
|
|
59
|
+
function MyRenderer({ value, onChange }) {
|
|
60
|
+
const node = useCurrentNode();
|
|
61
|
+
const context = useTreeContext();
|
|
62
|
+
return <div>{value.title}</div>;
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## react:list — самодостаточные list-item компоненты
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import type { View } from '@treenity/react/context';
|
|
70
|
+
|
|
71
|
+
// View для default — value: ComponentData (базовый тип, есть $type)
|
|
72
|
+
const DefaultListItem: View<ComponentData> = ({ value, ctx }) => {
|
|
73
|
+
const node = ctx!.node;
|
|
74
|
+
return (
|
|
75
|
+
<div className="child-card" onClick={() => navigate(node.$path)}>
|
|
76
|
+
<span className="child-icon">{typeIcon(node.$type)}</span>
|
|
77
|
+
<div className="child-info">
|
|
78
|
+
<span className="child-name">{pathName(node.$path)}</span>
|
|
79
|
+
<span className="child-type">{node.$type}</span>
|
|
80
|
+
</div>
|
|
81
|
+
<span className="child-chevron">›</span>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
register('default', 'react:list', DefaultListItem);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Fallback: `react:list` → `default@react:list` → strip `:list` → `react`.
|
|
89
|
+
|
|
90
|
+
## Нода КАК компонент — flat fields
|
|
91
|
+
|
|
92
|
+
Когда `node.$type` совпадает с `$type` компонента, нода **сама является** компонентом. Поля лежат плоско:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { createNode } from '#core';
|
|
96
|
+
|
|
97
|
+
// Правильно — createNode создаёт типизированную ноду
|
|
98
|
+
await store.set(createNode('/bot', 'brahman.bot', { token: '...', alias: '@bot' }));
|
|
99
|
+
|
|
100
|
+
// Неправильно — вложенный компонент с тем же $type что и нода
|
|
101
|
+
await store.set(createNode('/bot', 'brahman.bot', {
|
|
102
|
+
config: { $type: 'brahman.bot', token: '...' }, // WRONG: дублирует $type
|
|
103
|
+
}));
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Views — read-only
|
|
107
|
+
|
|
108
|
+
View (`react` контекст) — только отображение. Редактирование — через NodeEditor (edit panel + schema forms).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# 08 — Сервисы
|
|
2
|
+
|
|
3
|
+
Фоновые процессы: боты, сенсоры, воркеры. `register(type, "service", handler)` → возвращает `{ stop() }`.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { register, createNode, type NodeData } from '#core';
|
|
7
|
+
import { type ServiceHandle, type ServiceCtx } from '#contexts/service';
|
|
8
|
+
|
|
9
|
+
register('my-worker', 'service', async (node: NodeData, ctx: ServiceCtx) => {
|
|
10
|
+
const timer = setInterval(async () => {
|
|
11
|
+
await ctx.store.set(createNode(
|
|
12
|
+
`${node.$path}/${Date.now()}`,
|
|
13
|
+
'tick',
|
|
14
|
+
{ ts: Date.now() },
|
|
15
|
+
));
|
|
16
|
+
}, 5000);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
stop: async () => clearInterval(timer),
|
|
20
|
+
} satisfies ServiceHandle;
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Автозапуск
|
|
25
|
+
|
|
26
|
+
Создай ref-ноду в `/sys/autostart`:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { createNode } from '#core';
|
|
30
|
+
|
|
31
|
+
await store.set(createNode('/my-worker', 'my-worker'));
|
|
32
|
+
await store.set(createNode('/sys/autostart/my-worker', 'ref', { $ref: '/my-worker' }));
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
При старте сервера `startServices(store)` обходит `/sys/autostart`, резолвит refs, вызывает service-хэндлеры.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# 09 — Mount-адаптеры
|
|
2
|
+
|
|
3
|
+
Маршрутизация поддеревьев к другим бэкендам. Всё под `/mount-point/*` обслуживается подключённым Store.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
register('my-adapter', 'mount', async (config, parentStore, ctx, globalStore) => {
|
|
7
|
+
return createMongoStore(config.uri, config.db, config.col);
|
|
8
|
+
});
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Нода с маунтом:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
await store.set(createNode('/external', 'my-adapter', {
|
|
15
|
+
connection: { $type: 'connection', uri: '...', db: 'x', col: 'y' },
|
|
16
|
+
mount: { $type: 'my-adapter' },
|
|
17
|
+
}));
|
|
18
|
+
// Всё под /external/* теперь идёт в Mongo-коллекцию
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Встроенные маунты
|
|
22
|
+
|
|
23
|
+
| Тип | Назначение |
|
|
24
|
+
|-----|-----------|
|
|
25
|
+
| `t.mount.mongo` | MongoDB-коллекция |
|
|
26
|
+
| `t.mount.fs` | Файловая система |
|
|
27
|
+
| `t.mount.memory` | In-memory (volatile) |
|
|
28
|
+
| `t.mount.overlay` | Overlay двух store |
|
|
29
|
+
| `t.mount.query` | Виртуальная папка с sift-фильтром |
|
|
30
|
+
| `t.mount.types` | Интроспекция registry |
|
|
31
|
+
|
|
32
|
+
## Query Mounts — виртуальные папки
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
await store.set(createNode('/orders/incoming', 't.mount.query', {
|
|
36
|
+
mount: {
|
|
37
|
+
$type: 't.mount.query',
|
|
38
|
+
source: '/orders/data',
|
|
39
|
+
match: { status: { value: 'incoming' } },
|
|
40
|
+
},
|
|
41
|
+
}));
|
|
42
|
+
// GET /orders/incoming → только ноды из /orders/data с status.value === 'incoming'
|
|
43
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# 10 — ACL, валидация, volatile
|
|
2
|
+
|
|
3
|
+
## ACL
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { R, W, A, S, type GroupPerm } from '#core';
|
|
7
|
+
|
|
8
|
+
// R=1 Read, W=2 Write, A=4 Admin, S=8 Subscribe
|
|
9
|
+
// p > 0: allow bits
|
|
10
|
+
// p = 0: deny all (sticky)
|
|
11
|
+
// p < 0: deny specific bits (sticky)
|
|
12
|
+
|
|
13
|
+
node.$acl = [
|
|
14
|
+
{ g: 'admin', p: R | W | A | S }, // всё
|
|
15
|
+
{ g: 'authenticated', p: R | S }, // чтение + подписка
|
|
16
|
+
{ g: 'public', p: R }, // только чтение
|
|
17
|
+
{ g: 'banned', p: 0 }, // блок (sticky)
|
|
18
|
+
];
|
|
19
|
+
node.$owner = 'user123';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Уровни: node-level (`$acl`, `$owner`) + component-level (`register(type, "acl", handler)`).
|
|
23
|
+
|
|
24
|
+
ACL на тип по умолчанию:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
register('secret', 'acl', () => [{ g: 'admin', p: R | W | A | S }]);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Валидация
|
|
31
|
+
|
|
32
|
+
`withValidation(store)` — write-barrier: проверяет компоненты против JSON Schema перед store.set().
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { withValidation } from '#server/validate';
|
|
36
|
+
|
|
37
|
+
const validated = withValidation(store);
|
|
38
|
+
// validated.set() бросит ошибку, если компонент не проходит schema
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Volatile Nodes
|
|
42
|
+
|
|
43
|
+
Ноды с `$volatile: true` хранятся только в памяти, не персистятся на диск/Mongo.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { withVolatile } from '#server/volatile';
|
|
47
|
+
|
|
48
|
+
const store = withVolatile(backingStore);
|
|
49
|
+
await store.set(createNode('/temp', 'session', { $volatile: true }));
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Server Pipeline
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
bootstrap store (fs/mongo)
|
|
56
|
+
→ mountable (mount system)
|
|
57
|
+
→ volatile (memory-only nodes)
|
|
58
|
+
→ validated (JSON Schema check)
|
|
59
|
+
→ subscriptions (events + CDC)
|
|
60
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 11 — Server: tRPC, MCP, Seed
|
|
2
|
+
|
|
3
|
+
## Seed
|
|
4
|
+
|
|
5
|
+
`seed(store)` — идемпотентно создаёт системные ноды:
|
|
6
|
+
- `/sys`, `/sys/autostart`
|
|
7
|
+
- `/auth`, `/auth/users`, `/auth/sessions`
|
|
8
|
+
- `/mnt/orders`, `/entities`, `/orders`
|
|
9
|
+
|
|
10
|
+
## MCP Server
|
|
11
|
+
|
|
12
|
+
Инструменты (без ACL):
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
get_node(path) // → NodeData | undefined
|
|
16
|
+
list_children(path, depth?) // → Page<NodeData>
|
|
17
|
+
set_node(path, type, components?) // read-merge-write → NodeData
|
|
18
|
+
remove_node(path) // → boolean
|
|
19
|
+
execute(path, action, component?, data?) // → result
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## tRPC Router — все endpoints
|
|
23
|
+
|
|
24
|
+
### Чтение
|
|
25
|
+
```ts
|
|
26
|
+
get({ path, watch? }) // → NodeData | undefined
|
|
27
|
+
getChildren({ path, limit?, offset?, watch?, watchNew? }) // → Page<NodeData>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Запись
|
|
31
|
+
```ts
|
|
32
|
+
set({ node }) // → void
|
|
33
|
+
setComponent({ path, name, data, rev? }) // → void
|
|
34
|
+
remove({ path }) // → boolean
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Экшены
|
|
38
|
+
```ts
|
|
39
|
+
execute({ path, type?, key?, action, data? }) // → result
|
|
40
|
+
streamAction({ path, type?, key?, action, data? }) // → AsyncIterable (subscription)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Шаблоны
|
|
44
|
+
```ts
|
|
45
|
+
getTemplates() // → NodeData[]
|
|
46
|
+
applyTemplate({ templatePath, targetPath }) // → { applied, blocks }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Аутентификация
|
|
50
|
+
```ts
|
|
51
|
+
register({ userId, password }) // → { token, userId }
|
|
52
|
+
login({ userId, password }) // → { token, userId }
|
|
53
|
+
anonLogin() // → { token, userId }
|
|
54
|
+
me() // → { userId } | null
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Watch
|
|
58
|
+
```ts
|
|
59
|
+
unwatch({ paths }) // отписаться от exact-path
|
|
60
|
+
unwatchChildren({ paths }) // отписаться от prefix-watch
|
|
61
|
+
events // SSE поток NodeEvent
|
|
62
|
+
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# 12 — Naming, стили, правила
|
|
2
|
+
|
|
3
|
+
## Naming Convention
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
string → core built-in: dir, ref, root, user, type, mount-point, autostart
|
|
7
|
+
t.* → treenity infrastructure: t.mount.fs, t.mount.mongo, t.llm
|
|
8
|
+
{vendor}.* → package types: acme.block.hero, acme.bot, order.status
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Разделитель: только `.` (не `/`, не `@`, не `:`).
|
|
12
|
+
Паттерн: `{namespace}.{category}.{name}`.
|
|
13
|
+
|
|
14
|
+
## Стили
|
|
15
|
+
|
|
16
|
+
Используй **Tailwind CSS** классы, не inline styles. Tailwind 4 + `@tailwindcss/vite` подключены.
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
// Правильно
|
|
20
|
+
<div className="flex gap-2 text-sm px-2 py-1 bg-muted rounded">
|
|
21
|
+
|
|
22
|
+
// Неправильно
|
|
23
|
+
<div style={{ display: 'flex', gap: 8, fontSize: 13 }}>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Для составных компонентов используй shadcn/ui (`@/components/ui/*`): `Badge`, `Button`, `Input`, `Card` и др.
|
|
27
|
+
|
|
28
|
+
## Контексты — сводная таблица
|
|
29
|
+
|
|
30
|
+
| Контекст | Тип handler | Назначение |
|
|
31
|
+
| --------------- | -------------------------------- | --------------------------- |
|
|
32
|
+
| `schema` | `() => JSONSchema` | JSON Schema для UI-форм |
|
|
33
|
+
| `react` | `FC<{ value, onChange? }>` | React-компонент |
|
|
34
|
+
| `react:compact` | | fallback к `react` |
|
|
35
|
+
| `text` | `(data) => string` | Текстовый рендер |
|
|
36
|
+
| `action:*` | `(ctx: ActionCtx, data) => any` | Серверный экшен |
|
|
37
|
+
| `service` | `(node, ctx) => ServiceHandle` | Фоновый сервис |
|
|
38
|
+
| `mount` | `(config, parent, ctx, global) => Store` | Mount-адаптер |
|
|
39
|
+
| `acl` | `() => GroupPerm[]` | ACL по умолчанию для типа |
|
|
40
|
+
| `class` | `Class<T>` | Registered component class |
|
|
41
|
+
| `telegram` | `(node, tgCtx) => void` | Telegram-хэндлер |
|
|
42
|
+
|
|
43
|
+
## TypeScript — дисциплина типов
|
|
44
|
+
|
|
45
|
+
**`as any` ЗАПРЕЩЁН.** Не "только в emergency" — НИКОГДА. Если типы не сходятся, чини типы. `as any` прячет баги, ломает inference, расползается как рак.
|
|
46
|
+
|
|
47
|
+
Допустимые касты:
|
|
48
|
+
- `as const` — сужение литерала
|
|
49
|
+
- `as 'idle'` — сужение к известному union-варианту
|
|
50
|
+
- `as SensorReading` — сужение к конкретному типу (когда ты знаешь что это он)
|
|
51
|
+
|
|
52
|
+
**Создание нод — ВСЕГДА через `createNode()`:**
|
|
53
|
+
```ts
|
|
54
|
+
// Со строковым типом — T выводится из data:
|
|
55
|
+
await store.set(createNode('/path', 'my.type', { field: 'value' }));
|
|
56
|
+
|
|
57
|
+
// С Class<T> — data проверяется по полям класса (Partial<T>):
|
|
58
|
+
await store.set(createNode('/sensors/temp', SensorConfig, { interval: 10, source: 'api' }));
|
|
59
|
+
// ^^^^^^^^ autocomplete + type check
|
|
60
|
+
|
|
61
|
+
// С компонентами:
|
|
62
|
+
await store.set(createNode('/path', 'sensor', { interval: 5 }, {
|
|
63
|
+
config: { $type: 'sensor.config', source: 'api' },
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
// ЗАПРЕЩЕНО — as NodeData убивает типизацию
|
|
67
|
+
await store.set({ $path: '/path', $type: 'my.type', field: 'value' } as NodeData);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Views — типизированные через `View<T>`:**
|
|
71
|
+
```tsx
|
|
72
|
+
import type { View } from '@treenity/react/context';
|
|
73
|
+
|
|
74
|
+
// value — данные компонента. path — через ctx!.node.$path
|
|
75
|
+
const MyView: View<MyType> = ({ value, ctx }) => { ... };
|
|
76
|
+
|
|
77
|
+
// register принимает Class<T> — T пробрасывается автоматически
|
|
78
|
+
register(MyType, 'react', MyView);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Запрещённые паттерны:**
|
|
82
|
+
- `value as NodeData & MyType` — value УЖЕ типизирован через View<T>
|
|
83
|
+
- `(node as any).field` — используй `getComp(node, Class)` для типобезопасного доступа
|
|
84
|
+
- `register('type', 'react', handler as any)` — используй `register(Class, 'react', handler)`
|
|
85
|
+
|
|
86
|
+
## Ошибки
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { OpError } from '#server/errors';
|
|
90
|
+
|
|
91
|
+
// Коды: 'NOT_FOUND' | 'BAD_REQUEST' | 'CONFLICT' | 'FORBIDDEN'
|
|
92
|
+
throw new OpError('NOT_FOUND', 'Node not found: /path');
|
|
93
|
+
throw new OpError('CONFLICT', 'Stale revision');
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`OpError` → автоматически маппится на tRPC error (NOT_FOUND → 404, CONFLICT → 409 и т.д.).
|
|
97
|
+
|
|
98
|
+
## Архитектурные правила
|
|
99
|
+
|
|
100
|
+
1. **Core < 500 строк.** Всё остальное — в контекстах и модах
|
|
101
|
+
2. **Zero dependencies в core.** Только TypeScript
|
|
102
|
+
3. **Layer model:** нижний слой не знает о верхнем
|
|
103
|
+
4. **Sealed registry:** нет переопределений, только расширение
|
|
104
|
+
5. **Компонент знает только свои данные.** Соседи — через `needs`
|
|
105
|
+
6. **Refs только на ноды** (`$ref: "/path"`), никогда глубокие пути
|
|
106
|
+
7. **Дети — по path prefix query**, не хранятся в родителе
|
|
107
|
+
8. **`$` prefix — системные поля.** В Mongo `$` ↔ `_` автоматически
|
|
108
|
+
9. **Fallback контекстов:** exact → default@same-ctx → strip suffix → recurse → null
|