@aigne/afs-did-space 1.12.0-beta.5
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/LICENSE.md +26 -0
- package/README.md +129 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
- package/dist/_virtual/rolldown_runtime.cjs +29 -0
- package/dist/afs-metadata-context.cjs +20 -0
- package/dist/afs-metadata-context.d.cts +21 -0
- package/dist/afs-metadata-context.d.cts.map +1 -0
- package/dist/afs-metadata-context.d.mts +21 -0
- package/dist/afs-metadata-context.d.mts.map +1 -0
- package/dist/afs-metadata-context.mjs +18 -0
- package/dist/afs-metadata-context.mjs.map +1 -0
- package/dist/blocklet-hook.cjs +180 -0
- package/dist/blocklet-hook.d.cts +29 -0
- package/dist/blocklet-hook.d.cts.map +1 -0
- package/dist/blocklet-hook.d.mts +29 -0
- package/dist/blocklet-hook.d.mts.map +1 -0
- package/dist/blocklet-hook.mjs +178 -0
- package/dist/blocklet-hook.mjs.map +1 -0
- package/dist/changelog-schema.cjs +603 -0
- package/dist/changelog-schema.d.cts +395 -0
- package/dist/changelog-schema.d.cts.map +1 -0
- package/dist/changelog-schema.d.mts +395 -0
- package/dist/changelog-schema.d.mts.map +1 -0
- package/dist/changelog-schema.mjs +570 -0
- package/dist/changelog-schema.mjs.map +1 -0
- package/dist/changelog-write.cjs +80 -0
- package/dist/changelog-write.d.cts +70 -0
- package/dist/changelog-write.d.cts.map +1 -0
- package/dist/changelog-write.d.mts +70 -0
- package/dist/changelog-write.d.mts.map +1 -0
- package/dist/changelog-write.mjs +77 -0
- package/dist/changelog-write.mjs.map +1 -0
- package/dist/cid-byte-cache.cjs +126 -0
- package/dist/cid-byte-cache.d.cts +46 -0
- package/dist/cid-byte-cache.d.cts.map +1 -0
- package/dist/cid-byte-cache.d.mts +47 -0
- package/dist/cid-byte-cache.d.mts.map +1 -0
- package/dist/cid-byte-cache.mjs +125 -0
- package/dist/cid-byte-cache.mjs.map +1 -0
- package/dist/cid.cjs +68 -0
- package/dist/cid.d.cts +22 -0
- package/dist/cid.d.cts.map +1 -0
- package/dist/cid.d.mts +22 -0
- package/dist/cid.d.mts.map +1 -0
- package/dist/cid.mjs +65 -0
- package/dist/cid.mjs.map +1 -0
- package/dist/client.cjs +221 -0
- package/dist/client.d.cts +72 -0
- package/dist/client.d.cts.map +1 -0
- package/dist/client.d.mts +72 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +220 -0
- package/dist/client.mjs.map +1 -0
- package/dist/cloudflare.cjs +510 -0
- package/dist/cloudflare.d.cts +307 -0
- package/dist/cloudflare.d.cts.map +1 -0
- package/dist/cloudflare.d.mts +308 -0
- package/dist/cloudflare.d.mts.map +1 -0
- package/dist/cloudflare.mjs +507 -0
- package/dist/cloudflare.mjs.map +1 -0
- package/dist/ctime-backfill.cjs +272 -0
- package/dist/ctime-backfill.d.cts +169 -0
- package/dist/ctime-backfill.d.cts.map +1 -0
- package/dist/ctime-backfill.d.mts +169 -0
- package/dist/ctime-backfill.d.mts.map +1 -0
- package/dist/ctime-backfill.mjs +267 -0
- package/dist/ctime-backfill.mjs.map +1 -0
- package/dist/d1-gc-queue.cjs +80 -0
- package/dist/d1-gc-queue.d.cts +59 -0
- package/dist/d1-gc-queue.d.cts.map +1 -0
- package/dist/d1-gc-queue.d.mts +59 -0
- package/dist/d1-gc-queue.d.mts.map +1 -0
- package/dist/d1-gc-queue.mjs +81 -0
- package/dist/d1-gc-queue.mjs.map +1 -0
- package/dist/d1-resolve-store.cjs +189 -0
- package/dist/d1-resolve-store.d.cts +93 -0
- package/dist/d1-resolve-store.d.cts.map +1 -0
- package/dist/d1-resolve-store.d.mts +93 -0
- package/dist/d1-resolve-store.d.mts.map +1 -0
- package/dist/d1-resolve-store.mjs +190 -0
- package/dist/d1-resolve-store.mjs.map +1 -0
- package/dist/d1-schema.cjs +361 -0
- package/dist/d1-schema.d.cts +237 -0
- package/dist/d1-schema.d.cts.map +1 -0
- package/dist/d1-schema.d.mts +237 -0
- package/dist/d1-schema.d.mts.map +1 -0
- package/dist/d1-schema.mjs +341 -0
- package/dist/d1-schema.mjs.map +1 -0
- package/dist/d1-share-store.cjs +0 -0
- package/dist/d1-share-store.d.cts +53 -0
- package/dist/d1-share-store.d.cts.map +1 -0
- package/dist/d1-share-store.d.mts +53 -0
- package/dist/d1-share-store.d.mts.map +1 -0
- package/dist/d1-share-store.mjs +0 -0
- package/dist/d1-share-store.mjs.map +1 -0
- package/dist/d1-tree-index.cjs +1098 -0
- package/dist/d1-tree-index.d.cts +203 -0
- package/dist/d1-tree-index.d.cts.map +1 -0
- package/dist/d1-tree-index.d.mts +203 -0
- package/dist/d1-tree-index.d.mts.map +1 -0
- package/dist/d1-tree-index.mjs +1094 -0
- package/dist/d1-tree-index.mjs.map +1 -0
- package/dist/data-backend.cjs +147 -0
- package/dist/data-backend.d.cts +30 -0
- package/dist/data-backend.d.cts.map +1 -0
- package/dist/data-backend.d.mts +30 -0
- package/dist/data-backend.d.mts.map +1 -0
- package/dist/data-backend.mjs +148 -0
- package/dist/data-backend.mjs.map +1 -0
- package/dist/dedup-backfill.cjs +278 -0
- package/dist/dedup-backfill.d.cts +165 -0
- package/dist/dedup-backfill.d.cts.map +1 -0
- package/dist/dedup-backfill.d.mts +165 -0
- package/dist/dedup-backfill.d.mts.map +1 -0
- package/dist/dedup-backfill.mjs +273 -0
- package/dist/dedup-backfill.mjs.map +1 -0
- package/dist/did-space-like.d.cts +2 -0
- package/dist/did-space-like.d.mts +2 -0
- package/dist/did-utils.cjs +44 -0
- package/dist/did-utils.d.cts +25 -0
- package/dist/did-utils.d.cts.map +1 -0
- package/dist/did-utils.d.mts +25 -0
- package/dist/did-utils.d.mts.map +1 -0
- package/dist/did-utils.mjs +43 -0
- package/dist/did-utils.mjs.map +1 -0
- package/dist/dirty-path-queue.cjs +31 -0
- package/dist/dirty-path-queue.d.cts +104 -0
- package/dist/dirty-path-queue.d.cts.map +1 -0
- package/dist/dirty-path-queue.d.mts +104 -0
- package/dist/dirty-path-queue.d.mts.map +1 -0
- package/dist/dirty-path-queue.mjs +31 -0
- package/dist/dirty-path-queue.mjs.map +1 -0
- package/dist/dirty-path-schema.cjs +142 -0
- package/dist/dirty-path-schema.d.cts +90 -0
- package/dist/dirty-path-schema.d.cts.map +1 -0
- package/dist/dirty-path-schema.d.mts +90 -0
- package/dist/dirty-path-schema.d.mts.map +1 -0
- package/dist/dirty-path-schema.mjs +136 -0
- package/dist/dirty-path-schema.mjs.map +1 -0
- package/dist/download-actions.cjs +43 -0
- package/dist/download-actions.mjs +40 -0
- package/dist/download-actions.mjs.map +1 -0
- package/dist/fs-object-store.cjs +153 -0
- package/dist/fs-object-store.d.cts +21 -0
- package/dist/fs-object-store.d.cts.map +1 -0
- package/dist/fs-object-store.d.mts +22 -0
- package/dist/fs-object-store.d.mts.map +1 -0
- package/dist/fs-object-store.mjs +153 -0
- package/dist/fs-object-store.mjs.map +1 -0
- package/dist/gc-queue.d.cts +43 -0
- package/dist/gc-queue.d.cts.map +1 -0
- package/dist/gc-queue.d.mts +43 -0
- package/dist/gc-queue.d.mts.map +1 -0
- package/dist/index.cjs +2712 -0
- package/dist/index.d.cts +504 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +505 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2537 -0
- package/dist/index.mjs.map +1 -0
- package/dist/inline-content-migration.cjs +212 -0
- package/dist/inline-content-migration.d.cts +110 -0
- package/dist/inline-content-migration.d.cts.map +1 -0
- package/dist/inline-content-migration.d.mts +111 -0
- package/dist/inline-content-migration.d.mts.map +1 -0
- package/dist/inline-content-migration.mjs +207 -0
- package/dist/inline-content-migration.mjs.map +1 -0
- package/dist/inline-content.cjs +145 -0
- package/dist/inline-content.d.cts +98 -0
- package/dist/inline-content.d.cts.map +1 -0
- package/dist/inline-content.d.mts +98 -0
- package/dist/inline-content.d.mts.map +1 -0
- package/dist/inline-content.mjs +137 -0
- package/dist/inline-content.mjs.map +1 -0
- package/dist/local-changelog.cjs +241 -0
- package/dist/local-changelog.d.cts +119 -0
- package/dist/local-changelog.d.cts.map +1 -0
- package/dist/local-changelog.d.mts +119 -0
- package/dist/local-changelog.d.mts.map +1 -0
- package/dist/local-changelog.mjs +240 -0
- package/dist/local-changelog.mjs.map +1 -0
- package/dist/local.cjs +435 -0
- package/dist/local.d.cts +254 -0
- package/dist/local.d.cts.map +1 -0
- package/dist/local.d.mts +254 -0
- package/dist/local.d.mts.map +1 -0
- package/dist/local.mjs +427 -0
- package/dist/local.mjs.map +1 -0
- package/dist/memory-gc-queue.cjs +36 -0
- package/dist/memory-gc-queue.d.cts +22 -0
- package/dist/memory-gc-queue.d.cts.map +1 -0
- package/dist/memory-gc-queue.d.mts +22 -0
- package/dist/memory-gc-queue.d.mts.map +1 -0
- package/dist/memory-gc-queue.mjs +36 -0
- package/dist/memory-gc-queue.mjs.map +1 -0
- package/dist/memory-tree-index.cjs +734 -0
- package/dist/memory-tree-index.d.cts +159 -0
- package/dist/memory-tree-index.d.cts.map +1 -0
- package/dist/memory-tree-index.d.mts +159 -0
- package/dist/memory-tree-index.d.mts.map +1 -0
- package/dist/memory-tree-index.mjs +735 -0
- package/dist/memory-tree-index.mjs.map +1 -0
- package/dist/metadata-db.cjs +562 -0
- package/dist/metadata-db.d.cts +102 -0
- package/dist/metadata-db.d.cts.map +1 -0
- package/dist/metadata-db.d.mts +102 -0
- package/dist/metadata-db.d.mts.map +1 -0
- package/dist/metadata-db.mjs +562 -0
- package/dist/metadata-db.mjs.map +1 -0
- package/dist/mime-utils.cjs +2 -0
- package/dist/mime-utils.d.cts +2 -0
- package/dist/mime-utils.d.mts +2 -0
- package/dist/mime-utils.mjs +3 -0
- package/dist/object-key.cjs +41 -0
- package/dist/object-key.d.cts +25 -0
- package/dist/object-key.d.cts.map +1 -0
- package/dist/object-key.d.mts +25 -0
- package/dist/object-key.d.mts.map +1 -0
- package/dist/object-key.mjs +40 -0
- package/dist/object-key.mjs.map +1 -0
- package/dist/packages/session/dist/index.cjs +788 -0
- package/dist/packages/session/dist/index.mjs +782 -0
- package/dist/packages/session/dist/index.mjs.map +1 -0
- package/dist/platform/r2/dist/types.d.cts +49 -0
- package/dist/platform/r2/dist/types.d.cts.map +1 -0
- package/dist/prefix-range.cjs +33 -0
- package/dist/prefix-range.d.cts +29 -0
- package/dist/prefix-range.d.cts.map +1 -0
- package/dist/prefix-range.d.mts +29 -0
- package/dist/prefix-range.d.mts.map +1 -0
- package/dist/prefix-range.mjs +33 -0
- package/dist/prefix-range.mjs.map +1 -0
- package/dist/prefixed-tree-index.cjs +238 -0
- package/dist/prefixed-tree-index.d.cts +85 -0
- package/dist/prefixed-tree-index.d.cts.map +1 -0
- package/dist/prefixed-tree-index.d.mts +85 -0
- package/dist/prefixed-tree-index.d.mts.map +1 -0
- package/dist/prefixed-tree-index.mjs +239 -0
- package/dist/prefixed-tree-index.mjs.map +1 -0
- package/dist/presign-signer.cjs +7 -0
- package/dist/presign-signer.d.cts +99 -0
- package/dist/presign-signer.d.cts.map +1 -0
- package/dist/presign-signer.d.mts +99 -0
- package/dist/presign-signer.d.mts.map +1 -0
- package/dist/presign-signer.mjs +7 -0
- package/dist/presign-signer.mjs.map +1 -0
- package/dist/providers/platform/r2/dist/index.d.mts +3 -0
- package/dist/providers/platform/r2/dist/types.d.mts +49 -0
- package/dist/providers/platform/r2/dist/types.d.mts.map +1 -0
- package/dist/reconcile.cjs +184 -0
- package/dist/reconcile.d.cts +26 -0
- package/dist/reconcile.d.cts.map +1 -0
- package/dist/reconcile.d.mts +26 -0
- package/dist/reconcile.d.mts.map +1 -0
- package/dist/reconcile.mjs +184 -0
- package/dist/reconcile.mjs.map +1 -0
- package/dist/reference-check.cjs +49 -0
- package/dist/reference-check.d.cts +10 -0
- package/dist/reference-check.d.cts.map +1 -0
- package/dist/reference-check.d.mts +10 -0
- package/dist/reference-check.d.mts.map +1 -0
- package/dist/reference-check.mjs +48 -0
- package/dist/reference-check.mjs.map +1 -0
- package/dist/remote-afs.cjs +681 -0
- package/dist/remote-afs.d.cts +236 -0
- package/dist/remote-afs.d.cts.map +1 -0
- package/dist/remote-afs.d.mts +236 -0
- package/dist/remote-afs.d.mts.map +1 -0
- package/dist/remote-afs.mjs +676 -0
- package/dist/remote-afs.mjs.map +1 -0
- package/dist/rename-guard.cjs +18 -0
- package/dist/rename-guard.mjs +18 -0
- package/dist/rename-guard.mjs.map +1 -0
- package/dist/resolve.cjs +260 -0
- package/dist/resolve.d.cts +113 -0
- package/dist/resolve.d.cts.map +1 -0
- package/dist/resolve.d.mts +113 -0
- package/dist/resolve.d.mts.map +1 -0
- package/dist/resolve.mjs +260 -0
- package/dist/resolve.mjs.map +1 -0
- package/dist/rsync-content.cjs +33 -0
- package/dist/rsync-content.mjs +33 -0
- package/dist/rsync-content.mjs.map +1 -0
- package/dist/rsync.cjs +400 -0
- package/dist/rsync.d.cts +157 -0
- package/dist/rsync.d.cts.map +1 -0
- package/dist/rsync.d.mts +157 -0
- package/dist/rsync.d.mts.map +1 -0
- package/dist/rsync.mjs +397 -0
- package/dist/rsync.mjs.map +1 -0
- package/dist/run-gc.cjs +57 -0
- package/dist/run-gc.d.cts +40 -0
- package/dist/run-gc.d.cts.map +1 -0
- package/dist/run-gc.d.mts +41 -0
- package/dist/run-gc.d.mts.map +1 -0
- package/dist/run-gc.mjs +57 -0
- package/dist/run-gc.mjs.map +1 -0
- package/dist/scope-id.cjs +70 -0
- package/dist/scope-id.d.cts +35 -0
- package/dist/scope-id.d.cts.map +1 -0
- package/dist/scope-id.d.mts +35 -0
- package/dist/scope-id.d.mts.map +1 -0
- package/dist/scope-id.mjs +68 -0
- package/dist/scope-id.mjs.map +1 -0
- package/dist/scope-migration-node.cjs +172 -0
- package/dist/scope-migration-node.d.cts +44 -0
- package/dist/scope-migration-node.d.cts.map +1 -0
- package/dist/scope-migration-node.d.mts +44 -0
- package/dist/scope-migration-node.d.mts.map +1 -0
- package/dist/scope-migration-node.mjs +171 -0
- package/dist/scope-migration-node.mjs.map +1 -0
- package/dist/scope-migration.cjs +155 -0
- package/dist/scope-migration.d.cts +65 -0
- package/dist/scope-migration.d.cts.map +1 -0
- package/dist/scope-migration.d.mts +65 -0
- package/dist/scope-migration.d.mts.map +1 -0
- package/dist/scope-migration.mjs +154 -0
- package/dist/scope-migration.mjs.map +1 -0
- package/dist/share-declaration.cjs +225 -0
- package/dist/share-declaration.d.cts +30 -0
- package/dist/share-declaration.d.cts.map +1 -0
- package/dist/share-declaration.d.mts +32 -0
- package/dist/share-declaration.d.mts.map +1 -0
- package/dist/share-declaration.mjs +221 -0
- package/dist/share-declaration.mjs.map +1 -0
- package/dist/share-hook.cjs +63 -0
- package/dist/share-hook.mjs +62 -0
- package/dist/share-hook.mjs.map +1 -0
- package/dist/share-resolve.cjs +176 -0
- package/dist/share-resolve.d.cts +36 -0
- package/dist/share-resolve.d.cts.map +1 -0
- package/dist/share-resolve.d.mts +36 -0
- package/dist/share-resolve.d.mts.map +1 -0
- package/dist/share-resolve.mjs +177 -0
- package/dist/share-resolve.mjs.map +1 -0
- package/dist/share-serve.cjs +145 -0
- package/dist/share-serve.d.cts +30 -0
- package/dist/share-serve.d.cts.map +1 -0
- package/dist/share-serve.d.mts +30 -0
- package/dist/share-serve.d.mts.map +1 -0
- package/dist/share-serve.mjs +144 -0
- package/dist/share-serve.mjs.map +1 -0
- package/dist/share-store.cjs +25 -0
- package/dist/share-store.d.cts +65 -0
- package/dist/share-store.d.cts.map +1 -0
- package/dist/share-store.d.mts +65 -0
- package/dist/share-store.d.mts.map +1 -0
- package/dist/share-store.mjs +25 -0
- package/dist/share-store.mjs.map +1 -0
- package/dist/share-virtual-path.cjs +102 -0
- package/dist/share-virtual-path.mjs +101 -0
- package/dist/share-virtual-path.mjs.map +1 -0
- package/dist/space-resolver.cjs +54 -0
- package/dist/space-resolver.d.cts +34 -0
- package/dist/space-resolver.d.cts.map +1 -0
- package/dist/space-resolver.d.mts +34 -0
- package/dist/space-resolver.d.mts.map +1 -0
- package/dist/space-resolver.mjs +55 -0
- package/dist/space-resolver.mjs.map +1 -0
- package/dist/sqlite-gc-queue.cjs +51 -0
- package/dist/sqlite-gc-queue.d.cts +22 -0
- package/dist/sqlite-gc-queue.d.cts.map +1 -0
- package/dist/sqlite-gc-queue.d.mts +22 -0
- package/dist/sqlite-gc-queue.d.mts.map +1 -0
- package/dist/sqlite-gc-queue.mjs +52 -0
- package/dist/sqlite-gc-queue.mjs.map +1 -0
- package/dist/sqlite-resolve-store.cjs +163 -0
- package/dist/sqlite-resolve-store.d.cts +50 -0
- package/dist/sqlite-resolve-store.d.cts.map +1 -0
- package/dist/sqlite-resolve-store.d.mts +50 -0
- package/dist/sqlite-resolve-store.d.mts.map +1 -0
- package/dist/sqlite-resolve-store.mjs +164 -0
- package/dist/sqlite-resolve-store.mjs.map +1 -0
- package/dist/sqlite-share-store.cjs +157 -0
- package/dist/sqlite-share-store.d.cts +31 -0
- package/dist/sqlite-share-store.d.cts.map +1 -0
- package/dist/sqlite-share-store.d.mts +31 -0
- package/dist/sqlite-share-store.d.mts.map +1 -0
- package/dist/sqlite-share-store.mjs +157 -0
- package/dist/sqlite-share-store.mjs.map +1 -0
- package/dist/sqlite-tree-index.cjs +901 -0
- package/dist/sqlite-tree-index.d.cts +107 -0
- package/dist/sqlite-tree-index.d.cts.map +1 -0
- package/dist/sqlite-tree-index.d.mts +107 -0
- package/dist/sqlite-tree-index.d.mts.map +1 -0
- package/dist/sqlite-tree-index.mjs +902 -0
- package/dist/sqlite-tree-index.mjs.map +1 -0
- package/dist/sync-engine.cjs +1324 -0
- package/dist/sync-engine.d.cts +473 -0
- package/dist/sync-engine.d.cts.map +1 -0
- package/dist/sync-engine.d.mts +473 -0
- package/dist/sync-engine.d.mts.map +1 -0
- package/dist/sync-engine.mjs +1315 -0
- package/dist/sync-engine.mjs.map +1 -0
- package/dist/sync-state.cjs +303 -0
- package/dist/sync-state.d.cts +224 -0
- package/dist/sync-state.d.cts.map +1 -0
- package/dist/sync-state.d.mts +224 -0
- package/dist/sync-state.d.mts.map +1 -0
- package/dist/sync-state.mjs +297 -0
- package/dist/sync-state.mjs.map +1 -0
- package/dist/timestamp.cjs +92 -0
- package/dist/timestamp.mjs +91 -0
- package/dist/timestamp.mjs.map +1 -0
- package/dist/transports/http.cjs +54 -0
- package/dist/transports/http.d.cts +26 -0
- package/dist/transports/http.d.cts.map +1 -0
- package/dist/transports/http.d.mts +26 -0
- package/dist/transports/http.d.mts.map +1 -0
- package/dist/transports/http.mjs +54 -0
- package/dist/transports/http.mjs.map +1 -0
- package/dist/transports/static.cjs +55 -0
- package/dist/transports/static.d.cts +28 -0
- package/dist/transports/static.d.cts.map +1 -0
- package/dist/transports/static.d.mts +28 -0
- package/dist/transports/static.d.mts.map +1 -0
- package/dist/transports/static.mjs +55 -0
- package/dist/transports/static.mjs.map +1 -0
- package/dist/transports/types.cjs +13 -0
- package/dist/transports/types.d.cts +72 -0
- package/dist/transports/types.d.cts.map +1 -0
- package/dist/transports/types.d.mts +72 -0
- package/dist/transports/types.d.mts.map +1 -0
- package/dist/transports/types.mjs +13 -0
- package/dist/transports/types.mjs.map +1 -0
- package/dist/transports/ws.cjs +207 -0
- package/dist/transports/ws.d.cts +47 -0
- package/dist/transports/ws.d.cts.map +1 -0
- package/dist/transports/ws.d.mts +47 -0
- package/dist/transports/ws.d.mts.map +1 -0
- package/dist/transports/ws.mjs +206 -0
- package/dist/transports/ws.mjs.map +1 -0
- package/dist/tree-index.cjs +333 -0
- package/dist/tree-index.d.cts +524 -0
- package/dist/tree-index.d.cts.map +1 -0
- package/dist/tree-index.d.mts +524 -0
- package/dist/tree-index.d.mts.map +1 -0
- package/dist/tree-index.mjs +322 -0
- package/dist/tree-index.mjs.map +1 -0
- package/dist/tree-query.cjs +655 -0
- package/dist/tree-query.d.cts +70 -0
- package/dist/tree-query.d.cts.map +1 -0
- package/dist/tree-query.d.mts +70 -0
- package/dist/tree-query.d.mts.map +1 -0
- package/dist/tree-query.mjs +648 -0
- package/dist/tree-query.mjs.map +1 -0
- package/dist/upload-actions.cjs +97 -0
- package/dist/upload-actions.d.cts +19 -0
- package/dist/upload-actions.d.cts.map +1 -0
- package/dist/upload-actions.d.mts +21 -0
- package/dist/upload-actions.d.mts.map +1 -0
- package/dist/upload-actions.mjs +90 -0
- package/dist/upload-actions.mjs.map +1 -0
- package/dist/upload-session-store.cjs +185 -0
- package/dist/upload-session-store.d.cts +99 -0
- package/dist/upload-session-store.d.cts.map +1 -0
- package/dist/upload-session-store.d.mts +99 -0
- package/dist/upload-session-store.d.mts.map +1 -0
- package/dist/upload-session-store.mjs +184 -0
- package/dist/upload-session-store.mjs.map +1 -0
- package/dist/url-normalize.cjs +61 -0
- package/dist/url-normalize.d.cts +33 -0
- package/dist/url-normalize.d.cts.map +1 -0
- package/dist/url-normalize.d.mts +33 -0
- package/dist/url-normalize.d.mts.map +1 -0
- package/dist/url-normalize.mjs +61 -0
- package/dist/url-normalize.mjs.map +1 -0
- package/dist/versioned-content-backends.cjs +155 -0
- package/dist/versioned-content-backends.d.cts +49 -0
- package/dist/versioned-content-backends.d.cts.map +1 -0
- package/dist/versioned-content-backends.d.mts +49 -0
- package/dist/versioned-content-backends.d.mts.map +1 -0
- package/dist/versioned-content-backends.mjs +154 -0
- package/dist/versioned-content-backends.mjs.map +1 -0
- package/dist/versioned-content-index.cjs +102 -0
- package/dist/versioned-content-index.d.cts +46 -0
- package/dist/versioned-content-index.d.cts.map +1 -0
- package/dist/versioned-content-index.d.mts +46 -0
- package/dist/versioned-content-index.d.mts.map +1 -0
- package/dist/versioned-content-index.mjs +103 -0
- package/dist/versioned-content-index.mjs.map +1 -0
- package/dist/versioned-content-store.cjs +121 -0
- package/dist/versioned-content-store.d.cts +90 -0
- package/dist/versioned-content-store.d.cts.map +1 -0
- package/dist/versioned-content-store.d.mts +90 -0
- package/dist/versioned-content-store.d.mts.map +1 -0
- package/dist/versioned-content-store.mjs +122 -0
- package/dist/versioned-content-store.mjs.map +1 -0
- package/dist/versioned-scope.cjs +39 -0
- package/dist/versioned-scope.d.cts +57 -0
- package/dist/versioned-scope.d.cts.map +1 -0
- package/dist/versioned-scope.d.mts +57 -0
- package/dist/versioned-scope.d.mts.map +1 -0
- package/dist/versioned-scope.mjs +37 -0
- package/dist/versioned-scope.mjs.map +1 -0
- package/migrations/0001_tree_entries.sql +17 -0
- package/migrations/0002_resolve_entries.sql +7 -0
- package/migrations/0003_entries_v2.sql +38 -0
- package/migrations/0004_gc_queue.sql +5 -0
- package/migrations/0006_resolve_enhance.sql +14 -0
- package/migrations/0007_resolve_created_at.sql +10 -0
- package/migrations/0008_changelog.sql +34 -0
- package/migrations/0009_device_sync_state.sql +29 -0
- package/migrations/0010_scope_meta.sql +33 -0
- package/migrations/0011_shares.sql +25 -0
- package/migrations/0012_scope_meta_file_count.sql +41 -0
- package/migrations/0013_scope_meta_total_bytes.sql +47 -0
- package/migrations/0014_rename_tables.sql +62 -0
- package/package.json +102 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { AFSAlreadyExistsError, AFSError, AFSForbiddenError, AFSValidationError } from "@aigne/afs";
|
|
2
|
+
import { load } from "js-yaml";
|
|
3
|
+
|
|
4
|
+
//#region src/share-declaration.ts
|
|
5
|
+
/**
|
|
6
|
+
* Phase 0.2 — ShareDeclaration: YAML schema parsing + path helpers.
|
|
7
|
+
*
|
|
8
|
+
* Exported functions used by Phase 0.3 (ShareResolver) and Phase 0.4 (writeHandler hook):
|
|
9
|
+
* - parseShareDeclaration
|
|
10
|
+
* - isShareDeclarationPath
|
|
11
|
+
* - isShareReservedPath
|
|
12
|
+
* - deriveSourcePath
|
|
13
|
+
* - mapShareErrorToAFSError
|
|
14
|
+
*/
|
|
15
|
+
const KNOWN_FIELDS = new Set([
|
|
16
|
+
"slug",
|
|
17
|
+
"kind",
|
|
18
|
+
"status",
|
|
19
|
+
"expires_at",
|
|
20
|
+
"password",
|
|
21
|
+
"visibility",
|
|
22
|
+
"description",
|
|
23
|
+
"domain"
|
|
24
|
+
]);
|
|
25
|
+
const SLUG_REGEX = /^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/;
|
|
26
|
+
const MAX_CONTENT_BYTES = 4096;
|
|
27
|
+
const MAX_DESCRIPTION_LENGTH = 200;
|
|
28
|
+
/**
|
|
29
|
+
* Parse and validate a `.share` file's content.
|
|
30
|
+
*
|
|
31
|
+
* Validation order (strict, per spec):
|
|
32
|
+
* 1. Size check (> 4096 bytes) — before YAML parse
|
|
33
|
+
* 2. Empty content (0 bytes) → { ok: true, data: {} }
|
|
34
|
+
* 3. UTF-8 decode (fatal mode)
|
|
35
|
+
* 4. YAML parse with maxAliasCount: 0
|
|
36
|
+
* 5. Unknown field detection
|
|
37
|
+
* 6. slug format
|
|
38
|
+
* 7. kind enum
|
|
39
|
+
* 8. status enum
|
|
40
|
+
* 9. description length
|
|
41
|
+
* 10. expires_at format
|
|
42
|
+
* 11. password structure
|
|
43
|
+
*/
|
|
44
|
+
function parseShareDeclaration(content) {
|
|
45
|
+
if (content.byteLength > MAX_CONTENT_BYTES) return {
|
|
46
|
+
ok: false,
|
|
47
|
+
code: "share-content-too-large",
|
|
48
|
+
message: `Content size ${content.byteLength} bytes exceeds ${MAX_CONTENT_BYTES} byte limit`,
|
|
49
|
+
detail: {
|
|
50
|
+
sizeBytes: content.byteLength,
|
|
51
|
+
limit: MAX_CONTENT_BYTES
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
if (content.byteLength === 0) return {
|
|
55
|
+
ok: true,
|
|
56
|
+
data: {}
|
|
57
|
+
};
|
|
58
|
+
let text;
|
|
59
|
+
try {
|
|
60
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
61
|
+
} catch {
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
code: "share-yaml-parse-error",
|
|
65
|
+
message: "Content is not valid UTF-8"
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
let parsed;
|
|
69
|
+
try {
|
|
70
|
+
parsed = load(text);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return {
|
|
73
|
+
ok: false,
|
|
74
|
+
code: "share-yaml-parse-error",
|
|
75
|
+
message: err instanceof Error ? err.message : String(err),
|
|
76
|
+
detail: err
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (parsed == null) return {
|
|
80
|
+
ok: true,
|
|
81
|
+
data: {}
|
|
82
|
+
};
|
|
83
|
+
if (typeof parsed !== "object" || Array.isArray(parsed)) return {
|
|
84
|
+
ok: false,
|
|
85
|
+
code: "share-yaml-parse-error",
|
|
86
|
+
message: "Expected a YAML mapping (object), got a different type"
|
|
87
|
+
};
|
|
88
|
+
const obj = parsed;
|
|
89
|
+
for (const key of Object.keys(obj)) if (!KNOWN_FIELDS.has(key)) return {
|
|
90
|
+
ok: false,
|
|
91
|
+
code: "share-field-unknown",
|
|
92
|
+
message: `Unknown field: ${key}`,
|
|
93
|
+
detail: { field: key }
|
|
94
|
+
};
|
|
95
|
+
if (obj.slug !== void 0) {
|
|
96
|
+
if (typeof obj.slug !== "string" || !SLUG_REGEX.test(obj.slug)) return {
|
|
97
|
+
ok: false,
|
|
98
|
+
code: "share-slug-invalid",
|
|
99
|
+
message: `slug must match /^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/, got: ${JSON.stringify(obj.slug)}`,
|
|
100
|
+
detail: { slug: obj.slug }
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (obj.kind !== void 0) {
|
|
104
|
+
if (obj.kind !== "raw" && obj.kind !== "web") return {
|
|
105
|
+
ok: false,
|
|
106
|
+
code: "share-kind-invalid",
|
|
107
|
+
message: `kind must be "raw" or "web", got: ${JSON.stringify(obj.kind)}`,
|
|
108
|
+
detail: { kind: obj.kind }
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (obj.status !== void 0) {
|
|
112
|
+
if (obj.status !== "active" && obj.status !== "revoked") return {
|
|
113
|
+
ok: false,
|
|
114
|
+
code: "share-status-invalid",
|
|
115
|
+
message: `status must be "active" or "revoked", got: ${JSON.stringify(obj.status)}`,
|
|
116
|
+
detail: { status: obj.status }
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
if (obj.description !== void 0) {
|
|
120
|
+
if (typeof obj.description !== "string" || obj.description.length > MAX_DESCRIPTION_LENGTH) return {
|
|
121
|
+
ok: false,
|
|
122
|
+
code: "share-field-invalid",
|
|
123
|
+
message: `description must be a string with at most ${MAX_DESCRIPTION_LENGTH} characters`,
|
|
124
|
+
detail: { field: "description" }
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
if (obj.expires_at !== void 0) {
|
|
128
|
+
if (typeof obj.expires_at !== "string" || !isValidExpiresAt(obj.expires_at)) return {
|
|
129
|
+
ok: false,
|
|
130
|
+
code: "share-field-invalid",
|
|
131
|
+
message: `expires_at must be a valid ISO 8601 datetime or Unix milliseconds string`,
|
|
132
|
+
detail: { field: "expires_at" }
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (obj.password !== void 0) {
|
|
136
|
+
const pwd = obj.password;
|
|
137
|
+
if (typeof pwd !== "object" || pwd === null || Array.isArray(pwd) || pwd.algorithm !== "argon2id" || typeof pwd.hash !== "string") return {
|
|
138
|
+
ok: false,
|
|
139
|
+
code: "share-field-invalid",
|
|
140
|
+
message: "password must be {algorithm: \"argon2id\", hash: string}",
|
|
141
|
+
detail: { field: "password" }
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
ok: true,
|
|
146
|
+
data: obj
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function isValidExpiresAt(value) {
|
|
150
|
+
if (/^\d+$/.test(value)) return true;
|
|
151
|
+
const d = new Date(value);
|
|
152
|
+
return !Number.isNaN(d.getTime());
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Returns true if `path` is a `.share` declaration file (in-tree or sidecar).
|
|
156
|
+
*
|
|
157
|
+
* Examples:
|
|
158
|
+
* `.share` → true (root in-tree)
|
|
159
|
+
* `/.share` → true (root in-tree with leading slash)
|
|
160
|
+
* `docs/.share` → true (subdirectory in-tree)
|
|
161
|
+
* `file.pdf.share` → true (sidecar)
|
|
162
|
+
* `.shares/foo` → false (reserved virtual view)
|
|
163
|
+
* `README.md` → false
|
|
164
|
+
*/
|
|
165
|
+
function isShareDeclarationPath(path) {
|
|
166
|
+
return (path.startsWith("/") ? path.slice(1) : path).endsWith(".share");
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Derives the source path from a declaration path.
|
|
170
|
+
*
|
|
171
|
+
* Examples:
|
|
172
|
+
* `.share` → `""` (root in-tree → source is root directory)
|
|
173
|
+
* `docs/.share` → `"docs"`
|
|
174
|
+
* `file.pdf.share` → `"file.pdf"`
|
|
175
|
+
*/
|
|
176
|
+
function deriveSourcePath(declPath) {
|
|
177
|
+
const p = declPath.startsWith("/") ? declPath.slice(1) : declPath;
|
|
178
|
+
if (p.endsWith("/.share")) return p.slice(0, -7);
|
|
179
|
+
return p.slice(0, -6);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Returns true if `path` is a reserved share virtual path (read-only view, not writable).
|
|
183
|
+
*
|
|
184
|
+
* Reserved paths:
|
|
185
|
+
* `.shares` → the root virtual share listing
|
|
186
|
+
* `.shares/<anything>` → entries under the root listing
|
|
187
|
+
* `instances/<iid>/.shares` → per-instance listing
|
|
188
|
+
* `instances/<iid>/.shares/<…>` → per-instance listing entries
|
|
189
|
+
*/
|
|
190
|
+
function isShareReservedPath(path) {
|
|
191
|
+
const norm = path.replace(/^\/+/, "");
|
|
192
|
+
if (norm === ".shares" || norm.startsWith(".shares/")) return true;
|
|
193
|
+
if (/^instances\/[^/]+\/\.shares(\/|$)/.test(norm)) return true;
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Maps a ShareResolver / parser error code to the appropriate AFS error type
|
|
198
|
+
* so that writeHandler can throw with the correct HTTP status code.
|
|
199
|
+
*/
|
|
200
|
+
function mapShareErrorToAFSError(code, message, path) {
|
|
201
|
+
switch (code) {
|
|
202
|
+
case "share-yaml-parse-error":
|
|
203
|
+
case "share-content-too-large":
|
|
204
|
+
case "share-field-unknown":
|
|
205
|
+
case "share-field-invalid":
|
|
206
|
+
case "share-slug-invalid":
|
|
207
|
+
case "share-kind-invalid":
|
|
208
|
+
case "share-status-invalid":
|
|
209
|
+
case "share-web-no-decl":
|
|
210
|
+
case "share-sidecar-target-missing":
|
|
211
|
+
case "share-nested": return new AFSValidationError(`[${path}] ${code}: ${message}`);
|
|
212
|
+
case "share-path-forbidden":
|
|
213
|
+
case "share-path-reserved": return new AFSForbiddenError(path, code);
|
|
214
|
+
case "share-slug-conflict": return new AFSAlreadyExistsError(path, message);
|
|
215
|
+
default: return new AFSError(`${code}: ${message}`, code);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
//#endregion
|
|
220
|
+
export { deriveSourcePath, isShareDeclarationPath, isShareReservedPath, mapShareErrorToAFSError, parseShareDeclaration };
|
|
221
|
+
//# sourceMappingURL=share-declaration.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-declaration.mjs","names":["yamlParse"],"sources":["../src/share-declaration.ts"],"sourcesContent":["/**\n * Phase 0.2 — ShareDeclaration: YAML schema parsing + path helpers.\n *\n * Exported functions used by Phase 0.3 (ShareResolver) and Phase 0.4 (writeHandler hook):\n * - parseShareDeclaration\n * - isShareDeclarationPath\n * - isShareReservedPath\n * - deriveSourcePath\n * - mapShareErrorToAFSError\n */\n\nimport { AFSAlreadyExistsError, AFSError, AFSForbiddenError, AFSValidationError } from \"@aigne/afs\";\nimport { load as yamlParse } from \"js-yaml\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** All fields are optional; an empty file is equivalent to `{}`. */\nexport interface ShareDeclaration {\n slug?: string;\n kind?: \"raw\" | \"web\";\n status?: \"active\" | \"revoked\";\n expires_at?: string; // ISO 8601 or Unix ms string\n password?: { algorithm: \"argon2id\"; hash: string };\n visibility?: \"public\" | \"unlisted\";\n description?: string; // max 200 characters\n domain?: string; // Phase 2 only\n}\n\ntype ParseOk = { ok: true; data: ShareDeclaration };\ntype ParseFail = { ok: false; code: string; message: string; detail?: unknown };\nexport type ParseResult = ParseOk | ParseFail;\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nconst KNOWN_FIELDS = new Set([\n \"slug\",\n \"kind\",\n \"status\",\n \"expires_at\",\n \"password\",\n \"visibility\",\n \"description\",\n \"domain\",\n]);\n\nconst SLUG_REGEX = /^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/;\n\nconst MAX_CONTENT_BYTES = 4096;\nconst MAX_DESCRIPTION_LENGTH = 200;\n\n// ─── Parser ───────────────────────────────────────────────────────────────────\n\n/**\n * Parse and validate a `.share` file's content.\n *\n * Validation order (strict, per spec):\n * 1. Size check (> 4096 bytes) — before YAML parse\n * 2. Empty content (0 bytes) → { ok: true, data: {} }\n * 3. UTF-8 decode (fatal mode)\n * 4. YAML parse with maxAliasCount: 0\n * 5. Unknown field detection\n * 6. slug format\n * 7. kind enum\n * 8. status enum\n * 9. description length\n * 10. expires_at format\n * 11. password structure\n */\nexport function parseShareDeclaration(content: Uint8Array): ParseResult {\n // Step 1: size check — MUST happen before YAML parse\n if (content.byteLength > MAX_CONTENT_BYTES) {\n return {\n ok: false,\n code: \"share-content-too-large\",\n message: `Content size ${content.byteLength} bytes exceeds ${MAX_CONTENT_BYTES} byte limit`,\n detail: { sizeBytes: content.byteLength, limit: MAX_CONTENT_BYTES },\n };\n }\n\n // Step 2: empty content\n if (content.byteLength === 0) {\n return { ok: true, data: {} };\n }\n\n // Step 3: UTF-8 decode (fatal — reject non-UTF-8 bytes)\n let text: string;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: true }).decode(content);\n } catch {\n return {\n ok: false,\n code: \"share-yaml-parse-error\",\n message: \"Content is not valid UTF-8\",\n };\n }\n\n // Step 4: YAML parse (content size already capped at 4096 bytes above)\n let parsed: unknown;\n try {\n parsed = yamlParse(text);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n ok: false,\n code: \"share-yaml-parse-error\",\n message: msg,\n detail: err,\n };\n }\n\n // null / undefined YAML (empty doc, comment-only, \"---\\n\") → empty declaration\n if (parsed == null) {\n return { ok: true, data: {} };\n }\n\n // Must be a plain object\n if (typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return {\n ok: false,\n code: \"share-yaml-parse-error\",\n message: \"Expected a YAML mapping (object), got a different type\",\n };\n }\n\n const obj = parsed as Record<string, unknown>;\n\n // Step 5: unknown fields\n for (const key of Object.keys(obj)) {\n if (!KNOWN_FIELDS.has(key)) {\n return {\n ok: false,\n code: \"share-field-unknown\",\n message: `Unknown field: ${key}`,\n detail: { field: key },\n };\n }\n }\n\n // Step 6: slug format\n if (obj.slug !== undefined) {\n if (typeof obj.slug !== \"string\" || !SLUG_REGEX.test(obj.slug)) {\n return {\n ok: false,\n code: \"share-slug-invalid\",\n message: `slug must match /^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/, got: ${JSON.stringify(obj.slug)}`,\n detail: { slug: obj.slug },\n };\n }\n }\n\n // Step 7: kind enum\n if (obj.kind !== undefined) {\n if (obj.kind !== \"raw\" && obj.kind !== \"web\") {\n return {\n ok: false,\n code: \"share-kind-invalid\",\n message: `kind must be \"raw\" or \"web\", got: ${JSON.stringify(obj.kind)}`,\n detail: { kind: obj.kind },\n };\n }\n }\n\n // Step 8: status enum\n if (obj.status !== undefined) {\n if (obj.status !== \"active\" && obj.status !== \"revoked\") {\n return {\n ok: false,\n code: \"share-status-invalid\",\n message: `status must be \"active\" or \"revoked\", got: ${JSON.stringify(obj.status)}`,\n detail: { status: obj.status },\n };\n }\n }\n\n // Step 9: description length\n if (obj.description !== undefined) {\n if (typeof obj.description !== \"string\" || obj.description.length > MAX_DESCRIPTION_LENGTH) {\n return {\n ok: false,\n code: \"share-field-invalid\",\n message: `description must be a string with at most ${MAX_DESCRIPTION_LENGTH} characters`,\n detail: { field: \"description\" },\n };\n }\n }\n\n // Step 10: expires_at format\n if (obj.expires_at !== undefined) {\n if (typeof obj.expires_at !== \"string\" || !isValidExpiresAt(obj.expires_at)) {\n return {\n ok: false,\n code: \"share-field-invalid\",\n message: `expires_at must be a valid ISO 8601 datetime or Unix milliseconds string`,\n detail: { field: \"expires_at\" },\n };\n }\n }\n\n // Step 11: password structure\n if (obj.password !== undefined) {\n const pwd = obj.password as Record<string, unknown>;\n if (\n typeof pwd !== \"object\" ||\n pwd === null ||\n Array.isArray(pwd) ||\n pwd.algorithm !== \"argon2id\" ||\n typeof pwd.hash !== \"string\"\n ) {\n return {\n ok: false,\n code: \"share-field-invalid\",\n message: 'password must be {algorithm: \"argon2id\", hash: string}',\n detail: { field: \"password\" },\n };\n }\n }\n\n return { ok: true, data: obj as ShareDeclaration };\n}\n\nfunction isValidExpiresAt(value: string): boolean {\n // Accept Unix milliseconds (all-digit string)\n if (/^\\d+$/.test(value)) return true;\n // Accept ISO 8601 (anything Date can parse)\n const d = new Date(value);\n return !Number.isNaN(d.getTime());\n}\n\n// ─── Path helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Returns true if `path` is a `.share` declaration file (in-tree or sidecar).\n *\n * Examples:\n * `.share` → true (root in-tree)\n * `/.share` → true (root in-tree with leading slash)\n * `docs/.share` → true (subdirectory in-tree)\n * `file.pdf.share` → true (sidecar)\n * `.shares/foo` → false (reserved virtual view)\n * `README.md` → false\n */\nexport function isShareDeclarationPath(path: string): boolean {\n const p = path.startsWith(\"/\") ? path.slice(1) : path;\n // All three cases (.share, dir/.share, file.pdf.share) end with \".share\"\n // Note: \".shares\" ends with \".shares\", not \".share\", so it correctly returns false\n return p.endsWith(\".share\");\n}\n\n/**\n * Derives the source path from a declaration path.\n *\n * Examples:\n * `.share` → `\"\"` (root in-tree → source is root directory)\n * `docs/.share` → `\"docs\"`\n * `file.pdf.share` → `\"file.pdf\"`\n */\nexport function deriveSourcePath(declPath: string): string {\n const p = declPath.startsWith(\"/\") ? declPath.slice(1) : declPath;\n if (p.endsWith(\"/.share\")) return p.slice(0, -\"/.share\".length);\n // Root in-tree (\".share\") → slice(0, -6) === \"\" ✓; sidecar (\"file.pdf.share\") → \"file.pdf\" ✓\n return p.slice(0, -\".share\".length);\n}\n\n/**\n * Returns true if `path` is a reserved share virtual path (read-only view, not writable).\n *\n * Reserved paths:\n * `.shares` → the root virtual share listing\n * `.shares/<anything>` → entries under the root listing\n * `instances/<iid>/.shares` → per-instance listing\n * `instances/<iid>/.shares/<…>` → per-instance listing entries\n */\nexport function isShareReservedPath(path: string): boolean {\n const norm = path.replace(/^\\/+/, \"\");\n if (norm === \".shares\" || norm.startsWith(\".shares/\")) return true;\n if (/^instances\\/[^/]+\\/\\.shares(\\/|$)/.test(norm)) return true;\n return false;\n}\n\n// ─── Error mapper ─────────────────────────────────────────────────────────────\n\n/**\n * Maps a ShareResolver / parser error code to the appropriate AFS error type\n * so that writeHandler can throw with the correct HTTP status code.\n */\nexport function mapShareErrorToAFSError(\n code: string,\n message: string,\n path: string,\n): AFSValidationError | AFSForbiddenError | AFSAlreadyExistsError | AFSError {\n switch (code) {\n // 400 Bad Request — validation\n case \"share-yaml-parse-error\":\n case \"share-content-too-large\":\n case \"share-field-unknown\":\n case \"share-field-invalid\":\n case \"share-slug-invalid\":\n case \"share-kind-invalid\":\n case \"share-status-invalid\":\n case \"share-web-no-decl\":\n case \"share-sidecar-target-missing\":\n case \"share-nested\":\n return new AFSValidationError(`[${path}] ${code}: ${message}`);\n // 403 Forbidden\n case \"share-path-forbidden\":\n case \"share-path-reserved\":\n return new AFSForbiddenError(path, code);\n // 409 Conflict — slug already used by a different decl_path\n case \"share-slug-conflict\":\n return new AFSAlreadyExistsError(path, message);\n // 500 fallback\n default:\n return new AFSError(`${code}: ${message}`, code);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_share_declaration = require('./share-declaration.cjs');
|
|
3
|
+
let _aigne_afs = require("@aigne/afs");
|
|
4
|
+
|
|
5
|
+
//#region src/share-hook.ts
|
|
6
|
+
/**
|
|
7
|
+
* Phase 0.4 — Share write/delete hooks for all DID Space write paths.
|
|
8
|
+
*
|
|
9
|
+
* Provides applyShareWriteHook and applyShareDeleteHook, shared utilities
|
|
10
|
+
* called from all three write paths:
|
|
11
|
+
* - CloudflareDIDSpace.internalWrite (REST API)
|
|
12
|
+
* - DIDSpaceProvider.internalWrite (SyncEngine)
|
|
13
|
+
* - DIDSpaceProvider.writeHandler (AFS protocol)
|
|
14
|
+
*
|
|
15
|
+
* Separated from share-declaration.ts to avoid circular imports:
|
|
16
|
+
* share-hook.ts → share-resolve.ts + share-declaration.ts
|
|
17
|
+
* share-resolve.ts → share-declaration.ts
|
|
18
|
+
* share-declaration.ts → (no share deps)
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* applyShareWriteHook — called in any DID Space write path for .share files.
|
|
22
|
+
*
|
|
23
|
+
* phase="pre-io": validates BEFORE R2 PUT (dryRun=true).
|
|
24
|
+
* Validation failure → throws AFS error; R2/D1 not written.
|
|
25
|
+
*
|
|
26
|
+
* phase="post-io": reconciles AFTER R2 + tree_entries written (dryRun=false).
|
|
27
|
+
* Failure → throws AFSError (eventual consistency; R2 already written).
|
|
28
|
+
*/
|
|
29
|
+
async function applyShareWriteHook(params) {
|
|
30
|
+
if (!params.resolver || !require_share_declaration.isShareDeclarationPath(params.afsPath)) return;
|
|
31
|
+
const { afsPath, treePath, bytes, cid, ownerDid, resolver, phase } = params;
|
|
32
|
+
if (phase === "pre-io") {
|
|
33
|
+
const validation = await resolver.reconcileFromDecl({
|
|
34
|
+
declPath: treePath,
|
|
35
|
+
declContent: bytes,
|
|
36
|
+
declCid: cid,
|
|
37
|
+
ownerDid,
|
|
38
|
+
dryRun: true
|
|
39
|
+
});
|
|
40
|
+
if (!validation.ok) throw require_share_declaration.mapShareErrorToAFSError(validation.code, validation.message, afsPath);
|
|
41
|
+
} else {
|
|
42
|
+
const result = await resolver.reconcileFromDecl({
|
|
43
|
+
declPath: treePath,
|
|
44
|
+
declContent: bytes,
|
|
45
|
+
declCid: cid,
|
|
46
|
+
ownerDid
|
|
47
|
+
});
|
|
48
|
+
if (!result.ok) throw new _aigne_afs.AFSError(`share-index-failed: ${result.code} — ${result.message}`, result.code);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* applyShareDeleteHook — called in any DID Space delete path for .share files.
|
|
53
|
+
*
|
|
54
|
+
* Should be called AFTER tree_entries is deleted, to clean up shares index.
|
|
55
|
+
*/
|
|
56
|
+
async function applyShareDeleteHook(params) {
|
|
57
|
+
if (!params.resolver || !require_share_declaration.isShareDeclarationPath(params.afsPath)) return;
|
|
58
|
+
await params.resolver.reconcileDelete(params.ownerDid, params.treePath);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
exports.applyShareDeleteHook = applyShareDeleteHook;
|
|
63
|
+
exports.applyShareWriteHook = applyShareWriteHook;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { isShareDeclarationPath, mapShareErrorToAFSError } from "./share-declaration.mjs";
|
|
2
|
+
import { AFSError } from "@aigne/afs";
|
|
3
|
+
|
|
4
|
+
//#region src/share-hook.ts
|
|
5
|
+
/**
|
|
6
|
+
* Phase 0.4 — Share write/delete hooks for all DID Space write paths.
|
|
7
|
+
*
|
|
8
|
+
* Provides applyShareWriteHook and applyShareDeleteHook, shared utilities
|
|
9
|
+
* called from all three write paths:
|
|
10
|
+
* - CloudflareDIDSpace.internalWrite (REST API)
|
|
11
|
+
* - DIDSpaceProvider.internalWrite (SyncEngine)
|
|
12
|
+
* - DIDSpaceProvider.writeHandler (AFS protocol)
|
|
13
|
+
*
|
|
14
|
+
* Separated from share-declaration.ts to avoid circular imports:
|
|
15
|
+
* share-hook.ts → share-resolve.ts + share-declaration.ts
|
|
16
|
+
* share-resolve.ts → share-declaration.ts
|
|
17
|
+
* share-declaration.ts → (no share deps)
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* applyShareWriteHook — called in any DID Space write path for .share files.
|
|
21
|
+
*
|
|
22
|
+
* phase="pre-io": validates BEFORE R2 PUT (dryRun=true).
|
|
23
|
+
* Validation failure → throws AFS error; R2/D1 not written.
|
|
24
|
+
*
|
|
25
|
+
* phase="post-io": reconciles AFTER R2 + tree_entries written (dryRun=false).
|
|
26
|
+
* Failure → throws AFSError (eventual consistency; R2 already written).
|
|
27
|
+
*/
|
|
28
|
+
async function applyShareWriteHook(params) {
|
|
29
|
+
if (!params.resolver || !isShareDeclarationPath(params.afsPath)) return;
|
|
30
|
+
const { afsPath, treePath, bytes, cid, ownerDid, resolver, phase } = params;
|
|
31
|
+
if (phase === "pre-io") {
|
|
32
|
+
const validation = await resolver.reconcileFromDecl({
|
|
33
|
+
declPath: treePath,
|
|
34
|
+
declContent: bytes,
|
|
35
|
+
declCid: cid,
|
|
36
|
+
ownerDid,
|
|
37
|
+
dryRun: true
|
|
38
|
+
});
|
|
39
|
+
if (!validation.ok) throw mapShareErrorToAFSError(validation.code, validation.message, afsPath);
|
|
40
|
+
} else {
|
|
41
|
+
const result = await resolver.reconcileFromDecl({
|
|
42
|
+
declPath: treePath,
|
|
43
|
+
declContent: bytes,
|
|
44
|
+
declCid: cid,
|
|
45
|
+
ownerDid
|
|
46
|
+
});
|
|
47
|
+
if (!result.ok) throw new AFSError(`share-index-failed: ${result.code} — ${result.message}`, result.code);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* applyShareDeleteHook — called in any DID Space delete path for .share files.
|
|
52
|
+
*
|
|
53
|
+
* Should be called AFTER tree_entries is deleted, to clean up shares index.
|
|
54
|
+
*/
|
|
55
|
+
async function applyShareDeleteHook(params) {
|
|
56
|
+
if (!params.resolver || !isShareDeclarationPath(params.afsPath)) return;
|
|
57
|
+
await params.resolver.reconcileDelete(params.ownerDid, params.treePath);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
export { applyShareDeleteHook, applyShareWriteHook };
|
|
62
|
+
//# sourceMappingURL=share-hook.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-hook.mjs","names":[],"sources":["../src/share-hook.ts"],"sourcesContent":["/**\n * Phase 0.4 — Share write/delete hooks for all DID Space write paths.\n *\n * Provides applyShareWriteHook and applyShareDeleteHook, shared utilities\n * called from all three write paths:\n * - CloudflareDIDSpace.internalWrite (REST API)\n * - DIDSpaceProvider.internalWrite (SyncEngine)\n * - DIDSpaceProvider.writeHandler (AFS protocol)\n *\n * Separated from share-declaration.ts to avoid circular imports:\n * share-hook.ts → share-resolve.ts + share-declaration.ts\n * share-resolve.ts → share-declaration.ts\n * share-declaration.ts → (no share deps)\n */\n\nimport { AFSError } from \"@aigne/afs\";\nimport { isShareDeclarationPath, mapShareErrorToAFSError } from \"./share-declaration.js\";\nimport type { ShareResolver } from \"./share-resolve.js\";\n\n/**\n * applyShareWriteHook — called in any DID Space write path for .share files.\n *\n * phase=\"pre-io\": validates BEFORE R2 PUT (dryRun=true).\n * Validation failure → throws AFS error; R2/D1 not written.\n *\n * phase=\"post-io\": reconciles AFTER R2 + tree_entries written (dryRun=false).\n * Failure → throws AFSError (eventual consistency; R2 already written).\n */\nexport async function applyShareWriteHook(params: {\n afsPath: string;\n treePath: string;\n bytes: Uint8Array;\n cid: string;\n ownerDid: string;\n resolver: ShareResolver | undefined;\n phase: \"pre-io\" | \"post-io\";\n}): Promise<void> {\n if (!params.resolver || !isShareDeclarationPath(params.afsPath)) return;\n\n const { afsPath, treePath, bytes, cid, ownerDid, resolver, phase } = params;\n\n if (phase === \"pre-io\") {\n const validation = await resolver.reconcileFromDecl({\n declPath: treePath,\n declContent: bytes,\n declCid: cid,\n ownerDid,\n dryRun: true,\n });\n if (!validation.ok) {\n throw mapShareErrorToAFSError(validation.code, validation.message, afsPath);\n }\n } else {\n // post-io: R2 already written — best-effort D1 update\n const result = await resolver.reconcileFromDecl({\n declPath: treePath,\n declContent: bytes,\n declCid: cid,\n ownerDid,\n });\n if (!result.ok) {\n throw new AFSError(`share-index-failed: ${result.code} — ${result.message}`, result.code);\n }\n }\n}\n\n/**\n * applyShareDeleteHook — called in any DID Space delete path for .share files.\n *\n * Should be called AFTER tree_entries is deleted, to clean up shares index.\n */\nexport async function applyShareDeleteHook(params: {\n afsPath: string;\n treePath: string;\n ownerDid: string;\n resolver: ShareResolver | undefined;\n}): Promise<void> {\n if (!params.resolver || !isShareDeclarationPath(params.afsPath)) return;\n await params.resolver.reconcileDelete(params.ownerDid, params.treePath);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,eAAsB,oBAAoB,QAQxB;AAChB,KAAI,CAAC,OAAO,YAAY,CAAC,uBAAuB,OAAO,QAAQ,CAAE;CAEjE,MAAM,EAAE,SAAS,UAAU,OAAO,KAAK,UAAU,UAAU,UAAU;AAErE,KAAI,UAAU,UAAU;EACtB,MAAM,aAAa,MAAM,SAAS,kBAAkB;GAClD,UAAU;GACV,aAAa;GACb,SAAS;GACT;GACA,QAAQ;GACT,CAAC;AACF,MAAI,CAAC,WAAW,GACd,OAAM,wBAAwB,WAAW,MAAM,WAAW,SAAS,QAAQ;QAExE;EAEL,MAAM,SAAS,MAAM,SAAS,kBAAkB;GAC9C,UAAU;GACV,aAAa;GACb,SAAS;GACT;GACD,CAAC;AACF,MAAI,CAAC,OAAO,GACV,OAAM,IAAI,SAAS,uBAAuB,OAAO,KAAK,KAAK,OAAO,WAAW,OAAO,KAAK;;;;;;;;AAU/F,eAAsB,qBAAqB,QAKzB;AAChB,KAAI,CAAC,OAAO,YAAY,CAAC,uBAAuB,OAAO,QAAQ,CAAE;AACjE,OAAM,OAAO,SAAS,gBAAgB,OAAO,UAAU,OAAO,SAAS"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
const require_share_declaration = require('./share-declaration.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/share-resolve.ts
|
|
4
|
+
/**
|
|
5
|
+
* Phase 0.4 — ShareResolver: storage-agnostic share reconcile orchestrator.
|
|
6
|
+
*
|
|
7
|
+
* Holds the reconcile BUSINESS LOGIC (YAML parse + schema validation, reserved
|
|
8
|
+
* / forbidden / traversal path checks, sourcePath derivation, nested-share
|
|
9
|
+
* detection, kind auto-detection, slug determination + conflict check) and
|
|
10
|
+
* delegates ALL `shares` table access to an injected {@link ShareStore}. This
|
|
11
|
+
* mirrors the repo's `DIDSpaceResolver + KeyValueStore` precedent — one
|
|
12
|
+
* orchestrator, swappable backend (D1 / libsql), no adapter.
|
|
13
|
+
*
|
|
14
|
+
* Identity is owner-scoped: `(ownerDid, declPath)` is the composite key, so two
|
|
15
|
+
* owners that share one D1 / one daemon-global `_shares.db` never clobber each
|
|
16
|
+
* other (CRITICAL #1 fix). `slug` stays globally unique.
|
|
17
|
+
*
|
|
18
|
+
* Offline full rebuild (`reconcileAll`) is intentionally NOT here — see
|
|
19
|
+
* `D1ShareReconciler` in d1-share-store.ts (D1-only, needs an ObjectStore).
|
|
20
|
+
*/
|
|
21
|
+
/** 21-character random ID using Web Crypto (base-36, no external deps). */
|
|
22
|
+
function generateId() {
|
|
23
|
+
return Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(36).padStart(2, "0")).join("").slice(0, 21);
|
|
24
|
+
}
|
|
25
|
+
/** Paths under these prefixes are forbidden from having shares. */
|
|
26
|
+
const FORBIDDEN_PREFIXES = ["config/", "vault/"];
|
|
27
|
+
function isForbiddenPath(path) {
|
|
28
|
+
const p = path.startsWith("/") ? path.slice(1) : path;
|
|
29
|
+
return FORBIDDEN_PREFIXES.some((prefix) => p.startsWith(prefix));
|
|
30
|
+
}
|
|
31
|
+
function hasPathTraversal(path) {
|
|
32
|
+
return path.split("/").includes("..");
|
|
33
|
+
}
|
|
34
|
+
/** Returns true if the declPath is a sidecar (not root, not in-tree /.share). */
|
|
35
|
+
function isSidecarPath(declPath) {
|
|
36
|
+
const p = declPath.startsWith("/") ? declPath.slice(1) : declPath;
|
|
37
|
+
return p !== ".share" && !p.endsWith("/.share");
|
|
38
|
+
}
|
|
39
|
+
var ShareResolver = class {
|
|
40
|
+
constructor(store, treeIndex) {
|
|
41
|
+
this.store = store;
|
|
42
|
+
this.treeIndex = treeIndex;
|
|
43
|
+
}
|
|
44
|
+
resolveBySlug(slug) {
|
|
45
|
+
return this.store.resolveBySlug(slug);
|
|
46
|
+
}
|
|
47
|
+
listByOwner(ownerDid) {
|
|
48
|
+
return this.store.listByOwner(ownerDid);
|
|
49
|
+
}
|
|
50
|
+
listByInstance(ownerDid, instanceDid) {
|
|
51
|
+
return this.store.listByInstance(ownerDid, instanceDid);
|
|
52
|
+
}
|
|
53
|
+
readShare(ownerDid, slug) {
|
|
54
|
+
return this.store.readByOwnerAndSlug(ownerDid, slug);
|
|
55
|
+
}
|
|
56
|
+
findByOwnerAndDeclPath(ownerDid, declPath) {
|
|
57
|
+
return this.store.findByOwnerAndDeclPath(ownerDid, declPath);
|
|
58
|
+
}
|
|
59
|
+
async reconcileFromDecl(params) {
|
|
60
|
+
const { declPath, declContent, declCid, ownerDid, dryRun = false } = params;
|
|
61
|
+
const parsed = require_share_declaration.parseShareDeclaration(declContent);
|
|
62
|
+
if (!parsed.ok) return parsed;
|
|
63
|
+
if (require_share_declaration.isShareReservedPath(declPath)) return {
|
|
64
|
+
ok: false,
|
|
65
|
+
code: "share-path-reserved",
|
|
66
|
+
message: `Path is reserved and cannot have a share declaration: ${declPath}`
|
|
67
|
+
};
|
|
68
|
+
if (isForbiddenPath(declPath)) return {
|
|
69
|
+
ok: false,
|
|
70
|
+
code: "share-path-forbidden",
|
|
71
|
+
message: `Path prefix is forbidden for share declarations: ${declPath}`
|
|
72
|
+
};
|
|
73
|
+
if (hasPathTraversal(declPath)) return {
|
|
74
|
+
ok: false,
|
|
75
|
+
code: "share-path-forbidden",
|
|
76
|
+
message: `Path traversal detected in declaration path: ${declPath}`
|
|
77
|
+
};
|
|
78
|
+
const sourcePath = require_share_declaration.deriveSourcePath(declPath);
|
|
79
|
+
const isSidecar = isSidecarPath(declPath);
|
|
80
|
+
if (sourcePath !== "") {
|
|
81
|
+
const nested = await this.store.findNestedConflict(ownerDid, declPath, sourcePath);
|
|
82
|
+
if (nested) return {
|
|
83
|
+
ok: false,
|
|
84
|
+
code: "share-nested",
|
|
85
|
+
message: `Share declaration conflicts with ${nested}`
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (isSidecar && this.treeIndex && sourcePath) {
|
|
89
|
+
if (!await this.treeIndex.get(sourcePath, { includeContent: false })) return {
|
|
90
|
+
ok: false,
|
|
91
|
+
code: "share-sidecar-target-missing",
|
|
92
|
+
message: `Sidecar target file not found: ${sourcePath}`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
let resolvedKind;
|
|
96
|
+
if (parsed.data.kind) {
|
|
97
|
+
resolvedKind = parsed.data.kind;
|
|
98
|
+
if (resolvedKind === "web" && this.treeIndex) {
|
|
99
|
+
const webPrefix = sourcePath ? `${sourcePath}/.web/` : ".web/";
|
|
100
|
+
const { entries } = await this.treeIndex.list(webPrefix, { limit: 1 });
|
|
101
|
+
if (entries.length === 0) return {
|
|
102
|
+
ok: false,
|
|
103
|
+
code: "share-web-no-decl",
|
|
104
|
+
message: `kind:web requires a .web/ directory at ${webPrefix}`
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
} else if (isSidecar) resolvedKind = "raw";
|
|
108
|
+
else if (this.treeIndex) {
|
|
109
|
+
const webPrefix = sourcePath ? `${sourcePath}/.web/` : ".web/";
|
|
110
|
+
const { entries } = await this.treeIndex.list(webPrefix, { limit: 1 });
|
|
111
|
+
resolvedKind = entries.length > 0 ? "web" : "raw";
|
|
112
|
+
} else resolvedKind = "raw";
|
|
113
|
+
const existing = await this.store.findByOwnerAndDeclPath(ownerDid, declPath);
|
|
114
|
+
let slug;
|
|
115
|
+
if (parsed.data.slug) slug = parsed.data.slug;
|
|
116
|
+
else if (existing) slug = existing.slug;
|
|
117
|
+
else slug = generateId();
|
|
118
|
+
if (!existing || existing.slug !== slug) {
|
|
119
|
+
const conflicting = await this.store.findSlugConflict(slug, ownerDid, declPath);
|
|
120
|
+
if (conflicting) return {
|
|
121
|
+
ok: false,
|
|
122
|
+
code: "share-slug-conflict",
|
|
123
|
+
message: `Slug "${slug}" is already claimed by ${conflicting}`
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const now = Date.now();
|
|
127
|
+
const id = existing?.id ?? generateId();
|
|
128
|
+
const status = parsed.data.status ?? "active";
|
|
129
|
+
if (dryRun) return {
|
|
130
|
+
ok: true,
|
|
131
|
+
entry: {
|
|
132
|
+
id,
|
|
133
|
+
ownerDid,
|
|
134
|
+
sourcePath,
|
|
135
|
+
declPath,
|
|
136
|
+
slug,
|
|
137
|
+
kind: resolvedKind,
|
|
138
|
+
status,
|
|
139
|
+
declCid,
|
|
140
|
+
config: parsed.data,
|
|
141
|
+
createdAt: existing?.createdAt ?? now,
|
|
142
|
+
updatedAt: now
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const row = {
|
|
146
|
+
id,
|
|
147
|
+
owner_did: ownerDid,
|
|
148
|
+
source_path: sourcePath,
|
|
149
|
+
decl_path: declPath,
|
|
150
|
+
slug,
|
|
151
|
+
kind: resolvedKind,
|
|
152
|
+
status,
|
|
153
|
+
decl_cid: declCid,
|
|
154
|
+
config_json: JSON.stringify(parsed.data),
|
|
155
|
+
created_at: existing?.createdAt ?? now,
|
|
156
|
+
updated_at: now
|
|
157
|
+
};
|
|
158
|
+
await this.store.upsert(row);
|
|
159
|
+
const final = await this.store.findByOwnerAndDeclPath(ownerDid, declPath);
|
|
160
|
+
if (!final) return {
|
|
161
|
+
ok: false,
|
|
162
|
+
code: "share-internal-error",
|
|
163
|
+
message: "Failed to read back the upserted share row"
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
ok: true,
|
|
167
|
+
entry: final
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
reconcileDelete(ownerDid, declPath) {
|
|
171
|
+
return this.store.deleteByOwnerAndDeclPath(ownerDid, declPath);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
//#endregion
|
|
176
|
+
exports.ShareResolver = ShareResolver;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ShareEntry, ShareStore } from "./share-store.cjs";
|
|
2
|
+
import { TreeIndex } from "./tree-index.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/share-resolve.d.ts
|
|
5
|
+
type ReconcileOk = {
|
|
6
|
+
ok: true;
|
|
7
|
+
entry: ShareEntry;
|
|
8
|
+
};
|
|
9
|
+
type ReconcileFail = {
|
|
10
|
+
ok: false;
|
|
11
|
+
code: string;
|
|
12
|
+
message: string;
|
|
13
|
+
detail?: unknown;
|
|
14
|
+
};
|
|
15
|
+
type ReconcileResult = ReconcileOk | ReconcileFail;
|
|
16
|
+
declare class ShareResolver {
|
|
17
|
+
private store;
|
|
18
|
+
private treeIndex?;
|
|
19
|
+
constructor(store: ShareStore, treeIndex?: TreeIndex | undefined);
|
|
20
|
+
resolveBySlug(slug: string): Promise<ShareEntry | null>;
|
|
21
|
+
listByOwner(ownerDid: string): Promise<ShareEntry[]>;
|
|
22
|
+
listByInstance(ownerDid: string, instanceDid: string): Promise<ShareEntry[]>;
|
|
23
|
+
readShare(ownerDid: string, slug: string): Promise<ShareEntry | null>;
|
|
24
|
+
findByOwnerAndDeclPath(ownerDid: string, declPath: string): Promise<ShareEntry | null>;
|
|
25
|
+
reconcileFromDecl(params: {
|
|
26
|
+
declPath: string;
|
|
27
|
+
declContent: Uint8Array;
|
|
28
|
+
declCid: string;
|
|
29
|
+
ownerDid: string;
|
|
30
|
+
dryRun?: boolean;
|
|
31
|
+
}): Promise<ReconcileResult>;
|
|
32
|
+
reconcileDelete(ownerDid: string, declPath: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { ShareResolver };
|
|
36
|
+
//# sourceMappingURL=share-resolve.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-resolve.d.cts","names":[],"sources":["../src/share-resolve.ts"],"mappings":";;;;KAyDK,WAAA;EAAgB,EAAA;EAAU,KAAA,EAAO,UAAA;AAAA;AAAA,KACjC,aAAA;EAAkB,EAAA;EAAW,IAAA;EAAc,OAAA;EAAiB,MAAA;AAAA;AAAA,KAC5D,eAAA,GAAkB,WAAA,GAAc,aAAA;AAAA,cAIxB,aAAA;EAAA,QAED,KAAA;EAAA,QAMA,SAAA;cANA,KAAA,EAAO,UAAA,EAMP,SAAA,GAAY,SAAA;EAKtB,aAAA,CAAc,IAAA,WAAe,OAAA,CAAQ,UAAA;EAMrC,WAAA,CAAY,QAAA,WAAmB,OAAA,CAAQ,UAAA;EAIvC,cAAA,CAAe,QAAA,UAAkB,WAAA,WAAsB,OAAA,CAAQ,UAAA;EAI/D,SAAA,CAAU,QAAA,UAAkB,IAAA,WAAe,OAAA,CAAQ,UAAA;EAInD,sBAAA,CAAuB,QAAA,UAAkB,QAAA,WAAmB,OAAA,CAAQ,UAAA;EAM9D,iBAAA,CAAkB,MAAA;IACtB,QAAA;IACA,WAAA,EAAa,UAAA;IACb,OAAA;IACA,QAAA;IACA,MAAA;EAAA,IACE,OAAA,CAAQ,eAAA;EAyKZ,eAAA,CAAgB,QAAA,UAAkB,QAAA,WAAmB,OAAA;AAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ShareEntry, ShareStore } from "./share-store.mjs";
|
|
2
|
+
import { TreeIndex } from "./tree-index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/share-resolve.d.ts
|
|
5
|
+
type ReconcileOk = {
|
|
6
|
+
ok: true;
|
|
7
|
+
entry: ShareEntry;
|
|
8
|
+
};
|
|
9
|
+
type ReconcileFail = {
|
|
10
|
+
ok: false;
|
|
11
|
+
code: string;
|
|
12
|
+
message: string;
|
|
13
|
+
detail?: unknown;
|
|
14
|
+
};
|
|
15
|
+
type ReconcileResult = ReconcileOk | ReconcileFail;
|
|
16
|
+
declare class ShareResolver {
|
|
17
|
+
private store;
|
|
18
|
+
private treeIndex?;
|
|
19
|
+
constructor(store: ShareStore, treeIndex?: TreeIndex | undefined);
|
|
20
|
+
resolveBySlug(slug: string): Promise<ShareEntry | null>;
|
|
21
|
+
listByOwner(ownerDid: string): Promise<ShareEntry[]>;
|
|
22
|
+
listByInstance(ownerDid: string, instanceDid: string): Promise<ShareEntry[]>;
|
|
23
|
+
readShare(ownerDid: string, slug: string): Promise<ShareEntry | null>;
|
|
24
|
+
findByOwnerAndDeclPath(ownerDid: string, declPath: string): Promise<ShareEntry | null>;
|
|
25
|
+
reconcileFromDecl(params: {
|
|
26
|
+
declPath: string;
|
|
27
|
+
declContent: Uint8Array;
|
|
28
|
+
declCid: string;
|
|
29
|
+
ownerDid: string;
|
|
30
|
+
dryRun?: boolean;
|
|
31
|
+
}): Promise<ReconcileResult>;
|
|
32
|
+
reconcileDelete(ownerDid: string, declPath: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { ShareResolver };
|
|
36
|
+
//# sourceMappingURL=share-resolve.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-resolve.d.mts","names":[],"sources":["../src/share-resolve.ts"],"mappings":";;;;KAyDK,WAAA;EAAgB,EAAA;EAAU,KAAA,EAAO,UAAA;AAAA;AAAA,KACjC,aAAA;EAAkB,EAAA;EAAW,IAAA;EAAc,OAAA;EAAiB,MAAA;AAAA;AAAA,KAC5D,eAAA,GAAkB,WAAA,GAAc,aAAA;AAAA,cAIxB,aAAA;EAAA,QAED,KAAA;EAAA,QAMA,SAAA;cANA,KAAA,EAAO,UAAA,EAMP,SAAA,GAAY,SAAA;EAKtB,aAAA,CAAc,IAAA,WAAe,OAAA,CAAQ,UAAA;EAMrC,WAAA,CAAY,QAAA,WAAmB,OAAA,CAAQ,UAAA;EAIvC,cAAA,CAAe,QAAA,UAAkB,WAAA,WAAsB,OAAA,CAAQ,UAAA;EAI/D,SAAA,CAAU,QAAA,UAAkB,IAAA,WAAe,OAAA,CAAQ,UAAA;EAInD,sBAAA,CAAuB,QAAA,UAAkB,QAAA,WAAmB,OAAA,CAAQ,UAAA;EAM9D,iBAAA,CAAkB,MAAA;IACtB,QAAA;IACA,WAAA,EAAa,UAAA;IACb,OAAA;IACA,QAAA;IACA,MAAA;EAAA,IACE,OAAA,CAAQ,eAAA;EAyKZ,eAAA,CAAgB,QAAA,UAAkB,QAAA,WAAmB,OAAA;AAAA"}
|