@gnufoo/canaad 0.1.2 → 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.
Files changed (3) hide show
  1. package/package.json +3 -2
  2. package/tool.d.ts +16 -2
  3. package/tool.js +38 -7
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@gnufoo/canaad",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "main": "canaad_wasm.js",
6
6
  "types": "canaad_wasm.d.ts",
7
7
  "exports": {
8
8
  ".": "./canaad_wasm.js",
9
9
  "./meta": "./meta.js",
10
- "./tool": "./tool.js"
10
+ "./tool": "./tool.js",
11
+ "./wasm": "./canaad_wasm_bg.wasm"
11
12
  },
12
13
  "dependencies": {
13
14
  "zod": "^3.24.0"
package/tool.d.ts CHANGED
@@ -1,5 +1,19 @@
1
- import { meta, CanaadInput, CanaadOutput } from './meta.js';
1
+ import type { meta, CanaadInput, CanaadOutput } from './meta.js';
2
2
 
3
- export declare const toolDefinition: typeof meta & {
3
+ /**
4
+ * Initialize the WASM module.
5
+ *
6
+ * @param wasmSource - Optional WASM source:
7
+ * - Browser: omit (fetches automatically)
8
+ * - Cloudflare Workers: pass WebAssembly.Module from import
9
+ */
10
+ export function ensureReady(wasmSource?:
11
+ | WebAssembly.Module
12
+ | ArrayBuffer
13
+ | URL
14
+ | string
15
+ ): Promise<void>;
16
+
17
+ export const toolDefinition: typeof meta & {
4
18
  execute(input: CanaadInput): Promise<CanaadOutput>;
5
19
  };
package/tool.js CHANGED
@@ -1,18 +1,49 @@
1
1
  import { meta, inputSchema } from './meta.js';
2
- import init, { canonicalize, canonicalize_string, hash, validate, AadBuilder } from './canaad_wasm.js';
2
+ import init, { canonicalize, canonicalizeString, hash, validate, AadBuilder } from './canaad_wasm.js';
3
3
 
4
- let ready = false;
5
- async function ensureReady() {
6
- if (!ready) { await init(); ready = true; }
4
+ // --- Initialization state ---
5
+ let initialized = false;
6
+ let initPromise = null;
7
+
8
+ /**
9
+ * Initialize the WASM module.
10
+ *
11
+ * @param {WebAssembly.Module | ArrayBuffer | URL | string} [wasmSource]
12
+ * - Browser: omit or pass URL/string path (uses fetch)
13
+ * - Cloudflare Workers: pass the imported WebAssembly.Module
14
+ *
15
+ * @example
16
+ * // Browser (fetch automatically)
17
+ * await ensureReady();
18
+ *
19
+ * @example
20
+ * // Cloudflare Workers (pre-compiled module)
21
+ * import wasmModule from '@gnufoo/canaad/wasm';
22
+ * await ensureReady(wasmModule);
23
+ */
24
+ export async function ensureReady(wasmSource) {
25
+ if (initialized) return;
26
+ if (initPromise) return initPromise;
27
+
28
+ initPromise = init(wasmSource).then(() => {
29
+ initialized = true;
30
+ });
31
+
32
+ return initPromise;
7
33
  }
8
34
 
35
+ // --- Helpers ---
9
36
  const bytesToHex = (bytes) => Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
10
37
  const bytesToBase64 = (bytes) => btoa(String.fromCharCode(...bytes));
11
38
 
39
+ // --- Tool Definition ---
12
40
  export const toolDefinition = {
13
41
  ...meta,
42
+
14
43
  async execute(rawInput) {
44
+ // Default initialization (browser) - no wasmSource needed
15
45
  await ensureReady();
46
+
16
47
  const input = inputSchema.parse(rawInput);
17
48
 
18
49
  switch (input.action) {
@@ -20,7 +51,7 @@ export const toolDefinition = {
20
51
  if (input.outputFormat === 'bytes') {
21
52
  return { action: 'canonicalize', output: Array.from(canonicalize(input.input)), outputFormat: 'bytes' };
22
53
  }
23
- return { action: 'canonicalize', output: canonicalize_string(input.input), outputFormat: 'string' };
54
+ return { action: 'canonicalize', output: canonicalizeString(input.input), outputFormat: 'string' };
24
55
  }
25
56
  case 'validate':
26
57
  return { action: 'validate', valid: validate(input.input) };
@@ -32,12 +63,12 @@ export const toolDefinition = {
32
63
  let b = new AadBuilder().tenant(input.tenant).resource(input.resource).purpose(input.purpose);
33
64
  if (input.timestamp !== undefined) b = b.timestamp(input.timestamp);
34
65
  for (const ext of input.extensions || []) {
35
- b = typeof ext.value === 'string' ? b.extension_string(ext.key, ext.value) : b.extension_int(ext.key, ext.value);
66
+ b = typeof ext.value === 'string' ? b.extensionString(ext.key, ext.value) : b.extensionInt(ext.key, ext.value);
36
67
  }
37
68
  if (input.outputFormat === 'bytes') {
38
69
  return { action: 'build', output: Array.from(b.build()), outputFormat: 'bytes' };
39
70
  }
40
- return { action: 'build', output: b.build_string(), outputFormat: 'string' };
71
+ return { action: 'build', output: b.buildString(), outputFormat: 'string' };
41
72
  }
42
73
  }
43
74
  },