@imgly/codesign-mcp 0.1.6 → 0.1.7
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 +5 -10
- package/dist/cli/http.d.ts.map +1 -1
- package/dist/cli/http.js +12 -2
- package/dist/cli/http.js.map +1 -1
- package/dist/cli/stdio.d.ts.map +1 -1
- package/dist/cli/stdio.js +103 -35
- package/dist/cli/stdio.js.map +1 -1
- package/dist/config.d.ts +11 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -1
- package/dist/config.js.map +1 -1
- package/dist/diagnostics/events.d.ts +6 -0
- package/dist/diagnostics/events.d.ts.map +1 -1
- package/dist/diagnostics/events.js.map +1 -1
- package/dist/engine/cesdk-adapter.d.ts +5 -1
- package/dist/engine/cesdk-adapter.d.ts.map +1 -1
- package/dist/engine/cesdk-adapter.js +8 -1
- package/dist/engine/cesdk-adapter.js.map +1 -1
- package/dist/engine/engine-capacity.d.ts +16 -0
- package/dist/engine/engine-capacity.d.ts.map +1 -0
- package/dist/engine/engine-capacity.js +48 -0
- package/dist/engine/engine-capacity.js.map +1 -0
- package/dist/engine/engine-slots.d.ts +48 -0
- package/dist/engine/engine-slots.d.ts.map +1 -0
- package/dist/engine/engine-slots.js +182 -0
- package/dist/engine/engine-slots.js.map +1 -0
- package/dist/tools/engine.d.ts +13 -0
- package/dist/tools/engine.d.ts.map +1 -1
- package/dist/tools/engine.js +28 -0
- package/dist/tools/engine.js.map +1 -1
- package/package.json +2 -2
- package/dist/dashboard/router.d.ts +0 -3
- package/dist/dashboard/router.d.ts.map +0 -1
- package/dist/dashboard/router.js +0 -19
- package/dist/dashboard/router.js.map +0 -1
- package/dist/dashboard/spa-assets.generated.d.ts +0 -2
- package/dist/dashboard/spa-assets.generated.d.ts.map +0 -1
- package/dist/dashboard/spa-assets.generated.js +0 -220
- package/dist/dashboard/spa-assets.generated.js.map +0 -1
- package/dist/metrics/mount.d.ts +0 -11
- package/dist/metrics/mount.d.ts.map +0 -1
- package/dist/metrics/mount.js +0 -13
- package/dist/metrics/mount.js.map +0 -1
- package/dist/metrics/recorder.d.ts +0 -55
- package/dist/metrics/recorder.d.ts.map +0 -1
- package/dist/metrics/recorder.js +0 -97
- package/dist/metrics/recorder.js.map +0 -1
- package/dist/test/scripts/changelog-add.d.ts +0 -8
- package/dist/test/scripts/changelog-add.d.ts.map +0 -1
- package/dist/test/scripts/changelog-add.js +0 -50
- package/dist/test/scripts/changelog-add.js.map +0 -1
- package/dist/test/scripts/changelog-collate.d.ts +0 -38
- package/dist/test/scripts/changelog-collate.d.ts.map +0 -1
- package/dist/test/scripts/changelog-collate.js +0 -171
- package/dist/test/scripts/changelog-collate.js.map +0 -1
- package/dist/test/test/changelog.test.d.ts +0 -2
- package/dist/test/test/changelog.test.d.ts.map +0 -1
- package/dist/test/test/changelog.test.js +0 -293
- package/dist/test/test/changelog.test.js.map +0 -1
- package/dist/test/test/cli/dispatcher.test.d.ts +0 -2
- package/dist/test/test/cli/dispatcher.test.d.ts.map +0 -1
- package/dist/test/test/cli/dispatcher.test.js +0 -54
- package/dist/test/test/cli/dispatcher.test.js.map +0 -1
- package/dist/test/test/cli/redirect-console.test.d.ts +0 -2
- package/dist/test/test/cli/redirect-console.test.d.ts.map +0 -1
- package/dist/test/test/cli/redirect-console.test.js +0 -78
- package/dist/test/test/cli/redirect-console.test.js.map +0 -1
- package/dist/test/test/cli/resolve-license.test.d.ts +0 -2
- package/dist/test/test/cli/resolve-license.test.d.ts.map +0 -1
- package/dist/test/test/cli/resolve-license.test.js +0 -29
- package/dist/test/test/cli/resolve-license.test.js.map +0 -1
- package/dist/test/test/cli/stdio-diagnostics.test.d.ts +0 -2
- package/dist/test/test/cli/stdio-diagnostics.test.d.ts.map +0 -1
- package/dist/test/test/cli/stdio-diagnostics.test.js +0 -31
- package/dist/test/test/cli/stdio-diagnostics.test.js.map +0 -1
- package/dist/test/test/cli/stdio-license.test.d.ts +0 -2
- package/dist/test/test/cli/stdio-license.test.d.ts.map +0 -1
- package/dist/test/test/cli/stdio-license.test.js +0 -19
- package/dist/test/test/cli/stdio-license.test.js.map +0 -1
- package/dist/test/test/config.test.d.ts +0 -2
- package/dist/test/test/config.test.d.ts.map +0 -1
- package/dist/test/test/config.test.js +0 -95
- package/dist/test/test/config.test.js.map +0 -1
- package/dist/test/test/cross-ref.test.d.ts +0 -2
- package/dist/test/test/cross-ref.test.d.ts.map +0 -1
- package/dist/test/test/cross-ref.test.js +0 -39
- package/dist/test/test/cross-ref.test.js.map +0 -1
- package/dist/test/test/diagnostics/bundle.test.d.ts +0 -2
- package/dist/test/test/diagnostics/bundle.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/bundle.test.js +0 -53
- package/dist/test/test/diagnostics/bundle.test.js.map +0 -1
- package/dist/test/test/diagnostics/compose.test.d.ts +0 -2
- package/dist/test/test/diagnostics/compose.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/compose.test.js +0 -31
- package/dist/test/test/diagnostics/compose.test.js.map +0 -1
- package/dist/test/test/diagnostics/file-sink.test.d.ts +0 -2
- package/dist/test/test/diagnostics/file-sink.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/file-sink.test.js +0 -113
- package/dist/test/test/diagnostics/file-sink.test.js.map +0 -1
- package/dist/test/test/diagnostics/redact.test.d.ts +0 -2
- package/dist/test/test/diagnostics/redact.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/redact.test.js +0 -59
- package/dist/test/test/diagnostics/redact.test.js.map +0 -1
- package/dist/test/test/diagnostics/tool-call-adapter.test.d.ts +0 -2
- package/dist/test/test/diagnostics/tool-call-adapter.test.d.ts.map +0 -1
- package/dist/test/test/diagnostics/tool-call-adapter.test.js +0 -34
- package/dist/test/test/diagnostics/tool-call-adapter.test.js.map +0 -1
- package/dist/test/test/engine/asset-sources.test.d.ts +0 -2
- package/dist/test/test/engine/asset-sources.test.d.ts.map +0 -1
- package/dist/test/test/engine/asset-sources.test.js +0 -100
- package/dist/test/test/engine/asset-sources.test.js.map +0 -1
- package/dist/test/test/engine/cesdk-adapter.test.d.ts +0 -2
- package/dist/test/test/engine/cesdk-adapter.test.d.ts.map +0 -1
- package/dist/test/test/engine/cesdk-adapter.test.js +0 -32
- package/dist/test/test/engine/cesdk-adapter.test.js.map +0 -1
- package/dist/test/test/engine/mutex.test.d.ts +0 -2
- package/dist/test/test/engine/mutex.test.d.ts.map +0 -1
- package/dist/test/test/engine/mutex.test.js +0 -63
- package/dist/test/test/engine/mutex.test.js.map +0 -1
- package/dist/test/test/engine/session.test.d.ts +0 -2
- package/dist/test/test/engine/session.test.d.ts.map +0 -1
- package/dist/test/test/engine/session.test.js +0 -159
- package/dist/test/test/engine/session.test.js.map +0 -1
- package/dist/test/test/engine/unsplash-source.test.d.ts +0 -2
- package/dist/test/test/engine/unsplash-source.test.d.ts.map +0 -1
- package/dist/test/test/engine/unsplash-source.test.js +0 -129
- package/dist/test/test/engine/unsplash-source.test.js.map +0 -1
- package/dist/test/test/engine/uri-resolver.test.d.ts +0 -2
- package/dist/test/test/engine/uri-resolver.test.d.ts.map +0 -1
- package/dist/test/test/engine/uri-resolver.test.js +0 -38
- package/dist/test/test/engine/uri-resolver.test.js.map +0 -1
- package/dist/test/test/gateway/hosted-stub.test.d.ts +0 -2
- package/dist/test/test/gateway/hosted-stub.test.d.ts.map +0 -1
- package/dist/test/test/gateway/hosted-stub.test.js +0 -11
- package/dist/test/test/gateway/hosted-stub.test.js.map +0 -1
- package/dist/test/test/gateway/local.test.d.ts +0 -2
- package/dist/test/test/gateway/local.test.d.ts.map +0 -1
- package/dist/test/test/gateway/local.test.js +0 -29
- package/dist/test/test/gateway/local.test.js.map +0 -1
- package/dist/test/test/handbook-contract.test.d.ts +0 -2
- package/dist/test/test/handbook-contract.test.d.ts.map +0 -1
- package/dist/test/test/handbook-contract.test.js +0 -79
- package/dist/test/test/handbook-contract.test.js.map +0 -1
- package/dist/test/test/http/server.test.d.ts +0 -2
- package/dist/test/test/http/server.test.d.ts.map +0 -1
- package/dist/test/test/http/server.test.js +0 -338
- package/dist/test/test/http/server.test.js.map +0 -1
- package/dist/test/test/http/session-id-header.test.d.ts +0 -2
- package/dist/test/test/http/session-id-header.test.d.ts.map +0 -1
- package/dist/test/test/http/session-id-header.test.js +0 -76
- package/dist/test/test/http/session-id-header.test.js.map +0 -1
- package/dist/test/test/http/session-manager.test.d.ts +0 -2
- package/dist/test/test/http/session-manager.test.d.ts.map +0 -1
- package/dist/test/test/http/session-manager.test.js +0 -97
- package/dist/test/test/http/session-manager.test.js.map +0 -1
- package/dist/test/test/http/workspace-auth.test.d.ts +0 -2
- package/dist/test/test/http/workspace-auth.test.d.ts.map +0 -1
- package/dist/test/test/http/workspace-auth.test.js +0 -40
- package/dist/test/test/http/workspace-auth.test.js.map +0 -1
- package/dist/test/test/metrics/mount.test.d.ts +0 -2
- package/dist/test/test/metrics/mount.test.d.ts.map +0 -1
- package/dist/test/test/metrics/mount.test.js +0 -59
- package/dist/test/test/metrics/mount.test.js.map +0 -1
- package/dist/test/test/metrics/recorder.test.d.ts +0 -2
- package/dist/test/test/metrics/recorder.test.d.ts.map +0 -1
- package/dist/test/test/metrics/recorder.test.js +0 -118
- package/dist/test/test/metrics/recorder.test.js.map +0 -1
- package/dist/test/test/revisions/hash.test.d.ts +0 -2
- package/dist/test/test/revisions/hash.test.d.ts.map +0 -1
- package/dist/test/test/revisions/hash.test.js +0 -33
- package/dist/test/test/revisions/hash.test.js.map +0 -1
- package/dist/test/test/revisions/store.test.d.ts +0 -2
- package/dist/test/test/revisions/store.test.d.ts.map +0 -1
- package/dist/test/test/revisions/store.test.js +0 -315
- package/dist/test/test/revisions/store.test.js.map +0 -1
- package/dist/test/test/server.metrics.test.d.ts +0 -2
- package/dist/test/test/server.metrics.test.d.ts.map +0 -1
- package/dist/test/test/server.metrics.test.js +0 -87
- package/dist/test/test/server.metrics.test.js.map +0 -1
- package/dist/test/test/server.test.d.ts +0 -2
- package/dist/test/test/server.test.d.ts.map +0 -1
- package/dist/test/test/server.test.js +0 -146
- package/dist/test/test/server.test.js.map +0 -1
- package/dist/test/test/skill-tools.test.d.ts +0 -2
- package/dist/test/test/skill-tools.test.d.ts.map +0 -1
- package/dist/test/test/skill-tools.test.js +0 -84
- package/dist/test/test/skill-tools.test.js.map +0 -1
- package/dist/test/test/smoke.test.d.ts +0 -2
- package/dist/test/test/smoke.test.d.ts.map +0 -1
- package/dist/test/test/smoke.test.js +0 -8
- package/dist/test/test/smoke.test.js.map +0 -1
- package/dist/test/test/tools/asset-generate.test.d.ts +0 -2
- package/dist/test/test/tools/asset-generate.test.d.ts.map +0 -1
- package/dist/test/test/tools/asset-generate.test.js +0 -66
- package/dist/test/test/tools/asset-generate.test.js.map +0 -1
- package/dist/test/test/tools/asset-search.test.d.ts +0 -2
- package/dist/test/test/tools/asset-search.test.d.ts.map +0 -1
- package/dist/test/test/tools/asset-search.test.js +0 -121
- package/dist/test/test/tools/asset-search.test.js.map +0 -1
- package/dist/test/test/tools/edit-harness.d.ts +0 -14
- package/dist/test/test/tools/edit-harness.d.ts.map +0 -1
- package/dist/test/test/tools/edit-harness.js +0 -30
- package/dist/test/test/tools/edit-harness.js.map +0 -1
- package/dist/test/test/tools/edit.telemetry.test.d.ts +0 -2
- package/dist/test/test/tools/edit.telemetry.test.d.ts.map +0 -1
- package/dist/test/test/tools/edit.telemetry.test.js +0 -46
- package/dist/test/test/tools/edit.telemetry.test.js.map +0 -1
- package/dist/test/test/tools/edit.test.d.ts +0 -2
- package/dist/test/test/tools/edit.test.d.ts.map +0 -1
- package/dist/test/test/tools/edit.test.js +0 -267
- package/dist/test/test/tools/edit.test.js.map +0 -1
- package/dist/test/test/tools/export-harness.d.ts +0 -13
- package/dist/test/test/tools/export-harness.d.ts.map +0 -1
- package/dist/test/test/tools/export-harness.js +0 -27
- package/dist/test/test/tools/export-harness.js.map +0 -1
- package/dist/test/test/tools/export.telemetry.test.d.ts +0 -2
- package/dist/test/test/tools/export.telemetry.test.d.ts.map +0 -1
- package/dist/test/test/tools/export.telemetry.test.js +0 -65
- package/dist/test/test/tools/export.telemetry.test.js.map +0 -1
- package/dist/test/test/tools/export.test.d.ts +0 -2
- package/dist/test/test/tools/export.test.d.ts.map +0 -1
- package/dist/test/test/tools/export.test.js +0 -174
- package/dist/test/test/tools/export.test.js.map +0 -1
- package/dist/test/test/tools/history.test.d.ts +0 -2
- package/dist/test/test/tools/history.test.d.ts.map +0 -1
- package/dist/test/test/tools/history.test.js +0 -29
- package/dist/test/test/tools/history.test.js.map +0 -1
- package/dist/test/test/tools/import.test.d.ts +0 -2
- package/dist/test/test/tools/import.test.d.ts.map +0 -1
- package/dist/test/test/tools/import.test.js +0 -122
- package/dist/test/test/tools/import.test.js.map +0 -1
- package/dist/test/test/tools/index.test.d.ts +0 -2
- package/dist/test/test/tools/index.test.d.ts.map +0 -1
- package/dist/test/test/tools/index.test.js +0 -117
- package/dist/test/test/tools/index.test.js.map +0 -1
- package/dist/test/test/tools/inspect.test.d.ts +0 -2
- package/dist/test/test/tools/inspect.test.d.ts.map +0 -1
- package/dist/test/test/tools/inspect.test.js +0 -62
- package/dist/test/test/tools/inspect.test.js.map +0 -1
- package/dist/test/test/tools/list.test.d.ts +0 -2
- package/dist/test/test/tools/list.test.d.ts.map +0 -1
- package/dist/test/test/tools/list.test.js +0 -23
- package/dist/test/test/tools/list.test.js.map +0 -1
- package/dist/test/test/tools/load.integration.test.d.ts +0 -2
- package/dist/test/test/tools/load.integration.test.d.ts.map +0 -1
- package/dist/test/test/tools/load.integration.test.js +0 -165
- package/dist/test/test/tools/load.integration.test.js.map +0 -1
- package/dist/test/test/tools/load.test.d.ts +0 -2
- package/dist/test/test/tools/load.test.d.ts.map +0 -1
- package/dist/test/test/tools/load.test.js +0 -387
- package/dist/test/test/tools/load.test.js.map +0 -1
- package/dist/test/test/tools/metrics.test.d.ts +0 -2
- package/dist/test/test/tools/metrics.test.d.ts.map +0 -1
- package/dist/test/test/tools/metrics.test.js +0 -29
- package/dist/test/test/tools/metrics.test.js.map +0 -1
- package/dist/test/test/tools/open-editor.test.d.ts +0 -2
- package/dist/test/test/tools/open-editor.test.d.ts.map +0 -1
- package/dist/test/test/tools/open-editor.test.js +0 -53
- package/dist/test/test/tools/open-editor.test.js.map +0 -1
- package/dist/test/test/tools/preview-harness.d.ts +0 -9
- package/dist/test/test/tools/preview-harness.d.ts.map +0 -1
- package/dist/test/test/tools/preview-harness.js +0 -23
- package/dist/test/test/tools/preview-harness.js.map +0 -1
- package/dist/test/test/tools/preview.telemetry.test.d.ts +0 -2
- package/dist/test/test/tools/preview.telemetry.test.d.ts.map +0 -1
- package/dist/test/test/tools/preview.telemetry.test.js +0 -36
- package/dist/test/test/tools/preview.telemetry.test.js.map +0 -1
- package/dist/test/test/tools/preview.test.d.ts +0 -2
- package/dist/test/test/tools/preview.test.d.ts.map +0 -1
- package/dist/test/test/tools/preview.test.js +0 -75
- package/dist/test/test/tools/preview.test.js.map +0 -1
- package/dist/test/test/tools/rename.test.d.ts +0 -2
- package/dist/test/test/tools/rename.test.d.ts.map +0 -1
- package/dist/test/test/tools/rename.test.js +0 -16
- package/dist/test/test/tools/rename.test.js.map +0 -1
- package/dist/test/test/tools/save.test.d.ts +0 -2
- package/dist/test/test/tools/save.test.d.ts.map +0 -1
- package/dist/test/test/tools/save.test.js +0 -137
- package/dist/test/test/tools/save.test.js.map +0 -1
- package/dist/test/test/tools/schema-best-practices.d.ts +0 -13
- package/dist/test/test/tools/schema-best-practices.d.ts.map +0 -1
- package/dist/test/test/tools/schema-best-practices.js +0 -169
- package/dist/test/test/tools/schema-best-practices.js.map +0 -1
- package/dist/test/test/tools/schema-best-practices.test.d.ts +0 -3
- package/dist/test/test/tools/schema-best-practices.test.d.ts.map +0 -1
- package/dist/test/test/tools/schema-best-practices.test.js +0 -194
- package/dist/test/test/tools/schema-best-practices.test.js.map +0 -1
- package/dist/test/test/tools/spans.test.d.ts +0 -2
- package/dist/test/test/tools/spans.test.d.ts.map +0 -1
- package/dist/test/test/tools/spans.test.js +0 -84
- package/dist/test/test/tools/spans.test.js.map +0 -1
- package/dist/test/test/viewer/broadcaster.test.d.ts +0 -2
- package/dist/test/test/viewer/broadcaster.test.d.ts.map +0 -1
- package/dist/test/test/viewer/broadcaster.test.js +0 -53
- package/dist/test/test/viewer/broadcaster.test.js.map +0 -1
- package/dist/test/test/viewer/cesdk-cdn.test.d.ts +0 -2
- package/dist/test/test/viewer/cesdk-cdn.test.d.ts.map +0 -1
- package/dist/test/test/viewer/cesdk-cdn.test.js +0 -19
- package/dist/test/test/viewer/cesdk-cdn.test.js.map +0 -1
- package/dist/test/test/viewer/config-route.test.d.ts +0 -2
- package/dist/test/test/viewer/config-route.test.d.ts.map +0 -1
- package/dist/test/test/viewer/config-route.test.js +0 -28
- package/dist/test/test/viewer/config-route.test.js.map +0 -1
- package/dist/test/test/viewer/resource-route.test.d.ts +0 -2
- package/dist/test/test/viewer/resource-route.test.d.ts.map +0 -1
- package/dist/test/test/viewer/resource-route.test.js +0 -70
- package/dist/test/test/viewer/resource-route.test.js.map +0 -1
- package/dist/test/test/viewer/router.test.d.ts +0 -2
- package/dist/test/test/viewer/router.test.d.ts.map +0 -1
- package/dist/test/test/viewer/router.test.js +0 -227
- package/dist/test/test/viewer/router.test.js.map +0 -1
- package/dist/test/test/viewer/session-mount.test.d.ts +0 -2
- package/dist/test/test/viewer/session-mount.test.d.ts.map +0 -1
- package/dist/test/test/viewer/session-mount.test.js +0 -52
- package/dist/test/test/viewer/session-mount.test.js.map +0 -1
- package/dist/test/test/viewer/spa-version.test.d.ts +0 -2
- package/dist/test/test/viewer/spa-version.test.d.ts.map +0 -1
- package/dist/test/test/viewer/spa-version.test.js +0 -14
- package/dist/test/test/viewer/spa-version.test.js.map +0 -1
- package/dist/test/test/viewer/url-builder.test.d.ts +0 -2
- package/dist/test/test/viewer/url-builder.test.d.ts.map +0 -1
- package/dist/test/test/viewer/url-builder.test.js +0 -98
- package/dist/test/test/viewer/url-builder.test.js.map +0 -1
- package/dist/test/test/workspace/content-hash.test.d.ts +0 -2
- package/dist/test/test/workspace/content-hash.test.d.ts.map +0 -1
- package/dist/test/test/workspace/content-hash.test.js +0 -17
- package/dist/test/test/workspace/content-hash.test.js.map +0 -1
- package/dist/test/test/workspace/hosted-stub.test.d.ts +0 -2
- package/dist/test/test/workspace/hosted-stub.test.d.ts.map +0 -1
- package/dist/test/test/workspace/hosted-stub.test.js +0 -30
- package/dist/test/test/workspace/hosted-stub.test.js.map +0 -1
- package/dist/test/test/workspace/in-memory.test.d.ts +0 -2
- package/dist/test/test/workspace/in-memory.test.d.ts.map +0 -1
- package/dist/test/test/workspace/in-memory.test.js +0 -4
- package/dist/test/test/workspace/in-memory.test.js.map +0 -1
- package/dist/test/test/workspace/node-fs.test.d.ts +0 -2
- package/dist/test/test/workspace/node-fs.test.d.ts.map +0 -1
- package/dist/test/test/workspace/node-fs.test.js +0 -20
- package/dist/test/test/workspace/node-fs.test.js.map +0 -1
- package/dist/test/test/workspace/s3.test.d.ts +0 -2
- package/dist/test/test/workspace/s3.test.d.ts.map +0 -1
- package/dist/test/test/workspace/s3.test.js +0 -153
- package/dist/test/test/workspace/s3.test.js.map +0 -1
- package/dist/test/test/workspace/scoped.test.d.ts +0 -2
- package/dist/test/test/workspace/scoped.test.d.ts.map +0 -1
- package/dist/test/test/workspace/scoped.test.js +0 -59
- package/dist/test/test/workspace/scoped.test.js.map +0 -1
- package/dist/test/test/workspace/shared-contract.d.ts +0 -3
- package/dist/test/test/workspace/shared-contract.d.ts.map +0 -1
- package/dist/test/test/workspace/shared-contract.js +0 -92
- package/dist/test/test/workspace/shared-contract.js.map +0 -1
- package/dist/test/tsconfig.test.tsbuildinfo +0 -1
- package/dist/test/vitest.config.d.ts +0 -3
- package/dist/test/vitest.config.d.ts.map +0 -1
- package/dist/test/vitest.config.js +0 -8
- package/dist/test/vitest.config.js.map +0 -1
- package/dist/tools/metrics.d.ts +0 -11
- package/dist/tools/metrics.d.ts.map +0 -1
- package/dist/tools/metrics.js +0 -28
- package/dist/tools/metrics.js.map +0 -1
|
@@ -1,315 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { RevisionStore } from '../../src/revisions/store.js';
|
|
3
|
-
import { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';
|
|
4
|
-
function makeStore() {
|
|
5
|
-
const fs = new InMemoryWorkspaceFS();
|
|
6
|
-
const store = new RevisionStore(fs);
|
|
7
|
-
return { store, fs };
|
|
8
|
-
}
|
|
9
|
-
describe('RevisionStore.write + .read', () => {
|
|
10
|
-
it('writes a root revision, returns its id, and round-trips scene + meta', async () => {
|
|
11
|
-
const { store, fs } = makeStore();
|
|
12
|
-
const written = await store.write({
|
|
13
|
-
scene: '<scene-bytes-v1/>',
|
|
14
|
-
parent: null,
|
|
15
|
-
title: 'Wedding card',
|
|
16
|
-
note: 'initial layout'
|
|
17
|
-
});
|
|
18
|
-
expect(written.id).toMatch(/^[0-9a-f]{12}$/);
|
|
19
|
-
expect(written.meta.parent).toBeNull();
|
|
20
|
-
expect(written.meta.title).toBe('Wedding card');
|
|
21
|
-
const round = await store.read(written.id);
|
|
22
|
-
expect(round.scene).toBe('<scene-bytes-v1/>');
|
|
23
|
-
expect(round.meta.title).toBe('Wedding card');
|
|
24
|
-
expect(round.meta.note).toBe('initial layout');
|
|
25
|
-
// Sharded under objects/<first-2-hex>/<rest>.{scene,json}
|
|
26
|
-
const shard = written.id.slice(0, 2);
|
|
27
|
-
const rest = written.id.slice(2);
|
|
28
|
-
expect(await fs.exists(`objects/${shard}/${rest}.scene`)).toBe(true);
|
|
29
|
-
expect(await fs.exists(`objects/${shard}/${rest}.json`)).toBe(true);
|
|
30
|
-
});
|
|
31
|
-
it('chains a child revision off a parent', async () => {
|
|
32
|
-
const { store } = makeStore();
|
|
33
|
-
const root = await store.write({ scene: 'v1', parent: null, title: 'T' });
|
|
34
|
-
const child = await store.write({
|
|
35
|
-
scene: 'v2',
|
|
36
|
-
parent: root.id,
|
|
37
|
-
note: 'moved title'
|
|
38
|
-
});
|
|
39
|
-
expect(child.meta.parent).toBe(root.id);
|
|
40
|
-
const back = await store.read(child.id);
|
|
41
|
-
expect(back.meta.parent).toBe(root.id);
|
|
42
|
-
expect(back.scene).toBe('v2');
|
|
43
|
-
});
|
|
44
|
-
it('read throws on unknown revision id', async () => {
|
|
45
|
-
const { store } = makeStore();
|
|
46
|
-
await expect(store.read('deadbeefdead')).rejects.toMatchObject({
|
|
47
|
-
code: 'ENOENT'
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
it('persists code as a sibling .code.js file when provided', async () => {
|
|
51
|
-
const { store, fs } = makeStore();
|
|
52
|
-
const written = await store.write({
|
|
53
|
-
scene: 'scene-bytes',
|
|
54
|
-
parent: null,
|
|
55
|
-
title: 'T',
|
|
56
|
-
code: 'engine.scene.create();'
|
|
57
|
-
});
|
|
58
|
-
const shard = written.id.slice(0, 2);
|
|
59
|
-
const rest = written.id.slice(2);
|
|
60
|
-
expect(await fs.exists(`objects/${shard}/${rest}.code.js`)).toBe(true);
|
|
61
|
-
expect(await fs.readFile(`objects/${shard}/${rest}.code.js`, 'utf8')).toBe('engine.scene.create();');
|
|
62
|
-
});
|
|
63
|
-
it('omits the .code.js file when no code is provided', async () => {
|
|
64
|
-
const { store, fs } = makeStore();
|
|
65
|
-
const written = await store.write({
|
|
66
|
-
scene: 'scene-bytes',
|
|
67
|
-
parent: null,
|
|
68
|
-
title: 'T'
|
|
69
|
-
});
|
|
70
|
-
const shard = written.id.slice(0, 2);
|
|
71
|
-
const rest = written.id.slice(2);
|
|
72
|
-
expect(await fs.exists(`objects/${shard}/${rest}.code.js`)).toBe(false);
|
|
73
|
-
});
|
|
74
|
-
it('does NOT include code in the revisionId hash (same scene + parent + note → same id regardless of code)', async () => {
|
|
75
|
-
const { store } = makeStore();
|
|
76
|
-
const a = await store.write({
|
|
77
|
-
scene: 's',
|
|
78
|
-
parent: null,
|
|
79
|
-
note: 'n',
|
|
80
|
-
code: '// path A'
|
|
81
|
-
});
|
|
82
|
-
// Writing again with the same scene/parent/note but different code overwrites at the same id.
|
|
83
|
-
const b = await store.write({
|
|
84
|
-
scene: 's',
|
|
85
|
-
parent: null,
|
|
86
|
-
note: 'n',
|
|
87
|
-
code: '// path B (different)'
|
|
88
|
-
});
|
|
89
|
-
expect(b.id).toBe(a.id);
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
describe('RevisionStore.readCode', () => {
|
|
93
|
-
it('returns the persisted code', async () => {
|
|
94
|
-
const { store } = makeStore();
|
|
95
|
-
const written = await store.write({
|
|
96
|
-
scene: 's',
|
|
97
|
-
parent: null,
|
|
98
|
-
title: 'T',
|
|
99
|
-
code: 'const page = engine.scene.create();'
|
|
100
|
-
});
|
|
101
|
-
expect(await store.readCode(written.id)).toBe('const page = engine.scene.create();');
|
|
102
|
-
});
|
|
103
|
-
it('returns undefined when no code was persisted for the revision', async () => {
|
|
104
|
-
const { store } = makeStore();
|
|
105
|
-
const written = await store.write({ scene: 's', parent: null, title: 'T' });
|
|
106
|
-
expect(await store.readCode(written.id)).toBeUndefined();
|
|
107
|
-
});
|
|
108
|
-
it('returns undefined when the revision id is unknown (the caller surfaces ENOENT via .read)', async () => {
|
|
109
|
-
const { store } = makeStore();
|
|
110
|
-
expect(await store.readCode('deadbeefdead')).toBeUndefined();
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
describe('RevisionStore.listRoots', () => {
|
|
114
|
-
it('returns empty when no roots exist', async () => {
|
|
115
|
-
const { store } = makeStore();
|
|
116
|
-
expect(await store.listRoots()).toEqual([]);
|
|
117
|
-
});
|
|
118
|
-
it('returns root entries sorted by updatedAt desc', async () => {
|
|
119
|
-
const { store } = makeStore();
|
|
120
|
-
const r1 = await store.write({ scene: 'a', parent: null, title: 'First' });
|
|
121
|
-
// small delay so updatedAt differs
|
|
122
|
-
await new Promise((r) => setTimeout(r, 5));
|
|
123
|
-
const r2 = await store.write({ scene: 'b', parent: null, title: 'Second' });
|
|
124
|
-
const list = await store.listRoots();
|
|
125
|
-
expect(list.map((e) => e.rootRevision)).toEqual([r2.id, r1.id]);
|
|
126
|
-
expect(list[0].title).toBe('Second');
|
|
127
|
-
});
|
|
128
|
-
it('updates latestLeaf on each edit', async () => {
|
|
129
|
-
const { store } = makeStore();
|
|
130
|
-
const root = await store.write({ scene: 'v1', parent: null, title: 'T' });
|
|
131
|
-
await new Promise((r) => setTimeout(r, 5));
|
|
132
|
-
const child = await store.write({ scene: 'v2', parent: root.id });
|
|
133
|
-
const list = await store.listRoots();
|
|
134
|
-
expect(list[0]).toMatchObject({
|
|
135
|
-
rootRevision: root.id,
|
|
136
|
-
latestLeaf: child.id
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
it('latestLeaf is the most recently written leaf, even across a fork', async () => {
|
|
140
|
-
const { store } = makeStore();
|
|
141
|
-
const root = await store.write({ scene: 'v1', parent: null, title: 'T' });
|
|
142
|
-
await store.write({ scene: 'v2', parent: root.id });
|
|
143
|
-
await new Promise((r) => setTimeout(r, 5));
|
|
144
|
-
const r3 = await store.write({ scene: 'v3', parent: root.id }); // fork off root
|
|
145
|
-
const list = await store.listRoots();
|
|
146
|
-
expect(list[0].latestLeaf).toBe(r3.id);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
describe('RevisionStore.currentTitle', () => {
|
|
150
|
-
it('returns the creation title for a freshly created root', async () => {
|
|
151
|
-
const { store } = makeStore();
|
|
152
|
-
const root = await store.write({ scene: 'v1', parent: null, title: 'Hi' });
|
|
153
|
-
expect(await store.currentTitle(root.id)).toBe('Hi');
|
|
154
|
-
});
|
|
155
|
-
it('returns "Untitled" for an unknown root', async () => {
|
|
156
|
-
const { store } = makeStore();
|
|
157
|
-
expect(await store.currentTitle('deadbeefdead')).toBe('Untitled');
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
describe('RevisionStore.historyOf', () => {
|
|
161
|
-
it('returns the chain from root to revision', async () => {
|
|
162
|
-
const { store } = makeStore();
|
|
163
|
-
const r1 = await store.write({ scene: 'a', parent: null, title: 'T' });
|
|
164
|
-
const r2 = await store.write({ scene: 'b', parent: r1.id });
|
|
165
|
-
const r3 = await store.write({ scene: 'c', parent: r2.id });
|
|
166
|
-
const chain = await store.historyOf(r3.id);
|
|
167
|
-
expect(chain.map((r) => r.id)).toEqual([r1.id, r2.id, r3.id]);
|
|
168
|
-
});
|
|
169
|
-
it('returns just the root for a root revision', async () => {
|
|
170
|
-
const { store } = makeStore();
|
|
171
|
-
const r = await store.write({ scene: 'a', parent: null, title: 'T' });
|
|
172
|
-
const chain = await store.historyOf(r.id);
|
|
173
|
-
expect(chain.map((c) => c.id)).toEqual([r.id]);
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
describe('RevisionStore.renameRoot', () => {
|
|
177
|
-
it('renames the root when given the root id (reflected via currentTitle + listRoots)', async () => {
|
|
178
|
-
const { store } = makeStore();
|
|
179
|
-
const r = await store.write({ scene: 'a', parent: null, title: 'Old' });
|
|
180
|
-
const { rootRevision } = await store.renameRoot(r.id, 'New');
|
|
181
|
-
expect(rootRevision).toBe(r.id);
|
|
182
|
-
expect(await store.currentTitle(r.id)).toBe('New');
|
|
183
|
-
const list = await store.listRoots();
|
|
184
|
-
expect(list[0].title).toBe('New');
|
|
185
|
-
});
|
|
186
|
-
it('does NOT mutate the root revision meta (titles are append-only events)', async () => {
|
|
187
|
-
const { store } = makeStore();
|
|
188
|
-
const r = await store.write({ scene: 'a', parent: null, title: 'Old' });
|
|
189
|
-
await store.renameRoot(r.id, 'New');
|
|
190
|
-
// The immutable revision keeps its creation-time title; the live title
|
|
191
|
-
// lives in the titles/ event log, not in the object meta.
|
|
192
|
-
expect((await store.read(r.id)).meta.title).toBe('Old');
|
|
193
|
-
});
|
|
194
|
-
it('walks to the root when given a mid-chain id', async () => {
|
|
195
|
-
const { store } = makeStore();
|
|
196
|
-
const r1 = await store.write({ scene: 'a', parent: null, title: 'Old' });
|
|
197
|
-
const r2 = await store.write({ scene: 'b', parent: r1.id });
|
|
198
|
-
const r3 = await store.write({ scene: 'c', parent: r2.id });
|
|
199
|
-
const { rootRevision } = await store.renameRoot(r3.id, 'Mid-chain rename');
|
|
200
|
-
expect(rootRevision).toBe(r1.id);
|
|
201
|
-
expect(await store.currentTitle(r1.id)).toBe('Mid-chain rename');
|
|
202
|
-
});
|
|
203
|
-
it('throws ENOENT for an unknown revision id', async () => {
|
|
204
|
-
const { store } = makeStore();
|
|
205
|
-
await expect(store.renameRoot('deadbeefdead', 'X')).rejects.toMatchObject({
|
|
206
|
-
code: 'ENOENT'
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
describe('RevisionStore root pointer', () => {
|
|
211
|
-
it('sets meta.root to its own id for a root revision', async () => {
|
|
212
|
-
const { store } = makeStore();
|
|
213
|
-
const root = await store.write({ scene: 'v1', parent: null, title: 'T' });
|
|
214
|
-
expect(root.meta.root).toBe(root.id);
|
|
215
|
-
});
|
|
216
|
-
it('inherits meta.root from the parent for a child revision', async () => {
|
|
217
|
-
const { store } = makeStore();
|
|
218
|
-
const root = await store.write({ scene: 'v1', parent: null, title: 'T' });
|
|
219
|
-
const child = await store.write({ scene: 'v2', parent: root.id });
|
|
220
|
-
const grandchild = await store.write({ scene: 'v3', parent: child.id });
|
|
221
|
-
expect(child.meta.root).toBe(root.id);
|
|
222
|
-
expect(grandchild.meta.root).toBe(root.id);
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
describe('RevisionStore journal', () => {
|
|
226
|
-
it('appends one write-once journal entry per revision under journal/<root>/', async () => {
|
|
227
|
-
const { store, fs } = makeStore();
|
|
228
|
-
const root = await store.write({ scene: 'v1', parent: null, title: 'T' });
|
|
229
|
-
const child = await store.write({ scene: 'v2', parent: root.id });
|
|
230
|
-
const entries = await fs.readdir(`journal/${root.id}`);
|
|
231
|
-
expect(entries).toHaveLength(2);
|
|
232
|
-
// Each entry is `<paddedTs>-<leafId>`; the leaf id is after the first dash.
|
|
233
|
-
const leaves = entries.map((e) => e.slice(e.indexOf('-') + 1)).sort();
|
|
234
|
-
expect(leaves).toEqual([root.id, child.id].sort());
|
|
235
|
-
// Journal entries are empty — the filename carries all the data.
|
|
236
|
-
expect(await fs.readFile(`journal/${root.id}/${entries[0]}`, 'utf8')).toBe('');
|
|
237
|
-
});
|
|
238
|
-
it('seeds a title event under titles/<root>/ when a root is created', async () => {
|
|
239
|
-
const { store, fs } = makeStore();
|
|
240
|
-
const root = await store.write({
|
|
241
|
-
scene: 'v1',
|
|
242
|
-
parent: null,
|
|
243
|
-
title: 'Hello'
|
|
244
|
-
});
|
|
245
|
-
const titleEvents = await fs.readdir(`titles/${root.id}`);
|
|
246
|
-
expect(titleEvents).toHaveLength(1);
|
|
247
|
-
expect(await fs.readFile(`titles/${root.id}/${titleEvents[0]}`, 'utf8')).toBe('Hello');
|
|
248
|
-
});
|
|
249
|
-
it('defaults a titleless root to "Untitled" in its seed event', async () => {
|
|
250
|
-
const { store, fs } = makeStore();
|
|
251
|
-
const root = await store.write({ scene: 'v1', parent: null });
|
|
252
|
-
const titleEvents = await fs.readdir(`titles/${root.id}`);
|
|
253
|
-
expect(await fs.readFile(`titles/${root.id}/${titleEvents[0]}`, 'utf8')).toBe('Untitled');
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
describe('RevisionStore.treeOf', () => {
|
|
257
|
-
it('returns every revision of a linear chain, sorted by createdAt', async () => {
|
|
258
|
-
const { store } = makeStore();
|
|
259
|
-
const r1 = await store.write({ scene: 'a', parent: null, title: 'T' });
|
|
260
|
-
await new Promise((r) => setTimeout(r, 5));
|
|
261
|
-
const r2 = await store.write({ scene: 'b', parent: r1.id, note: 'second' });
|
|
262
|
-
await new Promise((r) => setTimeout(r, 5));
|
|
263
|
-
const r3 = await store.write({ scene: 'c', parent: r2.id });
|
|
264
|
-
const tree = await store.treeOf(r1.id);
|
|
265
|
-
expect(tree.map((n) => n.id)).toEqual([r1.id, r2.id, r3.id]);
|
|
266
|
-
expect(tree[1]).toMatchObject({ id: r2.id, parent: r1.id, note: 'second' });
|
|
267
|
-
});
|
|
268
|
-
it('includes forked branches', async () => {
|
|
269
|
-
const { store } = makeStore();
|
|
270
|
-
const r1 = await store.write({ scene: 'a', parent: null, title: 'T' });
|
|
271
|
-
const r2 = await store.write({ scene: 'b', parent: r1.id });
|
|
272
|
-
const fork = await store.write({
|
|
273
|
-
scene: 'b2',
|
|
274
|
-
parent: r1.id,
|
|
275
|
-
note: 'fork'
|
|
276
|
-
});
|
|
277
|
-
const tree = await store.treeOf(r1.id);
|
|
278
|
-
expect(tree.map((n) => n.id).sort()).toEqual([r1.id, r2.id, fork.id].sort());
|
|
279
|
-
});
|
|
280
|
-
it('accepts a mid-chain revision and returns the whole design tree', async () => {
|
|
281
|
-
const { store } = makeStore();
|
|
282
|
-
const r1 = await store.write({ scene: 'a', parent: null, title: 'T' });
|
|
283
|
-
const r2 = await store.write({ scene: 'b', parent: r1.id });
|
|
284
|
-
const r3 = await store.write({ scene: 'c', parent: r2.id });
|
|
285
|
-
const tree = await store.treeOf(r2.id);
|
|
286
|
-
expect(tree.map((n) => n.id).sort()).toEqual([r1.id, r2.id, r3.id].sort());
|
|
287
|
-
});
|
|
288
|
-
it("returns only the queried design's revisions", async () => {
|
|
289
|
-
const { store } = makeStore();
|
|
290
|
-
const a1 = await store.write({
|
|
291
|
-
scene: 'a',
|
|
292
|
-
parent: null,
|
|
293
|
-
title: 'Design A'
|
|
294
|
-
});
|
|
295
|
-
const a2 = await store.write({ scene: 'a2', parent: a1.id });
|
|
296
|
-
const b1 = await store.write({
|
|
297
|
-
scene: 'b',
|
|
298
|
-
parent: null,
|
|
299
|
-
title: 'Design B'
|
|
300
|
-
});
|
|
301
|
-
const tree = await store.treeOf(a1.id);
|
|
302
|
-
expect(tree.map((n) => n.id).sort()).toEqual([a1.id, a2.id].sort());
|
|
303
|
-
expect(tree.map((n) => n.id)).not.toContain(b1.id);
|
|
304
|
-
});
|
|
305
|
-
it('returns [] for an unknown revision id', async () => {
|
|
306
|
-
const { store } = makeStore();
|
|
307
|
-
await store.write({ scene: 'a', parent: null, title: 'T' });
|
|
308
|
-
expect(await store.treeOf('deadbeefdead')).toEqual([]);
|
|
309
|
-
});
|
|
310
|
-
it('returns [] for an empty store', async () => {
|
|
311
|
-
const { store } = makeStore();
|
|
312
|
-
expect(await store.treeOf('deadbeefdead')).toEqual([]);
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
//# sourceMappingURL=store.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.test.js","sourceRoot":"","sources":["../../../../test/revisions/store.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from 'vitest';\nimport { RevisionStore } from '../../src/revisions/store.js';\nimport { InMemoryWorkspaceFS } from '../../src/workspace/in-memory.js';\n\nfunction makeStore(): { store: RevisionStore; fs: InMemoryWorkspaceFS } {\n const fs = new InMemoryWorkspaceFS();\n const store = new RevisionStore(fs);\n return { store, fs };\n}\n\ndescribe('RevisionStore.write + .read', () => {\n it('writes a root revision, returns its id, and round-trips scene + meta', async () => {\n const { store, fs } = makeStore();\n const written = await store.write({\n scene: '<scene-bytes-v1/>',\n parent: null,\n title: 'Wedding card',\n note: 'initial layout'\n });\n expect(written.id).toMatch(/^[0-9a-f]{12}$/);\n expect(written.meta.parent).toBeNull();\n expect(written.meta.title).toBe('Wedding card');\n\n const round = await store.read(written.id);\n expect(round.scene).toBe('<scene-bytes-v1/>');\n expect(round.meta.title).toBe('Wedding card');\n expect(round.meta.note).toBe('initial layout');\n\n // Sharded under objects/<first-2-hex>/<rest>.{scene,json}\n const shard = written.id.slice(0, 2);\n const rest = written.id.slice(2);\n expect(await fs.exists(`objects/${shard}/${rest}.scene`)).toBe(true);\n expect(await fs.exists(`objects/${shard}/${rest}.json`)).toBe(true);\n });\n\n it('chains a child revision off a parent', async () => {\n const { store } = makeStore();\n const root = await store.write({ scene: 'v1', parent: null, title: 'T' });\n const child = await store.write({\n scene: 'v2',\n parent: root.id,\n note: 'moved title'\n });\n expect(child.meta.parent).toBe(root.id);\n\n const back = await store.read(child.id);\n expect(back.meta.parent).toBe(root.id);\n expect(back.scene).toBe('v2');\n });\n\n it('read throws on unknown revision id', async () => {\n const { store } = makeStore();\n await expect(store.read('deadbeefdead')).rejects.toMatchObject({\n code: 'ENOENT'\n });\n });\n\n it('persists code as a sibling .code.js file when provided', async () => {\n const { store, fs } = makeStore();\n const written = await store.write({\n scene: 'scene-bytes',\n parent: null,\n title: 'T',\n code: 'engine.scene.create();'\n });\n const shard = written.id.slice(0, 2);\n const rest = written.id.slice(2);\n expect(await fs.exists(`objects/${shard}/${rest}.code.js`)).toBe(true);\n expect(await fs.readFile(`objects/${shard}/${rest}.code.js`, 'utf8')).toBe(\n 'engine.scene.create();'\n );\n });\n\n it('omits the .code.js file when no code is provided', async () => {\n const { store, fs } = makeStore();\n const written = await store.write({\n scene: 'scene-bytes',\n parent: null,\n title: 'T'\n });\n const shard = written.id.slice(0, 2);\n const rest = written.id.slice(2);\n expect(await fs.exists(`objects/${shard}/${rest}.code.js`)).toBe(false);\n });\n\n it('does NOT include code in the revisionId hash (same scene + parent + note → same id regardless of code)', async () => {\n const { store } = makeStore();\n const a = await store.write({\n scene: 's',\n parent: null,\n note: 'n',\n code: '// path A'\n });\n // Writing again with the same scene/parent/note but different code overwrites at the same id.\n const b = await store.write({\n scene: 's',\n parent: null,\n note: 'n',\n code: '// path B (different)'\n });\n expect(b.id).toBe(a.id);\n });\n});\n\ndescribe('RevisionStore.readCode', () => {\n it('returns the persisted code', async () => {\n const { store } = makeStore();\n const written = await store.write({\n scene: 's',\n parent: null,\n title: 'T',\n code: 'const page = engine.scene.create();'\n });\n expect(await store.readCode(written.id)).toBe(\n 'const page = engine.scene.create();'\n );\n });\n\n it('returns undefined when no code was persisted for the revision', async () => {\n const { store } = makeStore();\n const written = await store.write({ scene: 's', parent: null, title: 'T' });\n expect(await store.readCode(written.id)).toBeUndefined();\n });\n\n it('returns undefined when the revision id is unknown (the caller surfaces ENOENT via .read)', async () => {\n const { store } = makeStore();\n expect(await store.readCode('deadbeefdead')).toBeUndefined();\n });\n});\n\ndescribe('RevisionStore.listRoots', () => {\n it('returns empty when no roots exist', async () => {\n const { store } = makeStore();\n expect(await store.listRoots()).toEqual([]);\n });\n\n it('returns root entries sorted by updatedAt desc', async () => {\n const { store } = makeStore();\n const r1 = await store.write({ scene: 'a', parent: null, title: 'First' });\n // small delay so updatedAt differs\n await new Promise((r) => setTimeout(r, 5));\n const r2 = await store.write({ scene: 'b', parent: null, title: 'Second' });\n const list = await store.listRoots();\n expect(list.map((e) => e.rootRevision)).toEqual([r2.id, r1.id]);\n expect(list[0].title).toBe('Second');\n });\n\n it('updates latestLeaf on each edit', async () => {\n const { store } = makeStore();\n const root = await store.write({ scene: 'v1', parent: null, title: 'T' });\n await new Promise((r) => setTimeout(r, 5));\n const child = await store.write({ scene: 'v2', parent: root.id });\n const list = await store.listRoots();\n expect(list[0]).toMatchObject({\n rootRevision: root.id,\n latestLeaf: child.id\n });\n });\n\n it('latestLeaf is the most recently written leaf, even across a fork', async () => {\n const { store } = makeStore();\n const root = await store.write({ scene: 'v1', parent: null, title: 'T' });\n await store.write({ scene: 'v2', parent: root.id });\n await new Promise((r) => setTimeout(r, 5));\n const r3 = await store.write({ scene: 'v3', parent: root.id }); // fork off root\n const list = await store.listRoots();\n expect(list[0].latestLeaf).toBe(r3.id);\n });\n});\n\ndescribe('RevisionStore.currentTitle', () => {\n it('returns the creation title for a freshly created root', async () => {\n const { store } = makeStore();\n const root = await store.write({ scene: 'v1', parent: null, title: 'Hi' });\n expect(await store.currentTitle(root.id)).toBe('Hi');\n });\n\n it('returns \"Untitled\" for an unknown root', async () => {\n const { store } = makeStore();\n expect(await store.currentTitle('deadbeefdead')).toBe('Untitled');\n });\n});\n\ndescribe('RevisionStore.historyOf', () => {\n it('returns the chain from root to revision', async () => {\n const { store } = makeStore();\n const r1 = await store.write({ scene: 'a', parent: null, title: 'T' });\n const r2 = await store.write({ scene: 'b', parent: r1.id });\n const r3 = await store.write({ scene: 'c', parent: r2.id });\n const chain = await store.historyOf(r3.id);\n expect(chain.map((r) => r.id)).toEqual([r1.id, r2.id, r3.id]);\n });\n\n it('returns just the root for a root revision', async () => {\n const { store } = makeStore();\n const r = await store.write({ scene: 'a', parent: null, title: 'T' });\n const chain = await store.historyOf(r.id);\n expect(chain.map((c) => c.id)).toEqual([r.id]);\n });\n});\n\ndescribe('RevisionStore.renameRoot', () => {\n it('renames the root when given the root id (reflected via currentTitle + listRoots)', async () => {\n const { store } = makeStore();\n const r = await store.write({ scene: 'a', parent: null, title: 'Old' });\n const { rootRevision } = await store.renameRoot(r.id, 'New');\n expect(rootRevision).toBe(r.id);\n expect(await store.currentTitle(r.id)).toBe('New');\n const list = await store.listRoots();\n expect(list[0].title).toBe('New');\n });\n\n it('does NOT mutate the root revision meta (titles are append-only events)', async () => {\n const { store } = makeStore();\n const r = await store.write({ scene: 'a', parent: null, title: 'Old' });\n await store.renameRoot(r.id, 'New');\n // The immutable revision keeps its creation-time title; the live title\n // lives in the titles/ event log, not in the object meta.\n expect((await store.read(r.id)).meta.title).toBe('Old');\n });\n\n it('walks to the root when given a mid-chain id', async () => {\n const { store } = makeStore();\n const r1 = await store.write({ scene: 'a', parent: null, title: 'Old' });\n const r2 = await store.write({ scene: 'b', parent: r1.id });\n const r3 = await store.write({ scene: 'c', parent: r2.id });\n const { rootRevision } = await store.renameRoot(r3.id, 'Mid-chain rename');\n expect(rootRevision).toBe(r1.id);\n expect(await store.currentTitle(r1.id)).toBe('Mid-chain rename');\n });\n\n it('throws ENOENT for an unknown revision id', async () => {\n const { store } = makeStore();\n await expect(store.renameRoot('deadbeefdead', 'X')).rejects.toMatchObject({\n code: 'ENOENT'\n });\n });\n});\n\ndescribe('RevisionStore root pointer', () => {\n it('sets meta.root to its own id for a root revision', async () => {\n const { store } = makeStore();\n const root = await store.write({ scene: 'v1', parent: null, title: 'T' });\n expect(root.meta.root).toBe(root.id);\n });\n\n it('inherits meta.root from the parent for a child revision', async () => {\n const { store } = makeStore();\n const root = await store.write({ scene: 'v1', parent: null, title: 'T' });\n const child = await store.write({ scene: 'v2', parent: root.id });\n const grandchild = await store.write({ scene: 'v3', parent: child.id });\n expect(child.meta.root).toBe(root.id);\n expect(grandchild.meta.root).toBe(root.id);\n });\n});\n\ndescribe('RevisionStore journal', () => {\n it('appends one write-once journal entry per revision under journal/<root>/', async () => {\n const { store, fs } = makeStore();\n const root = await store.write({ scene: 'v1', parent: null, title: 'T' });\n const child = await store.write({ scene: 'v2', parent: root.id });\n\n const entries = await fs.readdir(`journal/${root.id}`);\n expect(entries).toHaveLength(2);\n // Each entry is `<paddedTs>-<leafId>`; the leaf id is after the first dash.\n const leaves = entries.map((e) => e.slice(e.indexOf('-') + 1)).sort();\n expect(leaves).toEqual([root.id, child.id].sort());\n // Journal entries are empty — the filename carries all the data.\n expect(await fs.readFile(`journal/${root.id}/${entries[0]}`, 'utf8')).toBe(\n ''\n );\n });\n\n it('seeds a title event under titles/<root>/ when a root is created', async () => {\n const { store, fs } = makeStore();\n const root = await store.write({\n scene: 'v1',\n parent: null,\n title: 'Hello'\n });\n const titleEvents = await fs.readdir(`titles/${root.id}`);\n expect(titleEvents).toHaveLength(1);\n expect(\n await fs.readFile(`titles/${root.id}/${titleEvents[0]}`, 'utf8')\n ).toBe('Hello');\n });\n\n it('defaults a titleless root to \"Untitled\" in its seed event', async () => {\n const { store, fs } = makeStore();\n const root = await store.write({ scene: 'v1', parent: null });\n const titleEvents = await fs.readdir(`titles/${root.id}`);\n expect(\n await fs.readFile(`titles/${root.id}/${titleEvents[0]}`, 'utf8')\n ).toBe('Untitled');\n });\n});\n\ndescribe('RevisionStore.treeOf', () => {\n it('returns every revision of a linear chain, sorted by createdAt', async () => {\n const { store } = makeStore();\n const r1 = await store.write({ scene: 'a', parent: null, title: 'T' });\n await new Promise((r) => setTimeout(r, 5));\n const r2 = await store.write({ scene: 'b', parent: r1.id, note: 'second' });\n await new Promise((r) => setTimeout(r, 5));\n const r3 = await store.write({ scene: 'c', parent: r2.id });\n const tree = await store.treeOf(r1.id);\n expect(tree.map((n) => n.id)).toEqual([r1.id, r2.id, r3.id]);\n expect(tree[1]).toMatchObject({ id: r2.id, parent: r1.id, note: 'second' });\n });\n\n it('includes forked branches', async () => {\n const { store } = makeStore();\n const r1 = await store.write({ scene: 'a', parent: null, title: 'T' });\n const r2 = await store.write({ scene: 'b', parent: r1.id });\n const fork = await store.write({\n scene: 'b2',\n parent: r1.id,\n note: 'fork'\n });\n const tree = await store.treeOf(r1.id);\n expect(tree.map((n) => n.id).sort()).toEqual(\n [r1.id, r2.id, fork.id].sort()\n );\n });\n\n it('accepts a mid-chain revision and returns the whole design tree', async () => {\n const { store } = makeStore();\n const r1 = await store.write({ scene: 'a', parent: null, title: 'T' });\n const r2 = await store.write({ scene: 'b', parent: r1.id });\n const r3 = await store.write({ scene: 'c', parent: r2.id });\n const tree = await store.treeOf(r2.id);\n expect(tree.map((n) => n.id).sort()).toEqual([r1.id, r2.id, r3.id].sort());\n });\n\n it(\"returns only the queried design's revisions\", async () => {\n const { store } = makeStore();\n const a1 = await store.write({\n scene: 'a',\n parent: null,\n title: 'Design A'\n });\n const a2 = await store.write({ scene: 'a2', parent: a1.id });\n const b1 = await store.write({\n scene: 'b',\n parent: null,\n title: 'Design B'\n });\n const tree = await store.treeOf(a1.id);\n expect(tree.map((n) => n.id).sort()).toEqual([a1.id, a2.id].sort());\n expect(tree.map((n) => n.id)).not.toContain(b1.id);\n });\n\n it('returns [] for an unknown revision id', async () => {\n const { store } = makeStore();\n await store.write({ scene: 'a', parent: null, title: 'T' });\n expect(await store.treeOf('deadbeefdead')).toEqual([]);\n });\n\n it('returns [] for an empty store', async () => {\n const { store } = makeStore();\n expect(await store.treeOf('deadbeefdead')).toEqual([]);\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.metrics.test.d.ts","sourceRoot":"","sources":["../../../test/server.metrics.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
-
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
4
|
-
import { MetricsRecorder } from '../src/metrics/recorder.js';
|
|
5
|
-
import { createCodesignMcpServer } from '../src/server.js';
|
|
6
|
-
const ASSETS = { 'agent/SYSTEM.md': 'sys' };
|
|
7
|
-
function tools() {
|
|
8
|
-
return [
|
|
9
|
-
{
|
|
10
|
-
name: 'slow_ok',
|
|
11
|
-
description: 'resolves after ~20ms',
|
|
12
|
-
inputSchema: { type: 'object', properties: {} },
|
|
13
|
-
call: async () => {
|
|
14
|
-
await new Promise((r) => setTimeout(r, 20));
|
|
15
|
-
return { content: [{ type: 'text', text: 'done' }] };
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
name: 'soft_error',
|
|
20
|
-
description: 'returns isError:true',
|
|
21
|
-
inputSchema: { type: 'object', properties: {} },
|
|
22
|
-
call: async () => ({
|
|
23
|
-
content: [{ type: 'text', text: 'bad' }],
|
|
24
|
-
isError: true
|
|
25
|
-
})
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: 'thrower',
|
|
29
|
-
description: 'throws',
|
|
30
|
-
inputSchema: { type: 'object', properties: {} },
|
|
31
|
-
call: async () => {
|
|
32
|
-
throw new Error('boom');
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
];
|
|
36
|
-
}
|
|
37
|
-
async function connect(metrics) {
|
|
38
|
-
const server = createCodesignMcpServer({
|
|
39
|
-
assets: ASSETS,
|
|
40
|
-
tools: tools(),
|
|
41
|
-
...(metrics ? { metrics } : {})
|
|
42
|
-
});
|
|
43
|
-
const [clientT, serverT] = InMemoryTransport.createLinkedPair();
|
|
44
|
-
await server.connect(serverT);
|
|
45
|
-
const client = new Client({ name: 'test', version: '0' });
|
|
46
|
-
await client.connect(clientT);
|
|
47
|
-
return client;
|
|
48
|
-
}
|
|
49
|
-
describe('dispatch wrapper records tool metrics', () => {
|
|
50
|
-
it('times a successful call and marks ok:true', async () => {
|
|
51
|
-
const recorder = new MetricsRecorder();
|
|
52
|
-
const client = await connect(recorder);
|
|
53
|
-
await client.callTool({ name: 'slow_ok', arguments: {} });
|
|
54
|
-
const stat = recorder.snapshot().tools.find((t) => t.tool === 'slow_ok');
|
|
55
|
-
expect(stat.count).toBe(1);
|
|
56
|
-
expect(stat.errorCount).toBe(0);
|
|
57
|
-
expect(stat.max).toBeGreaterThanOrEqual(15); // ~20ms with slack
|
|
58
|
-
await client.close();
|
|
59
|
-
});
|
|
60
|
-
it('marks an isError:true result as ok:false', async () => {
|
|
61
|
-
const recorder = new MetricsRecorder();
|
|
62
|
-
const client = await connect(recorder);
|
|
63
|
-
await client.callTool({ name: 'soft_error', arguments: {} });
|
|
64
|
-
const stat = recorder
|
|
65
|
-
.snapshot()
|
|
66
|
-
.tools.find((t) => t.tool === 'soft_error');
|
|
67
|
-
expect(stat.count).toBe(1);
|
|
68
|
-
expect(stat.errorCount).toBe(1);
|
|
69
|
-
await client.close();
|
|
70
|
-
});
|
|
71
|
-
it('marks a thrown error as ok:false and still records', async () => {
|
|
72
|
-
const recorder = new MetricsRecorder();
|
|
73
|
-
const client = await connect(recorder);
|
|
74
|
-
await expect(client.callTool({ name: 'thrower', arguments: {} })).rejects.toBeDefined();
|
|
75
|
-
const stat = recorder.snapshot().tools.find((t) => t.tool === 'thrower');
|
|
76
|
-
expect(stat.count).toBe(1);
|
|
77
|
-
expect(stat.errorCount).toBe(1);
|
|
78
|
-
await client.close();
|
|
79
|
-
});
|
|
80
|
-
it('without a recorder, tool calls still work and nothing is recorded', async () => {
|
|
81
|
-
const client = await connect(); // no metrics
|
|
82
|
-
const res = await client.callTool({ name: 'slow_ok', arguments: {} });
|
|
83
|
-
expect(res.content).toEqual([{ type: 'text', text: 'done' }]);
|
|
84
|
-
await client.close();
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
//# sourceMappingURL=server.metrics.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.metrics.test.js","sourceRoot":"","sources":["../../../test/server.metrics.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';\nimport { describe, expect, it } from 'vitest';\nimport { MetricsRecorder } from '../src/metrics/recorder.js';\nimport { createCodesignMcpServer } from '../src/server.js';\n\nconst ASSETS = { 'agent/SYSTEM.md': 'sys' };\n\nfunction tools() {\n return [\n {\n name: 'slow_ok',\n description: 'resolves after ~20ms',\n inputSchema: { type: 'object', properties: {} },\n call: async () => {\n await new Promise((r) => setTimeout(r, 20));\n return { content: [{ type: 'text' as const, text: 'done' }] };\n }\n },\n {\n name: 'soft_error',\n description: 'returns isError:true',\n inputSchema: { type: 'object', properties: {} },\n call: async () => ({\n content: [{ type: 'text' as const, text: 'bad' }],\n isError: true\n })\n },\n {\n name: 'thrower',\n description: 'throws',\n inputSchema: { type: 'object', properties: {} },\n call: async () => {\n throw new Error('boom');\n }\n }\n ];\n}\n\nasync function connect(metrics?: MetricsRecorder) {\n const server = createCodesignMcpServer({\n assets: ASSETS,\n tools: tools(),\n ...(metrics ? { metrics } : {})\n });\n const [clientT, serverT] = InMemoryTransport.createLinkedPair();\n await server.connect(serverT);\n const client = new Client({ name: 'test', version: '0' });\n await client.connect(clientT);\n return client;\n}\n\ndescribe('dispatch wrapper records tool metrics', () => {\n it('times a successful call and marks ok:true', async () => {\n const recorder = new MetricsRecorder();\n const client = await connect(recorder);\n await client.callTool({ name: 'slow_ok', arguments: {} });\n const stat = recorder.snapshot().tools.find((t) => t.tool === 'slow_ok')!;\n expect(stat.count).toBe(1);\n expect(stat.errorCount).toBe(0);\n expect(stat.max).toBeGreaterThanOrEqual(15); // ~20ms with slack\n await client.close();\n });\n\n it('marks an isError:true result as ok:false', async () => {\n const recorder = new MetricsRecorder();\n const client = await connect(recorder);\n await client.callTool({ name: 'soft_error', arguments: {} });\n const stat = recorder\n .snapshot()\n .tools.find((t) => t.tool === 'soft_error')!;\n expect(stat.count).toBe(1);\n expect(stat.errorCount).toBe(1);\n await client.close();\n });\n\n it('marks a thrown error as ok:false and still records', async () => {\n const recorder = new MetricsRecorder();\n const client = await connect(recorder);\n await expect(\n client.callTool({ name: 'thrower', arguments: {} })\n ).rejects.toBeDefined();\n const stat = recorder.snapshot().tools.find((t) => t.tool === 'thrower')!;\n expect(stat.count).toBe(1);\n expect(stat.errorCount).toBe(1);\n await client.close();\n });\n\n it('without a recorder, tool calls still work and nothing is recorded', async () => {\n const client = await connect(); // no metrics\n const res = await client.callTool({ name: 'slow_ok', arguments: {} });\n expect(res.content).toEqual([{ type: 'text', text: 'done' }]);\n await client.close();\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../../../test/server.test.ts"],"names":[],"mappings":""}
|