functionalscript 0.29.1 → 0.31.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.
Files changed (191) hide show
  1. package/fs/asn.1/module.f.js +18 -22
  2. package/fs/asn.1/proof.f.d.ts +5 -0
  3. package/fs/asn.1/proof.f.js +38 -2
  4. package/fs/base64/module.f.d.ts +9 -0
  5. package/fs/base64/module.f.js +60 -0
  6. package/fs/base64/proof.f.d.ts +11 -0
  7. package/fs/base64/proof.f.js +117 -0
  8. package/fs/base_n/module.f.d.ts +44 -0
  9. package/fs/base_n/module.f.js +54 -0
  10. package/fs/base_n/proof.f.d.ts +10 -0
  11. package/fs/base_n/proof.f.js +86 -0
  12. package/fs/bnf/data/module.f.d.ts +4 -9
  13. package/fs/bnf/data/module.f.js +4 -3
  14. package/fs/bnf/module.f.d.ts +3 -4
  15. package/fs/bnf/module.f.js +3 -2
  16. package/fs/bnf/proof.f.d.ts +9 -0
  17. package/fs/bnf/proof.f.js +98 -1
  18. package/fs/cas/mcp/module.f.d.ts +40 -0
  19. package/fs/cas/mcp/module.f.js +223 -0
  20. package/fs/cas/mcp/proof.f.d.ts +30 -0
  21. package/fs/cas/mcp/proof.f.js +310 -0
  22. package/fs/cas/module.f.d.ts +9 -3
  23. package/fs/cas/module.f.js +104 -69
  24. package/fs/cas/proof.f.d.ts +2 -0
  25. package/fs/cas/proof.f.js +30 -1
  26. package/fs/cbase32/module.f.d.ts +1 -1
  27. package/fs/cbase32/module.f.js +19 -40
  28. package/fs/cbase32/proof.f.d.ts +1 -0
  29. package/fs/cbase32/proof.f.js +15 -0
  30. package/fs/ci/bun/module.f.d.ts +2 -2
  31. package/fs/ci/bun/module.f.js +7 -14
  32. package/fs/ci/common/module.f.d.ts +3 -1
  33. package/fs/ci/common/module.f.js +9 -2
  34. package/fs/ci/config/module.f.d.ts +7 -5
  35. package/fs/ci/config/module.f.js +11 -5
  36. package/fs/ci/deno/module.f.d.ts +1 -1
  37. package/fs/ci/deno/module.f.js +7 -5
  38. package/fs/ci/module.f.d.ts +6 -3
  39. package/fs/ci/module.f.js +24 -54
  40. package/fs/ci/node/module.f.d.ts +3 -3
  41. package/fs/ci/node/module.f.js +30 -26
  42. package/fs/ci/playwright/module.f.js +1 -1
  43. package/fs/ci/proof.f.d.ts +6 -7
  44. package/fs/ci/proof.f.js +63 -36
  45. package/fs/ci/rust/module.f.d.ts +2 -1
  46. package/fs/ci/rust/module.f.js +33 -16
  47. package/fs/cli/module.f.d.ts +3 -1
  48. package/fs/cli/module.f.js +22 -12
  49. package/fs/cli/proof.f.d.ts +5 -0
  50. package/fs/cli/proof.f.js +76 -0
  51. package/fs/crypto/hmac/proof.f.d.ts +1 -0
  52. package/fs/crypto/hmac/proof.f.js +8 -0
  53. package/fs/crypto/secp/proof.f.d.ts +1 -0
  54. package/fs/crypto/secp/proof.f.js +10 -0
  55. package/fs/crypto/sign/module.f.js +1 -4
  56. package/fs/dev/module.f.d.ts +5 -3
  57. package/fs/dev/module.f.js +13 -2
  58. package/fs/dev/package_json/proof.f.d.ts +1 -0
  59. package/fs/dev/package_json/proof.f.js +5 -0
  60. package/fs/dev/proof.f.d.ts +1 -0
  61. package/fs/dev/proof.f.js +12 -1
  62. package/fs/djs/ast/module.f.d.ts +1 -1
  63. package/fs/djs/ast/proof.f.d.ts +5 -0
  64. package/fs/djs/ast/proof.f.js +17 -0
  65. package/fs/djs/module.f.d.ts +1 -1
  66. package/fs/djs/module.f.js +2 -3
  67. package/fs/djs/serializer/module.f.js +24 -11
  68. package/fs/djs/transpiler/module.f.js +3 -4
  69. package/fs/effects/memory/module.f.d.ts +37 -0
  70. package/fs/effects/memory/module.f.js +24 -0
  71. package/fs/effects/memory/proof.f.d.ts +6 -0
  72. package/fs/effects/memory/proof.f.js +64 -0
  73. package/fs/effects/mock/module.f.d.ts +7 -2
  74. package/fs/effects/mock/module.f.js +12 -8
  75. package/fs/effects/module.d.ts +1 -1
  76. package/fs/effects/module.f.d.ts +41 -0
  77. package/fs/effects/module.f.js +25 -0
  78. package/fs/effects/module.js +6 -7
  79. package/fs/effects/node/memory/module.d.ts +20 -0
  80. package/fs/effects/node/memory/module.js +44 -0
  81. package/fs/effects/node/memory/proof.d.ts +10 -0
  82. package/fs/effects/node/memory/proof.js +35 -0
  83. package/fs/effects/node/module.d.ts +1 -1
  84. package/fs/effects/node/module.f.d.ts +54 -8
  85. package/fs/effects/node/module.f.js +55 -4
  86. package/fs/effects/node/module.js +166 -135
  87. package/fs/effects/node/proof.f.d.ts +10 -0
  88. package/fs/effects/node/proof.f.js +88 -21
  89. package/fs/effects/node/virtual/module.f.d.ts +6 -0
  90. package/fs/effects/node/virtual/module.f.js +48 -16
  91. package/fs/effects/node/virtual/proof.f.d.ts +17 -0
  92. package/fs/effects/node/virtual/proof.f.js +79 -0
  93. package/fs/effects/proof.f.d.ts +5 -0
  94. package/fs/effects/proof.f.js +54 -34
  95. package/fs/emergent_testing/module.f.d.ts +6 -1
  96. package/fs/emergent_testing/module.f.js +8 -3
  97. package/fs/emergent_testing/proof.f.d.ts +11 -0
  98. package/fs/emergent_testing/proof.f.js +52 -16
  99. package/fs/fjs/module.f.js +2 -2
  100. package/fs/fjs/proof.f.d.ts +8 -0
  101. package/fs/fjs/proof.f.js +39 -0
  102. package/fs/fsc/module.f.d.ts +5 -0
  103. package/fs/fsc/module.f.js +17 -27
  104. package/fs/fsc/proof.f.d.ts +8 -0
  105. package/fs/fsc/proof.f.js +48 -2
  106. package/fs/fsm/module.f.d.ts +2 -3
  107. package/fs/fsm/module.f.js +1 -1
  108. package/fs/html/module.f.d.ts +2 -3
  109. package/fs/html/module.f.js +7 -6
  110. package/fs/html/proof.f.d.ts +1 -0
  111. package/fs/html/proof.f.js +7 -0
  112. package/fs/js/tokenizer/module.f.js +1 -1
  113. package/fs/js/tokenizer/proof.f.js +7 -0
  114. package/fs/json/module.f.d.ts +9 -2
  115. package/fs/json/module.f.js +9 -7
  116. package/fs/json/parser/module.f.js +4 -6
  117. package/fs/json/parser/proof.f.js +19 -10
  118. package/fs/json/proof.f.d.ts +2 -1
  119. package/fs/json/proof.f.js +33 -6
  120. package/fs/json/rpc/module.f.d.ts +5 -0
  121. package/fs/json/rpc/module.f.js +16 -11
  122. package/fs/json/schema/module.f.d.ts +15 -14
  123. package/fs/json/schema/proof.f.d.ts +3 -0
  124. package/fs/json/schema/proof.f.js +16 -1
  125. package/fs/mcp/module.f.d.ts +103 -5
  126. package/fs/mcp/module.f.js +139 -2
  127. package/fs/mcp/proof.f.d.ts +34 -0
  128. package/fs/mcp/proof.f.js +207 -0
  129. package/fs/mcp/stdio/module.f.d.ts +39 -0
  130. package/fs/mcp/stdio/module.f.js +54 -0
  131. package/fs/mcp/stdio/proof.f.d.ts +10 -0
  132. package/fs/mcp/stdio/proof.f.js +92 -0
  133. package/fs/mime/module.f.d.ts +39 -0
  134. package/fs/mime/module.f.js +78 -0
  135. package/fs/mime/proof.f.d.ts +15 -0
  136. package/fs/mime/proof.f.js +30 -0
  137. package/fs/path/module.f.d.ts +8 -0
  138. package/fs/path/module.f.js +10 -3
  139. package/fs/path/proof.f.d.ts +1 -0
  140. package/fs/path/proof.f.js +40 -2
  141. package/fs/text/sgr/proof.f.js +30 -2
  142. package/fs/text/utf8/module.f.d.ts +7 -0
  143. package/fs/text/utf8/module.f.js +85 -31
  144. package/fs/text/utf8/proof.f.d.ts +1 -0
  145. package/fs/text/utf8/proof.f.js +60 -1
  146. package/fs/types/bigfloat/module.f.d.ts +3 -0
  147. package/fs/types/bigfloat/module.f.js +30 -31
  148. package/fs/types/bigint/module.f.d.ts +24 -2
  149. package/fs/types/bigint/module.f.js +30 -2
  150. package/fs/types/bigint/proof.f.d.ts +7 -0
  151. package/fs/types/bigint/proof.f.js +47 -16
  152. package/fs/types/bit_vec/module.f.d.ts +18 -0
  153. package/fs/types/bit_vec/module.f.js +18 -0
  154. package/fs/types/bit_vec/proof.f.d.ts +1 -0
  155. package/fs/types/bit_vec/proof.f.js +13 -1
  156. package/fs/types/function/operator/proof.f.d.ts +2 -0
  157. package/fs/types/function/operator/proof.f.js +20 -2
  158. package/fs/types/list/module.f.js +1 -4
  159. package/fs/types/list/proof.f.d.ts +1 -1
  160. package/fs/types/list/proof.f.js +14 -6
  161. package/fs/types/map/proof.f.d.ts +1 -0
  162. package/fs/types/map/proof.f.js +10 -1
  163. package/fs/types/nibble_set/module.f.d.ts +13 -0
  164. package/fs/types/nibble_set/module.f.js +16 -0
  165. package/fs/types/object/module.f.d.ts +12 -8
  166. package/fs/types/object/module.f.js +9 -2
  167. package/fs/types/object/proof.f.d.ts +14 -0
  168. package/fs/types/object/proof.f.js +4 -0
  169. package/fs/types/ordered_map/proof.f.d.ts +1 -0
  170. package/fs/types/ordered_map/proof.f.js +39 -79
  171. package/fs/types/phantom/module.f.d.ts +22 -0
  172. package/fs/types/phantom/module.f.js +11 -0
  173. package/fs/types/prime_field/proof.f.d.ts +7 -0
  174. package/fs/types/prime_field/proof.f.js +63 -122
  175. package/fs/types/rtti/common/module.f.d.ts +4 -4
  176. package/fs/types/rtti/common/module.f.js +1 -1
  177. package/fs/types/rtti/module.f.d.ts +2 -3
  178. package/fs/types/rtti/parse/module.f.js +0 -1
  179. package/fs/types/rtti/ts/module.f.d.ts +26 -32
  180. package/fs/types/rtti/ts/module.f.js +2 -2
  181. package/fs/types/rtti/ts/proof.f.js +3 -3
  182. package/fs/types/rtti/validate/module.f.js +0 -1
  183. package/fs/types/sorted_list/module.f.d.ts +6 -0
  184. package/fs/types/sorted_list/module.f.js +11 -0
  185. package/fs/types/sorted_set/module.f.js +2 -8
  186. package/fs/types/ts/module.f.d.ts +1 -1
  187. package/fs/types/ts/module.f.js +3 -1
  188. package/fs/types/ts/proof.f.js +3 -2
  189. package/fs/website/proof.f.d.ts +1 -0
  190. package/fs/website/proof.f.js +8 -1
  191. package/package.json +3 -3
package/fs/ci/proof.f.js CHANGED
@@ -1,12 +1,14 @@
1
1
  import { ci, main } from "./module.f.js";
2
+ import { functionalscript } from "./config/module.f.js";
2
3
  import { utf8, utf8ToString } from "../text/module.f.js";
3
4
  import { empty as emptyVec, isVec } from "../types/bit_vec/module.f.js";
4
- import { test, parseGitHubAction } from "./common/module.f.js";
5
+ import { test, ubuntu, parseGitHubAction } from "./common/module.f.js";
5
6
  import { assert } from "../asserts/module.f.js";
6
7
  import { emptyState, virtual } from "../effects/node/virtual/module.f.js";
7
8
  import { parse as jsonParse } from "../json/module.f.js";
8
9
  import { unwrap } from "../types/result/module.f.js";
9
- const hasRun = (cmd) => (gha) => Object.values(gha.jobs).some(job => job.steps.some(step => step.run?.includes(cmd)));
10
+ import { definedValues } from "../types/object/module.f.js";
11
+ const hasRun = (cmd) => (gha) => definedValues(gha.jobs).some(job => job.steps.some(step => step.run?.includes(cmd)));
10
12
  const hasRunInJob = (jobId, cmd) => (gha) => gha.jobs[jobId]?.steps.some(step => step.run?.includes(cmd)) ?? false;
11
13
  const makeState = (rust, packageJson) => ({
12
14
  ...emptyState,
@@ -26,7 +28,7 @@ const workflow = (state) => {
26
28
  return unwrap(parseGitHubAction(jsonParse(utf8ToString(file))));
27
29
  };
28
30
  const run = (rust, nodeExtra = () => []) => {
29
- const [state, result] = virtual(makeState(rust))(ci({ nodeExtra, denoExtra: [], bunExtra: [] }));
31
+ const [state, result] = virtual(makeState(rust))(ci({ nodeExtra }));
30
32
  assert(result === 0, result);
31
33
  return workflow(state);
32
34
  };
@@ -36,6 +38,41 @@ const runDefault = (packageJson) => {
36
38
  return workflow(state);
37
39
  };
38
40
  export const proof = {
41
+ matrixShape: () => {
42
+ const gha = run(true);
43
+ assert(Object.keys(gha.jobs).length === 13, 'expected 13 CI jobs');
44
+ assert(gha.permissions.contents === 'read', 'expected read-only contents permission');
45
+ assert(Object.keys(gha.permissions).length === 1, 'expected least-privilege workflow permissions');
46
+ assert(hasRunInJob('ubuntu-intel', 'cargo test --target i686-unknown-linux-gnu')(gha), 'expected Ubuntu Intel i686 check');
47
+ assert(hasRunInJob('ubuntu-intel', 'cargo test --target i686-unknown-linux-gnu --release')(gha), 'expected Ubuntu Intel i686 release check');
48
+ assert(hasRunInJob('ubuntu-intel', 'cargo clippy --target i686-unknown-linux-gnu -- -D warnings')(gha), 'expected Ubuntu Intel i686 lint');
49
+ assert(hasRunInJob('ubuntu-intel', 'cargo clippy --target i686-unknown-linux-gnu --release -- -D warnings')(gha), 'expected Ubuntu Intel i686 release lint');
50
+ assert(hasRunInJob('ubuntu-arm', 'cargo test --release')(gha), 'expected native platform Rust release check');
51
+ assert(hasRunInJob('ubuntu-arm', 'cargo clippy -- -D warnings')(gha), 'expected native platform Rust lint');
52
+ assert(hasRunInJob('ubuntu-arm', 'cargo clippy --release -- -D warnings')(gha), 'expected native platform Rust release lint');
53
+ assert(hasRunInJob('wasm', 'cargo test --target wasm32-wasip1 --release')(gha), 'expected target-specific WASM release check');
54
+ assert(hasRunInJob('wasm', 'cargo clippy --target wasm32-wasip1 -- -D warnings')(gha), 'expected target-specific WASM Rust lint');
55
+ assert(hasRunInJob('wasm', 'cargo clippy --target wasm32-wasip1 --release -- -D warnings')(gha), 'expected target-specific WASM release lint');
56
+ assert(hasRunInJob('node22', 'fjs t')(gha), 'expected Node 22 FunctionalScript smoke test');
57
+ assert(hasRunInJob('node26', 'npm pack')(gha), 'expected Node 26 package check');
58
+ assert(!hasRun('npm publish --dry-run')(gha), 'unexpected npm publish dry-run');
59
+ for (const id of [
60
+ 'ubuntu-intel',
61
+ 'ubuntu-arm',
62
+ 'macos-intel',
63
+ 'macos-arm',
64
+ 'windows-intel',
65
+ 'windows-arm',
66
+ 'node22',
67
+ 'node24',
68
+ 'node26',
69
+ 'playwright',
70
+ ]) {
71
+ assert(hasRunInJob(id, 'npm ci')(gha), `expected npm ci in ${id}`);
72
+ }
73
+ assert(!hasRunInJob('deno', 'npm ci')(gha), 'unexpected npm ci in deno job');
74
+ assert(!hasRunInJob('bun', 'npm ci')(gha), 'unexpected npm ci in bun job');
75
+ },
39
76
  rust: () => {
40
77
  assert(hasRun('cargo')(run(true)), 'expected Rust steps');
41
78
  },
@@ -62,46 +99,36 @@ export const proof = {
62
99
  },
63
100
  },
64
101
  defaultSetup: {
65
- functionalscriptDemo: () => {
102
+ functionalscriptPackage: () => {
66
103
  const gha = runDefault('{"name":"functionalscript"}');
67
- assert(hasRun('fjs compile issues/demo/data/tree.json _tree.f.js')(gha), 'expected fjs demo compile');
68
104
  assert(hasRun('fjs t')(gha), 'expected fjs self-test');
69
- assert(hasRun('deno task fjs compile issues/demo/data/tree.json _tree.f.js')(gha), 'expected deno demo compile');
70
- assert(hasRun('deno task fjs t')(gha), 'expected deno self-test');
71
- assert(hasRun('bun ./fs/fjs/module.ts t')(gha), 'expected bun self-test');
72
- },
73
- otherPackageNoDemo: () => {
74
- const gha = runDefault('{"name":"other-package"}');
75
- assert(!hasRun('fjs compile issues/demo/data/tree.json _tree.f.js')(gha), 'unexpected fjs demo compile');
76
- assert(!hasRun('fjs t')(gha), 'unexpected fjs self-test');
77
- assert(!hasRun('deno task fjs compile issues/demo/data/tree.json _tree.f.js')(gha), 'unexpected deno demo compile');
78
- assert(!hasRun('deno task fjs t')(gha), 'unexpected deno self-test');
79
- assert(!hasRun('bun ./fs/fjs/module.ts t')(gha), 'unexpected bun self-test');
105
+ assert(hasRun(`deno run -A npm:functionalscript@${functionalscript} t`)(gha), 'expected deno self-test');
106
+ assert(hasRun(`bunx functionalscript@${functionalscript} t`)(gha), 'expected bun self-test');
80
107
  },
81
- uninstallPackageName: () => {
108
+ otherPackage: () => {
82
109
  const gha = runDefault('{"name":"other-package"}');
83
- assert(hasRun('npm uninstall other-package -g')(gha), 'expected package-specific uninstall');
84
- assert(!hasRun('npm uninstall functionalscript -g')(gha), 'unexpected functionalscript uninstall');
110
+ assert(hasRun(`deno run -A npm:functionalscript@${functionalscript} t`)(gha), 'expected canonical deno self-test');
111
+ assert(hasRun(`bunx functionalscript@${functionalscript} t`)(gha), 'expected canonical bun self-test');
85
112
  },
86
- malformedPackageJsonFallback: () => {
87
- const gha = runDefault('{');
88
- assert(!hasRun('fjs compile issues/demo/data/tree.json _tree.f.js')(gha), 'unexpected fjs demo compile');
89
- assert(hasRun('npm uninstall functionalscript -g')(gha), 'expected fallback uninstall');
113
+ configuredPackageVersion: () => {
114
+ const gha = runDefault('{"name":"other-package","version":"1.2.3"}');
115
+ assert(hasRun(`npm install -g functionalscript@${functionalscript}`)(gha), 'expected configured-version platform install');
116
+ assert(hasRun(`deno install -g -A npm:functionalscript@${functionalscript}`)(gha), 'expected configured-version deno install cache');
117
+ assert(hasRun('deno install --frozen')(gha), 'expected deno lock install');
118
+ assert(hasRun(`deno run -A npm:functionalscript@${functionalscript} t`)(gha), 'expected configured-version deno install');
119
+ assert(hasRun("deno test --allow-read --allow-env --allow-sys --coverage && deno coverage --include='.*module\\.f\\.ts'")(gha), 'expected limited-permission deno coverage');
120
+ assert(hasRun(`bun install -g functionalscript@${functionalscript}`)(gha), 'expected configured-version bun cache');
121
+ assert(hasRun('bun install --frozen-lockfile')(gha), 'expected bun lock install');
122
+ assert(hasRun(`bunx functionalscript@${functionalscript} t`)(gha), 'expected configured-version bun install');
90
123
  },
91
- missingPackageJsonFallback: () => {
124
+ missingPackageJson: () => {
92
125
  const gha = runDefault();
93
- assert(!hasRun('fjs compile issues/demo/data/tree.json _tree.f.js')(gha), 'unexpected fjs demo compile');
94
- assert(hasRun('npm uninstall functionalscript -g')(gha), 'expected fallback uninstall');
95
- },
96
- missingNameFallback: () => {
97
- const gha = runDefault('{"version":"1.0.0"}');
98
- assert(!hasRun('fjs compile issues/demo/data/tree.json _tree.f.js')(gha), 'unexpected fjs demo compile');
99
- assert(hasRun('npm uninstall functionalscript -g')(gha), 'expected fallback uninstall');
100
- },
101
- nonObjectFallback: () => {
102
- const gha = runDefault('[]');
103
- assert(!hasRun('fjs compile issues/demo/data/tree.json _tree.f.js')(gha), 'unexpected fjs demo compile');
104
- assert(hasRun('npm uninstall functionalscript -g')(gha), 'expected fallback uninstall');
126
+ assert(hasRun(`npm install -g functionalscript@${functionalscript}`)(gha), 'expected configured-version install');
105
127
  },
106
128
  },
129
+ ubuntu: () => {
130
+ const job = ubuntu([test({ run: 'echo hi' })]);
131
+ assert(job['runs-on'] !== undefined, 'expected runs-on');
132
+ assert(job.steps.length > 0, 'expected steps');
133
+ },
107
134
  };
@@ -1,2 +1,3 @@
1
1
  import { type Architecture, type MetaStep, type Os } from '../common/module.f.ts';
2
- export declare const rustSteps: (v: Os, a: Architecture) => readonly MetaStep[];
2
+ export declare const rustPlatformSteps: (v: Os, a: Architecture) => readonly MetaStep[];
3
+ export declare const rustWasmSteps: readonly MetaStep[];
@@ -1,50 +1,67 @@
1
1
  /**
2
- * CI step builder for the Rust crate: `cargo fmt`, `cargo clippy`, native and
3
- * `--release` test runs, plus matrix entries for WASM targets (Wasmtime,
4
- * Wasmer) and the 32-bit `i686` targets.
2
+ * CI step builder for the Rust crate: platform compatibility jobs run native
3
+ * tests and Clippy, Intel jobs also run 32-bit target tests and Clippy, and the
4
+ * canonical WASM job installs Wasmtime and Wasmer before exercising every WASM
5
+ * target.
5
6
  *
6
7
  * @module
7
8
  */
8
9
  import { wasmer, wasmtime } from "../config/module.f.js";
9
10
  import { install, test, uses } from "../common/module.f.js";
10
- const cargoTest = (target, config) => {
11
+ const cargoCommand = (tool, target, config) => {
11
12
  const to = target ? ` --target ${target}` : '';
12
13
  const co = config ? ` --config ${config}` : '';
13
- const main = `cargo test${to}${co}`;
14
+ return `cargo ${tool}${to}${co}`;
15
+ };
16
+ const cargoTest = (target, config) => test({ run: cargoCommand('test', target, config) });
17
+ const cargoClippy = (target) => test({ run: `${cargoCommand('clippy', target)} -- -D warnings` });
18
+ const cargoReleaseClippy = (target) => test({ run: `${cargoCommand('clippy', target)} --release -- -D warnings` });
19
+ const cargoTestPair = (target, config) => {
20
+ const main = cargoCommand('test', target, config);
14
21
  return [
15
- test({ run: main }),
22
+ cargoTest(target, config),
16
23
  test({ run: `${main} --release` })
17
24
  ];
18
25
  };
19
- const customTarget = (target) => [
26
+ const cargoReleaseTest = (target) => test({ run: `${cargoCommand('test', target)} --release` });
27
+ const targetChecks = (target) => [
28
+ cargoTest(target),
29
+ cargoReleaseTest(target),
30
+ cargoClippy(target),
31
+ cargoReleaseClippy(target)
32
+ ];
33
+ const rustTarget = (target) => [
20
34
  { type: 'rust', target },
21
- ...cargoTest(target)
35
+ ...targetChecks(target)
22
36
  ];
23
37
  const wasmTarget = (target) => [
24
- ...customTarget(target),
25
- ...cargoTest(target, '.cargo/config.wasmer.toml')
38
+ { type: 'rust', target },
39
+ ...targetChecks(target),
40
+ ...cargoTestPair(target, '.cargo/config.wasmer.toml')
26
41
  ];
27
42
  const i686 = (a, v) => {
28
43
  if (a === 'intel') {
29
44
  switch (v) {
30
- case 'windows': return customTarget('i686-pc-windows-msvc');
45
+ case 'windows': return rustTarget('i686-pc-windows-msvc');
31
46
  case 'ubuntu': return [
32
47
  { type: 'apt-get', package: 'libc6-dev-i386' },
33
- ...customTarget('i686-unknown-linux-gnu'),
48
+ ...rustTarget('i686-unknown-linux-gnu'),
34
49
  ];
35
50
  }
36
51
  }
37
52
  return [];
38
53
  };
39
- export const rustSteps = (v, a) => [
54
+ export const rustPlatformSteps = (v, a) => [
55
+ { type: 'rust' },
56
+ ...targetChecks(),
57
+ ...i686(a, v),
58
+ ];
59
+ export const rustWasmSteps = [
40
60
  test({ run: 'cargo fmt -- --check' }),
41
- test({ run: 'cargo clippy -- -D warnings' }),
42
- ...cargoTest(),
43
61
  install(uses('bytecodealliance/actions/wasmtime/setup', { version: wasmtime })),
44
62
  install(uses('wasmerio/setup-wasmer', { version: `v${wasmer}` })),
45
63
  ...wasmTarget('wasm32-wasip1'),
46
64
  ...wasmTarget('wasm32-wasip2'),
47
65
  ...wasmTarget('wasm32-unknown-unknown'),
48
66
  ...wasmTarget('wasm32-wasip1-threads'),
49
- ...i686(a, v),
50
67
  ];
@@ -1,9 +1,11 @@
1
1
  import { type NodeOp, type NodeProgramOptions, type Write } from '../effects/node/module.f.ts';
2
2
  import { type Effect } from '../effects/module.f.ts';
3
+ type Handler<O extends NodeOp> = (options: NodeProgramOptions) => Effect<O, number>;
3
4
  export type Command<O extends NodeOp> = {
4
5
  readonly names: readonly string[];
5
6
  readonly description: string;
6
- readonly handler: (options: NodeProgramOptions) => Effect<O, number>;
7
+ readonly handler: Handler<O> | Commands<O>;
7
8
  };
8
9
  export type Commands<O extends NodeOp> = readonly Command<O>[];
9
10
  export declare const dispatch: <O extends NodeOp>(commands: Commands<O>) => (options: NodeProgramOptions) => Effect<O | Write, number>;
11
+ export {};
@@ -1,24 +1,34 @@
1
1
  import { errorExit, log } from "../effects/node/module.f.js";
2
2
  import { pure } from "../effects/module.f.js";
3
+ import { at, fromEntries } from "../types/object/module.f.js";
3
4
  const helpMeta = { names: ['help', 'h', '?'], description: 'Print this help message' };
4
5
  export const dispatch = (commands) => (options) => {
5
6
  const [cmd, ...rest] = options.args;
6
7
  const rows = [...commands, helpMeta];
7
- const nameCol = rows.map(c => c.names.join(', '));
8
- const width = Math.max(...nameCol.map(s => s.length));
9
- const helpText = ['Available commands:', ...rows.map((c, i) => ` ${nameCol[i].padEnd(width)} ${c.description}`)].join('\n');
10
- const helpCommand = {
11
- ...helpMeta,
12
- handler: () => log(helpText).step(() => pure(0)),
13
- };
14
- const allCommands = [...commands, helpCommand];
15
- const map = Object.fromEntries(allCommands.flatMap(c => c.names.map(n => [n, c])));
8
+ const nameCol = rows.map(({ names }) => names.join(', '));
9
+ const width = Math.max(...nameCol.map(({ length }) => length));
10
+ const helpText = [
11
+ 'Available commands:',
12
+ ...rows.map(({ description }, i) => ` ${nameCol[i].padEnd(width)} ${description}`)
13
+ ].join('\n');
14
+ const map = fromEntries(commands.flatMap(c => c.names.map(n => [n, c])));
16
15
  if (cmd === undefined) {
17
16
  return errorExit(`Error: command is required.\n${helpText}`);
18
17
  }
19
- const found = map[cmd];
20
- if (found === undefined) {
18
+ if (helpMeta.names.includes(cmd)) {
19
+ const [target] = rest;
20
+ if (target !== undefined) {
21
+ const targetCmd = at(target)(map);
22
+ if (targetCmd !== null && typeof targetCmd.handler !== 'function') {
23
+ return dispatch(targetCmd.handler)({ ...options, args: ['help'] });
24
+ }
25
+ }
26
+ return log(helpText).step(() => pure(0));
27
+ }
28
+ const found = at(cmd)(map);
29
+ if (found === null) {
21
30
  return errorExit(`Error: unknown command "${cmd}".\n${helpText}`);
22
31
  }
23
- return found.handler({ ...options, args: rest });
32
+ const { handler } = found;
33
+ return (typeof handler === 'function' ? handler : dispatch(handler))({ ...options, args: rest });
24
34
  };
@@ -6,4 +6,9 @@ export declare const proof: {
6
6
  help: () => void;
7
7
  errorIncludesAvailable: () => void;
8
8
  handlerReceivesRemainingArgs: () => void;
9
+ nestedCommands: () => void;
10
+ nestedHelp: () => void;
11
+ prototypeNameIsUnknownCommand: () => void;
12
+ helpPrototypeSafe: () => void;
13
+ helpWithTarget: () => void;
9
14
  };
package/fs/cli/proof.f.js CHANGED
@@ -5,6 +5,7 @@ import { dispatch } from "./module.f.js";
5
5
  const makeOptions = (args) => ({
6
6
  args,
7
7
  env: {},
8
+ home: '.',
8
9
  std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
9
10
  testContext: { test: async () => { } },
10
11
  bunTestContext: { test: async () => { } },
@@ -83,4 +84,79 @@ export const proof = {
83
84
  throw ['unexpected args', captured];
84
85
  }
85
86
  },
87
+ nestedCommands: () => {
88
+ const inner = [{
89
+ names: ['ping'],
90
+ description: 'Inner ping',
91
+ handler: () => pure(42),
92
+ }];
93
+ const outer = [{
94
+ names: ['sub'],
95
+ description: 'Subcommand group',
96
+ handler: inner,
97
+ }];
98
+ const [, code] = run(outer)(['sub', 'ping']);
99
+ if (code !== 42) {
100
+ throw ['expected 42', code];
101
+ }
102
+ },
103
+ nestedHelp: () => {
104
+ const inner = [{
105
+ names: ['ping'],
106
+ description: 'Inner ping',
107
+ handler: () => pure(0),
108
+ }];
109
+ const outer = [{
110
+ names: ['sub'],
111
+ description: 'Subcommand group',
112
+ handler: inner,
113
+ }];
114
+ const [state, code] = run(outer)(['sub', 'help']);
115
+ if (code !== 0) {
116
+ throw ['expected exit 0', code];
117
+ }
118
+ if (!state.stdout.includes('ping')) {
119
+ throw 'expected inner command in help';
120
+ }
121
+ },
122
+ prototypeNameIsUnknownCommand: () => {
123
+ const [state, code] = run(echoCommands)(['toString']);
124
+ if (code !== 1) {
125
+ throw ['expected exit 1 for prototype-name command', code];
126
+ }
127
+ if (!state.stderr.includes('unknown command')) {
128
+ throw 'expected unknown-command error in stderr';
129
+ }
130
+ },
131
+ helpPrototypeSafe: () => {
132
+ const [state, code] = run(echoCommands)(['help', 'toString']);
133
+ if (code !== 0) {
134
+ throw ['expected exit 0, not a throw', code];
135
+ }
136
+ if (!state.stdout.includes('echo')) {
137
+ throw 'expected top-level help for unknown target';
138
+ }
139
+ },
140
+ helpWithTarget: () => {
141
+ const inner = [{
142
+ names: ['ping'],
143
+ description: 'Inner ping',
144
+ handler: () => pure(0),
145
+ }];
146
+ const outer = [{
147
+ names: ['sub'],
148
+ description: 'Subcommand group',
149
+ handler: inner,
150
+ }];
151
+ const [state, code] = run(outer)(['help', 'sub']);
152
+ if (code !== 0) {
153
+ throw ['expected exit 0', code];
154
+ }
155
+ if (!state.stdout.includes('ping')) {
156
+ throw 'expected inner command in help';
157
+ }
158
+ if (state.stdout.includes('Subcommand group')) {
159
+ throw 'expected inner help, not outer';
160
+ }
161
+ },
86
162
  };
@@ -3,4 +3,5 @@ export declare const proof: {
3
3
  sha256: () => void;
4
4
  sha384: () => void;
5
5
  sha512: () => void;
6
+ longKey: () => void;
6
7
  };
@@ -1,3 +1,4 @@
1
+ import { assertEq } from "../../asserts/module.f.js";
1
2
  import { utf8 } from "../../text/module.f.js";
2
3
  import { uint, vec } from "../../types/bit_vec/module.f.js";
3
4
  import { sha256, sha384, sha512 } from "../sha2/module.f.js";
@@ -28,5 +29,12 @@ export const proof = {
28
29
  if (r !== vec(512n)(0xb42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3an)) {
29
30
  throw r;
30
31
  }
32
+ },
33
+ // RFC 4231 Test Case 6: key (131 bytes of 0xaa = 1048 bits) exceeds SHA-256 block size (512 bits),
34
+ // so the key is first compressed via the hash function before use.
35
+ longKey: () => {
36
+ const key = vec(1048n)(BigInt('0x' + 'aa'.repeat(131)));
37
+ const r = hmac(sha256)(key)(utf8('Test Using Larger Than Block-Size Key - Hash Key First'));
38
+ assertEq(uint(r), 0x60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54n);
31
39
  }
32
40
  };
@@ -4,4 +4,5 @@ export declare const proof: {
4
4
  poker: () => {
5
5
  [k: string]: () => void;
6
6
  };
7
+ nullPointOps: () => void;
7
8
  };
@@ -1,3 +1,4 @@
1
+ import { assert } from "../../asserts/module.f.js";
1
2
  import { prime_field } from "../../types/prime_field/module.f.js";
2
3
  import { curve, secp256k1, secp192r1, secp256r1, eq, secp384r1, secp521r1 } from "./module.f.js";
3
4
  const poker = (param) => () => {
@@ -131,5 +132,14 @@ export const proof = {
131
132
  //secp256r1,
132
133
  };
133
134
  return Object.fromEntries(Object.entries(c).map(([k, v]) => [k, poker(v)]));
135
+ },
136
+ // Cover null (point at infinity) branches in neg, add, and eq.
137
+ nullPointOps: () => {
138
+ const c = secp256k1;
139
+ assert(c.neg(null) === null);
140
+ assert(eq(null)(null));
141
+ assert(!eq(null)(c.g));
142
+ assert(!eq(c.g)(null));
143
+ assert(eq(c.add(c.g)(null))(c.g));
134
144
  }
135
145
  };
@@ -1,10 +1,7 @@
1
- import { bitLength, divUp, roundUp } from "../../types/bigint/module.f.js";
1
+ import { bitLength, divUp8, roundUp8 } from "../../types/bigint/module.f.js";
2
2
  import { empty, length, msb, repeat, unpack, vec, vec8 } from "../../types/bit_vec/module.f.js";
3
3
  import { hmac } from "../hmac/module.f.js";
4
4
  import { computeSync } from "../sha2/module.f.js";
5
- // qlen to rlen
6
- const roundUp8 = roundUp(8n);
7
- const divUp8 = divUp(8n);
8
5
  /**
9
6
  * Builds RFC6979 helper conversions for a subgroup order.
10
7
  *
@@ -4,14 +4,13 @@
4
4
  * @module
5
5
  */
6
6
  import { type Access, type All, type Env, type Import, type Readdir } from '../effects/node/module.f.ts';
7
+ import type { StringMap } from '../types/object/module.f.ts';
7
8
  import { type Effect } from '../effects/module.f.ts';
8
9
  export type Module = {
9
10
  readonly proof?: unknown;
10
11
  readonly [k: string]: unknown;
11
12
  };
12
- export type ModuleMap = {
13
- readonly [k in string]: Module;
14
- };
13
+ export type ModuleMap = StringMap<string, Module>;
15
14
  /**
16
15
  * Returns `true` if the file should be loaded for proof discovery.
17
16
  *
@@ -41,3 +40,6 @@ export type LoadModuleOperations = Access | Import | All | Readdir;
41
40
  * deterministic regardless of filesystem traversal order.
42
41
  */
43
42
  export declare const loadModuleMap: (env: Env) => Effect<LoadModuleOperations, ModuleMap>;
43
+ export declare const proof: {
44
+ isSourceFile: () => void;
45
+ };
@@ -7,7 +7,8 @@ import { all, import_, readdir } from "../effects/node/module.f.js";
7
7
  import { cmp as strCmp } from "../types/string/module.f.js";
8
8
  import { unwrap } from "../types/result/module.f.js";
9
9
  import { pure } from "../effects/module.f.js";
10
- import { relativize, toPosix } from "../path/module.f.js";
10
+ import { join, relativize, toPosix } from "../path/module.f.js";
11
+ import { assert } from "../asserts/module.f.js";
11
12
  /**
12
13
  * Returns `true` if the file should be loaded for proof discovery.
13
14
  *
@@ -32,7 +33,7 @@ const allFiles = (s, predicate) => {
32
33
  if (name.startsWith('.')) {
33
34
  continue;
34
35
  }
35
- const file = `${p}/${name}`;
36
+ const file = join(p, name);
36
37
  if (!i.isFile) {
37
38
  if (name === 'node_modules') {
38
39
  continue;
@@ -80,3 +81,13 @@ export const loadModuleMap = (env) => {
80
81
  .map(([k, v]) => [relativize(prefix, k), v])
81
82
  .toSorted(([a], [b]) => strCmp(a)(b)))));
82
83
  };
84
+ export const proof = {
85
+ isSourceFile: () => {
86
+ assert(isSourceFile('module.js'));
87
+ assert(isSourceFile('module.ts'));
88
+ assert(isSourceFile('module.mts'));
89
+ assert(isSourceFile('module.mjs'));
90
+ assert(!isSourceFile('readme.md'));
91
+ assert(!isSourceFile('module.json'));
92
+ },
93
+ };
@@ -1,5 +1,6 @@
1
1
  export declare const proof: {
2
2
  parseMetadata: () => void;
3
3
  malformedJson: () => void;
4
+ validationError: () => void;
4
5
  validatePreservesOriginalObject: () => void;
5
6
  };
@@ -12,6 +12,11 @@ export const proof = {
12
12
  const result = validatePackageJsonText('{');
13
13
  assert(result[0] === 'error', result);
14
14
  },
15
+ validationError: () => {
16
+ // valid JSON but `name` is a number, not a string — validation should fail
17
+ const result = validatePackageJsonText('{"name": 42}');
18
+ assert(result[0] === 'error', result);
19
+ },
15
20
  validatePreservesOriginalObject: () => {
16
21
  const object = { name: 'x', version: '1.0.0', private: true };
17
22
  const metadata = unwrap(validatePackageJson(object));
@@ -1,4 +1,5 @@
1
1
  export declare const proof: {
2
+ shouldLoad: () => void;
2
3
  shouldPass: () => {
3
4
  then: () => undefined;
4
5
  };
package/fs/dev/proof.f.js CHANGED
@@ -1,5 +1,16 @@
1
- import { todo } from "../asserts/module.f.js";
1
+ import { assert, todo } from "../asserts/module.f.js";
2
+ import { shouldLoad } from "./module.f.js";
2
3
  export const proof = {
4
+ shouldLoad: () => {
5
+ assert(shouldLoad('foo.f.ts'));
6
+ assert(shouldLoad('bar.f.js'));
7
+ assert(shouldLoad('proof.ts'));
8
+ assert(shouldLoad('proof.js'));
9
+ assert(shouldLoad('proof.mts'));
10
+ assert(shouldLoad('proof.mjs'));
11
+ assert(!shouldLoad('module.ts'));
12
+ assert(!shouldLoad('readme.md'));
13
+ },
3
14
  shouldPass: () => ({
4
15
  then: () => undefined
5
16
  }),
@@ -9,7 +9,7 @@ export type AstConst = Primitive | AstModuleRef | AstArray | AstObject;
9
9
  export type AstModuleRef = ['aref' | 'cref', number];
10
10
  export type AstArray = ['array', readonly AstConst[]];
11
11
  export type AstObject = {
12
- readonly [k in string]: AstConst;
12
+ readonly [k in string]?: AstConst;
13
13
  };
14
14
  export type AstBody = readonly AstConst[];
15
15
  export declare const run: (body: AstBody) => (args: Array) => Unknown;
@@ -4,4 +4,9 @@ export declare const proof: {
4
4
  testAref: () => void;
5
5
  testArray: () => void;
6
6
  testObj: () => void;
7
+ testBool: () => void;
8
+ testStr: () => void;
9
+ testNull: () => void;
10
+ testBigint: () => void;
11
+ testUndefined: () => void;
7
12
  };
@@ -1,6 +1,7 @@
1
1
  import { sort } from "../../types/object/module.f.js";
2
2
  import { run } from "./module.f.js";
3
3
  import { stringifyAsTree } from "../serializer/module.f.js";
4
+ import { assertEq } from "../../asserts/module.f.js";
4
5
  export const proof = {
5
6
  test: () => {
6
7
  const djs = run([1])([]);
@@ -37,4 +38,20 @@ export const proof = {
37
38
  throw result;
38
39
  }
39
40
  },
41
+ testBool: () => {
42
+ assertEq(stringifyAsTree(sort)(run([true])([])), 'true');
43
+ assertEq(stringifyAsTree(sort)(run([false])([])), 'false');
44
+ },
45
+ testStr: () => {
46
+ assertEq(stringifyAsTree(sort)(run(['hello'])([])), '"hello"');
47
+ },
48
+ testNull: () => {
49
+ assertEq(stringifyAsTree(sort)(run([null])([])), 'null');
50
+ },
51
+ testBigint: () => {
52
+ assertEq(stringifyAsTree(sort)(run([42n])([])), '42n');
53
+ },
54
+ testUndefined: () => {
55
+ assertEq(stringifyAsTree(sort)(run([undefined])([])), 'undefined');
56
+ },
40
57
  };
@@ -7,7 +7,7 @@ import type { Primitive as JsonPrimitive } from '../json/module.f.ts';
7
7
  import { type Effect } from '../effects/module.f.ts';
8
8
  import { type WriteFile, type ReadFile, type Write } from '../effects/node/module.f.ts';
9
9
  export type Object = {
10
- readonly [k in string]: Unknown;
10
+ readonly [k in string]?: Unknown;
11
11
  };
12
12
  export type Array = readonly Unknown[];
13
13
  export type Primitive = JsonPrimitive | bigint | undefined;
@@ -2,8 +2,7 @@ import { transpile } from "./transpiler/module.f.js";
2
2
  import { stringify, stringifyAsTree } from "./serializer/module.f.js";
3
3
  import { sort } from "../types/object/module.f.js";
4
4
  import { pure } from "../effects/module.f.js";
5
- import { writeFile, error, } from "../effects/node/module.f.js";
6
- import { utf8 } from "../text/module.f.js";
5
+ import { writeUtf8File, error, } from "../effects/node/module.f.js";
7
6
  export const compile = args => {
8
7
  if (args.length < 2) {
9
8
  return error('Error: Requires 2 or more arguments')
@@ -20,7 +19,7 @@ export const compile = args => {
20
19
  const content = outputFileName.endsWith('.json')
21
20
  ? stringifyAsTree(sort)(result[1])
22
21
  : stringify(sort)(result[1]);
23
- return writeFile(outputFileName, utf8(content))
22
+ return writeUtf8File(outputFileName, content)
24
23
  .step(() => pure(0));
25
24
  });
26
25
  };