@haverstack/core 0.8.0 → 0.10.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/README.md +30 -14
- package/dist/access.d.ts +20 -7
- package/dist/access.d.ts.map +1 -1
- package/dist/access.js +37 -16
- package/dist/access.js.map +1 -1
- package/dist/adapter-entry.d.ts +12 -0
- package/dist/adapter-entry.d.ts.map +1 -0
- package/dist/adapter-entry.js +11 -0
- package/dist/adapter-entry.js.map +1 -0
- package/dist/attachment-download.d.ts +75 -0
- package/dist/attachment-download.d.ts.map +1 -0
- package/dist/attachment-download.js +128 -0
- package/dist/attachment-download.js.map +1 -0
- package/dist/auth.d.ts +88 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +145 -0
- package/dist/auth.js.map +1 -0
- package/dist/combine.d.ts.map +1 -1
- package/dist/combine.js +20 -3
- package/dist/combine.js.map +1 -1
- package/dist/did-entry.d.ts +12 -0
- package/dist/did-entry.d.ts.map +1 -0
- package/dist/did-entry.js +16 -0
- package/dist/did-entry.js.map +1 -0
- package/dist/did.d.ts +51 -0
- package/dist/did.d.ts.map +1 -0
- package/dist/did.js +153 -0
- package/dist/did.js.map +1 -0
- package/dist/id.d.ts +18 -6
- package/dist/id.d.ts.map +1 -1
- package/dist/id.js +39 -10
- package/dist/id.js.map +1 -1
- package/dist/index.d.ts +15 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/dist/merge.d.ts +11 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +38 -0
- package/dist/merge.js.map +1 -0
- package/dist/schema.d.ts +31 -9
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +134 -11
- package/dist/schema.js.map +1 -1
- package/dist/stack.d.ts +850 -152
- package/dist/stack.d.ts.map +1 -1
- package/dist/stack.js +2017 -365
- package/dist/stack.js.map +1 -1
- package/dist/testing.d.ts +85 -23
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +261 -19
- package/dist/testing.js.map +1 -1
- package/dist/types.d.ts +281 -31
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts +26 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +51 -1
- package/dist/validate.js.map +1 -1
- package/dist/wire-entry.d.ts +17 -0
- package/dist/wire-entry.d.ts.map +1 -0
- package/dist/wire-entry.js +24 -0
- package/dist/wire-entry.js.map +1 -0
- package/package.json +13 -1
package/dist/auth.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack — Authentication handshake primitives
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* The challenge–response handshake proves a client holds the key behind a
|
|
5
|
+
* DID, so a server can issue it a bearer token without an out-of-band
|
|
6
|
+
* secret handoff. See docs/spec/wire-format.md § Authentication.
|
|
7
|
+
*
|
|
8
|
+
* What lives here is the half both sides must agree on byte for byte: the
|
|
9
|
+
* payload that gets signed. A client builds it to sign; a server builds it
|
|
10
|
+
* to verify. Two implementations of "the same string" would diverge on the
|
|
11
|
+
* first ambiguity, and the failure mode is a signature that verifies
|
|
12
|
+
* against a payload nobody meant — so there is one constructor, exported,
|
|
13
|
+
* the same way the attachment content-type policy is shared rather than
|
|
14
|
+
* re-derived.
|
|
15
|
+
*
|
|
16
|
+
* Core verifies signatures; it does not run a server. Nonce storage,
|
|
17
|
+
* single-use enforcement and token issuance are the server's.
|
|
18
|
+
*/
|
|
19
|
+
import { isValidDid, signWithDid, verifyDidSignature } from './did.js';
|
|
20
|
+
// -------------------------------------------------------
|
|
21
|
+
// Errors
|
|
22
|
+
// -------------------------------------------------------
|
|
23
|
+
/**
|
|
24
|
+
* Malformed input to a handshake primitive — a bad origin, DID, or nonce,
|
|
25
|
+
* caught locally before anything is signed or verified. Outside the
|
|
26
|
+
* StackError hierarchy, like InvalidDidError: no Stack operation has begun,
|
|
27
|
+
* so there is no wire code or status to carry (docs/spec/wire-format.md
|
|
28
|
+
* § The taxonomy root).
|
|
29
|
+
*/
|
|
30
|
+
export class InvalidAuthChallengeError extends Error {
|
|
31
|
+
constructor(message = '') {
|
|
32
|
+
super(message || 'Invalid authentication challenge.');
|
|
33
|
+
this.name = 'InvalidAuthChallengeError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// -------------------------------------------------------
|
|
37
|
+
// The signed payload
|
|
38
|
+
// -------------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* Domain-separation tag. Version it rather than the payload's shape: a
|
|
41
|
+
* future signing primitive picks its own tag, so no signature made for one
|
|
42
|
+
* purpose can ever verify as another.
|
|
43
|
+
*/
|
|
44
|
+
export const AUTH_PAYLOAD_LABEL = 'haverstack-auth-v1';
|
|
45
|
+
/**
|
|
46
|
+
* A server-issued nonce is opaque, but not arbitrary — it lands in a
|
|
47
|
+
* newline-delimited payload, so the charset is what keeps a nonce from
|
|
48
|
+
* spanning fields. base64url, hex and UUID all satisfy it.
|
|
49
|
+
*/
|
|
50
|
+
const NONCE_FORMAT = /^[A-Za-z0-9_-]+$/;
|
|
51
|
+
/**
|
|
52
|
+
* Reduce a URL to the origin form the payload uses: scheme, host and a
|
|
53
|
+
* non-default port. A client derives it from the URL it dialed; a server
|
|
54
|
+
* MUST derive it from its own configured public origin rather than from a
|
|
55
|
+
* request header, which a client controls.
|
|
56
|
+
*/
|
|
57
|
+
export const authOriginFromUrl = (url) => {
|
|
58
|
+
let parsed;
|
|
59
|
+
try {
|
|
60
|
+
parsed = new URL(url);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
throw new InvalidAuthChallengeError(`Not a valid URL: "${url}"`);
|
|
64
|
+
}
|
|
65
|
+
// Opaque origins ("null") come from schemes with no host to bind to —
|
|
66
|
+
// there is nothing for a signature to be scoped by.
|
|
67
|
+
if (parsed.origin === 'null') {
|
|
68
|
+
throw new InvalidAuthChallengeError(`URL has no origin to bind a signature to: "${url}"`);
|
|
69
|
+
}
|
|
70
|
+
return parsed.origin;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Build the exact bytes a client signs and a server verifies.
|
|
74
|
+
*
|
|
75
|
+
* The origin is in the payload because the nonce alone doesn't scope a
|
|
76
|
+
* signature to a server: one that a client connects to can fetch a
|
|
77
|
+
* challenge from the client's real stack, pass that nonce along, and
|
|
78
|
+
* redeem the returned signature as a token. Signing the origin the client
|
|
79
|
+
* believes it is talking to makes such a signature verify nowhere else.
|
|
80
|
+
*/
|
|
81
|
+
export const buildAuthChallengePayload = (challenge) => {
|
|
82
|
+
const origin = authOriginFromUrl(challenge.origin);
|
|
83
|
+
if (!isValidDid(challenge.did)) {
|
|
84
|
+
throw new InvalidAuthChallengeError(`Not a valid DID: "${challenge.did}"`);
|
|
85
|
+
}
|
|
86
|
+
if (!NONCE_FORMAT.test(challenge.nonce)) {
|
|
87
|
+
throw new InvalidAuthChallengeError('Nonce must be a non-empty string of unreserved base64url characters.');
|
|
88
|
+
}
|
|
89
|
+
return new TextEncoder().encode(`${AUTH_PAYLOAD_LABEL}\n${origin}\n${challenge.did}\n${challenge.nonce}`);
|
|
90
|
+
};
|
|
91
|
+
// -------------------------------------------------------
|
|
92
|
+
// Sign / verify
|
|
93
|
+
// -------------------------------------------------------
|
|
94
|
+
/** Sign a challenge with the private key behind its DID. */
|
|
95
|
+
export const signAuthChallenge = async (privateKey, challenge) => signWithDid(privateKey, buildAuthChallengePayload(challenge));
|
|
96
|
+
/**
|
|
97
|
+
* Verify a challenge signature. Answers only "this signature was made by
|
|
98
|
+
* the key behind this DID, for this origin and nonce" — whether the nonce
|
|
99
|
+
* was ever issued, is unexpired, and has not already been spent is the
|
|
100
|
+
* server's to track, and all three matter.
|
|
101
|
+
*/
|
|
102
|
+
export const verifyAuthChallenge = async (challenge, signature) => {
|
|
103
|
+
const payload = buildAuthChallengePayload(challenge);
|
|
104
|
+
try {
|
|
105
|
+
return await verifyDidSignature(challenge.did, signature, payload);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// A DID whose key can't be decoded verifies nothing — a false answer,
|
|
109
|
+
// not an exceptional one, since the caller asked whether it verifies.
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Build a credential from a keypair, for callers holding key material in
|
|
115
|
+
* process and wanting no ceremony. Anything else implements DidCredential
|
|
116
|
+
* directly.
|
|
117
|
+
*/
|
|
118
|
+
export const didCredentialFromKeypair = (keypair) => ({
|
|
119
|
+
did: keypair.did,
|
|
120
|
+
sign: (payload) => signWithDid(keypair.privateKey, payload),
|
|
121
|
+
});
|
|
122
|
+
// -------------------------------------------------------
|
|
123
|
+
// base64url — how a signature travels in JSON
|
|
124
|
+
// -------------------------------------------------------
|
|
125
|
+
export const base64urlEncode = (bytes) => {
|
|
126
|
+
let binary = '';
|
|
127
|
+
for (const byte of bytes)
|
|
128
|
+
binary += String.fromCharCode(byte);
|
|
129
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
130
|
+
};
|
|
131
|
+
export const base64urlDecode = (encoded) => {
|
|
132
|
+
if (!NONCE_FORMAT.test(encoded)) {
|
|
133
|
+
throw new InvalidAuthChallengeError('Not valid base64url.');
|
|
134
|
+
}
|
|
135
|
+
const padded = encoded.replace(/-/g, '+').replace(/_/g, '/');
|
|
136
|
+
let binary;
|
|
137
|
+
try {
|
|
138
|
+
binary = atob(padded);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
throw new InvalidAuthChallengeError('Not valid base64url.');
|
|
142
|
+
}
|
|
143
|
+
return Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/combine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combine.d.ts","sourceRoot":"","sources":["../src/combine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,gBAAgB,CAAC;CACxB,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"combine.d.ts","sourceRoot":"","sources":["../src/combine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,gBAAgB,CAAC;CACxB,GAAG,YAAY,CA8Df"}
|
package/dist/combine.js
CHANGED
|
@@ -18,20 +18,37 @@ export function combineAdapters(parts) {
|
|
|
18
18
|
},
|
|
19
19
|
createRecord: (r) => parts.record.createRecord(r),
|
|
20
20
|
getRecord: (id) => parts.record.getRecord(id),
|
|
21
|
-
|
|
21
|
+
patchContent: (id, patch, opts) => parts.record.patchContent(id, patch, opts),
|
|
22
22
|
deleteRecord: (id, opts) => parts.record.deleteRecord(id, opts),
|
|
23
|
+
undeleteRecord: (id, opts) => parts.record.undeleteRecord(id, opts),
|
|
23
24
|
queryRecords: (q) => parts.record.queryRecords(q),
|
|
24
|
-
associate: (id, assoc) => parts.record.associate(id, assoc),
|
|
25
|
-
dissociate: (id, assoc) => parts.record.dissociate(id, assoc),
|
|
25
|
+
associate: (id, assoc, opts) => parts.record.associate(id, assoc, opts),
|
|
26
|
+
dissociate: (id, assoc, opts) => parts.record.dissociate(id, assoc, opts),
|
|
27
|
+
setPermissions: (id, permissions, opts) => parts.record.setPermissions(id, permissions, opts),
|
|
26
28
|
getVersions: (id) => parts.record.getVersions(id),
|
|
27
29
|
getVersion: (id, v) => parts.record.getVersion(id, v),
|
|
28
30
|
saveVersion: (id, v) => parts.record.saveVersion(id, v),
|
|
31
|
+
restoreVersion: (id, v, opts) => parts.record.restoreVersion(id, v, opts),
|
|
32
|
+
commitMigration: (id, toTypeId, content, opts) => parts.record.commitMigration(id, toTypeId, content, opts),
|
|
29
33
|
saveType: (t) => parts.record.saveType(t),
|
|
30
34
|
getType: (id) => parts.record.getType(id),
|
|
31
35
|
listTypes: () => parts.record.listTypes(),
|
|
36
|
+
// Conditionally spread so an unimplemented optional capability stays
|
|
37
|
+
// absent on the combined adapter, rather than silently becoming
|
|
38
|
+
// "supported" via a wrapper that forwards to a missing method.
|
|
39
|
+
...(parts.record.deleteUnreferencedAttachmentRecords && {
|
|
40
|
+
deleteUnreferencedAttachmentRecords: (fileId, metadataTypeId) => parts.record.deleteUnreferencedAttachmentRecords(fileId, metadataTypeId),
|
|
41
|
+
}),
|
|
42
|
+
// StackAdapter.putAttachmentWithMetadata is deliberately never
|
|
43
|
+
// synthesized here: glued backends have no shared transaction to honor
|
|
44
|
+
// its atomicity promise (docs/spec/adapters.md § Interface split).
|
|
45
|
+
// Stack.putAttachment() falls back to bytes-then-create().
|
|
32
46
|
putAttachment: (data) => parts.blob.putAttachment(data),
|
|
33
47
|
getAttachment: (id) => parts.blob.getAttachment(id),
|
|
34
48
|
deleteAttachment: (id) => parts.blob.deleteAttachment(id),
|
|
49
|
+
...(parts.blob.listFiles && {
|
|
50
|
+
listFiles: () => parts.blob.listFiles(),
|
|
51
|
+
}),
|
|
35
52
|
async flush() {
|
|
36
53
|
await parts.record.flush?.();
|
|
37
54
|
await parts.blob.flush?.();
|
package/dist/combine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combine.js","sourceRoot":"","sources":["../src/combine.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAG/B;IACC,OAAO;QACL,IAAI,YAAY;YACd,OAAO,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;QACnC,CAAC;QACD,IAAI,aAAa;YACf,OAAO,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;QACpC,CAAC;QACD,IAAI,QAAQ;YACV,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC/B,CAAC;QAED,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QACjD,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,YAAY,EAAE,CAAC,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"combine.js","sourceRoot":"","sources":["../src/combine.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAG/B;IACC,OAAO;QACL,IAAI,YAAY;YACd,OAAO,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;QACnC,CAAC;QACD,IAAI,aAAa;YACf,OAAO,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;QACpC,CAAC;QACD,IAAI,QAAQ;YACV,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC/B,CAAC;QAED,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QACjD,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,YAAY,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC;QAC7E,YAAY,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC;QAC/D,cAAc,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC;QACnE,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QAEjD,SAAS,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC;QACvE,UAAU,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC;QACzE,cAAc,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC;QAE7F,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACjD,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;QACrD,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;QACvD,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC;QACzE,eAAe,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAC/C,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;QAE3D,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE;QAEzC,qEAAqE;QACrE,gEAAgE;QAChE,+DAA+D;QAC/D,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mCAAmC,IAAI;YACtD,mCAAmC,EAAE,CAAC,MAAc,EAAE,cAAsB,EAAE,EAAE,CAC9E,KAAK,CAAC,MAAM,CAAC,mCAAoC,CAAC,MAAM,EAAE,cAAc,CAAC;SAC5E,CAAC;QAEF,+DAA+D;QAC/D,uEAAuE;QACvE,mEAAmE;QACnE,2DAA2D;QAC3D,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;QACvD,aAAa,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACnD,gBAAgB,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI;YAC1B,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAU,EAAE;SACzC,CAAC;QAEF,KAAK,CAAC,KAAK;YACT,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;YAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAC7B,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;YAC7B,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @haverstack/core/did
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* Key generation, custody and signing for did:key — the mandatory-floor
|
|
5
|
+
* DID method (see docs/spec/identity.md). Audience: apps at first-run
|
|
6
|
+
* keygen and key custody, and protocol implementers verifying signatures.
|
|
7
|
+
*/
|
|
8
|
+
export { InvalidDidError, generateDidKeypair, verifyDidSignature } from './did.js';
|
|
9
|
+
export type { DidKeypair } from './did.js';
|
|
10
|
+
export { isValidDid } from './did.js';
|
|
11
|
+
export { signWithDid, exportDidPrivateKeyJwk, importDidPrivateKeyJwk } from './did.js';
|
|
12
|
+
//# sourceMappingURL=did-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did-entry.d.ts","sourceRoot":"","sources":["../src/did-entry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnF,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAKtC,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @haverstack/core/did
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* Key generation, custody and signing for did:key — the mandatory-floor
|
|
5
|
+
* DID method (see docs/spec/identity.md). Audience: apps at first-run
|
|
6
|
+
* keygen and key custody, and protocol implementers verifying signatures.
|
|
7
|
+
*/
|
|
8
|
+
export { InvalidDidError, generateDidKeypair, verifyDidSignature } from './did.js';
|
|
9
|
+
// No in-repo caller: haverstack/server#54 validates ENTITY_ID as a DID at
|
|
10
|
+
// server startup.
|
|
11
|
+
export { isValidDid } from './did.js';
|
|
12
|
+
// No in-repo caller: root README.md § Key custody documents
|
|
13
|
+
// exportDidPrivateKeyJwk() -> store -> importDidPrivateKeyJwk() ->
|
|
14
|
+
// signWithDid() as the key-custody journey an app follows.
|
|
15
|
+
export { signWithDid, exportDidPrivateKeyJwk, importDidPrivateKeyJwk } from './did.js';
|
|
16
|
+
//# sourceMappingURL=did-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did-entry.js","sourceRoot":"","sources":["../src/did-entry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAGnF,0EAA0E;AAC1E,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,4DAA4D;AAC5D,mEAAmE;AACnE,2DAA2D;AAC3D,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/did.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack — Decentralized Identifiers
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* entityId values are DID strings (see docs/spec/identity.md). did:key —
|
|
5
|
+
* an Ed25519 public key, multicodec + multibase(base58btc) encoded — is the
|
|
6
|
+
* mandatory floor: zero infrastructure, zero resolution, verifiable by
|
|
7
|
+
* anyone from the string alone. Other methods (did:web, did:plc, ...) are
|
|
8
|
+
* valid entityId values too, but this module only knows how to mint and
|
|
9
|
+
* verify did:key.
|
|
10
|
+
*
|
|
11
|
+
* Uses Web Crypto (crypto.subtle) exclusively — no dependency, works in
|
|
12
|
+
* Node (>=22.5, matching the rest of core's floor), browsers, and Deno.
|
|
13
|
+
*/
|
|
14
|
+
export declare class InvalidDidError extends Error {
|
|
15
|
+
constructor(message?: string);
|
|
16
|
+
}
|
|
17
|
+
export type DidKeypair = {
|
|
18
|
+
/** e.g. "did:key:z6Mk..." */
|
|
19
|
+
did: string;
|
|
20
|
+
publicKey: CryptoKey;
|
|
21
|
+
privateKey: CryptoKey;
|
|
22
|
+
};
|
|
23
|
+
/** Generate a fresh Ed25519 keypair and derive its did:key. */
|
|
24
|
+
export declare const generateDidKeypair: () => Promise<DidKeypair>;
|
|
25
|
+
/** Derive a did:key string from an Ed25519 CryptoKey. */
|
|
26
|
+
export declare const didFromPublicKey: (publicKey: CryptoKey) => Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Parse a did:key string and return its raw Ed25519 public key bytes, or
|
|
29
|
+
* null if it isn't a well-formed Ed25519 did:key (wrong prefix, bad base58,
|
|
30
|
+
* wrong multicodec, wrong length).
|
|
31
|
+
*/
|
|
32
|
+
export declare const parseDidKey: (did: string) => Uint8Array | null;
|
|
33
|
+
/** Whether a string is a well-formed Ed25519 did:key. */
|
|
34
|
+
export declare const isValidDidKey: (value: string) => boolean;
|
|
35
|
+
/** Import the Ed25519 public key encoded in a did:key, for verification. */
|
|
36
|
+
export declare const publicKeyFromDidKey: (did: string) => Promise<CryptoKey>;
|
|
37
|
+
/**
|
|
38
|
+
* Whether a string has the generic W3C DID Core syntax (did:<method>:<id>)
|
|
39
|
+
* — any method, not just did:key. Use isValidDidKey() to additionally
|
|
40
|
+
* require the did:key method and a well-formed Ed25519 key.
|
|
41
|
+
*/
|
|
42
|
+
export declare const isValidDid: (value: string) => boolean;
|
|
43
|
+
export declare const signWithDid: (privateKey: CryptoKey, data: Uint8Array) => Promise<Uint8Array>;
|
|
44
|
+
/**
|
|
45
|
+
* Verify a signature was produced by the private key behind a did:key.
|
|
46
|
+
* Requires no lookup — the public key is decoded from the DID itself.
|
|
47
|
+
*/
|
|
48
|
+
export declare const verifyDidSignature: (did: string, signature: Uint8Array, data: Uint8Array) => Promise<boolean>;
|
|
49
|
+
export declare const exportDidPrivateKeyJwk: (privateKey: CryptoKey) => Promise<JsonWebKey>;
|
|
50
|
+
export declare const importDidPrivateKeyJwk: (jwk: JsonWebKey) => Promise<CryptoKey>;
|
|
51
|
+
//# sourceMappingURL=did.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did.d.ts","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,SAAK;CAIzB;AA4DD,MAAM,MAAM,UAAU,GAAG;IACvB,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,UAAU,CAM7D,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,GAAU,WAAW,SAAS,KAAG,OAAO,CAAC,MAAM,CAM3E,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,UAAU,GAAG,IAoBtD,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,OAAsC,CAAC;AAErF,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,SAAS,CAIxE,CAAC;AASF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,OAAyC,CAAC;AAMrF,eAAO,MAAM,WAAW,GAAU,YAAY,SAAS,EAAE,MAAM,UAAU,KAAG,OAAO,CAAC,UAAU,CACP,CAAC;AAExF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,KAAK,MAAM,EACX,WAAW,UAAU,EACrB,MAAM,UAAU,KACf,OAAO,CAAC,OAAO,CAQjB,CAAC;AAWF,eAAO,MAAM,sBAAsB,GAAU,YAAY,SAAS,KAAG,OAAO,CAAC,UAAU,CAC3C,CAAC;AAE7C,eAAO,MAAM,sBAAsB,GAAU,KAAK,UAAU,KAAG,OAAO,CAAC,SAAS,CAChB,CAAC"}
|
package/dist/did.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack — Decentralized Identifiers
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* entityId values are DID strings (see docs/spec/identity.md). did:key —
|
|
5
|
+
* an Ed25519 public key, multicodec + multibase(base58btc) encoded — is the
|
|
6
|
+
* mandatory floor: zero infrastructure, zero resolution, verifiable by
|
|
7
|
+
* anyone from the string alone. Other methods (did:web, did:plc, ...) are
|
|
8
|
+
* valid entityId values too, but this module only knows how to mint and
|
|
9
|
+
* verify did:key.
|
|
10
|
+
*
|
|
11
|
+
* Uses Web Crypto (crypto.subtle) exclusively — no dependency, works in
|
|
12
|
+
* Node (>=22.5, matching the rest of core's floor), browsers, and Deno.
|
|
13
|
+
*/
|
|
14
|
+
// -------------------------------------------------------
|
|
15
|
+
// Errors
|
|
16
|
+
// -------------------------------------------------------
|
|
17
|
+
export class InvalidDidError extends Error {
|
|
18
|
+
constructor(message = '') {
|
|
19
|
+
super(message || 'Invalid DID.');
|
|
20
|
+
this.name = 'InvalidDidError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// -------------------------------------------------------
|
|
24
|
+
// base58btc (Bitcoin alphabet) — no leading-zero-safe library dependency
|
|
25
|
+
// -------------------------------------------------------
|
|
26
|
+
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
27
|
+
const base58btcEncode = (bytes) => {
|
|
28
|
+
let value = 0n;
|
|
29
|
+
for (const byte of bytes)
|
|
30
|
+
value = (value << 8n) | BigInt(byte);
|
|
31
|
+
let out = '';
|
|
32
|
+
while (value > 0n) {
|
|
33
|
+
const remainder = value % 58n;
|
|
34
|
+
value /= 58n;
|
|
35
|
+
out = BASE58_ALPHABET[Number(remainder)] + out;
|
|
36
|
+
}
|
|
37
|
+
for (const byte of bytes) {
|
|
38
|
+
if (byte !== 0)
|
|
39
|
+
break;
|
|
40
|
+
out = '1' + out;
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
};
|
|
44
|
+
const base58btcDecode = (encoded) => {
|
|
45
|
+
let value = 0n;
|
|
46
|
+
for (const char of encoded) {
|
|
47
|
+
const digit = BASE58_ALPHABET.indexOf(char);
|
|
48
|
+
if (digit === -1) {
|
|
49
|
+
throw new InvalidDidError(`Invalid base58 character: "${char}"`);
|
|
50
|
+
}
|
|
51
|
+
value = value * 58n + BigInt(digit);
|
|
52
|
+
}
|
|
53
|
+
const bytes = [];
|
|
54
|
+
while (value > 0n) {
|
|
55
|
+
bytes.unshift(Number(value & 0xffn));
|
|
56
|
+
value >>= 8n;
|
|
57
|
+
}
|
|
58
|
+
for (const char of encoded) {
|
|
59
|
+
if (char !== '1')
|
|
60
|
+
break;
|
|
61
|
+
bytes.unshift(0);
|
|
62
|
+
}
|
|
63
|
+
return new Uint8Array(bytes);
|
|
64
|
+
};
|
|
65
|
+
// -------------------------------------------------------
|
|
66
|
+
// did:key (Ed25519)
|
|
67
|
+
// -------------------------------------------------------
|
|
68
|
+
/** Multicodec varint prefix for "ed25519-pub" (code 0xed). */
|
|
69
|
+
const ED25519_MULTICODEC_PREFIX = new Uint8Array([0xed, 0x01]);
|
|
70
|
+
const ED25519_RAW_KEY_LENGTH = 32;
|
|
71
|
+
const DID_KEY_PREFIX = 'did:key:z';
|
|
72
|
+
/** Generate a fresh Ed25519 keypair and derive its did:key. */
|
|
73
|
+
export const generateDidKeypair = async () => {
|
|
74
|
+
const { publicKey, privateKey } = (await crypto.subtle.generateKey('Ed25519', true, [
|
|
75
|
+
'sign',
|
|
76
|
+
'verify',
|
|
77
|
+
]));
|
|
78
|
+
return { did: await didFromPublicKey(publicKey), publicKey, privateKey };
|
|
79
|
+
};
|
|
80
|
+
/** Derive a did:key string from an Ed25519 CryptoKey. */
|
|
81
|
+
export const didFromPublicKey = async (publicKey) => {
|
|
82
|
+
const raw = new Uint8Array(await crypto.subtle.exportKey('raw', publicKey));
|
|
83
|
+
const prefixed = new Uint8Array(ED25519_MULTICODEC_PREFIX.length + raw.length);
|
|
84
|
+
prefixed.set(ED25519_MULTICODEC_PREFIX, 0);
|
|
85
|
+
prefixed.set(raw, ED25519_MULTICODEC_PREFIX.length);
|
|
86
|
+
return DID_KEY_PREFIX + base58btcEncode(prefixed);
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Parse a did:key string and return its raw Ed25519 public key bytes, or
|
|
90
|
+
* null if it isn't a well-formed Ed25519 did:key (wrong prefix, bad base58,
|
|
91
|
+
* wrong multicodec, wrong length).
|
|
92
|
+
*/
|
|
93
|
+
export const parseDidKey = (did) => {
|
|
94
|
+
if (!did.startsWith(DID_KEY_PREFIX))
|
|
95
|
+
return null;
|
|
96
|
+
let decoded;
|
|
97
|
+
try {
|
|
98
|
+
decoded = base58btcDecode(did.slice(DID_KEY_PREFIX.length));
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const expectedLength = ED25519_MULTICODEC_PREFIX.length + ED25519_RAW_KEY_LENGTH;
|
|
104
|
+
if (decoded.length !== expectedLength ||
|
|
105
|
+
decoded[0] !== ED25519_MULTICODEC_PREFIX[0] ||
|
|
106
|
+
decoded[1] !== ED25519_MULTICODEC_PREFIX[1]) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
return decoded.slice(ED25519_MULTICODEC_PREFIX.length);
|
|
110
|
+
};
|
|
111
|
+
/** Whether a string is a well-formed Ed25519 did:key. */
|
|
112
|
+
export const isValidDidKey = (value) => parseDidKey(value) !== null;
|
|
113
|
+
/** Import the Ed25519 public key encoded in a did:key, for verification. */
|
|
114
|
+
export const publicKeyFromDidKey = async (did) => {
|
|
115
|
+
const raw = parseDidKey(did);
|
|
116
|
+
if (!raw)
|
|
117
|
+
throw new InvalidDidError(`Not a valid did:key: "${did}"`);
|
|
118
|
+
return crypto.subtle.importKey('raw', new Uint8Array(raw), 'Ed25519', true, ['verify']);
|
|
119
|
+
};
|
|
120
|
+
// -------------------------------------------------------
|
|
121
|
+
// Generic DID syntax (any method)
|
|
122
|
+
// -------------------------------------------------------
|
|
123
|
+
// did-core ABNF, simplified: "did:" method-name ":" method-specific-id
|
|
124
|
+
const GENERIC_DID_FORMAT = /^did:[a-z0-9]+:[A-Za-z0-9._:%-]+$/;
|
|
125
|
+
/**
|
|
126
|
+
* Whether a string has the generic W3C DID Core syntax (did:<method>:<id>)
|
|
127
|
+
* — any method, not just did:key. Use isValidDidKey() to additionally
|
|
128
|
+
* require the did:key method and a well-formed Ed25519 key.
|
|
129
|
+
*/
|
|
130
|
+
export const isValidDid = (value) => GENERIC_DID_FORMAT.test(value);
|
|
131
|
+
// -------------------------------------------------------
|
|
132
|
+
// Sign / verify
|
|
133
|
+
// -------------------------------------------------------
|
|
134
|
+
export const signWithDid = async (privateKey, data) => new Uint8Array(await crypto.subtle.sign('Ed25519', privateKey, new Uint8Array(data)));
|
|
135
|
+
/**
|
|
136
|
+
* Verify a signature was produced by the private key behind a did:key.
|
|
137
|
+
* Requires no lookup — the public key is decoded from the DID itself.
|
|
138
|
+
*/
|
|
139
|
+
export const verifyDidSignature = async (did, signature, data) => {
|
|
140
|
+
const publicKey = await publicKeyFromDidKey(did);
|
|
141
|
+
return crypto.subtle.verify('Ed25519', publicKey, new Uint8Array(signature), new Uint8Array(data));
|
|
142
|
+
};
|
|
143
|
+
// -------------------------------------------------------
|
|
144
|
+
// Private-key export/import
|
|
145
|
+
// -------------------------------------------------------
|
|
146
|
+
//
|
|
147
|
+
// Core never stores a private key itself — these exist so callers can
|
|
148
|
+
// persist the key material returned by generateDidKeypair() (encrypted key
|
|
149
|
+
// backup, OS keychain, etc.) and reconstruct it on a later run. Where that
|
|
150
|
+
// key lives is an app/UX concern, not this library's.
|
|
151
|
+
export const exportDidPrivateKeyJwk = async (privateKey) => crypto.subtle.exportKey('jwk', privateKey);
|
|
152
|
+
export const importDidPrivateKeyJwk = async (jwk) => crypto.subtle.importKey('jwk', jwk, 'Ed25519', true, ['sign']);
|
|
153
|
+
//# sourceMappingURL=did.js.map
|
package/dist/did.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did.js","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":"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"}
|
package/dist/id.d.ts
CHANGED
|
@@ -22,15 +22,27 @@ export declare const crockford32Encode: (n: number) => string;
|
|
|
22
22
|
export declare const crockford32Decode: (s: string) => number;
|
|
23
23
|
export declare const _setLastNowId: (chars: string) => void;
|
|
24
24
|
export declare const _setLastRandChars: (chars: string) => void;
|
|
25
|
+
export declare const _setLastTimestamp: (timestamp: number) => void;
|
|
26
|
+
/** Resets all module-level generator state. For test isolation only. */
|
|
27
|
+
export declare const _resetIdState: () => void;
|
|
25
28
|
/**
|
|
26
|
-
* Generate a new Stack record ID.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* and avoid collisions. Throws IdGenerationOverflowError if more than
|
|
31
|
-
* BASE^RAND_SUFFIX_LENGTH (32^3 = 32,768) IDs are generated in one millisecond.
|
|
29
|
+
* Generate a new Stack record ID. Time-sortable: lexicographic order
|
|
30
|
+
* matches creation order, with same-millisecond IDs monotonically
|
|
31
|
+
* incremented. Throws IdGenerationOverflowError past 32^3 IDs in one
|
|
32
|
+
* millisecond.
|
|
32
33
|
*
|
|
33
34
|
* @param timestamp - Override the timestamp (ms since epoch). Defaults to Date.now().
|
|
34
35
|
*/
|
|
35
36
|
export declare const generateId: (timestamp?: number) => string;
|
|
37
|
+
/**
|
|
38
|
+
* Check whether a string has the shape of a Stack record ID: exactly
|
|
39
|
+
* 12 lowercase Crockford base-32 characters. Does not check whether the
|
|
40
|
+
* ID actually exists — see Stack.create()'s duplicate check for that.
|
|
41
|
+
*/
|
|
42
|
+
export declare const isValidIdFormat: (id: string) => boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Extract the timestamp (ms since epoch) encoded in an ID's prefix.
|
|
45
|
+
* Only meaningful for IDs that pass isValidIdFormat().
|
|
46
|
+
*/
|
|
47
|
+
export declare const idTimestamp: (id: string) => number;
|
|
36
48
|
//# sourceMappingURL=id.d.ts.map
|
package/dist/id.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,eAAO,MAAM,IAAI,QAAoB,CAAC;AAGtC,eAAO,MAAM,kBAAkB,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,eAAO,MAAM,IAAI,QAAoB,CAAC;AAGtC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAcpC,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,SAAK;CAIzB;AAED,qBAAa,yBAA0B,SAAQ,iBAAiB;gBAClD,OAAO,SAAK;CAIzB;AAMD,eAAO,MAAM,iBAAiB,GAAI,GAAG,MAAM,KAAG,MAiB7C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,GAAG,MAAM,KAAG,MAe7C,CAAC;AAoCF,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,IAK7C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,KAAG,IAKjD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,KAAG,IAErD,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,aAAa,QAAO,IAIhC,CAAC;AAMF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,GAAI,YAAW,MAAmB,KAAG,MAU3D,CAAC;AASF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,IAAI,MAAM,KAAG,OAA6B,CAAC;AAE3E;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,IAAI,MAAM,KAAG,MACa,CAAC"}
|
package/dist/id.js
CHANGED
|
@@ -17,6 +17,10 @@ export const RAND_SUFFIX_LENGTH = 3;
|
|
|
17
17
|
// Module-level state for monotonicity within the same millisecond
|
|
18
18
|
let lastNowId = '';
|
|
19
19
|
let lastRandChars = '';
|
|
20
|
+
// Tracks the highest timestamp an ID has been minted for, so a backward
|
|
21
|
+
// clock step (NTP correction, suspend/resume) can't produce an ID that
|
|
22
|
+
// sorts before ones already generated in this process.
|
|
23
|
+
let lastTimestamp = 0;
|
|
20
24
|
// -------------------------------------------------------
|
|
21
25
|
// Errors
|
|
22
26
|
// -------------------------------------------------------
|
|
@@ -74,15 +78,15 @@ const pad = (chars, length) => chars.padStart(length, CHARACTERS[0]);
|
|
|
74
78
|
* Works in Node (>=19), browsers, Deno, and Bun.
|
|
75
79
|
*/
|
|
76
80
|
const generateRandChars = () => {
|
|
77
|
-
const
|
|
81
|
+
const modulus = Math.pow(BASE, RAND_SUFFIX_LENGTH);
|
|
78
82
|
const arr = new Uint32Array(1);
|
|
79
83
|
// Rejection sampling to avoid modulo bias
|
|
80
84
|
let value;
|
|
81
85
|
do {
|
|
82
86
|
crypto.getRandomValues(arr);
|
|
83
87
|
value = arr[0];
|
|
84
|
-
} while (value > Math.floor(0xffffffff /
|
|
85
|
-
return pad(crockford32Encode(value %
|
|
88
|
+
} while (value > Math.floor(0xffffffff / modulus) * modulus);
|
|
89
|
+
return pad(crockford32Encode(value % modulus), RAND_SUFFIX_LENGTH);
|
|
86
90
|
};
|
|
87
91
|
const incrementRandChars = (randChars) => {
|
|
88
92
|
const next = crockford32Encode(crockford32Decode(randChars) + 1);
|
|
@@ -106,24 +110,49 @@ export const _setLastRandChars = (chars) => {
|
|
|
106
110
|
}
|
|
107
111
|
lastRandChars = chars;
|
|
108
112
|
};
|
|
113
|
+
export const _setLastTimestamp = (timestamp) => {
|
|
114
|
+
lastTimestamp = timestamp;
|
|
115
|
+
};
|
|
116
|
+
/** Resets all module-level generator state. For test isolation only. */
|
|
117
|
+
export const _resetIdState = () => {
|
|
118
|
+
lastNowId = '';
|
|
119
|
+
lastRandChars = '';
|
|
120
|
+
lastTimestamp = 0;
|
|
121
|
+
};
|
|
109
122
|
// -------------------------------------------------------
|
|
110
123
|
// Public API
|
|
111
124
|
// -------------------------------------------------------
|
|
112
125
|
/**
|
|
113
|
-
* Generate a new Stack record ID.
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* and avoid collisions. Throws IdGenerationOverflowError if more than
|
|
118
|
-
* BASE^RAND_SUFFIX_LENGTH (32^3 = 32,768) IDs are generated in one millisecond.
|
|
126
|
+
* Generate a new Stack record ID. Time-sortable: lexicographic order
|
|
127
|
+
* matches creation order, with same-millisecond IDs monotonically
|
|
128
|
+
* incremented. Throws IdGenerationOverflowError past 32^3 IDs in one
|
|
129
|
+
* millisecond.
|
|
119
130
|
*
|
|
120
131
|
* @param timestamp - Override the timestamp (ms since epoch). Defaults to Date.now().
|
|
121
132
|
*/
|
|
122
133
|
export const generateId = (timestamp = Date.now()) => {
|
|
123
|
-
const
|
|
134
|
+
const effectiveTimestamp = Math.max(timestamp, lastTimestamp);
|
|
135
|
+
const nowId = pad(crockford32Encode(effectiveTimestamp), MIN_TIMESTAMP_LENGTH);
|
|
124
136
|
const randChars = nowId !== lastNowId ? generateRandChars() : incrementRandChars(lastRandChars);
|
|
137
|
+
lastTimestamp = effectiveTimestamp;
|
|
125
138
|
lastNowId = nowId;
|
|
126
139
|
lastRandChars = randChars;
|
|
127
140
|
return nowId + randChars;
|
|
128
141
|
};
|
|
142
|
+
// -------------------------------------------------------
|
|
143
|
+
// Format validation
|
|
144
|
+
// -------------------------------------------------------
|
|
145
|
+
const ID_LENGTH = MIN_TIMESTAMP_LENGTH + RAND_SUFFIX_LENGTH;
|
|
146
|
+
const ID_FORMAT = new RegExp(`^[${CHARACTERS}]{${ID_LENGTH}}$`);
|
|
147
|
+
/**
|
|
148
|
+
* Check whether a string has the shape of a Stack record ID: exactly
|
|
149
|
+
* 12 lowercase Crockford base-32 characters. Does not check whether the
|
|
150
|
+
* ID actually exists — see Stack.create()'s duplicate check for that.
|
|
151
|
+
*/
|
|
152
|
+
export const isValidIdFormat = (id) => ID_FORMAT.test(id);
|
|
153
|
+
/**
|
|
154
|
+
* Extract the timestamp (ms since epoch) encoded in an ID's prefix.
|
|
155
|
+
* Only meaningful for IDs that pass isValidIdFormat().
|
|
156
|
+
*/
|
|
157
|
+
export const idTimestamp = (id) => crockford32Decode(id.slice(0, MIN_TIMESTAMP_LENGTH));
|
|
129
158
|
//# sourceMappingURL=id.js.map
|
package/dist/id.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id.js","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,UAAU,GAAG,kCAAkC,CAAC;AAEtD,MAAM,CAAC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC;AAEtC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC,kEAAkE;AAClE,IAAI,SAAS,GAAG,EAAE,CAAC;AACnB,IAAI,aAAa,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"id.js","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"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"}
|