@earendil-works/chord 1.3.0 → 1.5.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 +54 -0
- package/README.md +129 -10
- package/dist/cell.d.ts +7 -7
- package/dist/cell.d.ts.map +1 -1
- package/dist/cell.js.map +1 -1
- package/dist/context/index.d.ts +8 -0
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +15 -0
- package/dist/context/index.js.map +1 -1
- package/dist/contract.d.ts +51 -52
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +19 -24
- package/dist/contract.js.map +1 -1
- package/dist/delta/apply-immutable-trusted.js +3 -4
- package/dist/delta/apply-immutable-trusted.js.map +1 -1
- package/dist/delta/diff.d.ts.map +1 -1
- package/dist/delta/diff.js +5 -3
- package/dist/delta/diff.js.map +1 -1
- package/dist/delta/index.d.ts +9 -1
- package/dist/delta/index.d.ts.map +1 -1
- package/dist/delta/index.js +15 -11
- package/dist/delta/index.js.map +1 -1
- package/dist/delta/pending.d.ts +36 -0
- package/dist/delta/pending.d.ts.map +1 -0
- package/dist/delta/pending.js +143 -0
- package/dist/delta/pending.js.map +1 -0
- package/dist/delta/tracker.d.ts +12 -0
- package/dist/delta/tracker.d.ts.map +1 -1
- package/dist/delta/tracker.js +109 -39
- package/dist/delta/tracker.js.map +1 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +9 -7
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/next/contracts/accepts.d.ts +81 -0
- package/dist/next/contracts/accepts.d.ts.map +1 -0
- package/dist/next/contracts/accepts.js +123 -0
- package/dist/next/contracts/accepts.js.map +1 -0
- package/dist/next/contracts/contract.d.ts +121 -0
- package/dist/next/contracts/contract.d.ts.map +1 -0
- package/dist/next/contracts/contract.js +50 -0
- package/dist/next/contracts/contract.js.map +1 -0
- package/dist/next/contracts/declare.d.ts +107 -0
- package/dist/next/contracts/declare.d.ts.map +1 -0
- package/dist/next/contracts/declare.js +136 -0
- package/dist/next/contracts/declare.js.map +1 -0
- package/dist/next/contracts/evolve.d.ts +92 -0
- package/dist/next/contracts/evolve.d.ts.map +1 -0
- package/dist/next/contracts/evolve.js +179 -0
- package/dist/next/contracts/evolve.js.map +1 -0
- package/dist/next/contracts/fingerprint.d.ts +16 -0
- package/dist/next/contracts/fingerprint.d.ts.map +1 -0
- package/dist/next/contracts/fingerprint.js +50 -0
- package/dist/next/contracts/fingerprint.js.map +1 -0
- package/dist/next/contracts/history.d.ts +71 -0
- package/dist/next/contracts/history.d.ts.map +1 -0
- package/dist/next/contracts/history.js +3 -0
- package/dist/next/contracts/history.js.map +1 -0
- package/dist/next/contracts/host-kind.d.ts +40 -0
- package/dist/next/contracts/host-kind.d.ts.map +1 -0
- package/dist/next/contracts/host-kind.js +37 -0
- package/dist/next/contracts/host-kind.js.map +1 -0
- package/dist/next/contracts/index.d.ts +7 -0
- package/dist/next/contracts/index.d.ts.map +1 -0
- package/dist/next/contracts/index.js +6 -0
- package/dist/next/contracts/index.js.map +1 -0
- package/dist/next/contracts/internal.d.ts +10 -0
- package/dist/next/contracts/internal.d.ts.map +1 -0
- package/dist/next/contracts/internal.js +9 -0
- package/dist/next/contracts/internal.js.map +1 -0
- package/dist/next/contracts/names.d.ts +3 -0
- package/dist/next/contracts/names.d.ts.map +1 -0
- package/dist/next/contracts/names.js +13 -0
- package/dist/next/contracts/names.js.map +1 -0
- package/dist/next/contracts/params.d.ts +28 -0
- package/dist/next/contracts/params.d.ts.map +1 -0
- package/dist/next/contracts/params.js +50 -0
- package/dist/next/contracts/params.js.map +1 -0
- package/dist/next/contracts/schema.d.ts +102 -0
- package/dist/next/contracts/schema.d.ts.map +1 -0
- package/dist/next/contracts/schema.js +103 -0
- package/dist/next/contracts/schema.js.map +1 -0
- package/dist/next/contracts/snapshot.d.ts +16 -0
- package/dist/next/contracts/snapshot.d.ts.map +1 -0
- package/dist/next/contracts/snapshot.js +167 -0
- package/dist/next/contracts/snapshot.js.map +1 -0
- package/dist/next/data/args.d.ts +50 -0
- package/dist/next/data/args.d.ts.map +1 -0
- package/dist/next/data/args.js +83 -0
- package/dist/next/data/args.js.map +1 -0
- package/dist/next/data/errors.d.ts +73 -0
- package/dist/next/data/errors.d.ts.map +1 -0
- package/dist/next/data/errors.js +107 -0
- package/dist/next/data/errors.js.map +1 -0
- package/dist/next/data/failure.d.ts +26 -0
- package/dist/next/data/failure.d.ts.map +1 -0
- package/dist/next/data/failure.js +72 -0
- package/dist/next/data/failure.js.map +1 -0
- package/dist/next/data/index.d.ts +4 -0
- package/dist/next/data/index.d.ts.map +1 -0
- package/dist/next/data/index.js +4 -0
- package/dist/next/data/index.js.map +1 -0
- package/dist/next/data/internal.d.ts +7 -0
- package/dist/next/data/internal.d.ts.map +1 -0
- package/dist/next/data/internal.js +8 -0
- package/dist/next/data/internal.js.map +1 -0
- package/dist/next/data/params.d.ts +20 -0
- package/dist/next/data/params.d.ts.map +1 -0
- package/dist/next/data/params.js +31 -0
- package/dist/next/data/params.js.map +1 -0
- package/dist/next/data/principal.d.ts +17 -0
- package/dist/next/data/principal.d.ts.map +1 -0
- package/dist/next/data/principal.js +41 -0
- package/dist/next/data/principal.js.map +1 -0
- package/dist/next/data/validator.d.ts +12 -0
- package/dist/next/data/validator.d.ts.map +1 -0
- package/dist/next/data/validator.js +34 -0
- package/dist/next/data/validator.js.map +1 -0
- package/dist/next/documents/address-source.d.ts +20 -0
- package/dist/next/documents/address-source.d.ts.map +1 -0
- package/dist/next/documents/address-source.js +44 -0
- package/dist/next/documents/address-source.js.map +1 -0
- package/dist/next/documents/definition.d.ts +84 -0
- package/dist/next/documents/definition.d.ts.map +1 -0
- package/dist/next/documents/definition.js +73 -0
- package/dist/next/documents/definition.js.map +1 -0
- package/dist/next/documents/documents.d.ts +106 -0
- package/dist/next/documents/documents.d.ts.map +1 -0
- package/dist/next/documents/documents.js +224 -0
- package/dist/next/documents/documents.js.map +1 -0
- package/dist/next/documents/fence.d.ts +9 -0
- package/dist/next/documents/fence.d.ts.map +1 -0
- package/dist/next/documents/fence.js +15 -0
- package/dist/next/documents/fence.js.map +1 -0
- package/dist/next/documents/handles.d.ts +76 -0
- package/dist/next/documents/handles.d.ts.map +1 -0
- package/dist/next/documents/handles.js +66 -0
- package/dist/next/documents/handles.js.map +1 -0
- package/dist/next/documents/index.d.ts +4 -0
- package/dist/next/documents/index.d.ts.map +1 -0
- package/dist/next/documents/index.js +3 -0
- package/dist/next/documents/index.js.map +1 -0
- package/dist/next/documents/internal.d.ts +9 -0
- package/dist/next/documents/internal.d.ts.map +1 -0
- package/dist/next/documents/internal.js +9 -0
- package/dist/next/documents/internal.js.map +1 -0
- package/dist/next/documents/keyed-slot.d.ts +103 -0
- package/dist/next/documents/keyed-slot.d.ts.map +1 -0
- package/dist/next/documents/keyed-slot.js +395 -0
- package/dist/next/documents/keyed-slot.js.map +1 -0
- package/dist/next/documents/line.d.ts +7 -0
- package/dist/next/documents/line.d.ts.map +1 -0
- package/dist/next/documents/line.js +14 -0
- package/dist/next/documents/line.js.map +1 -0
- package/dist/next/documents/persistence.d.ts +104 -0
- package/dist/next/documents/persistence.d.ts.map +1 -0
- package/dist/next/documents/persistence.js +128 -0
- package/dist/next/documents/persistence.js.map +1 -0
- package/dist/next/documents/residency.d.ts +31 -0
- package/dist/next/documents/residency.d.ts.map +1 -0
- package/dist/next/documents/residency.js +93 -0
- package/dist/next/documents/residency.js.map +1 -0
- package/dist/next/documents/slot.d.ts +109 -0
- package/dist/next/documents/slot.d.ts.map +1 -0
- package/dist/next/documents/slot.js +181 -0
- package/dist/next/documents/slot.js.map +1 -0
- package/dist/next/documents/transaction.d.ts +133 -0
- package/dist/next/documents/transaction.d.ts.map +1 -0
- package/dist/next/documents/transaction.js +409 -0
- package/dist/next/documents/transaction.js.map +1 -0
- package/dist/next/host/activity.d.ts +31 -0
- package/dist/next/host/activity.d.ts.map +1 -0
- package/dist/next/host/activity.js +40 -0
- package/dist/next/host/activity.js.map +1 -0
- package/dist/next/host/adapted.d.ts +49 -0
- package/dist/next/host/adapted.d.ts.map +1 -0
- package/dist/next/host/adapted.js +214 -0
- package/dist/next/host/adapted.js.map +1 -0
- package/dist/next/host/attempt.d.ts +278 -0
- package/dist/next/host/attempt.d.ts.map +1 -0
- package/dist/next/host/attempt.js +1072 -0
- package/dist/next/host/attempt.js.map +1 -0
- package/dist/next/host/backoff.d.ts +29 -0
- package/dist/next/host/backoff.d.ts.map +1 -0
- package/dist/next/host/backoff.js +69 -0
- package/dist/next/host/backoff.js.map +1 -0
- package/dist/next/host/ctx.d.ts +47 -0
- package/dist/next/host/ctx.d.ts.map +1 -0
- package/dist/next/host/ctx.js +108 -0
- package/dist/next/host/ctx.js.map +1 -0
- package/dist/next/host/deadline.d.ts +12 -0
- package/dist/next/host/deadline.d.ts.map +1 -0
- package/dist/next/host/deadline.js +40 -0
- package/dist/next/host/deadline.js.map +1 -0
- package/dist/next/host/dependencies.d.ts +65 -0
- package/dist/next/host/dependencies.d.ts.map +1 -0
- package/dist/next/host/dependencies.js +115 -0
- package/dist/next/host/dependencies.js.map +1 -0
- package/dist/next/host/destination.d.ts +48 -0
- package/dist/next/host/destination.d.ts.map +1 -0
- package/dist/next/host/destination.js +101 -0
- package/dist/next/host/destination.js.map +1 -0
- package/dist/next/host/facet.d.ts +79 -0
- package/dist/next/host/facet.d.ts.map +1 -0
- package/dist/next/host/facet.js +55 -0
- package/dist/next/host/facet.js.map +1 -0
- package/dist/next/host/follow.d.ts +52 -0
- package/dist/next/host/follow.d.ts.map +1 -0
- package/dist/next/host/follow.js +207 -0
- package/dist/next/host/follow.js.map +1 -0
- package/dist/next/host/host.d.ts +495 -0
- package/dist/next/host/host.d.ts.map +1 -0
- package/dist/next/host/host.js +1075 -0
- package/dist/next/host/host.js.map +1 -0
- package/dist/next/host/index.d.ts +17 -0
- package/dist/next/host/index.d.ts.map +1 -0
- package/dist/next/host/index.js +6 -0
- package/dist/next/host/index.js.map +1 -0
- package/dist/next/host/internal.d.ts +10 -0
- package/dist/next/host/internal.d.ts.map +1 -0
- package/dist/next/host/internal.js +8 -0
- package/dist/next/host/internal.js.map +1 -0
- package/dist/next/host/members.d.ts +50 -0
- package/dist/next/host/members.d.ts.map +1 -0
- package/dist/next/host/members.js +107 -0
- package/dist/next/host/members.js.map +1 -0
- package/dist/next/host/native.d.ts +55 -0
- package/dist/next/host/native.d.ts.map +1 -0
- package/dist/next/host/native.js +92 -0
- package/dist/next/host/native.js.map +1 -0
- package/dist/next/host/object.d.ts +290 -0
- package/dist/next/host/object.d.ts.map +1 -0
- package/dist/next/host/object.js +1127 -0
- package/dist/next/host/object.js.map +1 -0
- package/dist/next/host/parked.d.ts +23 -0
- package/dist/next/host/parked.d.ts.map +1 -0
- package/dist/next/host/parked.js +79 -0
- package/dist/next/host/parked.js.map +1 -0
- package/dist/next/host/presence.d.ts +34 -0
- package/dist/next/host/presence.d.ts.map +1 -0
- package/dist/next/host/presence.js +117 -0
- package/dist/next/host/presence.js.map +1 -0
- package/dist/next/host/ref-state.d.ts +53 -0
- package/dist/next/host/ref-state.d.ts.map +1 -0
- package/dist/next/host/ref-state.js +83 -0
- package/dist/next/host/ref-state.js.map +1 -0
- package/dist/next/host/reference-keys.d.ts +36 -0
- package/dist/next/host/reference-keys.d.ts.map +1 -0
- package/dist/next/host/reference-keys.js +168 -0
- package/dist/next/host/reference-keys.js.map +1 -0
- package/dist/next/host/reference-source.d.ts +65 -0
- package/dist/next/host/reference-source.d.ts.map +1 -0
- package/dist/next/host/reference-source.js +285 -0
- package/dist/next/host/reference-source.js.map +1 -0
- package/dist/next/host/reference.d.ts +308 -0
- package/dist/next/host/reference.d.ts.map +1 -0
- package/dist/next/host/reference.js +775 -0
- package/dist/next/host/reference.js.map +1 -0
- package/dist/next/host/retry-on.d.ts +28 -0
- package/dist/next/host/retry-on.d.ts.map +1 -0
- package/dist/next/host/retry-on.js +52 -0
- package/dist/next/host/retry-on.js.map +1 -0
- package/dist/next/host/revocation.d.ts +16 -0
- package/dist/next/host/revocation.d.ts.map +1 -0
- package/dist/next/host/revocation.js +27 -0
- package/dist/next/host/revocation.js.map +1 -0
- package/dist/next/host/root.d.ts +27 -0
- package/dist/next/host/root.d.ts.map +1 -0
- package/dist/next/host/root.js +68 -0
- package/dist/next/host/root.js.map +1 -0
- package/dist/next/host/route.d.ts +64 -0
- package/dist/next/host/route.d.ts.map +1 -0
- package/dist/next/host/route.js +190 -0
- package/dist/next/host/route.js.map +1 -0
- package/dist/next/host/routines.d.ts +76 -0
- package/dist/next/host/routines.d.ts.map +1 -0
- package/dist/next/host/routines.js +350 -0
- package/dist/next/host/routines.js.map +1 -0
- package/dist/next/host/sleep.d.ts +9 -0
- package/dist/next/host/sleep.d.ts.map +1 -0
- package/dist/next/host/sleep.js +40 -0
- package/dist/next/host/sleep.js.map +1 -0
- package/dist/next/host/staging.d.ts +94 -0
- package/dist/next/host/staging.d.ts.map +1 -0
- package/dist/next/host/staging.js +302 -0
- package/dist/next/host/staging.js.map +1 -0
- package/dist/next/host/unbound.d.ts +30 -0
- package/dist/next/host/unbound.d.ts.map +1 -0
- package/dist/next/host/unbound.js +67 -0
- package/dist/next/host/unbound.js.map +1 -0
- package/dist/next/host/uuid.d.ts +3 -0
- package/dist/next/host/uuid.d.ts.map +1 -0
- package/dist/next/host/uuid.js +38 -0
- package/dist/next/host/uuid.js.map +1 -0
- package/dist/next/index.d.ts +28 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +18 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/jobs/definition.d.ts +96 -0
- package/dist/next/jobs/definition.d.ts.map +1 -0
- package/dist/next/jobs/definition.js +83 -0
- package/dist/next/jobs/definition.js.map +1 -0
- package/dist/next/jobs/index.d.ts +5 -0
- package/dist/next/jobs/index.d.ts.map +1 -0
- package/dist/next/jobs/index.js +3 -0
- package/dist/next/jobs/index.js.map +1 -0
- package/dist/next/jobs/internal.d.ts +3 -0
- package/dist/next/jobs/internal.d.ts.map +1 -0
- package/dist/next/jobs/internal.js +4 -0
- package/dist/next/jobs/internal.js.map +1 -0
- package/dist/next/jobs/job.d.ts +152 -0
- package/dist/next/jobs/job.d.ts.map +1 -0
- package/dist/next/jobs/job.js +320 -0
- package/dist/next/jobs/job.js.map +1 -0
- package/dist/next/jobs/persisted.d.ts +38 -0
- package/dist/next/jobs/persisted.d.ts.map +1 -0
- package/dist/next/jobs/persisted.js +95 -0
- package/dist/next/jobs/persisted.js.map +1 -0
- package/dist/next/jobs/records.d.ts +231 -0
- package/dist/next/jobs/records.d.ts.map +1 -0
- package/dist/next/jobs/records.js +869 -0
- package/dist/next/jobs/records.js.map +1 -0
- package/dist/next/jobs/run-states.d.ts +69 -0
- package/dist/next/jobs/run-states.d.ts.map +1 -0
- package/dist/next/jobs/run-states.js +228 -0
- package/dist/next/jobs/run-states.js.map +1 -0
- package/dist/next/jobs/run.d.ts +113 -0
- package/dist/next/jobs/run.d.ts.map +1 -0
- package/dist/next/jobs/run.js +200 -0
- package/dist/next/jobs/run.js.map +1 -0
- package/dist/next/jobs/running.d.ts +44 -0
- package/dist/next/jobs/running.d.ts.map +1 -0
- package/dist/next/jobs/running.js +117 -0
- package/dist/next/jobs/running.js.map +1 -0
- package/dist/next/jobs/stored.d.ts +63 -0
- package/dist/next/jobs/stored.d.ts.map +1 -0
- package/dist/next/jobs/stored.js +55 -0
- package/dist/next/jobs/stored.js.map +1 -0
- package/dist/next/link/binary.d.ts +4 -0
- package/dist/next/link/binary.d.ts.map +1 -0
- package/dist/next/link/binary.js +534 -0
- package/dist/next/link/binary.js.map +1 -0
- package/dist/next/link/channel.d.ts +63 -0
- package/dist/next/link/channel.d.ts.map +1 -0
- package/dist/next/link/channel.js +202 -0
- package/dist/next/link/channel.js.map +1 -0
- package/dist/next/link/errors.d.ts +7 -0
- package/dist/next/link/errors.d.ts.map +1 -0
- package/dist/next/link/errors.js +21 -0
- package/dist/next/link/errors.js.map +1 -0
- package/dist/next/link/index.d.ts +8 -0
- package/dist/next/link/index.d.ts.map +1 -0
- package/dist/next/link/index.js +8 -0
- package/dist/next/link/index.js.map +1 -0
- package/dist/next/link/internal.d.ts +9 -0
- package/dist/next/link/internal.d.ts.map +1 -0
- package/dist/next/link/internal.js +10 -0
- package/dist/next/link/internal.js.map +1 -0
- package/dist/next/link/ipc.d.ts +22 -0
- package/dist/next/link/ipc.d.ts.map +1 -0
- package/dist/next/link/ipc.js +64 -0
- package/dist/next/link/ipc.js.map +1 -0
- package/dist/next/link/link.d.ts +34 -0
- package/dist/next/link/link.d.ts.map +1 -0
- package/dist/next/link/link.js +87 -0
- package/dist/next/link/link.js.map +1 -0
- package/dist/next/link/message.d.ts +249 -0
- package/dist/next/link/message.d.ts.map +1 -0
- package/dist/next/link/message.js +123 -0
- package/dist/next/link/message.js.map +1 -0
- package/dist/next/link/part.d.ts +80 -0
- package/dist/next/link/part.d.ts.map +1 -0
- package/dist/next/link/part.js +164 -0
- package/dist/next/link/part.js.map +1 -0
- package/dist/next/link/text.d.ts +6 -0
- package/dist/next/link/text.d.ts.map +1 -0
- package/dist/next/link/text.js +335 -0
- package/dist/next/link/text.js.map +1 -0
- package/dist/next/link/values.d.ts +40 -0
- package/dist/next/link/values.d.ts.map +1 -0
- package/dist/next/link/values.js +117 -0
- package/dist/next/link/values.js.map +1 -0
- package/dist/next/link/websocket.d.ts +26 -0
- package/dist/next/link/websocket.d.ts.map +1 -0
- package/dist/next/link/websocket.js +91 -0
- package/dist/next/link/websocket.js.map +1 -0
- package/dist/next/registries/contribution.d.ts +50 -0
- package/dist/next/registries/contribution.d.ts.map +1 -0
- package/dist/next/registries/contribution.js +129 -0
- package/dist/next/registries/contribution.js.map +1 -0
- package/dist/next/registries/entries.d.ts +18 -0
- package/dist/next/registries/entries.d.ts.map +1 -0
- package/dist/next/registries/entries.js +42 -0
- package/dist/next/registries/entries.js.map +1 -0
- package/dist/next/registries/index.d.ts +3 -0
- package/dist/next/registries/index.d.ts.map +1 -0
- package/dist/next/registries/index.js +5 -0
- package/dist/next/registries/index.js.map +1 -0
- package/dist/next/registries/internal.d.ts +4 -0
- package/dist/next/registries/internal.d.ts.map +1 -0
- package/dist/next/registries/internal.js +5 -0
- package/dist/next/registries/internal.js.map +1 -0
- package/dist/next/registries/record.d.ts +94 -0
- package/dist/next/registries/record.d.ts.map +1 -0
- package/dist/next/registries/record.js +253 -0
- package/dist/next/registries/record.js.map +1 -0
- package/dist/next/registries/registry.d.ts +74 -0
- package/dist/next/registries/registry.d.ts.map +1 -0
- package/dist/next/registries/registry.js +14 -0
- package/dist/next/registries/registry.js.map +1 -0
- package/dist/next/registries/value.d.ts +48 -0
- package/dist/next/registries/value.d.ts.map +1 -0
- package/dist/next/registries/value.js +199 -0
- package/dist/next/registries/value.js.map +1 -0
- package/dist/next/remote/calls.d.ts +25 -0
- package/dist/next/remote/calls.d.ts.map +1 -0
- package/dist/next/remote/calls.js +62 -0
- package/dist/next/remote/calls.js.map +1 -0
- package/dist/next/remote/consumer.d.ts +42 -0
- package/dist/next/remote/consumer.d.ts.map +1 -0
- package/dist/next/remote/consumer.js +343 -0
- package/dist/next/remote/consumer.js.map +1 -0
- package/dist/next/remote/hold.d.ts +130 -0
- package/dist/next/remote/hold.d.ts.map +1 -0
- package/dist/next/remote/hold.js +537 -0
- package/dist/next/remote/hold.js.map +1 -0
- package/dist/next/remote/host-link.d.ts +77 -0
- package/dist/next/remote/host-link.d.ts.map +1 -0
- package/dist/next/remote/host-link.js +182 -0
- package/dist/next/remote/host-link.js.map +1 -0
- package/dist/next/remote/internal.d.ts +6 -0
- package/dist/next/remote/internal.d.ts.map +1 -0
- package/dist/next/remote/internal.js +6 -0
- package/dist/next/remote/internal.js.map +1 -0
- package/dist/next/remote/path.d.ts +46 -0
- package/dist/next/remote/path.d.ts.map +1 -0
- package/dist/next/remote/path.js +73 -0
- package/dist/next/remote/path.js.map +1 -0
- package/dist/next/remote/provider.d.ts +76 -0
- package/dist/next/remote/provider.d.ts.map +1 -0
- package/dist/next/remote/provider.js +506 -0
- package/dist/next/remote/provider.js.map +1 -0
- package/dist/next/remote/relay.d.ts +58 -0
- package/dist/next/remote/relay.d.ts.map +1 -0
- package/dist/next/remote/relay.js +117 -0
- package/dist/next/remote/relay.js.map +1 -0
- package/dist/next/remote/remote-object.d.ts +133 -0
- package/dist/next/remote/remote-object.d.ts.map +1 -0
- package/dist/next/remote/remote-object.js +411 -0
- package/dist/next/remote/remote-object.js.map +1 -0
- package/dist/next/remote/replica.d.ts +59 -0
- package/dist/next/remote/replica.d.ts.map +1 -0
- package/dist/next/remote/replica.js +125 -0
- package/dist/next/remote/replica.js.map +1 -0
- package/dist/next/state/batch.d.ts +64 -0
- package/dist/next/state/batch.d.ts.map +1 -0
- package/dist/next/state/batch.js +163 -0
- package/dist/next/state/batch.js.map +1 -0
- package/dist/next/state/derive.d.ts +52 -0
- package/dist/next/state/derive.d.ts.map +1 -0
- package/dist/next/state/derive.js +182 -0
- package/dist/next/state/derive.js.map +1 -0
- package/dist/next/state/index.d.ts +6 -0
- package/dist/next/state/index.d.ts.map +1 -0
- package/dist/next/state/index.js +4 -0
- package/dist/next/state/index.js.map +1 -0
- package/dist/next/state/internal.d.ts +6 -0
- package/dist/next/state/internal.d.ts.map +1 -0
- package/dist/next/state/internal.js +8 -0
- package/dist/next/state/internal.js.map +1 -0
- package/dist/next/state/native-source.d.ts +106 -0
- package/dist/next/state/native-source.d.ts.map +1 -0
- package/dist/next/state/native-source.js +240 -0
- package/dist/next/state/native-source.js.map +1 -0
- package/dist/next/state/watchable.d.ts +114 -0
- package/dist/next/state/watchable.d.ts.map +1 -0
- package/dist/next/state/watchable.js +156 -0
- package/dist/next/state/watchable.js.map +1 -0
- package/dist/next/state/writable.d.ts +32 -0
- package/dist/next/state/writable.d.ts.map +1 -0
- package/dist/next/state/writable.js +49 -0
- package/dist/next/state/writable.js.map +1 -0
- package/dist/next/store/adapter.d.ts +67 -0
- package/dist/next/store/adapter.d.ts.map +1 -0
- package/dist/next/store/adapter.js +118 -0
- package/dist/next/store/adapter.js.map +1 -0
- package/dist/next/store/allocator.d.ts +17 -0
- package/dist/next/store/allocator.d.ts.map +1 -0
- package/dist/next/store/allocator.js +30 -0
- package/dist/next/store/allocator.js.map +1 -0
- package/dist/next/store/applier.d.ts +8 -0
- package/dist/next/store/applier.d.ts.map +1 -0
- package/dist/next/store/applier.js +375 -0
- package/dist/next/store/applier.js.map +1 -0
- package/dist/next/store/apply-batch.d.ts +12 -0
- package/dist/next/store/apply-batch.d.ts.map +1 -0
- package/dist/next/store/apply-batch.js +83 -0
- package/dist/next/store/apply-batch.js.map +1 -0
- package/dist/next/store/archive.d.ts +32 -0
- package/dist/next/store/archive.d.ts.map +1 -0
- package/dist/next/store/archive.js +129 -0
- package/dist/next/store/archive.js.map +1 -0
- package/dist/next/store/backend.d.ts +10 -0
- package/dist/next/store/backend.d.ts.map +1 -0
- package/dist/next/store/backend.js +15 -0
- package/dist/next/store/backend.js.map +1 -0
- package/dist/next/store/catalog.d.ts +24 -0
- package/dist/next/store/catalog.d.ts.map +1 -0
- package/dist/next/store/catalog.js +17 -0
- package/dist/next/store/catalog.js.map +1 -0
- package/dist/next/store/claims.d.ts +23 -0
- package/dist/next/store/claims.d.ts.map +1 -0
- package/dist/next/store/claims.js +65 -0
- package/dist/next/store/claims.js.map +1 -0
- package/dist/next/store/columns.d.ts +77 -0
- package/dist/next/store/columns.d.ts.map +1 -0
- package/dist/next/store/columns.js +77 -0
- package/dist/next/store/columns.js.map +1 -0
- package/dist/next/store/engine.d.ts +176 -0
- package/dist/next/store/engine.d.ts.map +1 -0
- package/dist/next/store/engine.js +283 -0
- package/dist/next/store/engine.js.map +1 -0
- package/dist/next/store/evaluate.d.ts +17 -0
- package/dist/next/store/evaluate.d.ts.map +1 -0
- package/dist/next/store/evaluate.js +128 -0
- package/dist/next/store/evaluate.js.map +1 -0
- package/dist/next/store/export.d.ts +17 -0
- package/dist/next/store/export.d.ts.map +1 -0
- package/dist/next/store/export.js +200 -0
- package/dist/next/store/export.js.map +1 -0
- package/dist/next/store/expression.d.ts +150 -0
- package/dist/next/store/expression.d.ts.map +1 -0
- package/dist/next/store/expression.js +268 -0
- package/dist/next/store/expression.js.map +1 -0
- package/dist/next/store/import.d.ts +10 -0
- package/dist/next/store/import.d.ts.map +1 -0
- package/dist/next/store/import.js +276 -0
- package/dist/next/store/import.js.map +1 -0
- package/dist/next/store/index.d.ts +16 -0
- package/dist/next/store/index.d.ts.map +1 -0
- package/dist/next/store/index.js +13 -0
- package/dist/next/store/index.js.map +1 -0
- package/dist/next/store/json-column.d.ts +33 -0
- package/dist/next/store/json-column.d.ts.map +1 -0
- package/dist/next/store/json-column.js +61 -0
- package/dist/next/store/json-column.js.map +1 -0
- package/dist/next/store/jsonl.d.ts +9 -0
- package/dist/next/store/jsonl.d.ts.map +1 -0
- package/dist/next/store/jsonl.js +61 -0
- package/dist/next/store/jsonl.js.map +1 -0
- package/dist/next/store/outbox.d.ts +26 -0
- package/dist/next/store/outbox.d.ts.map +1 -0
- package/dist/next/store/outbox.js +80 -0
- package/dist/next/store/outbox.js.map +1 -0
- package/dist/next/store/query.d.ts +39 -0
- package/dist/next/store/query.d.ts.map +1 -0
- package/dist/next/store/query.js +97 -0
- package/dist/next/store/query.js.map +1 -0
- package/dist/next/store/refusal.d.ts +15 -0
- package/dist/next/store/refusal.d.ts.map +1 -0
- package/dist/next/store/refusal.js +36 -0
- package/dist/next/store/refusal.js.map +1 -0
- package/dist/next/store/rows.d.ts +80 -0
- package/dist/next/store/rows.d.ts.map +1 -0
- package/dist/next/store/rows.js +183 -0
- package/dist/next/store/rows.js.map +1 -0
- package/dist/next/store/schema.d.ts +25 -0
- package/dist/next/store/schema.d.ts.map +1 -0
- package/dist/next/store/schema.js +115 -0
- package/dist/next/store/schema.js.map +1 -0
- package/dist/next/store/sql.d.ts +73 -0
- package/dist/next/store/sql.d.ts.map +1 -0
- package/dist/next/store/sql.js +234 -0
- package/dist/next/store/sql.js.map +1 -0
- package/dist/next/store/step.d.ts +48 -0
- package/dist/next/store/step.d.ts.map +1 -0
- package/dist/next/store/step.js +50 -0
- package/dist/next/store/step.js.map +1 -0
- package/dist/next/store/store.d.ts +161 -0
- package/dist/next/store/store.d.ts.map +1 -0
- package/dist/next/store/store.js +627 -0
- package/dist/next/store/store.js.map +1 -0
- package/dist/next/store/table-changes.d.ts +29 -0
- package/dist/next/store/table-changes.d.ts.map +1 -0
- package/dist/next/store/table-changes.js +102 -0
- package/dist/next/store/table-changes.js.map +1 -0
- package/dist/next/store/table-evolve.d.ts +74 -0
- package/dist/next/store/table-evolve.d.ts.map +1 -0
- package/dist/next/store/table-evolve.js +201 -0
- package/dist/next/store/table-evolve.js.map +1 -0
- package/dist/next/store/table-handle.d.ts +67 -0
- package/dist/next/store/table-handle.d.ts.map +1 -0
- package/dist/next/store/table-handle.js +101 -0
- package/dist/next/store/table-handle.js.map +1 -0
- package/dist/next/store/table-history.d.ts +75 -0
- package/dist/next/store/table-history.d.ts.map +1 -0
- package/dist/next/store/table-history.js +42 -0
- package/dist/next/store/table-history.js.map +1 -0
- package/dist/next/store/table-migration.d.ts +16 -0
- package/dist/next/store/table-migration.d.ts.map +1 -0
- package/dist/next/store/table-migration.js +202 -0
- package/dist/next/store/table-migration.js.map +1 -0
- package/dist/next/store/table-writes.d.ts +125 -0
- package/dist/next/store/table-writes.d.ts.map +1 -0
- package/dist/next/store/table-writes.js +165 -0
- package/dist/next/store/table-writes.js.map +1 -0
- package/dist/next/store/table.d.ts +80 -0
- package/dist/next/store/table.d.ts.map +1 -0
- package/dist/next/store/table.js +103 -0
- package/dist/next/store/table.js.map +1 -0
- package/dist/next/store/text.d.ts +14 -0
- package/dist/next/store/text.d.ts.map +1 -0
- package/dist/next/store/text.js +51 -0
- package/dist/next/store/text.js.map +1 -0
- package/dist/next/store/writes.d.ts +5 -0
- package/dist/next/store/writes.d.ts.map +1 -0
- package/dist/next/store/writes.js +4 -0
- package/dist/next/store/writes.js.map +1 -0
- package/dist/next-node/compression.d.ts +7 -0
- package/dist/next-node/compression.d.ts.map +1 -0
- package/dist/next-node/compression.js +24 -0
- package/dist/next-node/compression.js.map +1 -0
- package/dist/next-node/http/admission.d.ts +63 -0
- package/dist/next-node/http/admission.d.ts.map +1 -0
- package/dist/next-node/http/admission.js +134 -0
- package/dist/next-node/http/admission.js.map +1 -0
- package/dist/next-node/http/authenticate.d.ts +21 -0
- package/dist/next-node/http/authenticate.d.ts.map +1 -0
- package/dist/next-node/http/authenticate.js +34 -0
- package/dist/next-node/http/authenticate.js.map +1 -0
- package/dist/next-node/http/cookies.d.ts +24 -0
- package/dist/next-node/http/cookies.d.ts.map +1 -0
- package/dist/next-node/http/cookies.js +62 -0
- package/dist/next-node/http/cookies.js.map +1 -0
- package/dist/next-node/http/file.d.ts +23 -0
- package/dist/next-node/http/file.d.ts.map +1 -0
- package/dist/next-node/http/file.js +94 -0
- package/dist/next-node/http/file.js.map +1 -0
- package/dist/next-node/http/headers.d.ts +37 -0
- package/dist/next-node/http/headers.d.ts.map +1 -0
- package/dist/next-node/http/headers.js +129 -0
- package/dist/next-node/http/headers.js.map +1 -0
- package/dist/next-node/http/http.d.ts +100 -0
- package/dist/next-node/http/http.d.ts.map +1 -0
- package/dist/next-node/http/http.js +462 -0
- package/dist/next-node/http/http.js.map +1 -0
- package/dist/next-node/http/incoming.d.ts +19 -0
- package/dist/next-node/http/incoming.d.ts.map +1 -0
- package/dist/next-node/http/incoming.js +31 -0
- package/dist/next-node/http/incoming.js.map +1 -0
- package/dist/next-node/http/index.d.ts +11 -0
- package/dist/next-node/http/index.d.ts.map +1 -0
- package/dist/next-node/http/index.js +12 -0
- package/dist/next-node/http/index.js.map +1 -0
- package/dist/next-node/http/node.d.ts +78 -0
- package/dist/next-node/http/node.d.ts.map +1 -0
- package/dist/next-node/http/node.js +291 -0
- package/dist/next-node/http/node.js.map +1 -0
- package/dist/next-node/http/request.d.ts +54 -0
- package/dist/next-node/http/request.d.ts.map +1 -0
- package/dist/next-node/http/request.js +116 -0
- package/dist/next-node/http/request.js.map +1 -0
- package/dist/next-node/http/response.d.ts +63 -0
- package/dist/next-node/http/response.d.ts.map +1 -0
- package/dist/next-node/http/response.js +202 -0
- package/dist/next-node/http/response.js.map +1 -0
- package/dist/next-node/http/router.d.ts +114 -0
- package/dist/next-node/http/router.d.ts.map +1 -0
- package/dist/next-node/http/router.js +261 -0
- package/dist/next-node/http/router.js.map +1 -0
- package/dist/next-node/http/upgrades.d.ts +58 -0
- package/dist/next-node/http/upgrades.d.ts.map +1 -0
- package/dist/next-node/http/upgrades.js +184 -0
- package/dist/next-node/http/upgrades.js.map +1 -0
- package/dist/next-node/plugins/build.d.ts +57 -0
- package/dist/next-node/plugins/build.d.ts.map +1 -0
- package/dist/next-node/plugins/build.js +334 -0
- package/dist/next-node/plugins/build.js.map +1 -0
- package/dist/next-node/plugins/discover.d.ts +36 -0
- package/dist/next-node/plugins/discover.d.ts.map +1 -0
- package/dist/next-node/plugins/discover.js +91 -0
- package/dist/next-node/plugins/discover.js.map +1 -0
- package/dist/next-node/plugins/evaluate.d.ts +33 -0
- package/dist/next-node/plugins/evaluate.d.ts.map +1 -0
- package/dist/next-node/plugins/evaluate.js +98 -0
- package/dist/next-node/plugins/evaluate.js.map +1 -0
- package/dist/next-node/plugins/index.d.ts +9 -0
- package/dist/next-node/plugins/index.d.ts.map +1 -0
- package/dist/next-node/plugins/index.js +11 -0
- package/dist/next-node/plugins/index.js.map +1 -0
- package/dist/next-node/plugins/install.d.ts +13 -0
- package/dist/next-node/plugins/install.d.ts.map +1 -0
- package/dist/next-node/plugins/install.js +37 -0
- package/dist/next-node/plugins/install.js.map +1 -0
- package/dist/next-node/plugins/plugins.d.ts +135 -0
- package/dist/next-node/plugins/plugins.d.ts.map +1 -0
- package/dist/next-node/plugins/plugins.js +206 -0
- package/dist/next-node/plugins/plugins.js.map +1 -0
- package/dist/next-node/plugins/runtime.d.ts +41 -0
- package/dist/next-node/plugins/runtime.d.ts.map +1 -0
- package/dist/next-node/plugins/runtime.js +136 -0
- package/dist/next-node/plugins/runtime.js.map +1 -0
- package/dist/next-node/plugins/stack.d.ts +16 -0
- package/dist/next-node/plugins/stack.d.ts.map +1 -0
- package/dist/next-node/plugins/stack.js +61 -0
- package/dist/next-node/plugins/stack.js.map +1 -0
- package/dist/next-node/plugins/watcher.d.ts +58 -0
- package/dist/next-node/plugins/watcher.d.ts.map +1 -0
- package/dist/next-node/plugins/watcher.js +281 -0
- package/dist/next-node/plugins/watcher.js.map +1 -0
- package/dist/next-node/workers/control.d.ts +83 -0
- package/dist/next-node/workers/control.d.ts.map +1 -0
- package/dist/next-node/workers/control.js +77 -0
- package/dist/next-node/workers/control.js.map +1 -0
- package/dist/next-node/workers/index.d.ts +5 -0
- package/dist/next-node/workers/index.d.ts.map +1 -0
- package/dist/next-node/workers/index.js +7 -0
- package/dist/next-node/workers/index.js.map +1 -0
- package/dist/next-node/workers/lock.d.ts +21 -0
- package/dist/next-node/workers/lock.d.ts.map +1 -0
- package/dist/next-node/workers/lock.js +137 -0
- package/dist/next-node/workers/lock.js.map +1 -0
- package/dist/next-node/workers/main.d.ts +46 -0
- package/dist/next-node/workers/main.d.ts.map +1 -0
- package/dist/next-node/workers/main.js +230 -0
- package/dist/next-node/workers/main.js.map +1 -0
- package/dist/next-node/workers/process.d.ts +42 -0
- package/dist/next-node/workers/process.d.ts.map +1 -0
- package/dist/next-node/workers/process.js +125 -0
- package/dist/next-node/workers/process.js.map +1 -0
- package/dist/next-node/workers/workers.d.ts +80 -0
- package/dist/next-node/workers/workers.d.ts.map +1 -0
- package/dist/next-node/workers/workers.js +572 -0
- package/dist/next-node/workers/workers.js.map +1 -0
- package/dist/object.d.ts +4 -4
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +3 -4
- package/dist/object.js.map +1 -1
- package/dist/output.d.ts +9 -3
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +21 -9
- package/dist/output.js.map +1 -1
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +2 -2
- package/dist/remote.js.map +1 -1
- package/dist/schema.d.ts +8 -4
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +180 -5
- package/dist/schema.js.map +1 -1
- package/dist/sqlite/cloudflare.d.ts +54 -0
- package/dist/sqlite/cloudflare.d.ts.map +1 -0
- package/dist/sqlite/cloudflare.js +144 -0
- package/dist/sqlite/cloudflare.js.map +1 -0
- package/dist/sqlite/database.d.ts +40 -0
- package/dist/sqlite/database.d.ts.map +1 -0
- package/dist/sqlite/database.js +2 -0
- package/dist/sqlite/database.js.map +1 -0
- package/dist/sqlite/index.d.ts +4 -0
- package/dist/sqlite/index.d.ts.map +1 -0
- package/dist/sqlite/index.js +3 -0
- package/dist/sqlite/index.js.map +1 -0
- package/dist/sqlite/migrations.d.ts +10 -0
- package/dist/sqlite/migrations.d.ts.map +1 -0
- package/dist/sqlite/migrations.js +33 -0
- package/dist/sqlite/migrations.js.map +1 -0
- package/dist/sqlite/node.d.ts +41 -0
- package/dist/sqlite/node.d.ts.map +1 -0
- package/dist/sqlite/node.js +191 -0
- package/dist/sqlite/node.js.map +1 -0
- package/dist/sqlite/schema.d.ts +3 -0
- package/dist/sqlite/schema.d.ts.map +1 -0
- package/dist/sqlite/schema.js +10 -0
- package/dist/sqlite/schema.js.map +1 -0
- package/dist/telemetry-sqlite/index.d.ts +24 -0
- package/dist/telemetry-sqlite/index.d.ts.map +1 -0
- package/dist/telemetry-sqlite/index.js +273 -0
- package/dist/telemetry-sqlite/index.js.map +1 -0
- package/dist/telemetry-sqlite/store.d.ts +9 -0
- package/dist/telemetry-sqlite/store.d.ts.map +1 -0
- package/dist/telemetry-sqlite/store.js +110 -0
- package/dist/telemetry-sqlite/store.js.map +1 -0
- package/dist/watch.d.ts +194 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +383 -0
- package/dist/watch.js.map +1 -0
- package/dist/wire.d.ts +174 -193
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +81 -80
- package/dist/wire.js.map +1 -1
- package/docs/guide.md +15 -15
- package/docs/next/benchmarks.md +959 -0
- package/docs/next/decisions.md +2957 -0
- package/docs/next/dependencies/book.md +1671 -0
- package/docs/next/dependencies/index.html +2641 -0
- package/docs/next/dependencies/model.md +330 -0
- package/docs/next/design.md +2554 -0
- package/docs/next/durable-observers/book.md +432 -0
- package/docs/next/durable-observers/index.html +517 -0
- package/docs/next/flow-control/book.md +333 -0
- package/docs/next/flow-control/fold/index.html +265 -0
- package/docs/next/flow-control/index.html +548 -0
- package/docs/next/flow-control/window/index.html +228 -0
- package/docs/next/guide-plugins-hosts/book.md +607 -0
- package/docs/next/guide-plugins-hosts/index.html +652 -0
- package/docs/next/http-workers/book.md +378 -0
- package/docs/next/http-workers/index.html +515 -0
- package/docs/next/layer-1.md +311 -0
- package/docs/next/layer-2.md +216 -0
- package/docs/next/plugin-model/book.md +186 -0
- package/docs/next/plugin-model/index.html +310 -0
- package/docs/next/plugin-primer/book.md +273 -0
- package/docs/next/plugin-primer/index.html +430 -0
- package/docs/next/slice-1.md +236 -0
- package/docs/next/slice-10.md +285 -0
- package/docs/next/slice-11.md +93 -0
- package/docs/next/slice-2.md +174 -0
- package/docs/next/slice-3a.md +296 -0
- package/docs/next/slice-3b.md +197 -0
- package/docs/next/slice-4.md +146 -0
- package/docs/next/slice-4a.md +418 -0
- package/docs/next/slice-4b.md +208 -0
- package/docs/next/slice-5.md +281 -0
- package/docs/next/slice-6a.md +676 -0
- package/docs/next/slice-6b.md +332 -0
- package/docs/next/slice-7a.md +130 -0
- package/docs/next/slice-7b/book.md +608 -0
- package/docs/next/slice-7b/index.html +842 -0
- package/docs/next/slice-7b.md +255 -0
- package/docs/next/slice-7c.md +165 -0
- package/docs/next/slice-8.md +194 -0
- package/docs/next/slices.md +230 -0
- package/docs/next/store/book.md +665 -0
- package/docs/next/store/index.html +861 -0
- package/docs/next/store/walkthrough.md +193 -0
- package/docs/spec.md +9 -9
- package/docs/tutorial.md +26 -25
- package/package.json +42 -5
- package/src/delta/README.md +69 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Compares `a` and `b` by code point: negative, zero or positive. */
|
|
2
|
+
export declare function compareText(a: string, b: string): number;
|
|
3
|
+
/**
|
|
4
|
+
* `text` as the store keeps it: a lone surrogate replaced by U+FFFD (copied only when one occurs), NUL refused
|
|
5
|
+
* `invalid/args` (`what` names the value). Plugin strings are a trust boundary.
|
|
6
|
+
*/
|
|
7
|
+
export declare function storedText(text: string, what: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* The smallest string above every string starting with `prefix`, in code point order: the next code point after its
|
|
10
|
+
* last, carrying past U+10FFFF; `undefined` when there is none (`""` and all-U+10FFFF prefixes). `prefix` is
|
|
11
|
+
* well-formed.
|
|
12
|
+
*/
|
|
13
|
+
export declare function prefixUpperBound(prefix: string): string | undefined;
|
|
14
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/next/store/text.ts"],"names":[],"mappings":"AAMA,sEAAsE;AACtE,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQxD;AAWD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUnE"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Text in the store (decision "Text is plain UTF-8, in code point order"): Chord compares strings by code point, as
|
|
2
|
+
// SQLite's BINARY collation compares their UTF-8 bytes, never by JavaScript's UTF-16 code units; every stored string
|
|
3
|
+
// is well-formed and free of NUL, and a prefix becomes a range by its upper bound.
|
|
4
|
+
import { invalid } from "../data/internal.js";
|
|
5
|
+
/** Compares `a` and `b` by code point: negative, zero or positive. */
|
|
6
|
+
export function compareText(a, b) {
|
|
7
|
+
const length = Math.min(a.length, b.length);
|
|
8
|
+
for (let i = 0; i < length; i++) {
|
|
9
|
+
const x = a.charCodeAt(i);
|
|
10
|
+
const y = b.charCodeAt(i);
|
|
11
|
+
if (x !== y)
|
|
12
|
+
return codePointRank(x) - codePointRank(y);
|
|
13
|
+
}
|
|
14
|
+
return a.length - b.length;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A UTF-16 code unit's rank in code point order: a surrogate starts a code point above U+FFFF, so it ranks above every
|
|
18
|
+
* unit from U+E000 on.
|
|
19
|
+
*/
|
|
20
|
+
function codePointRank(unit) {
|
|
21
|
+
if (unit < 0xd800)
|
|
22
|
+
return unit;
|
|
23
|
+
return unit < 0xe000 ? unit + 0x2000 : unit - 0x800;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* `text` as the store keeps it: a lone surrogate replaced by U+FFFD (copied only when one occurs), NUL refused
|
|
27
|
+
* `invalid/args` (`what` names the value). Plugin strings are a trust boundary.
|
|
28
|
+
*/
|
|
29
|
+
export function storedText(text, what) {
|
|
30
|
+
if (text.includes("\0"))
|
|
31
|
+
throw invalid("args", `${what}: text may not contain NUL`);
|
|
32
|
+
return text.isWellFormed() ? text : text.toWellFormed();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The smallest string above every string starting with `prefix`, in code point order: the next code point after its
|
|
36
|
+
* last, carrying past U+10FFFF; `undefined` when there is none (`""` and all-U+10FFFF prefixes). `prefix` is
|
|
37
|
+
* well-formed.
|
|
38
|
+
*/
|
|
39
|
+
export function prefixUpperBound(prefix) {
|
|
40
|
+
const points = [...prefix];
|
|
41
|
+
while (points.length > 0) {
|
|
42
|
+
const last = points.pop().codePointAt(0);
|
|
43
|
+
if (last === 0x10ffff)
|
|
44
|
+
continue;
|
|
45
|
+
// The surrogates are no code points of well-formed text: after U+D7FF comes U+E000.
|
|
46
|
+
const next = last === 0xd7ff ? 0xe000 : last + 1;
|
|
47
|
+
return points.join("") + String.fromCodePoint(next);
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../../src/next/store/text.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,qHAAqH;AACrH,mFAAmF;AAEnF,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,sEAAsE;AACtE,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,CAAS;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,IAAY;IAClC,IAAI,IAAI,GAAG,MAAM;QAAE,OAAO,IAAI,CAAC;IAC/B,OAAO,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,IAAY;IACpD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,4BAA4B,CAAC,CAAC;IACpF,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC9C,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAG,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC;QAC3C,IAAI,IAAI,KAAK,QAAQ;YAAE,SAAS;QAChC,oFAAoF;QACpF,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC","sourcesContent":["// Text in the store (decision \"Text is plain UTF-8, in code point order\"): Chord compares strings by code point, as\n// SQLite's BINARY collation compares their UTF-8 bytes, never by JavaScript's UTF-16 code units; every stored string\n// is well-formed and free of NUL, and a prefix becomes a range by its upper bound.\n\nimport { invalid } from \"../data/internal.ts\";\n\n/** Compares `a` and `b` by code point: negative, zero or positive. */\nexport function compareText(a: string, b: string): number {\n\tconst length = Math.min(a.length, b.length);\n\tfor (let i = 0; i < length; i++) {\n\t\tconst x = a.charCodeAt(i);\n\t\tconst y = b.charCodeAt(i);\n\t\tif (x !== y) return codePointRank(x) - codePointRank(y);\n\t}\n\treturn a.length - b.length;\n}\n\n/**\n * A UTF-16 code unit's rank in code point order: a surrogate starts a code point above U+FFFF, so it ranks above every\n * unit from U+E000 on.\n */\nfunction codePointRank(unit: number): number {\n\tif (unit < 0xd800) return unit;\n\treturn unit < 0xe000 ? unit + 0x2000 : unit - 0x800;\n}\n\n/**\n * `text` as the store keeps it: a lone surrogate replaced by U+FFFD (copied only when one occurs), NUL refused\n * `invalid/args` (`what` names the value). Plugin strings are a trust boundary.\n */\nexport function storedText(text: string, what: string): string {\n\tif (text.includes(\"\\0\")) throw invalid(\"args\", `${what}: text may not contain NUL`);\n\treturn text.isWellFormed() ? text : text.toWellFormed();\n}\n\n/**\n * The smallest string above every string starting with `prefix`, in code point order: the next code point after its\n * last, carrying past U+10FFFF; `undefined` when there is none (`\"\"` and all-U+10FFFF prefixes). `prefix` is\n * well-formed.\n */\nexport function prefixUpperBound(prefix: string): string | undefined {\n\tconst points = [...prefix];\n\twhile (points.length > 0) {\n\t\tconst last = points.pop()!.codePointAt(0)!;\n\t\tif (last === 0x10ffff) continue;\n\t\t// The surrogates are no code points of well-formed text: after U+D7FF comes U+E000.\n\t\tconst next = last === 0xd7ff ? 0xe000 : last + 1;\n\t\treturn points.join(\"\") + String.fromCodePoint(next);\n\t}\n\treturn undefined;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writes.d.ts","sourceRoot":"","sources":["../../../src/next/store/writes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,iDAAiD;AACjD,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writes.js","sourceRoot":"","sources":["../../../src/next/store/writes.ts"],"names":[],"mappings":"AAAA,sHAAsH;AACtH,wDAAwD","sourcesContent":["// The store's write vocabulary (`StoreWrite`, slice 6a §7, §8; decision \"Writes carry their versions\"): one change of\n// the store each, as the outbox and archives record it.\n\nimport type { DocumentWrite } from \"./engine.ts\";\nimport type { TableWrite } from \"./table-writes.ts\";\n\n/** One change of the store, tagged by `kind`. */\nexport type StoreWrite = DocumentWrite | TableWrite;\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Compression } from "../next/link/index.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Raw deflate at level 1 (`deflateRawSync`), and inflate bounded by `maxOutputLength` (`inflateRawSync`): past the
|
|
4
|
+
* limit `too_large`, data that is no raw deflate stream `corrupt`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const nodeCompression: Compression;
|
|
7
|
+
//# sourceMappingURL=compression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../src/next-node/compression.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAY7B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Compression for Chord v2 hosts on Node (§22, slice 4b): the synchronous compressor `createHost({ compression })`
|
|
2
|
+
// takes, over Node's zlib. Node-only, so it lives outside `src/next`, which imports no Node module.
|
|
3
|
+
import { constants as buffer } from "node:buffer";
|
|
4
|
+
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
5
|
+
/**
|
|
6
|
+
* Raw deflate at level 1 (`deflateRawSync`), and inflate bounded by `maxOutputLength` (`inflateRawSync`): past the
|
|
7
|
+
* limit `too_large`, data that is no raw deflate stream `corrupt`.
|
|
8
|
+
*/
|
|
9
|
+
export const nodeCompression = {
|
|
10
|
+
deflate: (bytes) => deflateRawSync(bytes, { level: 1 }),
|
|
11
|
+
inflate: (bytes, limit) => {
|
|
12
|
+
try {
|
|
13
|
+
// zlib refuses a bound of 0: inflate at most one byte, and one byte is past a limit of 0.
|
|
14
|
+
const inflated = inflateRawSync(bytes, { maxOutputLength: Math.max(1, Math.min(limit, buffer.MAX_LENGTH)) });
|
|
15
|
+
return inflated.byteLength > limit ? { kind: "too_large" } : { kind: "bytes", bytes: inflated };
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (error.code === "ERR_BUFFER_TOO_LARGE")
|
|
19
|
+
return { kind: "too_large" };
|
|
20
|
+
return { kind: "corrupt", error };
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=compression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression.js","sourceRoot":"","sources":["../../src/next-node/compression.ts"],"names":[],"mappings":"AAAA,mHAAmH;AACnH,oGAAoG;AAEpG,OAAO,EAAE,SAAS,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3D;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAgB;IAC3C,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACvD,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACzB,IAAI,CAAC;YACJ,0FAA0F;YAC1F,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7G,OAAO,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QACjG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAK,KAAqC,CAAC,IAAI,KAAK,sBAAsB;gBAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;YACzG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACnC,CAAC;IACF,CAAC;CACD,CAAC","sourcesContent":["// Compression for Chord v2 hosts on Node (§22, slice 4b): the synchronous compressor `createHost({ compression })`\n// takes, over Node's zlib. Node-only, so it lives outside `src/next`, which imports no Node module.\n\nimport { constants as buffer } from \"node:buffer\";\nimport { deflateRawSync, inflateRawSync } from \"node:zlib\";\nimport type { Compression } from \"../next/link/index.ts\";\n\n/**\n * Raw deflate at level 1 (`deflateRawSync`), and inflate bounded by `maxOutputLength` (`inflateRawSync`): past the\n * limit `too_large`, data that is no raw deflate stream `corrupt`.\n */\nexport const nodeCompression: Compression = {\n\tdeflate: (bytes) => deflateRawSync(bytes, { level: 1 }),\n\tinflate: (bytes, limit) => {\n\t\ttry {\n\t\t\t// zlib refuses a bound of 0: inflate at most one byte, and one byte is past a limit of 0.\n\t\t\tconst inflated = inflateRawSync(bytes, { maxOutputLength: Math.max(1, Math.min(limit, buffer.MAX_LENGTH)) });\n\t\t\treturn inflated.byteLength > limit ? { kind: \"too_large\" } : { kind: \"bytes\", bytes: inflated };\n\t\t} catch (error) {\n\t\t\tif ((error as { readonly code?: unknown }).code === \"ERR_BUFFER_TOO_LARGE\") return { kind: \"too_large\" };\n\t\t\treturn { kind: \"corrupt\", error };\n\t\t}\n\t},\n};\n"]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Incoming } from "./incoming.ts";
|
|
2
|
+
import type { HttpRelay } from "./router.ts";
|
|
3
|
+
/** Where an admitted request came from. */
|
|
4
|
+
export type Provenance = {
|
|
5
|
+
readonly kind: "local";
|
|
6
|
+
} | {
|
|
7
|
+
readonly kind: "remote";
|
|
8
|
+
readonly host: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: "relayed";
|
|
11
|
+
readonly relay: string;
|
|
12
|
+
readonly origin: string;
|
|
13
|
+
};
|
|
14
|
+
/** The connection a request arrived on, as its listener knows it (a mounted handler passes what it has). */
|
|
15
|
+
export type Connection = {
|
|
16
|
+
readonly localAddress?: string;
|
|
17
|
+
readonly localPort?: number;
|
|
18
|
+
readonly remoteAddress?: string;
|
|
19
|
+
};
|
|
20
|
+
/** An admitted request: its provenance, its own origin, the origin allowed to frame it (a relay's), how it came. */
|
|
21
|
+
export type Admitted = {
|
|
22
|
+
readonly provenance: Provenance;
|
|
23
|
+
readonly origin: string;
|
|
24
|
+
readonly framer: string | undefined;
|
|
25
|
+
/** The allowed host it came through: its connections end when that host leaves. */
|
|
26
|
+
readonly allowed: string | undefined;
|
|
27
|
+
/** The relay that verified it: its connections end when that relay leaves. */
|
|
28
|
+
readonly relay: HttpRelay | undefined;
|
|
29
|
+
};
|
|
30
|
+
/** What admission refuses, and the relay hook that threw (reported by the caller). */
|
|
31
|
+
export type Refused = {
|
|
32
|
+
readonly kind: "refused";
|
|
33
|
+
readonly failed?: {
|
|
34
|
+
readonly relay: string;
|
|
35
|
+
readonly error: unknown;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Admits `request` arriving on `connection` with the allowed `hosts` and contributed `relays`, or refuses it (403):
|
|
40
|
+
* no or several `Host`s, a host neither loopback nor allowed, a loopback `Host` on another connection, forwarded
|
|
41
|
+
* headers no relay verifies.
|
|
42
|
+
*/
|
|
43
|
+
export declare function admit(request: Incoming, connection: Connection, hosts: ReadonlySet<string>, relays: readonly HttpRelay[]): Admitted | Refused;
|
|
44
|
+
/** What the Fetch Metadata and `Origin` checks read: a request's headers by name. */
|
|
45
|
+
export type HeaderSource = Pick<Incoming, "header">;
|
|
46
|
+
/** Whether `admission` refused its request. */
|
|
47
|
+
export declare function refused(admission: Admitted | Refused): admission is Refused;
|
|
48
|
+
/**
|
|
49
|
+
* Whether a request is another site's (Fetch Metadata, p2's rule): `Sec-Fetch-Site` neither `same-origin` nor `none`,
|
|
50
|
+
* or a frame or embed not from this origin. A request without the headers (a script, the TUI) is not.
|
|
51
|
+
*/
|
|
52
|
+
export declare function isForeign(headers: HeaderSource): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether a foreign request is a top-level navigation (a link followed to a page): `GET`, `navigate`, a `document` (or
|
|
55
|
+
* `empty`: Chrome on Android launching an installed app).
|
|
56
|
+
*/
|
|
57
|
+
export declare function isNavigation(method: string, headers: HeaderSource): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Whether `headers`' `Origin` is acceptable for a request whose own origin is `origin`: absent or equal, and for an
|
|
60
|
+
* unsafe method from a browser (one sending Fetch Metadata) present and equal.
|
|
61
|
+
*/
|
|
62
|
+
export declare function originAccepted(method: string, headers: HeaderSource, origin: string): boolean;
|
|
63
|
+
//# sourceMappingURL=admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../../src/next-node/http/admission.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,2CAA2C;AAC3C,MAAM,MAAM,UAAU,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF,4GAA4G;AAC5G,MAAM,MAAM,UAAU,GAAG;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,oHAAoH;AACpH,MAAM,MAAM,QAAQ,GAAG;IACtB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF,sFAAsF;AACtF,MAAM,MAAM,OAAO,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;CACtE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,KAAK,CACpB,OAAO,EAAE,QAAQ,EACjB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAC1B,MAAM,EAAE,SAAS,SAAS,EAAE,GAC1B,QAAQ,GAAG,OAAO,CAyBpB;AAED,qFAAqF;AACrF,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAEpD,+CAA+C;AAC/C,wBAAgB,OAAO,CAAC,SAAS,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,IAAI,OAAO,CAE3E;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAIxD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAK3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAI7F"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Admission (slice 10 §2, R4; decision "The HTTP component's security baseline" (1)-(3), "Relays"): where a request
|
|
2
|
+
// comes from, decided before anything else. Local only when the connection arrived on a loopback address, its `Host`
|
|
3
|
+
// is a loopback name with the listening port, and it carries no forwarded header; a forwarded request on loopback only
|
|
4
|
+
// when a contributed relay verifies it; otherwise only through an allowed host (https); else refused. Foreign requests
|
|
5
|
+
// (another site's, by Fetch Metadata) and a foreign `Origin` are classified here; the handler applies them per route.
|
|
6
|
+
/**
|
|
7
|
+
* Admits `request` arriving on `connection` with the allowed `hosts` and contributed `relays`, or refuses it (403):
|
|
8
|
+
* no or several `Host`s, a host neither loopback nor allowed, a loopback `Host` on another connection, forwarded
|
|
9
|
+
* headers no relay verifies.
|
|
10
|
+
*/
|
|
11
|
+
export function admit(request, connection, hosts, relays) {
|
|
12
|
+
const host = request.header("host")?.toLowerCase();
|
|
13
|
+
// Several `Host` headers arrive joined with commas.
|
|
14
|
+
if (host === undefined || host === "" || host.includes(","))
|
|
15
|
+
return REFUSED;
|
|
16
|
+
const { localAddress, localPort } = connection;
|
|
17
|
+
if (isLoopbackName(host, localPort)) {
|
|
18
|
+
if (localAddress === undefined || !isLoopbackAddress(localAddress))
|
|
19
|
+
return REFUSED;
|
|
20
|
+
if (!request.forwarded())
|
|
21
|
+
return {
|
|
22
|
+
provenance: LOCAL,
|
|
23
|
+
origin: `http://${host}`,
|
|
24
|
+
framer: undefined,
|
|
25
|
+
allowed: undefined,
|
|
26
|
+
relay: undefined,
|
|
27
|
+
};
|
|
28
|
+
return relayed(request, relays);
|
|
29
|
+
}
|
|
30
|
+
if (!hosts.has(host))
|
|
31
|
+
return REFUSED;
|
|
32
|
+
return {
|
|
33
|
+
provenance: { kind: "remote", host },
|
|
34
|
+
origin: `https://${host}`,
|
|
35
|
+
framer: undefined,
|
|
36
|
+
allowed: host,
|
|
37
|
+
relay: undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Whether `admission` refused its request. */
|
|
41
|
+
export function refused(admission) {
|
|
42
|
+
return "kind" in admission;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Whether a request is another site's (Fetch Metadata, p2's rule): `Sec-Fetch-Site` neither `same-origin` nor `none`,
|
|
46
|
+
* or a frame or embed not from this origin. A request without the headers (a script, the TUI) is not.
|
|
47
|
+
*/
|
|
48
|
+
export function isForeign(headers) {
|
|
49
|
+
const site = headers.header("sec-fetch-site");
|
|
50
|
+
if (site !== null && site !== "same-origin" && site !== "none")
|
|
51
|
+
return true;
|
|
52
|
+
return site !== "same-origin" && FRAMES.has(headers.header("sec-fetch-dest") ?? "");
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Whether a foreign request is a top-level navigation (a link followed to a page): `GET`, `navigate`, a `document` (or
|
|
56
|
+
* `empty`: Chrome on Android launching an installed app).
|
|
57
|
+
*/
|
|
58
|
+
export function isNavigation(method, headers) {
|
|
59
|
+
const dest = headers.header("sec-fetch-dest");
|
|
60
|
+
return (method === "GET" && headers.header("sec-fetch-mode") === "navigate" && (dest === "document" || dest === "empty"));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Whether `headers`' `Origin` is acceptable for a request whose own origin is `origin`: absent or equal, and for an
|
|
64
|
+
* unsafe method from a browser (one sending Fetch Metadata) present and equal.
|
|
65
|
+
*/
|
|
66
|
+
export function originAccepted(method, headers, origin) {
|
|
67
|
+
const sent = headers.header("origin");
|
|
68
|
+
if (sent !== null)
|
|
69
|
+
return sent === origin;
|
|
70
|
+
return SAFE.has(method) || headers.header("sec-fetch-site") === null;
|
|
71
|
+
}
|
|
72
|
+
const REFUSED = { kind: "refused" };
|
|
73
|
+
const LOCAL = { kind: "local" };
|
|
74
|
+
const LOOPBACK_NAMES = ["127.0.0.1", "localhost", "[::1]"];
|
|
75
|
+
/** Whether `host` (lowercased) names this server on loopback with `port` (without it on port 80). */
|
|
76
|
+
function isLoopbackName(host, port) {
|
|
77
|
+
if (port === undefined)
|
|
78
|
+
return false;
|
|
79
|
+
for (const name of LOOPBACK_NAMES) {
|
|
80
|
+
if (host === `${name}:${port}`)
|
|
81
|
+
return true;
|
|
82
|
+
if (port === 80 && host === name)
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
/** Whether `address` is a loopback address: 127.0.0.0/8, ::1, or 127.x mapped into IPv6. */
|
|
88
|
+
function isLoopbackAddress(address) {
|
|
89
|
+
return address === "::1" || address.startsWith("127.") || address.startsWith("::ffff:127.");
|
|
90
|
+
}
|
|
91
|
+
/** A forwarded request on loopback: admitted as relayed when a relay verifies it, else refused. */
|
|
92
|
+
function relayed(request, relays) {
|
|
93
|
+
for (const relay of relays) {
|
|
94
|
+
let verified;
|
|
95
|
+
try {
|
|
96
|
+
verified = relay.verify(request.request());
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return { kind: "refused", failed: { relay: relay.name, error } };
|
|
100
|
+
}
|
|
101
|
+
if (verified === undefined)
|
|
102
|
+
continue;
|
|
103
|
+
// Its origins reach the CSP: each must be one origin and nothing else (Fable's recheck N2).
|
|
104
|
+
for (const origin of [verified.origin, verified.framer]) {
|
|
105
|
+
if (origin === undefined || isOrigin(origin))
|
|
106
|
+
continue;
|
|
107
|
+
const error = new Error(`relay ${relay.name}: ${JSON.stringify(origin)} is no origin`);
|
|
108
|
+
return { kind: "refused", failed: { relay: relay.name, error } };
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
provenance: { kind: "relayed", relay: relay.name, origin: verified.origin },
|
|
112
|
+
origin: verified.origin,
|
|
113
|
+
framer: verified.framer,
|
|
114
|
+
allowed: undefined,
|
|
115
|
+
relay,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return REFUSED;
|
|
119
|
+
}
|
|
120
|
+
/** Whether `text` is exactly an origin (`https://host[:port]`): what the URL parser serializes it to. */
|
|
121
|
+
function isOrigin(text) {
|
|
122
|
+
try {
|
|
123
|
+
const url = new URL(text);
|
|
124
|
+
return (url.protocol === "https:" || url.protocol === "http:") && url.origin === text;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** The `Sec-Fetch-Dest` of a frame or an embed. */
|
|
131
|
+
const FRAMES = new Set(["iframe", "frame", "embed", "object", "fencedframe"]);
|
|
132
|
+
/** The methods that change nothing. */
|
|
133
|
+
const SAFE = new Set(["GET", "HEAD", "OPTIONS"]);
|
|
134
|
+
//# sourceMappingURL=admission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../../../src/next-node/http/admission.ts"],"names":[],"mappings":"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","sourcesContent":["// Admission (slice 10 §2, R4; decision \"The HTTP component's security baseline\" (1)-(3), \"Relays\"): where a request\n// comes from, decided before anything else. Local only when the connection arrived on a loopback address, its `Host`\n// is a loopback name with the listening port, and it carries no forwarded header; a forwarded request on loopback only\n// when a contributed relay verifies it; otherwise only through an allowed host (https); else refused. Foreign requests\n// (another site's, by Fetch Metadata) and a foreign `Origin` are classified here; the handler applies them per route.\n\nimport type { Incoming } from \"./incoming.ts\";\nimport type { HttpRelay } from \"./router.ts\";\n\n/** Where an admitted request came from. */\nexport type Provenance =\n\t| { readonly kind: \"local\" }\n\t| { readonly kind: \"remote\"; readonly host: string }\n\t| { readonly kind: \"relayed\"; readonly relay: string; readonly origin: string };\n\n/** The connection a request arrived on, as its listener knows it (a mounted handler passes what it has). */\nexport type Connection = {\n\treadonly localAddress?: string;\n\treadonly localPort?: number;\n\treadonly remoteAddress?: string;\n};\n\n/** An admitted request: its provenance, its own origin, the origin allowed to frame it (a relay's), how it came. */\nexport type Admitted = {\n\treadonly provenance: Provenance;\n\treadonly origin: string;\n\treadonly framer: string | undefined;\n\t/** The allowed host it came through: its connections end when that host leaves. */\n\treadonly allowed: string | undefined;\n\t/** The relay that verified it: its connections end when that relay leaves. */\n\treadonly relay: HttpRelay | undefined;\n};\n\n/** What admission refuses, and the relay hook that threw (reported by the caller). */\nexport type Refused = {\n\treadonly kind: \"refused\";\n\treadonly failed?: { readonly relay: string; readonly error: unknown };\n};\n\n/**\n * Admits `request` arriving on `connection` with the allowed `hosts` and contributed `relays`, or refuses it (403):\n * no or several `Host`s, a host neither loopback nor allowed, a loopback `Host` on another connection, forwarded\n * headers no relay verifies.\n */\nexport function admit(\n\trequest: Incoming,\n\tconnection: Connection,\n\thosts: ReadonlySet<string>,\n\trelays: readonly HttpRelay[],\n): Admitted | Refused {\n\tconst host = request.header(\"host\")?.toLowerCase();\n\t// Several `Host` headers arrive joined with commas.\n\tif (host === undefined || host === \"\" || host.includes(\",\")) return REFUSED;\n\tconst { localAddress, localPort } = connection;\n\tif (isLoopbackName(host, localPort)) {\n\t\tif (localAddress === undefined || !isLoopbackAddress(localAddress)) return REFUSED;\n\t\tif (!request.forwarded())\n\t\t\treturn {\n\t\t\t\tprovenance: LOCAL,\n\t\t\t\torigin: `http://${host}`,\n\t\t\t\tframer: undefined,\n\t\t\t\tallowed: undefined,\n\t\t\t\trelay: undefined,\n\t\t\t};\n\t\treturn relayed(request, relays);\n\t}\n\tif (!hosts.has(host)) return REFUSED;\n\treturn {\n\t\tprovenance: { kind: \"remote\", host },\n\t\torigin: `https://${host}`,\n\t\tframer: undefined,\n\t\tallowed: host,\n\t\trelay: undefined,\n\t};\n}\n\n/** What the Fetch Metadata and `Origin` checks read: a request's headers by name. */\nexport type HeaderSource = Pick<Incoming, \"header\">;\n\n/** Whether `admission` refused its request. */\nexport function refused(admission: Admitted | Refused): admission is Refused {\n\treturn \"kind\" in admission;\n}\n\n/**\n * Whether a request is another site's (Fetch Metadata, p2's rule): `Sec-Fetch-Site` neither `same-origin` nor `none`,\n * or a frame or embed not from this origin. A request without the headers (a script, the TUI) is not.\n */\nexport function isForeign(headers: HeaderSource): boolean {\n\tconst site = headers.header(\"sec-fetch-site\");\n\tif (site !== null && site !== \"same-origin\" && site !== \"none\") return true;\n\treturn site !== \"same-origin\" && FRAMES.has(headers.header(\"sec-fetch-dest\") ?? \"\");\n}\n\n/**\n * Whether a foreign request is a top-level navigation (a link followed to a page): `GET`, `navigate`, a `document` (or\n * `empty`: Chrome on Android launching an installed app).\n */\nexport function isNavigation(method: string, headers: HeaderSource): boolean {\n\tconst dest = headers.header(\"sec-fetch-dest\");\n\treturn (\n\t\tmethod === \"GET\" && headers.header(\"sec-fetch-mode\") === \"navigate\" && (dest === \"document\" || dest === \"empty\")\n\t);\n}\n\n/**\n * Whether `headers`' `Origin` is acceptable for a request whose own origin is `origin`: absent or equal, and for an\n * unsafe method from a browser (one sending Fetch Metadata) present and equal.\n */\nexport function originAccepted(method: string, headers: HeaderSource, origin: string): boolean {\n\tconst sent = headers.header(\"origin\");\n\tif (sent !== null) return sent === origin;\n\treturn SAFE.has(method) || headers.header(\"sec-fetch-site\") === null;\n}\n\nconst REFUSED: Refused = { kind: \"refused\" };\n\nconst LOCAL: Provenance = { kind: \"local\" };\n\nconst LOOPBACK_NAMES = [\"127.0.0.1\", \"localhost\", \"[::1]\"];\n\n/** Whether `host` (lowercased) names this server on loopback with `port` (without it on port 80). */\nfunction isLoopbackName(host: string, port: number | undefined): boolean {\n\tif (port === undefined) return false;\n\tfor (const name of LOOPBACK_NAMES) {\n\t\tif (host === `${name}:${port}`) return true;\n\t\tif (port === 80 && host === name) return true;\n\t}\n\treturn false;\n}\n\n/** Whether `address` is a loopback address: 127.0.0.0/8, ::1, or 127.x mapped into IPv6. */\nfunction isLoopbackAddress(address: string): boolean {\n\treturn address === \"::1\" || address.startsWith(\"127.\") || address.startsWith(\"::ffff:127.\");\n}\n\n/** A forwarded request on loopback: admitted as relayed when a relay verifies it, else refused. */\nfunction relayed(request: Incoming, relays: readonly HttpRelay[]): Admitted | Refused {\n\tfor (const relay of relays) {\n\t\tlet verified: ReturnType<HttpRelay[\"verify\"]>;\n\t\ttry {\n\t\t\tverified = relay.verify(request.request());\n\t\t} catch (error) {\n\t\t\treturn { kind: \"refused\", failed: { relay: relay.name, error } };\n\t\t}\n\t\tif (verified === undefined) continue;\n\t\t// Its origins reach the CSP: each must be one origin and nothing else (Fable's recheck N2).\n\t\tfor (const origin of [verified.origin, verified.framer]) {\n\t\t\tif (origin === undefined || isOrigin(origin)) continue;\n\t\t\tconst error = new Error(`relay ${relay.name}: ${JSON.stringify(origin)} is no origin`);\n\t\t\treturn { kind: \"refused\", failed: { relay: relay.name, error } };\n\t\t}\n\t\treturn {\n\t\t\tprovenance: { kind: \"relayed\", relay: relay.name, origin: verified.origin },\n\t\t\torigin: verified.origin,\n\t\t\tframer: verified.framer,\n\t\t\tallowed: undefined,\n\t\t\trelay,\n\t\t};\n\t}\n\treturn REFUSED;\n}\n\n/** Whether `text` is exactly an origin (`https://host[:port]`): what the URL parser serializes it to. */\nfunction isOrigin(text: string): boolean {\n\ttry {\n\t\tconst url = new URL(text);\n\t\treturn (url.protocol === \"https:\" || url.protocol === \"http:\") && url.origin === text;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/** The `Sec-Fetch-Dest` of a frame or an embed. */\nconst FRAMES: ReadonlySet<string> = new Set([\"iframe\", \"frame\", \"embed\", \"object\", \"fencedframe\"]);\n\n/** The methods that change nothing. */\nconst SAFE: ReadonlySet<string> = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Context } from "../../context/index.ts";
|
|
2
|
+
import type { Principal } from "../../next/data/index.ts";
|
|
3
|
+
import { type RegistryTable } from "../../next/registries/index.ts";
|
|
4
|
+
import type { HttpRequest } from "./request.ts";
|
|
5
|
+
/** Who `request` is, or `undefined` (anonymous here, maybe another authenticator knows). */
|
|
6
|
+
export type Authenticator = (request: HttpRequest, context: Context) => Principal | undefined | Promise<Principal | undefined>;
|
|
7
|
+
/** An authenticator with its plugin, as the component asks it. */
|
|
8
|
+
export type AuthenticatorEntry = {
|
|
9
|
+
readonly plugin: string;
|
|
10
|
+
readonly authenticate: Authenticator;
|
|
11
|
+
};
|
|
12
|
+
/** The registry of authenticators (served by `http.facet`). */
|
|
13
|
+
export declare const Authenticators: import("../../next/registries/registry.ts").Registry<Authenticator, readonly AuthenticatorEntry[]>;
|
|
14
|
+
/** Composes `Authenticators`: every contribution in contributor order. */
|
|
15
|
+
export declare function composeAuthenticators(table: RegistryTable<Authenticator>): readonly AuthenticatorEntry[];
|
|
16
|
+
/**
|
|
17
|
+
* The principal of `request`: the first one an authenticator returns, in order; one that throws is reported through
|
|
18
|
+
* `failed` and skipped; none: `undefined` (anonymous). Once `context` is aborted no further authenticator starts.
|
|
19
|
+
*/
|
|
20
|
+
export declare function authenticate(authenticators: readonly AuthenticatorEntry[], request: HttpRequest, failed: (plugin: string, error: unknown) => void, context: Context): Promise<Principal | undefined>;
|
|
21
|
+
//# sourceMappingURL=authenticate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authenticate.d.ts","sourceRoot":"","sources":["../../../src/next-node/http/authenticate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GAAG,CAC3B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,OAAO,KACZ,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;AAE5D,kEAAkE;AAClE,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAA;CAAE,CAAC;AAEnG,+DAA+D;AAC/D,eAAO,MAAM,cAAc,oGAK1B,CAAC;AAEF,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,SAAS,kBAAkB,EAAE,CAExG;AAED;;;GAGG;AACH,wBAAsB,YAAY,CACjC,cAAc,EAAE,SAAS,kBAAkB,EAAE,EAC7C,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,EAChD,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAYhC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Who someone is (decision "The HTTP server is a native object", replacing the `authenticate` option): the registry
|
|
2
|
+
// `Authenticators`, one function per contributor, asked in contributor order (plugin name: an order with no meaning, so
|
|
3
|
+
// an app needing precedence between credentials contributes one authenticator that decides); the first principal
|
|
4
|
+
// returned wins, a throwing one is reported and skipped.
|
|
5
|
+
import { defineRegistry } from "../../next/registries/index.js";
|
|
6
|
+
/** The registry of authenticators (served by `http.facet`). */
|
|
7
|
+
export const Authenticators = defineRegistry("chord.http.authenticators", {
|
|
8
|
+
version: 1,
|
|
9
|
+
});
|
|
10
|
+
/** Composes `Authenticators`: every contribution in contributor order. */
|
|
11
|
+
export function composeAuthenticators(table) {
|
|
12
|
+
return table.map(({ plugin, value }) => ({ plugin, authenticate: value }));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The principal of `request`: the first one an authenticator returns, in order; one that throws is reported through
|
|
16
|
+
* `failed` and skipped; none: `undefined` (anonymous). Once `context` is aborted no further authenticator starts.
|
|
17
|
+
*/
|
|
18
|
+
export async function authenticate(authenticators, request, failed, context) {
|
|
19
|
+
for (const { plugin, authenticate } of authenticators) {
|
|
20
|
+
// A request gone or sealed starts no new work (Sol's second recheck C).
|
|
21
|
+
if (context.abortSignal?.aborted)
|
|
22
|
+
return undefined;
|
|
23
|
+
try {
|
|
24
|
+
const principal = await authenticate(request, context);
|
|
25
|
+
if (principal !== undefined)
|
|
26
|
+
return principal;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
failed(plugin, error);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=authenticate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../../../src/next-node/http/authenticate.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,wHAAwH;AACxH,iHAAiH;AACjH,yDAAyD;AAIzD,OAAO,EAAE,cAAc,EAAsB,MAAM,gCAAgC,CAAC;AAYpF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAC3C,2BAA2B,EAC3B;IACC,OAAO,EAAE,CAAC;CACV,CACD,CAAC;AAEF,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB,CAAC,KAAmC;IACxE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,cAA6C,EAC7C,OAAoB,EACpB,MAAgD,EAChD,OAAgB;IAEhB,KAAK,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,cAAc,EAAE,CAAC;QACvD,wEAAwE;QACxE,IAAI,OAAO,CAAC,WAAW,EAAE,OAAO;YAAE,OAAO,SAAS,CAAC;QACnD,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACvD,IAAI,SAAS,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC","sourcesContent":["// Who someone is (decision \"The HTTP server is a native object\", replacing the `authenticate` option): the registry\n// `Authenticators`, one function per contributor, asked in contributor order (plugin name: an order with no meaning, so\n// an app needing precedence between credentials contributes one authenticator that decides); the first principal\n// returned wins, a throwing one is reported and skipped.\n\nimport type { Context } from \"../../context/index.ts\";\nimport type { Principal } from \"../../next/data/index.ts\";\nimport { defineRegistry, type RegistryTable } from \"../../next/registries/index.ts\";\nimport type { HttpRequest } from \"./request.ts\";\n\n/** Who `request` is, or `undefined` (anonymous here, maybe another authenticator knows). */\nexport type Authenticator = (\n\trequest: HttpRequest,\n\tcontext: Context,\n) => Principal | undefined | Promise<Principal | undefined>;\n\n/** An authenticator with its plugin, as the component asks it. */\nexport type AuthenticatorEntry = { readonly plugin: string; readonly authenticate: Authenticator };\n\n/** The registry of authenticators (served by `http.facet`). */\nexport const Authenticators = defineRegistry<Authenticator, readonly AuthenticatorEntry[]>(\n\t\"chord.http.authenticators\",\n\t{\n\t\tversion: 1,\n\t},\n);\n\n/** Composes `Authenticators`: every contribution in contributor order. */\nexport function composeAuthenticators(table: RegistryTable<Authenticator>): readonly AuthenticatorEntry[] {\n\treturn table.map(({ plugin, value }) => ({ plugin, authenticate: value }));\n}\n\n/**\n * The principal of `request`: the first one an authenticator returns, in order; one that throws is reported through\n * `failed` and skipped; none: `undefined` (anonymous). Once `context` is aborted no further authenticator starts.\n */\nexport async function authenticate(\n\tauthenticators: readonly AuthenticatorEntry[],\n\trequest: HttpRequest,\n\tfailed: (plugin: string, error: unknown) => void,\n\tcontext: Context,\n): Promise<Principal | undefined> {\n\tfor (const { plugin, authenticate } of authenticators) {\n\t\t// A request gone or sealed starts no new work (Sol's second recheck C).\n\t\tif (context.abortSignal?.aborted) return undefined;\n\t\ttry {\n\t\t\tconst principal = await authenticate(request, context);\n\t\t\tif (principal !== undefined) return principal;\n\t\t} catch (error) {\n\t\t\tfailed(plugin, error);\n\t\t}\n\t}\n\treturn undefined;\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { HttpRequest } from "./request.ts";
|
|
2
|
+
/** What `cookie` takes besides the name and the value. */
|
|
3
|
+
export type CookieOptions = {
|
|
4
|
+
/** The key it is signed with (HMAC-SHA256). */
|
|
5
|
+
readonly secret: string;
|
|
6
|
+
/** The request it answers: a remote one gets `Secure`. */
|
|
7
|
+
readonly request: HttpRequest;
|
|
8
|
+
/** `Strict` by default; `Lax` lets a top-level navigation from another site carry it. */
|
|
9
|
+
readonly sameSite?: "Strict" | "Lax";
|
|
10
|
+
/** Seconds until it expires; none: a session cookie. */
|
|
11
|
+
readonly maxAge?: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A signed `Set-Cookie` value for `name` and `value` (put it in a response's `headers`, `Set-Cookie`). With `maxAge`
|
|
15
|
+
* its expiry is signed with it: a copy read back later is refused (Opus's recheck R3); without, it holds until the
|
|
16
|
+
* secret changes.
|
|
17
|
+
*/
|
|
18
|
+
export declare function cookie(name: string, value: string, options: CookieOptions): string;
|
|
19
|
+
/**
|
|
20
|
+
* The value of cookie `name` on `request` when its signature with `secret` holds and its signed expiry has not passed;
|
|
21
|
+
* `undefined` otherwise.
|
|
22
|
+
*/
|
|
23
|
+
export declare function readCookie(request: HttpRequest, name: string, secret: string): string | undefined;
|
|
24
|
+
//# sourceMappingURL=cookies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../../src/next-node/http/cookies.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,0DAA0D;AAC1D,MAAM,MAAM,aAAa,GAAG;IAC3B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,yFAAyF;IACzF,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACrC,wDAAwD;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAalF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAsBjG"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Cookies (decision "The HTTP component's security baseline" (5)): `cookie` makes a signed `Set-Cookie` value with the
|
|
2
|
+
// safe defaults (`HttpOnly`, `Path=/`, `SameSite=Strict`, `Secure` on a remote origin), `readCookie` reads one back,
|
|
3
|
+
// its signature checked in constant time.
|
|
4
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
5
|
+
/**
|
|
6
|
+
* A signed `Set-Cookie` value for `name` and `value` (put it in a response's `headers`, `Set-Cookie`). With `maxAge`
|
|
7
|
+
* its expiry is signed with it: a copy read back later is refused (Opus's recheck R3); without, it holds until the
|
|
8
|
+
* secret changes.
|
|
9
|
+
*/
|
|
10
|
+
export function cookie(name, value, options) {
|
|
11
|
+
const encoded = encodeURIComponent(value);
|
|
12
|
+
const expires = options.maxAge === undefined ? "" : String(Math.floor(Date.now() / 1000 + options.maxAge));
|
|
13
|
+
const payload = `${encoded}.${expires}`;
|
|
14
|
+
const parts = [
|
|
15
|
+
`${name}=${payload}.${signature(name, payload, options.secret)}`,
|
|
16
|
+
"HttpOnly",
|
|
17
|
+
"Path=/",
|
|
18
|
+
`SameSite=${options.sameSite ?? "Strict"}`,
|
|
19
|
+
];
|
|
20
|
+
if (options.request.provenance.kind !== "local")
|
|
21
|
+
parts.push("Secure");
|
|
22
|
+
if (options.maxAge !== undefined)
|
|
23
|
+
parts.push(`Max-Age=${Math.floor(options.maxAge)}`);
|
|
24
|
+
return parts.join("; ");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The value of cookie `name` on `request` when its signature with `secret` holds and its signed expiry has not passed;
|
|
28
|
+
* `undefined` otherwise.
|
|
29
|
+
*/
|
|
30
|
+
export function readCookie(request, name, secret) {
|
|
31
|
+
for (const pair of (request.headers.get("cookie") ?? "").split(";")) {
|
|
32
|
+
const equals = pair.indexOf("=");
|
|
33
|
+
if (equals < 0 || pair.slice(0, equals).trim() !== name)
|
|
34
|
+
continue;
|
|
35
|
+
const signed = pair.slice(equals + 1).trim();
|
|
36
|
+
// From the right: the value may hold dots, the expiry and the signature never do.
|
|
37
|
+
const dot = signed.lastIndexOf(".");
|
|
38
|
+
const payload = signed.slice(0, dot);
|
|
39
|
+
const expiresAt = payload.lastIndexOf(".");
|
|
40
|
+
if (dot < 0 || expiresAt < 0)
|
|
41
|
+
return undefined;
|
|
42
|
+
const given = Buffer.from(signed.slice(dot + 1));
|
|
43
|
+
const expected = Buffer.from(signature(name, payload, secret));
|
|
44
|
+
if (given.length !== expected.length || !timingSafeEqual(given, expected))
|
|
45
|
+
return undefined;
|
|
46
|
+
const expires = payload.slice(expiresAt + 1);
|
|
47
|
+
if (expires !== "" && Number(expires) * 1000 <= Date.now())
|
|
48
|
+
return undefined;
|
|
49
|
+
try {
|
|
50
|
+
return decodeURIComponent(payload.slice(0, expiresAt));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
/** The signature of a cookie's name and payload (its encoded value and expiry). */
|
|
59
|
+
function signature(name, payload, secret) {
|
|
60
|
+
return createHmac("sha256", secret).update(`${name}=${payload}`).digest("base64url");
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=cookies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../../src/next-node/http/cookies.ts"],"names":[],"mappings":"AAAA,uHAAuH;AACvH,qHAAqH;AACrH,0CAA0C;AAE1C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAe1D;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,KAAa,EAAE,OAAsB;IACzE,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3G,MAAM,OAAO,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG;QACb,GAAG,IAAI,IAAI,OAAO,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE;QAChE,UAAU;QACV,QAAQ;QACR,YAAY,OAAO,CAAC,QAAQ,IAAI,QAAQ,EAAE;KAC1C,CAAC;IACF,IAAI,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,KAAK,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAoB,EAAE,IAAY,EAAE,MAAc;IAC5E,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI;YAAE,SAAS;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,kFAAkF;QAClF,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,GAAG,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/D,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5F,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC7C,IAAI,OAAO,KAAK,EAAE,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE;YAAE,OAAO,SAAS,CAAC;QAC7E,IAAI,CAAC;YACJ,OAAO,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,SAAS,CAAC;QAClB,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,mFAAmF;AACnF,SAAS,SAAS,CAAC,IAAY,EAAE,OAAe,EAAE,MAAc;IAC/D,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACtF,CAAC","sourcesContent":["// Cookies (decision \"The HTTP component's security baseline\" (5)): `cookie` makes a signed `Set-Cookie` value with the\n// safe defaults (`HttpOnly`, `Path=/`, `SameSite=Strict`, `Secure` on a remote origin), `readCookie` reads one back,\n// its signature checked in constant time.\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport type { HttpRequest } from \"./request.ts\";\n\n/** What `cookie` takes besides the name and the value. */\nexport type CookieOptions = {\n\t/** The key it is signed with (HMAC-SHA256). */\n\treadonly secret: string;\n\t/** The request it answers: a remote one gets `Secure`. */\n\treadonly request: HttpRequest;\n\t/** `Strict` by default; `Lax` lets a top-level navigation from another site carry it. */\n\treadonly sameSite?: \"Strict\" | \"Lax\";\n\t/** Seconds until it expires; none: a session cookie. */\n\treadonly maxAge?: number;\n};\n\n/**\n * A signed `Set-Cookie` value for `name` and `value` (put it in a response's `headers`, `Set-Cookie`). With `maxAge`\n * its expiry is signed with it: a copy read back later is refused (Opus's recheck R3); without, it holds until the\n * secret changes.\n */\nexport function cookie(name: string, value: string, options: CookieOptions): string {\n\tconst encoded = encodeURIComponent(value);\n\tconst expires = options.maxAge === undefined ? \"\" : String(Math.floor(Date.now() / 1000 + options.maxAge));\n\tconst payload = `${encoded}.${expires}`;\n\tconst parts = [\n\t\t`${name}=${payload}.${signature(name, payload, options.secret)}`,\n\t\t\"HttpOnly\",\n\t\t\"Path=/\",\n\t\t`SameSite=${options.sameSite ?? \"Strict\"}`,\n\t];\n\tif (options.request.provenance.kind !== \"local\") parts.push(\"Secure\");\n\tif (options.maxAge !== undefined) parts.push(`Max-Age=${Math.floor(options.maxAge)}`);\n\treturn parts.join(\"; \");\n}\n\n/**\n * The value of cookie `name` on `request` when its signature with `secret` holds and its signed expiry has not passed;\n * `undefined` otherwise.\n */\nexport function readCookie(request: HttpRequest, name: string, secret: string): string | undefined {\n\tfor (const pair of (request.headers.get(\"cookie\") ?? \"\").split(\";\")) {\n\t\tconst equals = pair.indexOf(\"=\");\n\t\tif (equals < 0 || pair.slice(0, equals).trim() !== name) continue;\n\t\tconst signed = pair.slice(equals + 1).trim();\n\t\t// From the right: the value may hold dots, the expiry and the signature never do.\n\t\tconst dot = signed.lastIndexOf(\".\");\n\t\tconst payload = signed.slice(0, dot);\n\t\tconst expiresAt = payload.lastIndexOf(\".\");\n\t\tif (dot < 0 || expiresAt < 0) return undefined;\n\t\tconst given = Buffer.from(signed.slice(dot + 1));\n\t\tconst expected = Buffer.from(signature(name, payload, secret));\n\t\tif (given.length !== expected.length || !timingSafeEqual(given, expected)) return undefined;\n\t\tconst expires = payload.slice(expiresAt + 1);\n\t\tif (expires !== \"\" && Number(expires) * 1000 <= Date.now()) return undefined;\n\t\ttry {\n\t\t\treturn decodeURIComponent(payload.slice(0, expiresAt));\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** The signature of a cookie's name and payload (its encoded value and expiry). */\nfunction signature(name: string, payload: string, secret: string): string {\n\treturn createHmac(\"sha256\", secret).update(`${name}=${payload}`).digest(\"base64url\");\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { HttpResponse } from "./response.ts";
|
|
2
|
+
/** What `fileResponse` takes besides the path. */
|
|
3
|
+
export type FileResponseOptions = {
|
|
4
|
+
/** Saved under this name. */
|
|
5
|
+
readonly download?: string;
|
|
6
|
+
/** Shown in the browser instead of saved (an image, a video), with a `sandbox` CSP. */
|
|
7
|
+
readonly inline?: true;
|
|
8
|
+
/**
|
|
9
|
+
* The directory the file must lie in once its symbolic links are resolved: one outside it (a link out) is refused
|
|
10
|
+
* 403. Without it the path is trusted (a plugin's own file).
|
|
11
|
+
*/
|
|
12
|
+
readonly root?: string;
|
|
13
|
+
/** Whether a single range is answered 206 (audio and video seek with it). */
|
|
14
|
+
readonly ranges?: boolean;
|
|
15
|
+
/** The type; by default from the extension (text, images, audio, video), else `application/octet-stream`. */
|
|
16
|
+
readonly mime?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The file at `path` as a `bytes` response; `HttpFailure` 404 for a missing one (anyone may ask for one: no failure
|
|
20
|
+
* of the route, Fable's recheck N1), 403 for one outside `root`; throws what else `stat` throws.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fileResponse(given: string, options?: FileResponseOptions): Promise<HttpResponse>;
|
|
23
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/next-node/http/file.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,kDAAkD;AAClD,MAAM,MAAM,mBAAmB,GAAG;IACjC,6BAA6B;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,uFAAuF;IACvF,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,6GAA6G;IAC7G,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC,CA6B1G"}
|