@q32/core 0.1.1 → 0.1.3

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 CHANGED
@@ -11,6 +11,7 @@ The first release focuses on common infrastructure repeated across Q32 apps:
11
11
  - environment parsing
12
12
  - email provider contracts and address helpers
13
13
  - IDs, tokens, and signed session cookies
14
+ - hash and HMAC helpers
14
15
  - HTTP JSON/error helpers
15
16
  - D1-like database types and migration runner
16
17
  - D1-backed jobs
@@ -39,7 +40,7 @@ pnpm build
39
40
 
40
41
  ## Release
41
42
 
42
- Publishing is handled by the `Release` GitHub Actions workflow when a GitHub release is published. Configure an npm automation token as the repository secret `NPM_TOKEN` before the first release.
43
+ Publishing is handled by the `Release` GitHub Actions workflow when a GitHub release is published. npm trusted publishing is configured for `q32llc/q32-core` using `.github/workflows/release.yml`, so the workflow publishes with provenance through GitHub OIDC.
43
44
 
44
45
  ## Modules
45
46
 
package/dist/hash.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export declare function toHex(bytes: Uint8Array): string;
2
+ export declare function toBase64(bytes: Uint8Array): string;
3
+ export declare function sha256Hex(value: string | ArrayBuffer): Promise<string>;
4
+ export declare function hmacSha256Hex(secret: string, value: string | ArrayBuffer): Promise<string>;
5
+ export declare function hmacSha256Base64(secret: string, value: string | ArrayBuffer): Promise<string>;
6
+ export declare function timingSafeEqual(a: string, b: string): boolean;
7
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAEA,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE/C;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIlD;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAI5E;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,WAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GAAG,WAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAO7D"}
package/dist/hash.js ADDED
@@ -0,0 +1,38 @@
1
+ const encoder = new TextEncoder();
2
+ export function toHex(bytes) {
3
+ return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
4
+ }
5
+ export function toBase64(bytes) {
6
+ let binary = "";
7
+ for (const byte of bytes)
8
+ binary += String.fromCharCode(byte);
9
+ return btoa(binary);
10
+ }
11
+ export async function sha256Hex(value) {
12
+ const data = typeof value === "string" ? encoder.encode(value) : value;
13
+ const digest = await crypto.subtle.digest("SHA-256", data);
14
+ return toHex(new Uint8Array(digest));
15
+ }
16
+ export async function hmacSha256Hex(secret, value) {
17
+ const signature = await hmacSha256(secret, value);
18
+ return toHex(new Uint8Array(signature));
19
+ }
20
+ export async function hmacSha256Base64(secret, value) {
21
+ const signature = await hmacSha256(secret, value);
22
+ return toBase64(new Uint8Array(signature));
23
+ }
24
+ export function timingSafeEqual(a, b) {
25
+ if (a.length !== b.length)
26
+ return false;
27
+ let mismatch = 0;
28
+ for (let index = 0; index < a.length; index += 1) {
29
+ mismatch |= a.charCodeAt(index) ^ b.charCodeAt(index);
30
+ }
31
+ return mismatch === 0;
32
+ }
33
+ async function hmacSha256(secret, value) {
34
+ const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
35
+ const data = typeof value === "string" ? encoder.encode(value) : value;
36
+ return crypto.subtle.sign("HMAC", key, data);
37
+ }
38
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,MAAM,UAAU,KAAK,CAAC,KAAiB;IACrC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAiB;IACxC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAA2B;IACzD,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACvE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,KAA2B;IAE3B,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAc,EACd,KAA2B;IAE3B,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAClD,OAAO,QAAQ,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,CAAS;IAClD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACjD,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,QAAQ,KAAK,CAAC,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,MAAc,EACd,KAA2B;IAE3B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACvC,KAAK,EACL,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EACtB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACvE,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC"}
package/dist/ids.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  export declare function createId(prefix: string, bytes?: number): string;
2
2
  export declare function createToken(prefix?: string, bytes?: number): string;
3
+ export declare function randomBase36(length: number): string;
4
+ export declare function createBase36Id(prefix: string, length?: number): string;
5
+ export declare function createBase36Token(prefix: string, length?: number): string;
3
6
  export declare function randomBase64Url(bytes?: number): string;
4
7
  export declare function toBase64Url(input: string | Uint8Array): string;
5
8
  export declare function fromBase64Url(value: string): Uint8Array;
package/dist/ids.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAI3D;AAED,wBAAgB,WAAW,CAAC,MAAM,SAAQ,EAAE,KAAK,SAAsB,GAAG,MAAM,CAE/E;AAED,wBAAgB,eAAe,CAAC,KAAK,SAAsB,GAAG,MAAM,CAInE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAK9D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAMvD;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9D"}
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAI3D;AAED,wBAAgB,WAAW,CAAC,MAAM,SAAQ,EAAE,KAAK,SAAsB,GAAG,MAAM,CAE/E;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,MAAM,CAIlE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,MAAM,CAIrE;AAED,wBAAgB,eAAe,CAAC,KAAK,SAAsB,GAAG,MAAM,CAInE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAK9D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAMvD;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9D"}
package/dist/ids.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const DEFAULT_TOKEN_BYTES = 32;
2
+ const BASE36_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
2
3
  export function createId(prefix, bytes = 12) {
3
4
  const cleanPrefix = prefix.trim().replace(/[^a-zA-Z0-9_-]/g, "_");
4
5
  if (!cleanPrefix)
@@ -8,6 +9,27 @@ export function createId(prefix, bytes = 12) {
8
9
  export function createToken(prefix = "tok", bytes = DEFAULT_TOKEN_BYTES) {
9
10
  return createId(prefix, bytes);
10
11
  }
12
+ export function randomBase36(length) {
13
+ const safeLength = Math.max(1, Math.floor(length));
14
+ const bytes = new Uint8Array(safeLength);
15
+ crypto.getRandomValues(bytes);
16
+ let value = "";
17
+ for (const byte of bytes)
18
+ value += BASE36_ALPHABET[byte % BASE36_ALPHABET.length];
19
+ return value;
20
+ }
21
+ export function createBase36Id(prefix, length = 20) {
22
+ const cleanPrefix = prefix.trim();
23
+ if (!cleanPrefix)
24
+ throw new Error("ID prefix is required.");
25
+ return `${cleanPrefix}_${randomBase36(length)}`;
26
+ }
27
+ export function createBase36Token(prefix, length = 40) {
28
+ const cleanPrefix = prefix.trim();
29
+ if (!cleanPrefix)
30
+ throw new Error("Token prefix is required.");
31
+ return `${cleanPrefix}_${randomBase36(length)}`;
32
+ }
11
33
  export function randomBase64Url(bytes = DEFAULT_TOKEN_BYTES) {
12
34
  const data = new Uint8Array(Math.max(1, Math.floor(bytes)));
13
35
  crypto.getRandomValues(data);
package/dist/ids.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,KAAK,GAAG,EAAE;IACjD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IAClE,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5D,OAAO,GAAG,WAAW,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAM,GAAG,KAAK,EAAE,KAAK,GAAG,mBAAmB;IACrE,OAAO,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAK,GAAG,mBAAmB;IACzD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAA0B;IACpD,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAClF,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACxG,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa;IAC3C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAChG,CAAC"}
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"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"}
@@ -19,8 +19,8 @@ Objective: working Q32 core libraries, with the common libraries discussed in th
19
19
 
20
20
  | Requirement | Status |
21
21
  | --- | --- |
22
- | npm package published | Not complete. Local `npm whoami` returns `E401`, and `@q32/core` does not exist on npm yet. |
23
- | npm publish step in CD | Workflow exists and skips safely when `NPM_TOKEN` is absent. Actual npm publishing cannot be proven until npm publishing is configured through `NPM_TOKEN` or npm trusted publishing for this repo/package. |
22
+ | npm package published | Complete for `@q32/core@0.1.1`; npm reports `0.1.1` as the latest published version. |
23
+ | npm publish step in CD | Trusted publishing is configured for `q32llc/q32-core` and `.github/workflows/release.yml`; verify on the next GitHub release. |
24
24
  | Proven replacement in existing apps | Not complete. The library is evaluated as suitable, but no existing app has been migrated to consume it yet. |
25
25
 
26
26
  ## Recommended Next Proof Step
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q32/core",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Shared TypeScript primitives for Q32 Cloudflare Worker projects.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -52,6 +52,10 @@
52
52
  "types": "./dist/env.d.ts",
53
53
  "default": "./dist/env.js"
54
54
  },
55
+ "./hash": {
56
+ "types": "./dist/hash.d.ts",
57
+ "default": "./dist/hash.js"
58
+ },
55
59
  "./http": {
56
60
  "types": "./dist/http.d.ts",
57
61
  "default": "./dist/http.js"