anchordb 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/dist/cjs/conflict/strategies.d.ts +110 -0
- package/dist/cjs/conflict/strategies.d.ts.map +1 -0
- package/dist/cjs/conflict/strategies.js +298 -0
- package/dist/cjs/conflict/strategies.js.map +1 -0
- package/dist/cjs/conflict/types.d.ts +38 -0
- package/dist/cjs/conflict/types.d.ts.map +1 -0
- package/dist/cjs/conflict/types.js +3 -0
- package/dist/cjs/conflict/types.js.map +1 -0
- package/dist/cjs/core/anchor-db.d.ts +154 -0
- package/dist/cjs/core/anchor-db.d.ts.map +1 -0
- package/dist/cjs/core/anchor-db.js +273 -0
- package/dist/cjs/core/anchor-db.js.map +1 -0
- package/dist/cjs/core/errors.d.ts +125 -0
- package/dist/cjs/core/errors.d.ts.map +1 -0
- package/dist/cjs/core/errors.js +174 -0
- package/dist/cjs/core/errors.js.map +1 -0
- package/dist/cjs/core/hex.d.ts +4 -0
- package/dist/cjs/core/hex.d.ts.map +1 -0
- package/dist/cjs/core/hex.js +41 -0
- package/dist/cjs/core/hex.js.map +1 -0
- package/dist/cjs/core/hlc.d.ts +96 -0
- package/dist/cjs/core/hlc.d.ts.map +1 -0
- package/dist/cjs/core/hlc.js +161 -0
- package/dist/cjs/core/hlc.js.map +1 -0
- package/dist/cjs/core/object-id.d.ts +38 -0
- package/dist/cjs/core/object-id.d.ts.map +1 -0
- package/dist/cjs/core/object-id.js +167 -0
- package/dist/cjs/core/object-id.js.map +1 -0
- package/dist/cjs/core/random.d.ts +6 -0
- package/dist/cjs/core/random.d.ts.map +1 -0
- package/dist/cjs/core/random.js +39 -0
- package/dist/cjs/core/random.js.map +1 -0
- package/dist/cjs/core/runtime.d.ts +96 -0
- package/dist/cjs/core/runtime.d.ts.map +1 -0
- package/dist/cjs/core/runtime.js +3 -0
- package/dist/cjs/core/runtime.js.map +1 -0
- package/dist/cjs/core/uuid.d.ts +16 -0
- package/dist/cjs/core/uuid.d.ts.map +1 -0
- package/dist/cjs/core/uuid.js +37 -0
- package/dist/cjs/core/uuid.js.map +1 -0
- package/dist/cjs/decorators/index.d.ts +48 -0
- package/dist/cjs/decorators/index.d.ts.map +1 -0
- package/dist/cjs/decorators/index.js +295 -0
- package/dist/cjs/decorators/index.js.map +1 -0
- package/dist/cjs/events/emitter.d.ts +16 -0
- package/dist/cjs/events/emitter.d.ts.map +1 -0
- package/dist/cjs/events/emitter.js +56 -0
- package/dist/cjs/events/emitter.js.map +1 -0
- package/dist/cjs/index/keys.d.ts +79 -0
- package/dist/cjs/index/keys.d.ts.map +1 -0
- package/dist/cjs/index/keys.js +208 -0
- package/dist/cjs/index/keys.js.map +1 -0
- package/dist/cjs/index.d.ts +81 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +193 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/inspector/agent.d.ts +75 -0
- package/dist/cjs/inspector/agent.d.ts.map +1 -0
- package/dist/cjs/inspector/agent.js +520 -0
- package/dist/cjs/inspector/agent.js.map +1 -0
- package/dist/cjs/inspector/auth.d.ts +49 -0
- package/dist/cjs/inspector/auth.d.ts.map +1 -0
- package/dist/cjs/inspector/auth.js +234 -0
- package/dist/cjs/inspector/auth.js.map +1 -0
- package/dist/cjs/inspector/bridge.d.ts +141 -0
- package/dist/cjs/inspector/bridge.d.ts.map +1 -0
- package/dist/cjs/inspector/bridge.js +190 -0
- package/dist/cjs/inspector/bridge.js.map +1 -0
- package/dist/cjs/inspector/client.d.ts +111 -0
- package/dist/cjs/inspector/client.d.ts.map +1 -0
- package/dist/cjs/inspector/client.js +218 -0
- package/dist/cjs/inspector/client.js.map +1 -0
- package/dist/cjs/inspector/protocol.d.ts +160 -0
- package/dist/cjs/inspector/protocol.d.ts.map +1 -0
- package/dist/cjs/inspector/protocol.js +53 -0
- package/dist/cjs/inspector/protocol.js.map +1 -0
- package/dist/cjs/inspector/transports/in-process.d.ts +7 -0
- package/dist/cjs/inspector/transports/in-process.d.ts.map +1 -0
- package/dist/cjs/inspector/transports/in-process.js +58 -0
- package/dist/cjs/inspector/transports/in-process.js.map +1 -0
- package/dist/cjs/inspector/transports/websocket.d.ts +39 -0
- package/dist/cjs/inspector/transports/websocket.d.ts.map +1 -0
- package/dist/cjs/inspector/transports/websocket.js +60 -0
- package/dist/cjs/inspector/transports/websocket.js.map +1 -0
- package/dist/cjs/interop/csv.d.ts +53 -0
- package/dist/cjs/interop/csv.d.ts.map +1 -0
- package/dist/cjs/interop/csv.js +230 -0
- package/dist/cjs/interop/csv.js.map +1 -0
- package/dist/cjs/interop/ejson.d.ts +41 -0
- package/dist/cjs/interop/ejson.d.ts.map +1 -0
- package/dist/cjs/interop/ejson.js +182 -0
- package/dist/cjs/interop/ejson.js.map +1 -0
- package/dist/cjs/interop/export-import.d.ts +98 -0
- package/dist/cjs/interop/export-import.d.ts.map +1 -0
- package/dist/cjs/interop/export-import.js +222 -0
- package/dist/cjs/interop/export-import.js.map +1 -0
- package/dist/cjs/model/document.d.ts +66 -0
- package/dist/cjs/model/document.d.ts.map +1 -0
- package/dist/cjs/model/document.js +302 -0
- package/dist/cjs/model/document.js.map +1 -0
- package/dist/cjs/model/model.d.ts +178 -0
- package/dist/cjs/model/model.d.ts.map +1 -0
- package/dist/cjs/model/model.js +823 -0
- package/dist/cjs/model/model.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/query/aggregation/expressions.d.ts +34 -0
- package/dist/cjs/query/aggregation/expressions.d.ts.map +1 -0
- package/dist/cjs/query/aggregation/expressions.js +552 -0
- package/dist/cjs/query/aggregation/expressions.js.map +1 -0
- package/dist/cjs/query/aggregation/pipeline.d.ts +79 -0
- package/dist/cjs/query/aggregation/pipeline.d.ts.map +1 -0
- package/dist/cjs/query/aggregation/pipeline.js +597 -0
- package/dist/cjs/query/aggregation/pipeline.js.map +1 -0
- package/dist/cjs/query/aggregation/source.d.ts +35 -0
- package/dist/cjs/query/aggregation/source.d.ts.map +1 -0
- package/dist/cjs/query/aggregation/source.js +81 -0
- package/dist/cjs/query/aggregation/source.js.map +1 -0
- package/dist/cjs/query/builder/query.d.ts +113 -0
- package/dist/cjs/query/builder/query.d.ts.map +1 -0
- package/dist/cjs/query/builder/query.js +215 -0
- package/dist/cjs/query/builder/query.js.map +1 -0
- package/dist/cjs/query/filter.d.ts +50 -0
- package/dist/cjs/query/filter.d.ts.map +1 -0
- package/dist/cjs/query/filter.js +275 -0
- package/dist/cjs/query/filter.js.map +1 -0
- package/dist/cjs/query/path.d.ts +41 -0
- package/dist/cjs/query/path.d.ts.map +1 -0
- package/dist/cjs/query/path.js +294 -0
- package/dist/cjs/query/path.js.map +1 -0
- package/dist/cjs/query/update.d.ts +30 -0
- package/dist/cjs/query/update.d.ts.map +1 -0
- package/dist/cjs/query/update.js +205 -0
- package/dist/cjs/query/update.js.map +1 -0
- package/dist/cjs/reactive/live-query.d.ts +41 -0
- package/dist/cjs/reactive/live-query.d.ts.map +1 -0
- package/dist/cjs/reactive/live-query.js +88 -0
- package/dist/cjs/reactive/live-query.js.map +1 -0
- package/dist/cjs/schema/cast.d.ts +38 -0
- package/dist/cjs/schema/cast.d.ts.map +1 -0
- package/dist/cjs/schema/cast.js +280 -0
- package/dist/cjs/schema/cast.js.map +1 -0
- package/dist/cjs/schema/index.d.ts +5 -0
- package/dist/cjs/schema/index.d.ts.map +1 -0
- package/dist/cjs/schema/index.js +27 -0
- package/dist/cjs/schema/index.js.map +1 -0
- package/dist/cjs/schema/schema.d.ts +58 -0
- package/dist/cjs/schema/schema.d.ts.map +1 -0
- package/dist/cjs/schema/schema.js +363 -0
- package/dist/cjs/schema/schema.js.map +1 -0
- package/dist/cjs/schema/types.d.ts +144 -0
- package/dist/cjs/schema/types.d.ts.map +1 -0
- package/dist/cjs/schema/types.js +20 -0
- package/dist/cjs/schema/types.js.map +1 -0
- package/dist/cjs/schema/validate.d.ts +15 -0
- package/dist/cjs/schema/validate.d.ts.map +1 -0
- package/dist/cjs/schema/validate.js +101 -0
- package/dist/cjs/schema/validate.js.map +1 -0
- package/dist/cjs/storage/adapters/capacitor-sqlite.d.ts +67 -0
- package/dist/cjs/storage/adapters/capacitor-sqlite.d.ts.map +1 -0
- package/dist/cjs/storage/adapters/capacitor-sqlite.js +69 -0
- package/dist/cjs/storage/adapters/capacitor-sqlite.js.map +1 -0
- package/dist/cjs/storage/adapters/expo-sqlite.d.ts +55 -0
- package/dist/cjs/storage/adapters/expo-sqlite.d.ts.map +1 -0
- package/dist/cjs/storage/adapters/expo-sqlite.js +53 -0
- package/dist/cjs/storage/adapters/expo-sqlite.js.map +1 -0
- package/dist/cjs/storage/adapters/indexeddb.d.ts +55 -0
- package/dist/cjs/storage/adapters/indexeddb.d.ts.map +1 -0
- package/dist/cjs/storage/adapters/indexeddb.js +393 -0
- package/dist/cjs/storage/adapters/indexeddb.js.map +1 -0
- package/dist/cjs/storage/adapters/memory.d.ts +44 -0
- package/dist/cjs/storage/adapters/memory.d.ts.map +1 -0
- package/dist/cjs/storage/adapters/memory.js +286 -0
- package/dist/cjs/storage/adapters/memory.js.map +1 -0
- package/dist/cjs/storage/adapters/node-sqlite.d.ts +59 -0
- package/dist/cjs/storage/adapters/node-sqlite.d.ts.map +1 -0
- package/dist/cjs/storage/adapters/node-sqlite.js +457 -0
- package/dist/cjs/storage/adapters/node-sqlite.js.map +1 -0
- package/dist/cjs/storage/adapters/sql-base.d.ts +84 -0
- package/dist/cjs/storage/adapters/sql-base.d.ts.map +1 -0
- package/dist/cjs/storage/adapters/sql-base.js +393 -0
- package/dist/cjs/storage/adapters/sql-base.js.map +1 -0
- package/dist/cjs/storage/types.d.ts +131 -0
- package/dist/cjs/storage/types.d.ts.map +1 -0
- package/dist/cjs/storage/types.js +3 -0
- package/dist/cjs/storage/types.js.map +1 -0
- package/dist/cjs/sync/adapters/rest.d.ts +31 -0
- package/dist/cjs/sync/adapters/rest.d.ts.map +1 -0
- package/dist/cjs/sync/adapters/rest.js +75 -0
- package/dist/cjs/sync/adapters/rest.js.map +1 -0
- package/dist/cjs/sync/attach.d.ts +30 -0
- package/dist/cjs/sync/attach.d.ts.map +1 -0
- package/dist/cjs/sync/attach.js +104 -0
- package/dist/cjs/sync/attach.js.map +1 -0
- package/dist/cjs/sync/engine.d.ts +96 -0
- package/dist/cjs/sync/engine.d.ts.map +1 -0
- package/dist/cjs/sync/engine.js +491 -0
- package/dist/cjs/sync/engine.js.map +1 -0
- package/dist/cjs/sync/protocol.d.ts +128 -0
- package/dist/cjs/sync/protocol.d.ts.map +1 -0
- package/dist/cjs/sync/protocol.js +38 -0
- package/dist/cjs/sync/protocol.js.map +1 -0
- package/dist/cjs/sync/queue.d.ts +77 -0
- package/dist/cjs/sync/queue.d.ts.map +1 -0
- package/dist/cjs/sync/queue.js +245 -0
- package/dist/cjs/sync/queue.js.map +1 -0
- package/dist/cjs/sync/server/memory-server.d.ts +65 -0
- package/dist/cjs/sync/server/memory-server.d.ts.map +1 -0
- package/dist/cjs/sync/server/memory-server.js +193 -0
- package/dist/cjs/sync/server/memory-server.js.map +1 -0
- package/dist/cjs/timestamps/index.d.ts +47 -0
- package/dist/cjs/timestamps/index.d.ts.map +1 -0
- package/dist/cjs/timestamps/index.js +88 -0
- package/dist/cjs/timestamps/index.js.map +1 -0
- package/dist/cjs/timestamps/timezone.d.ts +65 -0
- package/dist/cjs/timestamps/timezone.d.ts.map +1 -0
- package/dist/cjs/timestamps/timezone.js +208 -0
- package/dist/cjs/timestamps/timezone.js.map +1 -0
- package/dist/esm/conflict/strategies.d.ts +110 -0
- package/dist/esm/conflict/strategies.d.ts.map +1 -0
- package/dist/esm/conflict/strategies.js +289 -0
- package/dist/esm/conflict/strategies.js.map +1 -0
- package/dist/esm/conflict/types.d.ts +38 -0
- package/dist/esm/conflict/types.d.ts.map +1 -0
- package/dist/esm/conflict/types.js +2 -0
- package/dist/esm/conflict/types.js.map +1 -0
- package/dist/esm/core/anchor-db.d.ts +154 -0
- package/dist/esm/core/anchor-db.d.ts.map +1 -0
- package/dist/esm/core/anchor-db.js +269 -0
- package/dist/esm/core/anchor-db.js.map +1 -0
- package/dist/esm/core/errors.d.ts +125 -0
- package/dist/esm/core/errors.d.ts.map +1 -0
- package/dist/esm/core/errors.js +161 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/hex.d.ts +4 -0
- package/dist/esm/core/hex.d.ts.map +1 -0
- package/dist/esm/core/hex.js +37 -0
- package/dist/esm/core/hex.js.map +1 -0
- package/dist/esm/core/hlc.d.ts +96 -0
- package/dist/esm/core/hlc.d.ts.map +1 -0
- package/dist/esm/core/hlc.js +153 -0
- package/dist/esm/core/hlc.js.map +1 -0
- package/dist/esm/core/object-id.d.ts +38 -0
- package/dist/esm/core/object-id.d.ts.map +1 -0
- package/dist/esm/core/object-id.js +163 -0
- package/dist/esm/core/object-id.js.map +1 -0
- package/dist/esm/core/random.d.ts +6 -0
- package/dist/esm/core/random.d.ts.map +1 -0
- package/dist/esm/core/random.js +34 -0
- package/dist/esm/core/random.js.map +1 -0
- package/dist/esm/core/runtime.d.ts +96 -0
- package/dist/esm/core/runtime.d.ts.map +1 -0
- package/dist/esm/core/runtime.js +2 -0
- package/dist/esm/core/runtime.js.map +1 -0
- package/dist/esm/core/uuid.d.ts +16 -0
- package/dist/esm/core/uuid.d.ts.map +1 -0
- package/dist/esm/core/uuid.js +33 -0
- package/dist/esm/core/uuid.js.map +1 -0
- package/dist/esm/decorators/index.d.ts +48 -0
- package/dist/esm/decorators/index.d.ts.map +1 -0
- package/dist/esm/decorators/index.js +286 -0
- package/dist/esm/decorators/index.js.map +1 -0
- package/dist/esm/events/emitter.d.ts +16 -0
- package/dist/esm/events/emitter.d.ts.map +1 -0
- package/dist/esm/events/emitter.js +52 -0
- package/dist/esm/events/emitter.js.map +1 -0
- package/dist/esm/index/keys.d.ts +79 -0
- package/dist/esm/index/keys.d.ts.map +1 -0
- package/dist/esm/index/keys.js +198 -0
- package/dist/esm/index/keys.js.map +1 -0
- package/dist/esm/index.d.ts +81 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +59 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/inspector/agent.d.ts +75 -0
- package/dist/esm/inspector/agent.d.ts.map +1 -0
- package/dist/esm/inspector/agent.js +482 -0
- package/dist/esm/inspector/agent.js.map +1 -0
- package/dist/esm/inspector/auth.d.ts +49 -0
- package/dist/esm/inspector/auth.d.ts.map +1 -0
- package/dist/esm/inspector/auth.js +228 -0
- package/dist/esm/inspector/auth.js.map +1 -0
- package/dist/esm/inspector/bridge.d.ts +141 -0
- package/dist/esm/inspector/bridge.d.ts.map +1 -0
- package/dist/esm/inspector/bridge.js +182 -0
- package/dist/esm/inspector/bridge.js.map +1 -0
- package/dist/esm/inspector/client.d.ts +111 -0
- package/dist/esm/inspector/client.d.ts.map +1 -0
- package/dist/esm/inspector/client.js +213 -0
- package/dist/esm/inspector/client.js.map +1 -0
- package/dist/esm/inspector/protocol.d.ts +160 -0
- package/dist/esm/inspector/protocol.d.ts.map +1 -0
- package/dist/esm/inspector/protocol.js +43 -0
- package/dist/esm/inspector/protocol.js.map +1 -0
- package/dist/esm/inspector/transports/in-process.d.ts +7 -0
- package/dist/esm/inspector/transports/in-process.d.ts.map +1 -0
- package/dist/esm/inspector/transports/in-process.js +55 -0
- package/dist/esm/inspector/transports/in-process.js.map +1 -0
- package/dist/esm/inspector/transports/websocket.d.ts +39 -0
- package/dist/esm/inspector/transports/websocket.d.ts.map +1 -0
- package/dist/esm/inspector/transports/websocket.js +56 -0
- package/dist/esm/inspector/transports/websocket.js.map +1 -0
- package/dist/esm/interop/csv.d.ts +53 -0
- package/dist/esm/interop/csv.d.ts.map +1 -0
- package/dist/esm/interop/csv.js +222 -0
- package/dist/esm/interop/csv.js.map +1 -0
- package/dist/esm/interop/ejson.d.ts +41 -0
- package/dist/esm/interop/ejson.d.ts.map +1 -0
- package/dist/esm/interop/ejson.js +176 -0
- package/dist/esm/interop/ejson.js.map +1 -0
- package/dist/esm/interop/export-import.d.ts +98 -0
- package/dist/esm/interop/export-import.d.ts.map +1 -0
- package/dist/esm/interop/export-import.js +210 -0
- package/dist/esm/interop/export-import.js.map +1 -0
- package/dist/esm/model/document.d.ts +66 -0
- package/dist/esm/model/document.d.ts.map +1 -0
- package/dist/esm/model/document.js +297 -0
- package/dist/esm/model/document.js.map +1 -0
- package/dist/esm/model/model.d.ts +178 -0
- package/dist/esm/model/model.d.ts.map +1 -0
- package/dist/esm/model/model.js +815 -0
- package/dist/esm/model/model.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/query/aggregation/expressions.d.ts +34 -0
- package/dist/esm/query/aggregation/expressions.d.ts.map +1 -0
- package/dist/esm/query/aggregation/expressions.js +545 -0
- package/dist/esm/query/aggregation/expressions.js.map +1 -0
- package/dist/esm/query/aggregation/pipeline.d.ts +79 -0
- package/dist/esm/query/aggregation/pipeline.d.ts.map +1 -0
- package/dist/esm/query/aggregation/pipeline.js +591 -0
- package/dist/esm/query/aggregation/pipeline.js.map +1 -0
- package/dist/esm/query/aggregation/source.d.ts +35 -0
- package/dist/esm/query/aggregation/source.d.ts.map +1 -0
- package/dist/esm/query/aggregation/source.js +77 -0
- package/dist/esm/query/aggregation/source.js.map +1 -0
- package/dist/esm/query/builder/query.d.ts +113 -0
- package/dist/esm/query/builder/query.d.ts.map +1 -0
- package/dist/esm/query/builder/query.js +209 -0
- package/dist/esm/query/builder/query.js.map +1 -0
- package/dist/esm/query/filter.d.ts +50 -0
- package/dist/esm/query/filter.d.ts.map +1 -0
- package/dist/esm/query/filter.js +267 -0
- package/dist/esm/query/filter.js.map +1 -0
- package/dist/esm/query/path.d.ts +41 -0
- package/dist/esm/query/path.d.ts.map +1 -0
- package/dist/esm/query/path.js +282 -0
- package/dist/esm/query/path.js.map +1 -0
- package/dist/esm/query/update.d.ts +30 -0
- package/dist/esm/query/update.d.ts.map +1 -0
- package/dist/esm/query/update.js +198 -0
- package/dist/esm/query/update.js.map +1 -0
- package/dist/esm/reactive/live-query.d.ts +41 -0
- package/dist/esm/reactive/live-query.d.ts.map +1 -0
- package/dist/esm/reactive/live-query.js +83 -0
- package/dist/esm/reactive/live-query.js.map +1 -0
- package/dist/esm/schema/cast.d.ts +38 -0
- package/dist/esm/schema/cast.d.ts.map +1 -0
- package/dist/esm/schema/cast.js +275 -0
- package/dist/esm/schema/cast.js.map +1 -0
- package/dist/esm/schema/index.d.ts +5 -0
- package/dist/esm/schema/index.d.ts.map +1 -0
- package/dist/esm/schema/index.js +5 -0
- package/dist/esm/schema/index.js.map +1 -0
- package/dist/esm/schema/schema.d.ts +58 -0
- package/dist/esm/schema/schema.d.ts.map +1 -0
- package/dist/esm/schema/schema.js +358 -0
- package/dist/esm/schema/schema.js.map +1 -0
- package/dist/esm/schema/types.d.ts +144 -0
- package/dist/esm/schema/types.d.ts.map +1 -0
- package/dist/esm/schema/types.js +17 -0
- package/dist/esm/schema/types.js.map +1 -0
- package/dist/esm/schema/validate.d.ts +15 -0
- package/dist/esm/schema/validate.d.ts.map +1 -0
- package/dist/esm/schema/validate.js +98 -0
- package/dist/esm/schema/validate.js.map +1 -0
- package/dist/esm/storage/adapters/capacitor-sqlite.d.ts +67 -0
- package/dist/esm/storage/adapters/capacitor-sqlite.d.ts.map +1 -0
- package/dist/esm/storage/adapters/capacitor-sqlite.js +65 -0
- package/dist/esm/storage/adapters/capacitor-sqlite.js.map +1 -0
- package/dist/esm/storage/adapters/expo-sqlite.d.ts +55 -0
- package/dist/esm/storage/adapters/expo-sqlite.d.ts.map +1 -0
- package/dist/esm/storage/adapters/expo-sqlite.js +49 -0
- package/dist/esm/storage/adapters/expo-sqlite.js.map +1 -0
- package/dist/esm/storage/adapters/indexeddb.d.ts +55 -0
- package/dist/esm/storage/adapters/indexeddb.d.ts.map +1 -0
- package/dist/esm/storage/adapters/indexeddb.js +389 -0
- package/dist/esm/storage/adapters/indexeddb.js.map +1 -0
- package/dist/esm/storage/adapters/memory.d.ts +44 -0
- package/dist/esm/storage/adapters/memory.d.ts.map +1 -0
- package/dist/esm/storage/adapters/memory.js +282 -0
- package/dist/esm/storage/adapters/memory.js.map +1 -0
- package/dist/esm/storage/adapters/node-sqlite.d.ts +59 -0
- package/dist/esm/storage/adapters/node-sqlite.d.ts.map +1 -0
- package/dist/esm/storage/adapters/node-sqlite.js +450 -0
- package/dist/esm/storage/adapters/node-sqlite.js.map +1 -0
- package/dist/esm/storage/adapters/sql-base.d.ts +84 -0
- package/dist/esm/storage/adapters/sql-base.d.ts.map +1 -0
- package/dist/esm/storage/adapters/sql-base.js +383 -0
- package/dist/esm/storage/adapters/sql-base.js.map +1 -0
- package/dist/esm/storage/types.d.ts +131 -0
- package/dist/esm/storage/types.d.ts.map +1 -0
- package/dist/esm/storage/types.js +2 -0
- package/dist/esm/storage/types.js.map +1 -0
- package/dist/esm/sync/adapters/rest.d.ts +31 -0
- package/dist/esm/sync/adapters/rest.d.ts.map +1 -0
- package/dist/esm/sync/adapters/rest.js +71 -0
- package/dist/esm/sync/adapters/rest.js.map +1 -0
- package/dist/esm/sync/attach.d.ts +30 -0
- package/dist/esm/sync/attach.d.ts.map +1 -0
- package/dist/esm/sync/attach.js +98 -0
- package/dist/esm/sync/attach.js.map +1 -0
- package/dist/esm/sync/engine.d.ts +96 -0
- package/dist/esm/sync/engine.d.ts.map +1 -0
- package/dist/esm/sync/engine.js +487 -0
- package/dist/esm/sync/engine.js.map +1 -0
- package/dist/esm/sync/protocol.d.ts +128 -0
- package/dist/esm/sync/protocol.d.ts.map +1 -0
- package/dist/esm/sync/protocol.js +33 -0
- package/dist/esm/sync/protocol.js.map +1 -0
- package/dist/esm/sync/queue.d.ts +77 -0
- package/dist/esm/sync/queue.d.ts.map +1 -0
- package/dist/esm/sync/queue.js +241 -0
- package/dist/esm/sync/queue.js.map +1 -0
- package/dist/esm/sync/server/memory-server.d.ts +65 -0
- package/dist/esm/sync/server/memory-server.d.ts.map +1 -0
- package/dist/esm/sync/server/memory-server.js +189 -0
- package/dist/esm/sync/server/memory-server.js.map +1 -0
- package/dist/esm/timestamps/index.d.ts +47 -0
- package/dist/esm/timestamps/index.d.ts.map +1 -0
- package/dist/esm/timestamps/index.js +70 -0
- package/dist/esm/timestamps/index.js.map +1 -0
- package/dist/esm/timestamps/timezone.d.ts +65 -0
- package/dist/esm/timestamps/timezone.d.ts.map +1 -0
- package/dist/esm/timestamps/timezone.js +196 -0
- package/dist/esm/timestamps/timezone.js.map +1 -0
- package/package.json +163 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { zonedTimeToUtc } from "./timezone.js";
|
|
2
|
+
export * from "./timezone.js";
|
|
3
|
+
export interface TimeServiceOptions {
|
|
4
|
+
/** Business/reference zone (§26.2). Display only — never affects storage. */
|
|
5
|
+
serverTimeZone?: string;
|
|
6
|
+
/** Overridden by the sync engine once a server clock offset is known. */
|
|
7
|
+
now?: () => number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* `db.time` (§26.9).
|
|
11
|
+
*
|
|
12
|
+
* Every method either produces canonical UTC or formats canonical UTC for display. None of them can
|
|
13
|
+
* change a stored value — that separation is the whole point of §26.11.
|
|
14
|
+
*/
|
|
15
|
+
export declare class TimeService {
|
|
16
|
+
readonly deviceTimeZone: string;
|
|
17
|
+
readonly serverTimeZone: string | undefined;
|
|
18
|
+
private nowFn;
|
|
19
|
+
constructor(opts?: TimeServiceOptions);
|
|
20
|
+
/** Canonical current timestamp: ISO-8601, UTC, milliseconds. */
|
|
21
|
+
now(): string;
|
|
22
|
+
nowMs(): number;
|
|
23
|
+
nowDate(): Date;
|
|
24
|
+
/** Normalise anything date-like to canonical UTC. */
|
|
25
|
+
toUTC(value: Date | string | number): string;
|
|
26
|
+
/**
|
|
27
|
+
* Render a stored UTC value as wall-clock text in `tz` (defaults to the device zone).
|
|
28
|
+
* Display only: `db.time.fromUTC(stored, tz)` never rewrites `stored`.
|
|
29
|
+
*/
|
|
30
|
+
fromUTC(value: Date | string | number, tz?: string): string;
|
|
31
|
+
/** Same instant rendered in the configured server/business zone. */
|
|
32
|
+
inServerZone(value: Date | string | number): string;
|
|
33
|
+
/** Interpret a wall-clock reading in a zone and return canonical UTC. */
|
|
34
|
+
fromLocal(local: string, tz?: string): string;
|
|
35
|
+
/** UTC offset of a zone at an instant, e.g. "+05:30". */
|
|
36
|
+
offsetAt(value: Date | string | number, tz?: string): string;
|
|
37
|
+
/** Used by the sync engine to install a server-skew-corrected clock. */
|
|
38
|
+
setClock(now: () => number): void;
|
|
39
|
+
/** All three views of one instant — what Lens renders (§44). */
|
|
40
|
+
describe(value: Date | string | number): {
|
|
41
|
+
utc: string;
|
|
42
|
+
device: string;
|
|
43
|
+
server?: string;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export { zonedTimeToUtc };
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/timestamps/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,cAAc,EACf,MAAM,eAAe,CAAC;AAEvB,cAAc,eAAe,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,OAAO,CAAC,KAAK,CAAe;gBAEhB,IAAI,GAAE,kBAAuB;IAMzC,gEAAgE;IAChE,GAAG,IAAI,MAAM;IAIb,KAAK,IAAI,MAAM;IAIf,OAAO,IAAI,IAAI;IAIf,qDAAqD;IACrD,KAAK,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;IAI5C;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAI3D,oEAAoE;IACpE,YAAY,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;IAOnD,yEAAyE;IACzE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAI7C,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAK5D,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,GAAG,IAAI;IAIjC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAW1F;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.zonedTimeToUtc = exports.TimeService = void 0;
|
|
18
|
+
const timezone_ts_1 = require("./timezone.js");
|
|
19
|
+
Object.defineProperty(exports, "zonedTimeToUtc", { enumerable: true, get: function () { return timezone_ts_1.zonedTimeToUtc; } });
|
|
20
|
+
__exportStar(require("./timezone.js"), exports);
|
|
21
|
+
/**
|
|
22
|
+
* `db.time` (§26.9).
|
|
23
|
+
*
|
|
24
|
+
* Every method either produces canonical UTC or formats canonical UTC for display. None of them can
|
|
25
|
+
* change a stored value — that separation is the whole point of §26.11.
|
|
26
|
+
*/
|
|
27
|
+
class TimeService {
|
|
28
|
+
constructor(opts = {}) {
|
|
29
|
+
this.deviceTimeZone = (0, timezone_ts_1.detectDeviceTimeZone)();
|
|
30
|
+
this.serverTimeZone = opts.serverTimeZone ? (0, timezone_ts_1.assertValidTimeZone)(opts.serverTimeZone) : undefined;
|
|
31
|
+
this.nowFn = opts.now ?? (() => Date.now());
|
|
32
|
+
}
|
|
33
|
+
/** Canonical current timestamp: ISO-8601, UTC, milliseconds. */
|
|
34
|
+
now() {
|
|
35
|
+
return new Date(this.nowFn()).toISOString();
|
|
36
|
+
}
|
|
37
|
+
nowMs() {
|
|
38
|
+
return this.nowFn();
|
|
39
|
+
}
|
|
40
|
+
nowDate() {
|
|
41
|
+
return new Date(this.nowFn());
|
|
42
|
+
}
|
|
43
|
+
/** Normalise anything date-like to canonical UTC. */
|
|
44
|
+
toUTC(value) {
|
|
45
|
+
return (0, timezone_ts_1.toUtcIso)(value);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Render a stored UTC value as wall-clock text in `tz` (defaults to the device zone).
|
|
49
|
+
* Display only: `db.time.fromUTC(stored, tz)` never rewrites `stored`.
|
|
50
|
+
*/
|
|
51
|
+
fromUTC(value, tz) {
|
|
52
|
+
return (0, timezone_ts_1.formatInTimeZone)(value, tz ?? this.deviceTimeZone);
|
|
53
|
+
}
|
|
54
|
+
/** Same instant rendered in the configured server/business zone. */
|
|
55
|
+
inServerZone(value) {
|
|
56
|
+
if (!this.serverTimeZone) {
|
|
57
|
+
throw new Error("No server time zone configured. Pass `timezone: { server: \"...\" }` to AnchorDB.");
|
|
58
|
+
}
|
|
59
|
+
return (0, timezone_ts_1.formatInTimeZone)(value, this.serverTimeZone);
|
|
60
|
+
}
|
|
61
|
+
/** Interpret a wall-clock reading in a zone and return canonical UTC. */
|
|
62
|
+
fromLocal(local, tz) {
|
|
63
|
+
return (0, timezone_ts_1.parseZonedTimeToUtc)(local, tz ?? this.deviceTimeZone).toISOString();
|
|
64
|
+
}
|
|
65
|
+
/** UTC offset of a zone at an instant, e.g. "+05:30". */
|
|
66
|
+
offsetAt(value, tz) {
|
|
67
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
68
|
+
return (0, timezone_ts_1.formatOffset)((0, timezone_ts_1.getTimeZoneOffsetMs)(d, tz ?? this.deviceTimeZone));
|
|
69
|
+
}
|
|
70
|
+
/** Used by the sync engine to install a server-skew-corrected clock. */
|
|
71
|
+
setClock(now) {
|
|
72
|
+
this.nowFn = now;
|
|
73
|
+
}
|
|
74
|
+
/** All three views of one instant — what Lens renders (§44). */
|
|
75
|
+
describe(value) {
|
|
76
|
+
const utc = (0, timezone_ts_1.toUtcIso)(value);
|
|
77
|
+
const out = {
|
|
78
|
+
utc,
|
|
79
|
+
device: `${(0, timezone_ts_1.formatInTimeZone)(utc, this.deviceTimeZone)} ${this.deviceTimeZone}`,
|
|
80
|
+
};
|
|
81
|
+
if (this.serverTimeZone) {
|
|
82
|
+
out.server = `${(0, timezone_ts_1.formatInTimeZone)(utc, this.serverTimeZone)} ${this.serverTimeZone}`;
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.TimeService = TimeService;
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/timestamps/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,+CASuB;AA4Fd,+FA7FP,4BAAc,OA6FO;AA1FvB,gDAA8B;AAS9B;;;;;GAKG;AACH,MAAa,WAAW;IAKtB,YAAY,OAA2B,EAAE;QACvC,IAAI,CAAC,cAAc,GAAG,IAAA,kCAAoB,GAAE,CAAC;QAC7C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAA,iCAAmB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACjG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,gEAAgE;IAChE,GAAG;QACD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,qDAAqD;IACrD,KAAK,CAAC,KAA6B;QACjC,OAAO,IAAA,sBAAQ,EAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,KAA6B,EAAE,EAAW;QAChD,OAAO,IAAA,8BAAgB,EAAC,KAAK,EAAE,EAAE,IAAI,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5D,CAAC;IAED,oEAAoE;IACpE,YAAY,CAAC,KAA6B;QACxC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAC;QACvG,CAAC;QACD,OAAO,IAAA,8BAAgB,EAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IACtD,CAAC;IAED,yEAAyE;IACzE,SAAS,CAAC,KAAa,EAAE,EAAW;QAClC,OAAO,IAAA,iCAAmB,EAAC,KAAK,EAAE,EAAE,IAAI,IAAI,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7E,CAAC;IAED,yDAAyD;IACzD,QAAQ,CAAC,KAA6B,EAAE,EAAW;QACjD,MAAM,CAAC,GAAG,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D,OAAO,IAAA,0BAAY,EAAC,IAAA,iCAAmB,EAAC,CAAC,EAAE,EAAE,IAAI,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,wEAAwE;IACxE,QAAQ,CAAC,GAAiB;QACxB,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC;IACnB,CAAC;IAED,gEAAgE;IAChE,QAAQ,CAAC,KAA6B;QACpC,MAAM,GAAG,GAAG,IAAA,sBAAQ,EAAC,KAAK,CAAC,CAAC;QAC5B,MAAM,GAAG,GAAqD;YAC5D,GAAG;YACH,MAAM,EAAE,GAAG,IAAA,8BAAgB,EAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE;SAC/E,CAAC;QACF,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,GAAG,CAAC,MAAM,GAAG,GAAG,IAAA,8BAAgB,EAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACtF,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAzED,kCAyEC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timezone handling.
|
|
3
|
+
*
|
|
4
|
+
* The rule the whole system rests on: **UTC is the only canonical representation**. Device zone and
|
|
5
|
+
* configured server zone are presentation/reference concerns and can never influence what is
|
|
6
|
+
* stored. Everything here either produces UTC or formats UTC for display; nothing converts storage.
|
|
7
|
+
*
|
|
8
|
+
* Implemented entirely on `Intl`, with no date library, so React Native and browsers carry no extra
|
|
9
|
+
* dependency. The one platform caveat is ICU availability, handled in `assertIntlSupport()`.
|
|
10
|
+
*/
|
|
11
|
+
/** `Intl.DateTimeFormat().resolvedOptions().timeZone`, e.g. "Asia/Colombo". */
|
|
12
|
+
export declare function detectDeviceTimeZone(): string;
|
|
13
|
+
/**
|
|
14
|
+
* True for a real IANA zone. Prefers `Intl.supportedValuesOf('timeZone')` where present and falls
|
|
15
|
+
* back to constructing a formatter, which throws `RangeError` on an unknown zone.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isValidTimeZone(tz: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Fail loudly at configuration time (§26.10). Silently falling back to UTC would mean every
|
|
20
|
+
* displayed timestamp in the app is quietly wrong, which is far worse than refusing to start.
|
|
21
|
+
*/
|
|
22
|
+
export declare function assertValidTimeZone(tz: string, settingName?: string): string;
|
|
23
|
+
/** Detects the stripped-ICU builds where every zone silently formats as UTC. */
|
|
24
|
+
export declare function assertIntlSupport(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Offset of `tz` at a given instant, in milliseconds east of UTC.
|
|
27
|
+
* `Asia/Colombo` → +19800000 (5h30m). Handles DST because it asks about a specific instant.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getTimeZoneOffsetMs(instant: Date, tz: string): number;
|
|
30
|
+
/**
|
|
31
|
+
* Interpret a wall-clock reading *in a zone* and return the UTC instant.
|
|
32
|
+
*
|
|
33
|
+
* DST makes this genuinely ambiguous, so a naive "measure the offset then subtract it" pass is
|
|
34
|
+
* wrong — around a transition it can silently resolve to a different local time than the one asked
|
|
35
|
+
* for. We instead form the two candidate instants implied by the offsets on either side of any
|
|
36
|
+
* nearby transition and check which of them actually round-trips:
|
|
37
|
+
*
|
|
38
|
+
* both valid normal time, or a fall-back OVERLAP -> take the earlier instant
|
|
39
|
+
* one valid unambiguous
|
|
40
|
+
* neither a spring-forward GAP: the requested local time does not exist, so shift forward
|
|
41
|
+
* past the gap
|
|
42
|
+
*
|
|
43
|
+
* This matches Temporal's `disambiguation: "compatible"` and Luxon's default, which is the
|
|
44
|
+
* behaviour developers already expect. Both branches are covered by tests.
|
|
45
|
+
*/
|
|
46
|
+
export declare function zonedTimeToUtc(wall: {
|
|
47
|
+
year: number;
|
|
48
|
+
month: number;
|
|
49
|
+
day: number;
|
|
50
|
+
hour?: number;
|
|
51
|
+
minute?: number;
|
|
52
|
+
second?: number;
|
|
53
|
+
ms?: number;
|
|
54
|
+
}, tz: string): Date;
|
|
55
|
+
/** Parse "2026-08-31 10:29:00" / "2026-08-31T10:29" as a wall time in `tz`. */
|
|
56
|
+
export declare function parseZonedTimeToUtc(local: string, tz: string): Date;
|
|
57
|
+
/** Canonical storage format: ISO-8601, UTC, millisecond precision, `Z` suffix. */
|
|
58
|
+
export declare function toUtcIso(value: Date | string | number): string;
|
|
59
|
+
/** Render a UTC instant as wall-clock text in `tz`. Display only — storage is untouched. */
|
|
60
|
+
export declare function formatInTimeZone(value: Date | string | number, tz: string, opts?: {
|
|
61
|
+
withZone?: boolean;
|
|
62
|
+
separator?: string;
|
|
63
|
+
}): string;
|
|
64
|
+
export declare function formatOffset(offsetMs: number): string;
|
|
65
|
+
//# sourceMappingURL=timezone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../../../src/timestamps/timezone.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,+EAA+E;AAC/E,wBAAgB,oBAAoB,IAAI,MAAM,CAQ7C;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAcnD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,SAAoB,GAAG,MAAM,CAiBvF;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,IAAI,IAAI,CASxC;AA+CD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAIrE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAChH,EAAE,EAAE,MAAM,GACT,IAAI,CAyBN;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAmBnE;AAED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAM9D;AAED,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAC7B,EAAE,EAAE,MAAM,EACV,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,MAAM,CAUR;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMrD"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectDeviceTimeZone = detectDeviceTimeZone;
|
|
4
|
+
exports.isValidTimeZone = isValidTimeZone;
|
|
5
|
+
exports.assertValidTimeZone = assertValidTimeZone;
|
|
6
|
+
exports.assertIntlSupport = assertIntlSupport;
|
|
7
|
+
exports.getTimeZoneOffsetMs = getTimeZoneOffsetMs;
|
|
8
|
+
exports.zonedTimeToUtc = zonedTimeToUtc;
|
|
9
|
+
exports.parseZonedTimeToUtc = parseZonedTimeToUtc;
|
|
10
|
+
exports.toUtcIso = toUtcIso;
|
|
11
|
+
exports.formatInTimeZone = formatInTimeZone;
|
|
12
|
+
exports.formatOffset = formatOffset;
|
|
13
|
+
const errors_ts_1 = require("../core/errors.js");
|
|
14
|
+
/**
|
|
15
|
+
* Timezone handling.
|
|
16
|
+
*
|
|
17
|
+
* The rule the whole system rests on: **UTC is the only canonical representation**. Device zone and
|
|
18
|
+
* configured server zone are presentation/reference concerns and can never influence what is
|
|
19
|
+
* stored. Everything here either produces UTC or formats UTC for display; nothing converts storage.
|
|
20
|
+
*
|
|
21
|
+
* Implemented entirely on `Intl`, with no date library, so React Native and browsers carry no extra
|
|
22
|
+
* dependency. The one platform caveat is ICU availability, handled in `assertIntlSupport()`.
|
|
23
|
+
*/
|
|
24
|
+
/** `Intl.DateTimeFormat().resolvedOptions().timeZone`, e.g. "Asia/Colombo". */
|
|
25
|
+
function detectDeviceTimeZone() {
|
|
26
|
+
try {
|
|
27
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
28
|
+
if (tz)
|
|
29
|
+
return tz;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
/* fall through */
|
|
33
|
+
}
|
|
34
|
+
return "UTC";
|
|
35
|
+
}
|
|
36
|
+
const validCache = new Map();
|
|
37
|
+
/**
|
|
38
|
+
* True for a real IANA zone. Prefers `Intl.supportedValuesOf('timeZone')` where present and falls
|
|
39
|
+
* back to constructing a formatter, which throws `RangeError` on an unknown zone.
|
|
40
|
+
*/
|
|
41
|
+
function isValidTimeZone(tz) {
|
|
42
|
+
if (typeof tz !== "string" || tz.length === 0)
|
|
43
|
+
return false;
|
|
44
|
+
const cached = validCache.get(tz);
|
|
45
|
+
if (cached !== undefined)
|
|
46
|
+
return cached;
|
|
47
|
+
let valid = false;
|
|
48
|
+
try {
|
|
49
|
+
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
50
|
+
valid = true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
valid = false;
|
|
54
|
+
}
|
|
55
|
+
validCache.set(tz, valid);
|
|
56
|
+
return valid;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Fail loudly at configuration time (§26.10). Silently falling back to UTC would mean every
|
|
60
|
+
* displayed timestamp in the app is quietly wrong, which is far worse than refusing to start.
|
|
61
|
+
*/
|
|
62
|
+
function assertValidTimeZone(tz, settingName = "timezone.server") {
|
|
63
|
+
if (!isValidTimeZone(tz)) {
|
|
64
|
+
let suggestion = "";
|
|
65
|
+
try {
|
|
66
|
+
const all = Intl.supportedValuesOf?.("timeZone") ?? [];
|
|
67
|
+
const needle = tz.toLowerCase().replace(/[_\s-]/g, "");
|
|
68
|
+
const near = all.filter((z) => z.toLowerCase().replace(/[_\s-]/g, "").includes(needle)).slice(0, 3);
|
|
69
|
+
if (near.length)
|
|
70
|
+
suggestion = ` Did you mean: ${near.join(", ")}?`;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
/* suggestions are best-effort */
|
|
74
|
+
}
|
|
75
|
+
throw new errors_ts_1.AnchorConfigError(`Invalid IANA time zone "${tz}" for ${settingName}.${suggestion} ` +
|
|
76
|
+
`Expected a name like "Asia/Colombo", "America/New_York" or "UTC".`);
|
|
77
|
+
}
|
|
78
|
+
return tz;
|
|
79
|
+
}
|
|
80
|
+
/** Detects the stripped-ICU builds where every zone silently formats as UTC. */
|
|
81
|
+
function assertIntlSupport() {
|
|
82
|
+
const probe = new Date("2026-01-15T12:00:00.000Z");
|
|
83
|
+
const colombo = formatParts(probe, "Asia/Colombo");
|
|
84
|
+
if (colombo.hour === 12 && colombo.minute === 0) {
|
|
85
|
+
throw new errors_ts_1.AnchorConfigError("This JavaScript runtime has no full ICU data: time zone conversion silently returns UTC. " +
|
|
86
|
+
"On React Native, ensure Hermes is built with Intl support, or install a polyfill.");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const formatterCache = new Map();
|
|
90
|
+
function getFormatter(tz) {
|
|
91
|
+
let f = formatterCache.get(tz);
|
|
92
|
+
if (!f) {
|
|
93
|
+
f = new Intl.DateTimeFormat("en-US", {
|
|
94
|
+
timeZone: tz,
|
|
95
|
+
hourCycle: "h23", // h23 rather than hour12:false — some ICU builds emit hour "24" otherwise
|
|
96
|
+
year: "numeric",
|
|
97
|
+
month: "2-digit",
|
|
98
|
+
day: "2-digit",
|
|
99
|
+
hour: "2-digit",
|
|
100
|
+
minute: "2-digit",
|
|
101
|
+
second: "2-digit",
|
|
102
|
+
});
|
|
103
|
+
formatterCache.set(tz, f);
|
|
104
|
+
}
|
|
105
|
+
return f;
|
|
106
|
+
}
|
|
107
|
+
function formatParts(instant, tz) {
|
|
108
|
+
const parts = getFormatter(tz).formatToParts(instant);
|
|
109
|
+
const out = {};
|
|
110
|
+
for (const p of parts) {
|
|
111
|
+
if (p.type !== "literal")
|
|
112
|
+
out[p.type] = Number(p.value);
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
year: out.year ?? 0,
|
|
116
|
+
month: out.month ?? 1,
|
|
117
|
+
day: out.day ?? 1,
|
|
118
|
+
hour: out.hour ?? 0,
|
|
119
|
+
minute: out.minute ?? 0,
|
|
120
|
+
second: out.second ?? 0,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Offset of `tz` at a given instant, in milliseconds east of UTC.
|
|
125
|
+
* `Asia/Colombo` → +19800000 (5h30m). Handles DST because it asks about a specific instant.
|
|
126
|
+
*/
|
|
127
|
+
function getTimeZoneOffsetMs(instant, tz) {
|
|
128
|
+
const p = formatParts(instant, tz);
|
|
129
|
+
const asIfUtc = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second, instant.getUTCMilliseconds());
|
|
130
|
+
return asIfUtc - instant.getTime();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Interpret a wall-clock reading *in a zone* and return the UTC instant.
|
|
134
|
+
*
|
|
135
|
+
* DST makes this genuinely ambiguous, so a naive "measure the offset then subtract it" pass is
|
|
136
|
+
* wrong — around a transition it can silently resolve to a different local time than the one asked
|
|
137
|
+
* for. We instead form the two candidate instants implied by the offsets on either side of any
|
|
138
|
+
* nearby transition and check which of them actually round-trips:
|
|
139
|
+
*
|
|
140
|
+
* both valid normal time, or a fall-back OVERLAP -> take the earlier instant
|
|
141
|
+
* one valid unambiguous
|
|
142
|
+
* neither a spring-forward GAP: the requested local time does not exist, so shift forward
|
|
143
|
+
* past the gap
|
|
144
|
+
*
|
|
145
|
+
* This matches Temporal's `disambiguation: "compatible"` and Luxon's default, which is the
|
|
146
|
+
* behaviour developers already expect. Both branches are covered by tests.
|
|
147
|
+
*/
|
|
148
|
+
function zonedTimeToUtc(wall, tz) {
|
|
149
|
+
const naive = Date.UTC(wall.year, wall.month - 1, wall.day, wall.hour ?? 0, wall.minute ?? 0, wall.second ?? 0, wall.ms ?? 0);
|
|
150
|
+
const DAY = 86_400_000;
|
|
151
|
+
const offsetBefore = getTimeZoneOffsetMs(new Date(naive - DAY), tz);
|
|
152
|
+
const offsetAfter = getTimeZoneOffsetMs(new Date(naive + DAY), tz);
|
|
153
|
+
const candidateA = naive - offsetBefore;
|
|
154
|
+
const candidateB = naive - offsetAfter;
|
|
155
|
+
const aValid = getTimeZoneOffsetMs(new Date(candidateA), tz) === offsetBefore;
|
|
156
|
+
const bValid = getTimeZoneOffsetMs(new Date(candidateB), tz) === offsetAfter;
|
|
157
|
+
if (aValid && bValid)
|
|
158
|
+
return new Date(Math.min(candidateA, candidateB)); // overlap -> earlier
|
|
159
|
+
if (aValid)
|
|
160
|
+
return new Date(candidateA);
|
|
161
|
+
if (bValid)
|
|
162
|
+
return new Date(candidateB);
|
|
163
|
+
return new Date(Math.max(candidateA, candidateB)); // gap -> forward past it
|
|
164
|
+
}
|
|
165
|
+
/** Parse "2026-08-31 10:29:00" / "2026-08-31T10:29" as a wall time in `tz`. */
|
|
166
|
+
function parseZonedTimeToUtc(local, tz) {
|
|
167
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?(?:\.(\d{1,3}))?$/.exec(local.trim());
|
|
168
|
+
if (!m) {
|
|
169
|
+
throw new errors_ts_1.AnchorConfigError(`Expected a local date-time like "2026-08-31 10:29:00" but received "${local}".`);
|
|
170
|
+
}
|
|
171
|
+
return zonedTimeToUtc({
|
|
172
|
+
year: Number(m[1]),
|
|
173
|
+
month: Number(m[2]),
|
|
174
|
+
day: Number(m[3]),
|
|
175
|
+
hour: Number(m[4]),
|
|
176
|
+
minute: Number(m[5]),
|
|
177
|
+
second: m[6] ? Number(m[6]) : 0,
|
|
178
|
+
ms: m[7] ? Number(m[7].padEnd(3, "0")) : 0,
|
|
179
|
+
}, tz);
|
|
180
|
+
}
|
|
181
|
+
/** Canonical storage format: ISO-8601, UTC, millisecond precision, `Z` suffix. */
|
|
182
|
+
function toUtcIso(value) {
|
|
183
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
184
|
+
if (Number.isNaN(d.getTime())) {
|
|
185
|
+
throw new errors_ts_1.AnchorConfigError(`Cannot convert ${JSON.stringify(value)} to a UTC timestamp.`);
|
|
186
|
+
}
|
|
187
|
+
return d.toISOString();
|
|
188
|
+
}
|
|
189
|
+
/** Render a UTC instant as wall-clock text in `tz`. Display only — storage is untouched. */
|
|
190
|
+
function formatInTimeZone(value, tz, opts = {}) {
|
|
191
|
+
assertValidTimeZone(tz, "timezone");
|
|
192
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
193
|
+
const p = formatParts(d, tz);
|
|
194
|
+
const pad = (n, w = 2) => String(n).padStart(w, "0");
|
|
195
|
+
const sep = opts.separator ?? " ";
|
|
196
|
+
const base = `${p.year}-${pad(p.month)}-${pad(p.day)}${sep}${pad(p.hour)}:${pad(p.minute)}:${pad(p.second)}`;
|
|
197
|
+
if (!opts.withZone)
|
|
198
|
+
return base;
|
|
199
|
+
return `${base} ${formatOffset(getTimeZoneOffsetMs(d, tz))}`;
|
|
200
|
+
}
|
|
201
|
+
function formatOffset(offsetMs) {
|
|
202
|
+
const sign = offsetMs < 0 ? "-" : "+";
|
|
203
|
+
const abs = Math.abs(offsetMs);
|
|
204
|
+
const h = Math.floor(abs / 3_600_000);
|
|
205
|
+
const m = Math.floor((abs % 3_600_000) / 60_000);
|
|
206
|
+
return `${sign}${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=timezone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timezone.js","sourceRoot":"","sources":["../../../src/timestamps/timezone.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { ConflictContext, ConflictResolutionConfig, ConflictStrategyName, Resolution } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The five conflict strategies, behind one interface.
|
|
4
|
+
*
|
|
5
|
+
* The sync engine knows only `resolve(context) -> Resolution`. No strategy-specific branching leaks
|
|
6
|
+
* into the engine, which is what makes switching strategy a pure configuration change (§19) and
|
|
7
|
+
* makes a sixth strategy a matter of registering one more object.
|
|
8
|
+
*/
|
|
9
|
+
export interface ConflictStrategyHandler<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
10
|
+
readonly name: ConflictStrategyName | string;
|
|
11
|
+
resolve(context: ConflictContext<T>): Promise<Resolution<T>> | Resolution<T>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Last write wins — the default.
|
|
15
|
+
*
|
|
16
|
+
* "Latest" is decided by the hybrid logical clock, never by raw device wall-clock strings. The
|
|
17
|
+
* comparison order is documented in SYNC_PROTOCOL.md:
|
|
18
|
+
*
|
|
19
|
+
* 1. HLC physical time (already skew-corrected against the server)
|
|
20
|
+
* 2. HLC logical counter, for writes inside the same millisecond
|
|
21
|
+
* 3. clientId, lexicographically
|
|
22
|
+
*
|
|
23
|
+
* Step 3 is what makes this a *total* order. Without it two devices could produce genuinely equal
|
|
24
|
+
* stamps and the winner would depend on evaluation order — different devices would converge to
|
|
25
|
+
* different documents, which is precisely the failure LWW is supposed to prevent.
|
|
26
|
+
*
|
|
27
|
+
* On an exact tie the server wins, because the server's copy is the one everyone else has already
|
|
28
|
+
* observed; preferring the client would make convergence depend on who pushed last.
|
|
29
|
+
*/
|
|
30
|
+
export declare class LastWriteWinsStrategy<T extends Record<string, unknown>> implements ConflictStrategyHandler<T> {
|
|
31
|
+
readonly name = "last-write-wins";
|
|
32
|
+
resolve(ctx: ConflictContext<T>): Resolution<T>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Server wins — the local change is discarded and the server's document adopted.
|
|
36
|
+
*
|
|
37
|
+
* `pushBack: false` matters: re-pushing a document the server just gave us would create an endless
|
|
38
|
+
* echo between the two.
|
|
39
|
+
*/
|
|
40
|
+
export declare class ServerWinsStrategy<T extends Record<string, unknown>> implements ConflictStrategyHandler<T> {
|
|
41
|
+
readonly name = "server-wins";
|
|
42
|
+
resolve(ctx: ConflictContext<T>): Resolution<T>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Client wins — the local change overwrites the server's.
|
|
46
|
+
*
|
|
47
|
+
* The loop hazard is real and is handled by the engine rather than here: the re-push carries
|
|
48
|
+
* `baseVersion = remoteVersion` (the version we just observed), so the server's optimistic check
|
|
49
|
+
* now passes instead of conflicting again forever. The engine also caps `conflictAttempts`.
|
|
50
|
+
*/
|
|
51
|
+
export declare class ClientWinsStrategy<T extends Record<string, unknown>> implements ConflictStrategyHandler<T> {
|
|
52
|
+
readonly name = "client-wins";
|
|
53
|
+
resolve(ctx: ConflictContext<T>): Resolution<T>;
|
|
54
|
+
}
|
|
55
|
+
declare const DELETED: unique symbol;
|
|
56
|
+
/**
|
|
57
|
+
* Field-level three-way merge.
|
|
58
|
+
*
|
|
59
|
+
* Compares local and remote against their common ancestor (`base`, the last server-confirmed
|
|
60
|
+
* document kept in the shadow table). Paths only one side touched merge silently; paths both sides
|
|
61
|
+
* touched are a genuine conflict and fall to `fieldPolicy`.
|
|
62
|
+
*
|
|
63
|
+
* Documented edge cases, each with a test:
|
|
64
|
+
*
|
|
65
|
+
* - **No base.** Without an ancestor we cannot tell an edit from an insert, so a merge would be a
|
|
66
|
+
* guess. Falls back to last-write-wins rather than inventing a result.
|
|
67
|
+
* - **Arrays are atomic by default.** Element-wise merging of two concurrently reordered arrays
|
|
68
|
+
* has no correct answer in general. `arrayStrategy: "union-by-id"` opts into merging arrays of
|
|
69
|
+
* objects that carry `_id`/`id`.
|
|
70
|
+
* - **Deleted fields.** "Deleted on one side" is distinguished from "absent on both" by diffing
|
|
71
|
+
* against base — otherwise a deletion would be silently undone by the other side's copy.
|
|
72
|
+
* - **Type changes** (string -> object) are treated as an ordinary same-path conflict.
|
|
73
|
+
* - **Object replacement.** An edit at `a` conflicts with an edit at `a.b`: parent/child overlap is
|
|
74
|
+
* detected explicitly, because treating them as unrelated paths would resurrect a replaced object.
|
|
75
|
+
*/
|
|
76
|
+
export declare class FieldLevelStrategy<T extends Record<string, unknown>> implements ConflictStrategyHandler<T> {
|
|
77
|
+
readonly name = "field-level";
|
|
78
|
+
private readonly policy;
|
|
79
|
+
private readonly arrayStrategy;
|
|
80
|
+
private readonly fallback;
|
|
81
|
+
constructor(config?: ConflictResolutionConfig<T>);
|
|
82
|
+
resolve(ctx: ConflictContext<T>): Resolution<T>;
|
|
83
|
+
private decide;
|
|
84
|
+
/** Opt-in array merging for arrays of objects with a stable identity. */
|
|
85
|
+
private mergeArraysById;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Custom resolver.
|
|
89
|
+
*
|
|
90
|
+
* The developer's function may return either a bare document (treated as the resolved value) or a
|
|
91
|
+
* full `Resolution` when it needs to control `pushBack`. A throwing resolver is *not* caught here —
|
|
92
|
+
* the engine parks the mutation and keeps draining the queue, so one bad resolver cannot wedge sync
|
|
93
|
+
* for every other document.
|
|
94
|
+
*/
|
|
95
|
+
export declare class CustomStrategy<T extends Record<string, unknown>> implements ConflictStrategyHandler<T> {
|
|
96
|
+
readonly name = "custom";
|
|
97
|
+
private readonly resolver;
|
|
98
|
+
constructor(config: ConflictResolutionConfig<T>);
|
|
99
|
+
resolve(ctx: ConflictContext<T>): Promise<Resolution<T>>;
|
|
100
|
+
}
|
|
101
|
+
/** Registry — open for user-defined strategies (§11). */
|
|
102
|
+
export declare class ConflictStrategyRegistry<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
103
|
+
private readonly strategies;
|
|
104
|
+
constructor(config?: ConflictResolutionConfig<T>);
|
|
105
|
+
register(strategy: ConflictStrategyHandler<T>): void;
|
|
106
|
+
get(name: string): ConflictStrategyHandler<T>;
|
|
107
|
+
names(): string[];
|
|
108
|
+
}
|
|
109
|
+
export { DELETED as FIELD_DELETED };
|
|
110
|
+
//# sourceMappingURL=strategies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategies.d.ts","sourceRoot":"","sources":["../../../src/conflict/strategies.ts"],"names":[],"mappings":"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"}
|