@fulmenhq/tsfulmen 0.2.0 → 0.2.2

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 (107) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +60 -7
  3. package/config/crucible-ts/agentic/roles/README.md +3 -3
  4. package/config/crucible-ts/library/fulencode/fixtures/README.md +18 -0
  5. package/config/crucible-ts/library/fulencode/fixtures/bom/bom.yaml +14 -0
  6. package/config/crucible-ts/library/fulencode/fixtures/detection/detection.yaml +12 -0
  7. package/config/crucible-ts/library/fulencode/fixtures/invalid-encodings/base64.yaml +10 -0
  8. package/config/crucible-ts/library/fulencode/fixtures/normalization/text-safe.yaml +10 -0
  9. package/config/crucible-ts/library/fulencode/fixtures/telemetry/telemetry-test-cases.yaml +24 -0
  10. package/config/crucible-ts/library/fulencode/fixtures/valid-encodings/base64.yaml +11 -0
  11. package/config/crucible-ts/taxonomy/library/platform-modules/v1.0.0/modules.yaml +2 -2
  12. package/config/crucible-ts/taxonomy/metrics.yaml +79 -1
  13. package/dist/appidentity/index.d.ts +1 -1
  14. package/dist/appidentity/index.js +122 -56
  15. package/dist/appidentity/index.js.map +1 -1
  16. package/dist/config/index.js +122 -56
  17. package/dist/config/index.js.map +1 -1
  18. package/dist/crucible/index.js +122 -56
  19. package/dist/crucible/index.js.map +1 -1
  20. package/dist/errors/index.d.ts +1 -1
  21. package/dist/errors/index.js +122 -56
  22. package/dist/errors/index.js.map +1 -1
  23. package/dist/foundry/index.js +122 -56
  24. package/dist/foundry/index.js.map +1 -1
  25. package/dist/fulencode/index.d.ts +102 -0
  26. package/dist/fulencode/index.js +806 -0
  27. package/dist/fulencode/index.js.map +1 -0
  28. package/dist/index.d.ts +2 -2
  29. package/dist/index.js +123 -57
  30. package/dist/index.js.map +1 -1
  31. package/dist/pathfinder/index.d.ts +1 -1
  32. package/dist/pathfinder/index.js +122 -56
  33. package/dist/pathfinder/index.js.map +1 -1
  34. package/dist/reports/license-inventory.csv +7 -6
  35. package/dist/schema/index.d.ts +2 -2
  36. package/dist/schema/index.js +122 -56
  37. package/dist/schema/index.js.map +1 -1
  38. package/dist/signals/index.js +122 -56
  39. package/dist/signals/index.js.map +1 -1
  40. package/dist/telemetry/http/index.js +122 -56
  41. package/dist/telemetry/http/index.js.map +1 -1
  42. package/dist/telemetry/index.d.ts +1 -1
  43. package/dist/telemetry/index.js +122 -56
  44. package/dist/telemetry/index.js.map +1 -1
  45. package/dist/telemetry/prometheus/index.d.ts +1 -1
  46. package/dist/telemetry/prometheus/index.js +122 -56
  47. package/dist/telemetry/prometheus/index.js.map +1 -1
  48. package/dist/{types-BJswWpQC.d.ts → types-DdoeE7F5.d.ts} +1 -1
  49. package/package.json +7 -2
  50. package/schemas/crucible-ts/library/fulencode/v1.0.0/README.md +37 -0
  51. package/schemas/crucible-ts/library/fulencode/v1.0.0/bom-result.schema.json +48 -0
  52. package/schemas/crucible-ts/library/fulencode/v1.0.0/decode-options.schema.json +60 -0
  53. package/schemas/crucible-ts/library/fulencode/v1.0.0/decoding-result.schema.json +70 -0
  54. package/schemas/crucible-ts/library/fulencode/v1.0.0/detect-options.schema.json +25 -0
  55. package/schemas/crucible-ts/library/fulencode/v1.0.0/detection-result.schema.json +57 -0
  56. package/schemas/crucible-ts/library/fulencode/v1.0.0/encode-options.schema.json +71 -0
  57. package/schemas/crucible-ts/library/fulencode/v1.0.0/encoding-result.schema.json +57 -0
  58. package/schemas/crucible-ts/library/fulencode/v1.0.0/fulencode-config.schema.json +8 -4
  59. package/schemas/crucible-ts/library/fulencode/v1.0.0/fulencode-error.schema.json +66 -0
  60. package/schemas/crucible-ts/library/fulencode/v1.0.0/normalization-result.schema.json +73 -0
  61. package/schemas/crucible-ts/library/fulencode/v1.0.0/normalize-options.schema.json +44 -0
  62. package/schemas/crucible-ts/meta/README.md +38 -2
  63. package/schemas/crucible-ts/meta/draft-04/schema.json +222 -0
  64. package/schemas/crucible-ts/meta/draft-06/schema.json +218 -0
  65. package/schemas/crucible-ts/meta/draft-2019-09/meta/applicator.json +93 -0
  66. package/schemas/crucible-ts/meta/draft-2019-09/meta/content.json +21 -0
  67. package/schemas/crucible-ts/meta/draft-2019-09/meta/core.json +58 -0
  68. package/schemas/crucible-ts/meta/draft-2019-09/meta/format.json +15 -0
  69. package/schemas/crucible-ts/meta/draft-2019-09/meta/meta-data.json +35 -0
  70. package/schemas/crucible-ts/meta/draft-2019-09/meta/validation.json +119 -0
  71. package/schemas/crucible-ts/meta/draft-2019-09/offline.schema.json +148 -0
  72. package/schemas/crucible-ts/meta/draft-2019-09/schema.json +62 -0
  73. package/schemas/crucible-ts/meta/fixtures/draft-04-sample.json +16 -0
  74. package/schemas/crucible-ts/meta/fixtures/draft-06-sample.json +16 -0
  75. package/schemas/crucible-ts/meta/fixtures/draft-07-sample.json +34 -0
  76. package/schemas/crucible-ts/meta/fixtures/draft-2019-09-sample.json +21 -0
  77. package/schemas/crucible-ts/meta/fixtures/draft-2020-12-sample.json +21 -0
  78. package/schemas/crucible-ts/taxonomy/library/fulencode/normalization-profiles/v1.0.0/profiles.yaml +16 -0
  79. package/schemas/crucible-ts/upstream/3leaps/crucible/PROVENANCE.md +64 -0
  80. package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/access-tier.dimension.json +103 -0
  81. package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/retention-lifecycle.dimension.json +103 -0
  82. package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/schema-stability.dimension.json +100 -0
  83. package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/sensitivity.dimension.json +130 -0
  84. package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/velocity-mode.dimension.json +79 -0
  85. package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/volatility.dimension.json +72 -0
  86. package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/volume-tier.dimension.json +66 -0
  87. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/catalog/classifiers/README.md +29 -0
  88. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/access-tier-classification.md +163 -0
  89. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/classifiers-framework.md +157 -0
  90. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/data-sensitivity-classification.md +259 -0
  91. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/retention-lifecycle-classification.md +200 -0
  92. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/schema-stability-classification.md +205 -0
  93. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/velocity-mode-classification.md +222 -0
  94. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/volatility-classification.md +209 -0
  95. package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/volume-tier-classification.md +200 -0
  96. package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/ailink/v0/README.md +48 -0
  97. package/schemas/crucible-ts/upstream/3leaps/{ailink → crucible/schemas/ailink}/v0/prompt.schema.json +4 -18
  98. package/schemas/crucible-ts/upstream/3leaps/{ailink → crucible/schemas/ailink}/v0/search-response.schema.json +7 -37
  99. package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/classifiers/v0/dimension-definition.schema.json +247 -0
  100. package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/classifiers/v0/sensitivity-level.schema.json +67 -0
  101. package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/error-response.schema.json +59 -0
  102. package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/lifecycle-phases.data.json +102 -0
  103. package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/lifecycle-phases.schema.json +101 -0
  104. package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/release-phase.schema.json +18 -0
  105. package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/types.schema.json +177 -0
  106. package/schemas/crucible-ts/upstream/3leaps/PROVENANCE.md +0 -43
  107. /package/schemas/crucible-ts/upstream/3leaps/{agentic → crucible/schemas/agentic}/v0/role-prompt.schema.json +0 -0
@@ -0,0 +1,806 @@
1
+ import { crc32, xxhash128 } from 'hash-wasm';
2
+ import { createHash } from 'crypto';
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+
14
+ // src/crucible/fulhash/types.ts
15
+ var Algorithm;
16
+ var init_types = __esm({
17
+ "src/crucible/fulhash/types.ts"() {
18
+ Algorithm = /* @__PURE__ */ ((Algorithm2) => {
19
+ Algorithm2["XXH3_128"] = "xxh3-128";
20
+ Algorithm2["SHA256"] = "sha256";
21
+ Algorithm2["CRC32"] = "crc32";
22
+ Algorithm2["CRC32C"] = "crc32c";
23
+ return Algorithm2;
24
+ })(Algorithm || {});
25
+ }
26
+ });
27
+ function hexToBytes(hex) {
28
+ const bytes = new Uint8Array(4);
29
+ for (let i = 0; i < 4; i++) {
30
+ bytes[i] = Number.parseInt(hex.substr(i * 2, 2), 16);
31
+ }
32
+ return bytes;
33
+ }
34
+ async function hashBytes(data) {
35
+ const hex = await crc32(data);
36
+ return hexToBytes(hex);
37
+ }
38
+ async function hashString(str, encoding = "utf8") {
39
+ if (encoding !== "utf8") {
40
+ const buf = Buffer.from(str, encoding);
41
+ const hex2 = await crc32(buf);
42
+ return hexToBytes(hex2);
43
+ }
44
+ const hex = await crc32(str);
45
+ return hexToBytes(hex);
46
+ }
47
+ var init_crc32 = __esm({
48
+ "src/fulhash/algorithms/crc32.ts"() {
49
+ }
50
+ });
51
+ function hexToBytes2(hex) {
52
+ const bytes = new Uint8Array(4);
53
+ for (let i = 0; i < 4; i++) {
54
+ bytes[i] = Number.parseInt(hex.substr(i * 2, 2), 16);
55
+ }
56
+ return bytes;
57
+ }
58
+ async function hashBytes2(data) {
59
+ const hex = await crc32(data, CRC32C_POLYNOMIAL);
60
+ return hexToBytes2(hex);
61
+ }
62
+ async function hashString2(str, encoding = "utf8") {
63
+ if (encoding !== "utf8") {
64
+ const buf = Buffer.from(str, encoding);
65
+ const hex2 = await crc32(buf, CRC32C_POLYNOMIAL);
66
+ return hexToBytes2(hex2);
67
+ }
68
+ const hex = await crc32(str, CRC32C_POLYNOMIAL);
69
+ return hexToBytes2(hex);
70
+ }
71
+ var CRC32C_POLYNOMIAL;
72
+ var init_crc32c = __esm({
73
+ "src/fulhash/algorithms/crc32c.ts"() {
74
+ CRC32C_POLYNOMIAL = 2197175160;
75
+ }
76
+ });
77
+ function hashBytes3(data) {
78
+ const hash2 = createHash("sha256");
79
+ hash2.update(data);
80
+ return new Uint8Array(hash2.digest());
81
+ }
82
+ function hashString3(str, encoding = "utf8") {
83
+ const hash2 = createHash("sha256");
84
+ hash2.update(str, encoding);
85
+ return new Uint8Array(hash2.digest());
86
+ }
87
+ var init_sha256 = __esm({
88
+ "src/fulhash/algorithms/sha256.ts"() {
89
+ }
90
+ });
91
+
92
+ // src/fulhash/errors.ts
93
+ var FulHashError, UnsupportedAlgorithmError, InvalidChecksumError, InvalidChecksumFormatError;
94
+ var init_errors = __esm({
95
+ "src/fulhash/errors.ts"() {
96
+ FulHashError = class _FulHashError extends Error {
97
+ constructor(message) {
98
+ super(message);
99
+ this.name = "FulHashError";
100
+ Object.setPrototypeOf(this, _FulHashError.prototype);
101
+ }
102
+ };
103
+ UnsupportedAlgorithmError = class _UnsupportedAlgorithmError extends FulHashError {
104
+ constructor(algorithm, supportedAlgorithms) {
105
+ super(
106
+ `Unsupported algorithm "${algorithm}". Supported algorithms: ${supportedAlgorithms.join(", ")}`
107
+ );
108
+ this.name = "UnsupportedAlgorithmError";
109
+ Object.setPrototypeOf(this, _UnsupportedAlgorithmError.prototype);
110
+ }
111
+ };
112
+ InvalidChecksumError = class _InvalidChecksumError extends FulHashError {
113
+ constructor(checksum, reason) {
114
+ super(`Invalid checksum "${checksum}": ${reason}. Expected format: algorithm:hex`);
115
+ this.name = "InvalidChecksumError";
116
+ Object.setPrototypeOf(this, _InvalidChecksumError.prototype);
117
+ }
118
+ };
119
+ InvalidChecksumFormatError = class _InvalidChecksumFormatError extends InvalidChecksumError {
120
+ constructor(checksum, reason) {
121
+ super(checksum, reason);
122
+ this.name = "InvalidChecksumFormatError";
123
+ Object.setPrototypeOf(this, _InvalidChecksumFormatError.prototype);
124
+ }
125
+ };
126
+ }
127
+ });
128
+ function hexToBytes3(hex) {
129
+ const bytes = new Uint8Array(16);
130
+ for (let i = 0; i < 16; i++) {
131
+ bytes[i] = Number.parseInt(hex.substr(i * 2, 2), 16);
132
+ }
133
+ return bytes;
134
+ }
135
+ async function hashBytes4(data) {
136
+ const hex = await xxhash128(data);
137
+ return hexToBytes3(hex);
138
+ }
139
+ async function hashString4(str, encoding = "utf8") {
140
+ if (encoding !== "utf8") {
141
+ throw new FulHashError(
142
+ "XXH3-128 only supports UTF-8 encoding. Use utf8 encoding or convert data to Uint8Array."
143
+ );
144
+ }
145
+ const hex = await xxhash128(str);
146
+ return hexToBytes3(hex);
147
+ }
148
+ var init_xxh3 = __esm({
149
+ "src/fulhash/algorithms/xxh3.ts"() {
150
+ init_errors();
151
+ }
152
+ });
153
+
154
+ // src/fulhash/digest.ts
155
+ var Digest;
156
+ var init_digest = __esm({
157
+ "src/fulhash/digest.ts"() {
158
+ init_types();
159
+ init_errors();
160
+ Digest = class _Digest {
161
+ algorithm;
162
+ _bytes;
163
+ hex;
164
+ formatted;
165
+ constructor(algorithm, bytes) {
166
+ this.algorithm = algorithm;
167
+ this._bytes = new Uint8Array(bytes);
168
+ this.hex = Array.from(this._bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
169
+ this.formatted = `${this.algorithm}:${this.hex}`;
170
+ Object.freeze(this);
171
+ }
172
+ get bytes() {
173
+ return Array.from(this._bytes);
174
+ }
175
+ toJSON() {
176
+ return {
177
+ algorithm: this.algorithm,
178
+ hex: this.hex,
179
+ formatted: this.formatted
180
+ };
181
+ }
182
+ toString() {
183
+ return this.formatted;
184
+ }
185
+ static parse(formatted) {
186
+ if (!formatted.includes(":")) {
187
+ throw new InvalidChecksumFormatError(formatted, "missing separator");
188
+ }
189
+ const [algorithmStr, hex] = formatted.split(":", 2);
190
+ if (!algorithmStr || !hex) {
191
+ throw new InvalidChecksumFormatError(formatted, "invalid format");
192
+ }
193
+ const algorithm = algorithmStr;
194
+ if (!Object.values(Algorithm).includes(algorithm)) {
195
+ throw new UnsupportedAlgorithmError(algorithm, Object.values(Algorithm));
196
+ }
197
+ if (!/^[0-9a-f]+$/.test(hex)) {
198
+ throw new InvalidChecksumError(
199
+ formatted,
200
+ "hex must contain only lowercase hexadecimal characters"
201
+ );
202
+ }
203
+ let expectedLength;
204
+ switch (algorithm) {
205
+ case "xxh3-128" /* XXH3_128 */:
206
+ expectedLength = 32;
207
+ break;
208
+ case "sha256" /* SHA256 */:
209
+ expectedLength = 64;
210
+ break;
211
+ case "crc32" /* CRC32 */:
212
+ case "crc32c" /* CRC32C */:
213
+ expectedLength = 8;
214
+ break;
215
+ default:
216
+ throw new UnsupportedAlgorithmError(algorithm, Object.values(Algorithm));
217
+ }
218
+ if (hex.length !== expectedLength) {
219
+ throw new InvalidChecksumError(
220
+ formatted,
221
+ `invalid hex length for ${algorithm}: expected ${expectedLength}, got ${hex.length}`
222
+ );
223
+ }
224
+ const bytes = new Uint8Array(hex.length / 2);
225
+ for (let i = 0; i < hex.length; i += 2) {
226
+ bytes[i / 2] = Number.parseInt(hex.slice(i, i + 2), 16);
227
+ }
228
+ return new _Digest(algorithm, bytes);
229
+ }
230
+ equals(other) {
231
+ if (this.algorithm !== other.algorithm) {
232
+ return false;
233
+ }
234
+ if (this.hex !== other.hex) {
235
+ return false;
236
+ }
237
+ return true;
238
+ }
239
+ static async verify(data, checksum) {
240
+ const expected = _Digest.parse(checksum);
241
+ const { hash: hash2 } = await Promise.resolve().then(() => (init_hash(), hash_exports));
242
+ const actual = await hash2(data, { algorithm: expected.algorithm });
243
+ return actual.equals(expected);
244
+ }
245
+ };
246
+ }
247
+ });
248
+
249
+ // src/fulhash/hash.ts
250
+ var hash_exports = {};
251
+ __export(hash_exports, {
252
+ hash: () => hash,
253
+ hashBytes: () => hashBytes5,
254
+ hashString: () => hashString5
255
+ });
256
+ async function hash(input, options) {
257
+ const algorithm = options?.algorithm ?? "xxh3-128" /* XXH3_128 */;
258
+ const encoding = options?.encoding ?? "utf8";
259
+ let bytes;
260
+ switch (algorithm) {
261
+ case "sha256" /* SHA256 */:
262
+ if (typeof input === "string") {
263
+ bytes = hashString3(input, encoding);
264
+ } else {
265
+ bytes = hashBytes3(input);
266
+ }
267
+ break;
268
+ case "xxh3-128" /* XXH3_128 */:
269
+ if (typeof input === "string") {
270
+ if (encoding !== "utf8") {
271
+ bytes = await hashBytes4(Buffer.from(input, encoding));
272
+ } else {
273
+ bytes = await hashString4(input, "utf8");
274
+ }
275
+ } else {
276
+ bytes = await hashBytes4(input);
277
+ }
278
+ break;
279
+ case "crc32" /* CRC32 */:
280
+ if (typeof input === "string") {
281
+ bytes = await hashString(input, encoding);
282
+ } else {
283
+ bytes = await hashBytes(input);
284
+ }
285
+ break;
286
+ case "crc32c" /* CRC32C */:
287
+ if (typeof input === "string") {
288
+ bytes = await hashString2(input, encoding);
289
+ } else {
290
+ bytes = await hashBytes2(input);
291
+ }
292
+ break;
293
+ default:
294
+ throw new UnsupportedAlgorithmError(algorithm, Object.values(Algorithm));
295
+ }
296
+ return new Digest(algorithm, bytes);
297
+ }
298
+ async function hashString5(str, options) {
299
+ return hash(str, options);
300
+ }
301
+ async function hashBytes5(data, options) {
302
+ return hash(data, options);
303
+ }
304
+ var init_hash = __esm({
305
+ "src/fulhash/hash.ts"() {
306
+ init_types();
307
+ init_crc32();
308
+ init_crc32c();
309
+ init_sha256();
310
+ init_xxh3();
311
+ init_digest();
312
+ init_errors();
313
+ }
314
+ });
315
+
316
+ // src/fulencode/errors.ts
317
+ var FulencodeError = class extends Error {
318
+ code;
319
+ operation;
320
+ inputFormat;
321
+ outputFormat;
322
+ details;
323
+ constructor(args) {
324
+ super(args.message);
325
+ this.name = "FulencodeError";
326
+ this.code = args.code;
327
+ this.operation = args.operation;
328
+ this.inputFormat = args.inputFormat;
329
+ this.outputFormat = args.outputFormat;
330
+ this.details = args.details;
331
+ if (args.cause !== void 0) {
332
+ this.cause = args.cause;
333
+ }
334
+ }
335
+ };
336
+
337
+ // src/fulencode/types.ts
338
+ var EncodingFormat = {
339
+ BASE64: "base64",
340
+ BASE64URL: "base64url",
341
+ BASE64_RAW: "base64_raw",
342
+ BASE32: "base32",
343
+ BASE32HEX: "base32hex",
344
+ HEX: "hex",
345
+ UTF8: "utf-8",
346
+ UTF16LE: "utf-16le",
347
+ UTF16BE: "utf-16be",
348
+ ISO_8859_1: "iso-8859-1",
349
+ CP1252: "cp1252",
350
+ ASCII: "ascii"
351
+ };
352
+
353
+ // src/fulencode/fulencode.ts
354
+ init_types();
355
+ init_hash();
356
+
357
+ // src/fulencode/base32.ts
358
+ var RFC4648_BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
359
+ var RFC4648_BASE32HEX_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
360
+ function getAlphabet(variant) {
361
+ return variant === "base32" ? RFC4648_BASE32_ALPHABET : RFC4648_BASE32HEX_ALPHABET;
362
+ }
363
+ function encodeBase32(data, variant, options) {
364
+ if (data.length === 0) return "";
365
+ const alphabet = getAlphabet(variant);
366
+ let bits = 0;
367
+ let value = 0;
368
+ let out = "";
369
+ for (const b of data) {
370
+ value = value << 8 | b;
371
+ bits += 8;
372
+ while (bits >= 5) {
373
+ const idx = value >>> bits - 5 & 31;
374
+ out += alphabet[idx];
375
+ bits -= 5;
376
+ }
377
+ }
378
+ if (bits > 0) {
379
+ const idx = value << 5 - bits & 31;
380
+ out += alphabet[idx];
381
+ }
382
+ if (options.padding) {
383
+ while (out.length % 8 !== 0) out += "=";
384
+ }
385
+ return out;
386
+ }
387
+ function buildDecodeMap(alphabet) {
388
+ const map = /* @__PURE__ */ new Map();
389
+ for (let i = 0; i < alphabet.length; i++) {
390
+ const ch = alphabet[i];
391
+ map.set(ch, i);
392
+ map.set(ch.toLowerCase(), i);
393
+ }
394
+ return map;
395
+ }
396
+ function decodeBase32(input, variant, options) {
397
+ const alphabet = getAlphabet(variant);
398
+ const decodeMap = buildDecodeMap(alphabet);
399
+ let s = input;
400
+ if (options.ignoreWhitespace) {
401
+ s = s.replace(/[\n\r\t\s]/g, "");
402
+ }
403
+ const firstPad = s.indexOf("=");
404
+ if (firstPad !== -1) {
405
+ if (options.validatePadding) {
406
+ for (let i = firstPad; i < s.length; i++) {
407
+ if (s[i] !== "=") {
408
+ throw new Error("Invalid base32 padding");
409
+ }
410
+ }
411
+ if (s.length % 8 !== 0) {
412
+ throw new Error("Invalid base32 length (padding)");
413
+ }
414
+ }
415
+ s = s.slice(0, firstPad);
416
+ }
417
+ let bits = 0;
418
+ let value = 0;
419
+ const out = [];
420
+ for (let i = 0; i < s.length; i++) {
421
+ const ch = s[i];
422
+ const v = decodeMap.get(ch);
423
+ if (v === void 0) {
424
+ throw new Error(`Invalid base32 character: ${ch}`);
425
+ }
426
+ value = value << 5 | v;
427
+ bits += 5;
428
+ if (bits >= 8) {
429
+ out.push(value >>> bits - 8 & 255);
430
+ bits -= 8;
431
+ }
432
+ }
433
+ return Uint8Array.from(out);
434
+ }
435
+
436
+ // src/fulencode/fulencode.ts
437
+ function wrapLines(data, lineLength, lineEnding) {
438
+ if (lineLength <= 0) return data;
439
+ let out = "";
440
+ for (let i = 0; i < data.length; i += lineLength) {
441
+ out += data.slice(i, i + lineLength);
442
+ if (i + lineLength < data.length) out += lineEnding;
443
+ }
444
+ return out;
445
+ }
446
+ function requireBytes(input, format) {
447
+ if (typeof input === "string") {
448
+ throw new FulencodeError({
449
+ code: "INVALID_INPUT_TYPE",
450
+ message: `Format '${format}' requires binary input (Uint8Array)`,
451
+ operation: "encode",
452
+ outputFormat: format,
453
+ details: { expected: "Uint8Array", actual: "string" }
454
+ });
455
+ }
456
+ return input;
457
+ }
458
+ function normalizeWhitespace(input, ignoreWhitespace) {
459
+ if (!ignoreWhitespace) return input;
460
+ return input.replace(/[\n\r\t\s]/g, "");
461
+ }
462
+ function base64FromBytes(data) {
463
+ return Buffer.from(data).toString("base64");
464
+ }
465
+ function base64UrlFromBytes(data) {
466
+ return base64FromBytes(data).replace(/\+/g, "-").replace(/\//g, "_");
467
+ }
468
+ function applyBase64Padding(s, padding) {
469
+ return padding ? s.padEnd(Math.ceil(s.length / 4) * 4, "=") : s.replace(/=+$/g, "");
470
+ }
471
+ function decodeBase64Strict(input, variant, validatePadding) {
472
+ const allowed = variant === "base64" ? /^[A-Za-z0-9+/]*={0,2}$/ : /^[A-Za-z0-9\-_]*={0,2}$/;
473
+ if (!allowed.test(input)) {
474
+ throw new Error("Invalid base64 characters");
475
+ }
476
+ if (validatePadding) {
477
+ if (input.length % 4 !== 0) {
478
+ throw new Error("Invalid base64 length");
479
+ }
480
+ const firstPad = input.indexOf("=");
481
+ if (firstPad !== -1) {
482
+ for (let i = firstPad; i < input.length; i++) {
483
+ if (input[i] !== "=") throw new Error("Invalid base64 padding");
484
+ }
485
+ }
486
+ }
487
+ const s = variant === "base64url" ? input.replace(/-/g, "+").replace(/_/g, "/") : input;
488
+ return Uint8Array.from(Buffer.from(s, "base64"));
489
+ }
490
+ async function computeChecksumIfRequested(data, algorithm) {
491
+ if (!algorithm) return {};
492
+ if (algorithm !== "sha256" && algorithm !== "xxh3-128") {
493
+ throw new FulencodeError({
494
+ code: "UNSUPPORTED_CHECKSUM",
495
+ message: `Unsupported checksum algorithm: ${algorithm}`,
496
+ operation: "encode",
497
+ details: { algorithm }
498
+ });
499
+ }
500
+ const digest = await hashBytes5(data, {
501
+ algorithm: algorithm === "sha256" ? "sha256" /* SHA256 */ : "xxh3-128" /* XXH3_128 */
502
+ });
503
+ return { checksum: digest.toString(), checksumAlgorithm: algorithm };
504
+ }
505
+ async function encode(input, format, options = {}) {
506
+ const warnings = [];
507
+ if (options.embedChecksum) {
508
+ throw new FulencodeError({
509
+ code: "UNSUPPORTED_FEATURE",
510
+ message: "embedChecksum is not implemented in tsfulmen yet",
511
+ operation: "encode",
512
+ outputFormat: format
513
+ });
514
+ }
515
+ const padding = options.padding ?? true;
516
+ const lineLength = options.lineLength ?? null;
517
+ const lineEnding = options.lineEnding ?? "\n";
518
+ const maxEncodedSize = options.maxEncodedSize ?? 500 * 1024 * 1024;
519
+ const onError = options.onError ?? "strict";
520
+ let data;
521
+ let inputBytes;
522
+ try {
523
+ switch (format) {
524
+ case "base64": {
525
+ inputBytes = requireBytes(input, format);
526
+ data = applyBase64Padding(base64FromBytes(inputBytes), padding);
527
+ break;
528
+ }
529
+ case "base64url": {
530
+ inputBytes = requireBytes(input, format);
531
+ data = applyBase64Padding(base64UrlFromBytes(inputBytes), padding);
532
+ break;
533
+ }
534
+ case "base64_raw": {
535
+ inputBytes = requireBytes(input, format);
536
+ data = applyBase64Padding(base64FromBytes(inputBytes), false);
537
+ break;
538
+ }
539
+ case "hex": {
540
+ inputBytes = requireBytes(input, format);
541
+ const hex = Buffer.from(inputBytes).toString("hex");
542
+ data = (options.hexCase ?? "lower") === "upper" ? hex.toUpperCase() : hex;
543
+ break;
544
+ }
545
+ case "base32":
546
+ case "base32hex": {
547
+ inputBytes = requireBytes(input, format);
548
+ data = encodeBase32(inputBytes, format, { padding });
549
+ break;
550
+ }
551
+ case "utf-8": {
552
+ if (typeof input === "string") {
553
+ data = input;
554
+ inputBytes = new TextEncoder().encode(input);
555
+ warnings.push("string_input_passthrough");
556
+ } else {
557
+ inputBytes = input;
558
+ if (onError === "strict") {
559
+ data = new TextDecoder("utf-8", { fatal: true }).decode(inputBytes);
560
+ } else {
561
+ data = new TextDecoder("utf-8", { fatal: false }).decode(inputBytes);
562
+ }
563
+ }
564
+ break;
565
+ }
566
+ case "utf-16le": {
567
+ if (typeof input === "string") {
568
+ data = input;
569
+ inputBytes = Uint8Array.from(Buffer.from(input, "utf16le"));
570
+ warnings.push("string_input_passthrough");
571
+ } else {
572
+ inputBytes = input;
573
+ data = Buffer.from(inputBytes).toString("utf16le");
574
+ }
575
+ break;
576
+ }
577
+ case "utf-16be": {
578
+ if (typeof input === "string") {
579
+ data = input;
580
+ const le = Buffer.from(input, "utf16le");
581
+ for (let i = 0; i + 1 < le.length; i += 2) {
582
+ const a = le[i];
583
+ le[i] = le[i + 1];
584
+ le[i + 1] = a;
585
+ }
586
+ inputBytes = Uint8Array.from(le);
587
+ warnings.push("string_input_passthrough");
588
+ } else {
589
+ inputBytes = input;
590
+ const swapped = Buffer.from(inputBytes);
591
+ for (let i = 0; i + 1 < swapped.length; i += 2) {
592
+ const a = swapped[i];
593
+ swapped[i] = swapped[i + 1];
594
+ swapped[i + 1] = a;
595
+ }
596
+ data = swapped.toString("utf16le");
597
+ }
598
+ break;
599
+ }
600
+ case "iso-8859-1": {
601
+ if (typeof input === "string") {
602
+ data = input;
603
+ inputBytes = Uint8Array.from(Buffer.from(input, "latin1"));
604
+ warnings.push("string_input_passthrough");
605
+ } else {
606
+ inputBytes = input;
607
+ data = Buffer.from(inputBytes).toString("latin1");
608
+ }
609
+ break;
610
+ }
611
+ case "ascii": {
612
+ if (typeof input === "string") {
613
+ data = input;
614
+ inputBytes = Uint8Array.from(Buffer.from(input, "ascii"));
615
+ warnings.push("string_input_passthrough");
616
+ } else {
617
+ inputBytes = input;
618
+ data = Buffer.from(inputBytes).toString("ascii");
619
+ }
620
+ break;
621
+ }
622
+ case "cp1252": {
623
+ throw new FulencodeError({
624
+ code: "UNSUPPORTED_FORMAT",
625
+ message: "cp1252 is not implemented in tsfulmen yet",
626
+ operation: "encode",
627
+ outputFormat: format
628
+ });
629
+ }
630
+ default: {
631
+ throw new FulencodeError({
632
+ code: "UNSUPPORTED_FORMAT",
633
+ message: `Unsupported encoding format: ${format}`,
634
+ operation: "encode",
635
+ outputFormat: format
636
+ });
637
+ }
638
+ }
639
+ } catch (err) {
640
+ if (err instanceof FulencodeError) throw err;
641
+ throw new FulencodeError({
642
+ code: "ENCODE_FAILED",
643
+ message: err.message,
644
+ operation: "encode",
645
+ outputFormat: format,
646
+ cause: err
647
+ });
648
+ }
649
+ if (lineLength !== null) {
650
+ data = wrapLines(data, lineLength, lineEnding);
651
+ }
652
+ if (data.length > maxEncodedSize) {
653
+ throw new FulencodeError({
654
+ code: "OUTPUT_TOO_LARGE",
655
+ message: `Encoded output exceeds maxEncodedSize (${maxEncodedSize})`,
656
+ operation: "encode",
657
+ outputFormat: format,
658
+ details: { maxEncodedSize, outputSize: data.length }
659
+ });
660
+ }
661
+ const checksum = await computeChecksumIfRequested(inputBytes, options.computeChecksum);
662
+ return {
663
+ data,
664
+ format,
665
+ inputSize: inputBytes.length,
666
+ outputSize: data.length,
667
+ warnings,
668
+ ...checksum
669
+ };
670
+ }
671
+ async function decode(input, format, options = {}) {
672
+ const warnings = [];
673
+ const ignoreWhitespace = options.ignoreWhitespace ?? (format === "base64" || format === "base64url" || format === "hex" || format === "base32" || format === "base32hex");
674
+ const validatePadding = options.validatePadding ?? (format === "base64" || format === "base64url" || format === "base32" || format === "base32hex");
675
+ const maxDecodedSize = options.maxDecodedSize ?? 100 * 1024 * 1024;
676
+ const onError = options.onError ?? "strict";
677
+ const inputStr = typeof input === "string" ? input : Buffer.from(input).toString("utf8");
678
+ const normalized = normalizeWhitespace(inputStr, ignoreWhitespace);
679
+ let decoded;
680
+ const correctionsApplied = 0;
681
+ try {
682
+ switch (format) {
683
+ case "base64": {
684
+ const s = applyBase64Padding(normalized, true);
685
+ decoded = onError === "strict" ? decodeBase64Strict(s, "base64", validatePadding) : Uint8Array.from(Buffer.from(s, "base64"));
686
+ break;
687
+ }
688
+ case "base64url": {
689
+ const s = applyBase64Padding(normalized, true);
690
+ decoded = onError === "strict" ? decodeBase64Strict(s, "base64url", validatePadding) : Uint8Array.from(Buffer.from(s.replace(/-/g, "+").replace(/_/g, "/"), "base64"));
691
+ break;
692
+ }
693
+ case "base64_raw": {
694
+ const s = applyBase64Padding(normalized, true);
695
+ decoded = Uint8Array.from(Buffer.from(s, "base64"));
696
+ if (validatePadding) warnings.push("base64_raw does not support padding validation");
697
+ break;
698
+ }
699
+ case "hex": {
700
+ const s = normalized;
701
+ if (onError === "strict") {
702
+ if (!/^[0-9a-fA-F]*$/.test(s) || s.length % 2 !== 0) {
703
+ throw new Error("Invalid hex input");
704
+ }
705
+ }
706
+ decoded = Uint8Array.from(Buffer.from(s, "hex"));
707
+ break;
708
+ }
709
+ case "base32":
710
+ case "base32hex": {
711
+ decoded = decodeBase32(normalized, format, {
712
+ ignoreWhitespace,
713
+ validatePadding
714
+ });
715
+ break;
716
+ }
717
+ case "utf-8": {
718
+ decoded = new TextEncoder().encode(typeof input === "string" ? input : inputStr);
719
+ break;
720
+ }
721
+ case "utf-16le": {
722
+ decoded = Uint8Array.from(
723
+ Buffer.from(typeof input === "string" ? input : inputStr, "utf16le")
724
+ );
725
+ break;
726
+ }
727
+ case "utf-16be": {
728
+ const buf = Buffer.from(typeof input === "string" ? input : inputStr, "utf16le");
729
+ for (let i = 0; i + 1 < buf.length; i += 2) {
730
+ const a = buf[i];
731
+ buf[i] = buf[i + 1];
732
+ buf[i + 1] = a;
733
+ }
734
+ decoded = Uint8Array.from(buf);
735
+ break;
736
+ }
737
+ case "iso-8859-1": {
738
+ decoded = Uint8Array.from(
739
+ Buffer.from(typeof input === "string" ? input : inputStr, "latin1")
740
+ );
741
+ break;
742
+ }
743
+ case "ascii": {
744
+ decoded = Uint8Array.from(
745
+ Buffer.from(typeof input === "string" ? input : inputStr, "ascii")
746
+ );
747
+ break;
748
+ }
749
+ case "cp1252": {
750
+ throw new FulencodeError({
751
+ code: "UNSUPPORTED_FORMAT",
752
+ message: "cp1252 is not implemented in tsfulmen yet",
753
+ operation: "decode",
754
+ inputFormat: format
755
+ });
756
+ }
757
+ default: {
758
+ throw new FulencodeError({
759
+ code: "UNSUPPORTED_FORMAT",
760
+ message: `Unsupported decoding format: ${format}`,
761
+ operation: "decode",
762
+ inputFormat: format
763
+ });
764
+ }
765
+ }
766
+ } catch (err) {
767
+ if (err instanceof FulencodeError) throw err;
768
+ throw new FulencodeError({
769
+ code: "DECODE_FAILED",
770
+ message: err.message,
771
+ operation: "decode",
772
+ inputFormat: format,
773
+ cause: err
774
+ });
775
+ }
776
+ if (decoded.length > maxDecodedSize) {
777
+ throw new FulencodeError({
778
+ code: "OUTPUT_TOO_LARGE",
779
+ message: `Decoded output exceeds maxDecodedSize (${maxDecodedSize})`,
780
+ operation: "decode",
781
+ inputFormat: format,
782
+ details: { maxDecodedSize, outputSize: decoded.length }
783
+ });
784
+ }
785
+ const checksum = await computeChecksumIfRequested(decoded, options.computeChecksum);
786
+ return {
787
+ data: decoded,
788
+ format,
789
+ inputSize: typeof input === "string" ? Buffer.byteLength(input, "utf8") : input.length,
790
+ outputSize: decoded.length,
791
+ warnings,
792
+ correctionsApplied,
793
+ ...checksum
794
+ };
795
+ }
796
+
797
+ // src/fulencode/index.ts
798
+ var VERSION = "0.1.0";
799
+ var fulencode = {
800
+ encode,
801
+ decode
802
+ };
803
+
804
+ export { EncodingFormat, FulencodeError, VERSION, decode, encode, fulencode };
805
+ //# sourceMappingURL=index.js.map
806
+ //# sourceMappingURL=index.js.map