hbsig 0.3.1 → 0.3.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 (94) hide show
  1. package/.babelrc-cjs +5 -0
  2. package/.babelrc-esm +5 -0
  3. package/README.md +1 -0
  4. package/dist/package.json +39 -0
  5. package/make.js +36 -0
  6. package/package.json +16 -16
  7. package/src/bin_to_str.js +46 -0
  8. package/src/collect-body-keys.js +436 -0
  9. package/src/commit.js +219 -0
  10. package/src/encode-array-item.js +112 -0
  11. package/src/encode-utils.js +191 -0
  12. package/src/encode.js +1256 -0
  13. package/src/erl_json.js +292 -0
  14. package/src/erl_str.js +1144 -0
  15. package/src/flat.js +250 -0
  16. package/src/http-message-signatures/httpbis.js +438 -0
  17. package/src/http-message-signatures/index.js +4 -0
  18. package/src/http-message-signatures/structured-header.js +105 -0
  19. package/src/httpsig.js +866 -0
  20. package/src/id.js +459 -0
  21. package/src/index.js +13 -0
  22. package/src/nocrypto.js +4 -0
  23. package/src/parser.js +171 -0
  24. package/src/send-utils.js +1132 -0
  25. package/src/send.js +142 -0
  26. package/src/signer-utils.js +375 -0
  27. package/src/signer.js +312 -0
  28. package/src/structured.js +496 -0
  29. package/src/test.js +2 -0
  30. package/src/utils.js +29 -0
  31. package/test/commit.test.js +41 -0
  32. package/test/erl_json.test.js +8 -0
  33. package/test/flat.test.js +27 -0
  34. package/test/httpsig.test.js +31 -0
  35. package/test/id.test.js +114 -0
  36. package/test/lib/all_cases.js +408 -0
  37. package/test/lib/cases.js +408 -0
  38. package/test/lib/erl_json_cases.js +161 -0
  39. package/test/lib/flat_cases.js +189 -0
  40. package/test/lib/gen.js +528 -0
  41. package/test/lib/httpsig_cases.js +313 -0
  42. package/test/lib/structured_cases.js +222 -0
  43. package/test/lib/test-utils.js +399 -0
  44. package/test/signer.test.js +48 -0
  45. package/test/structured.test.js +35 -0
  46. /package/{cjs → dist/cjs}/bin_to_str.js +0 -0
  47. /package/{cjs → dist/cjs}/collect-body-keys.js +0 -0
  48. /package/{cjs → dist/cjs}/commit.js +0 -0
  49. /package/{cjs → dist/cjs}/encode-array-item.js +0 -0
  50. /package/{cjs → dist/cjs}/encode-utils.js +0 -0
  51. /package/{cjs → dist/cjs}/encode.js +0 -0
  52. /package/{cjs → dist/cjs}/erl_json.js +0 -0
  53. /package/{cjs → dist/cjs}/erl_str.js +0 -0
  54. /package/{cjs → dist/cjs}/flat.js +0 -0
  55. /package/{cjs → dist/cjs}/http-message-signatures/httpbis.js +0 -0
  56. /package/{cjs → dist/cjs}/http-message-signatures/index.js +0 -0
  57. /package/{cjs → dist/cjs}/http-message-signatures/structured-header.js +0 -0
  58. /package/{cjs → dist/cjs}/httpsig.js +0 -0
  59. /package/{cjs → dist/cjs}/id.js +0 -0
  60. /package/{cjs → dist/cjs}/index.js +0 -0
  61. /package/{cjs → dist/cjs}/nocrypto.js +0 -0
  62. /package/{cjs → dist/cjs}/parser.js +0 -0
  63. /package/{cjs → dist/cjs}/send-utils.js +0 -0
  64. /package/{cjs → dist/cjs}/send.js +0 -0
  65. /package/{cjs → dist/cjs}/signer-utils.js +0 -0
  66. /package/{cjs → dist/cjs}/signer.js +0 -0
  67. /package/{cjs → dist/cjs}/structured.js +0 -0
  68. /package/{cjs → dist/cjs}/test.js +0 -0
  69. /package/{cjs → dist/cjs}/utils.js +0 -0
  70. /package/{esm → dist/esm}/bin_to_str.js +0 -0
  71. /package/{esm → dist/esm}/collect-body-keys.js +0 -0
  72. /package/{esm → dist/esm}/commit.js +0 -0
  73. /package/{esm → dist/esm}/encode-array-item.js +0 -0
  74. /package/{esm → dist/esm}/encode-utils.js +0 -0
  75. /package/{esm → dist/esm}/encode.js +0 -0
  76. /package/{esm → dist/esm}/erl_json.js +0 -0
  77. /package/{esm → dist/esm}/erl_str.js +0 -0
  78. /package/{esm → dist/esm}/flat.js +0 -0
  79. /package/{esm → dist/esm}/http-message-signatures/httpbis.js +0 -0
  80. /package/{esm → dist/esm}/http-message-signatures/index.js +0 -0
  81. /package/{esm → dist/esm}/http-message-signatures/structured-header.js +0 -0
  82. /package/{esm → dist/esm}/httpsig.js +0 -0
  83. /package/{esm → dist/esm}/id.js +0 -0
  84. /package/{esm → dist/esm}/index.js +0 -0
  85. /package/{esm → dist/esm}/nocrypto.js +0 -0
  86. /package/{esm → dist/esm}/package.json +0 -0
  87. /package/{esm → dist/esm}/parser.js +0 -0
  88. /package/{esm → dist/esm}/send-utils.js +0 -0
  89. /package/{esm → dist/esm}/send.js +0 -0
  90. /package/{esm → dist/esm}/signer-utils.js +0 -0
  91. /package/{esm → dist/esm}/signer.js +0 -0
  92. /package/{esm → dist/esm}/structured.js +0 -0
  93. /package/{esm → dist/esm}/test.js +0 -0
  94. /package/{esm → dist/esm}/utils.js +0 -0
@@ -0,0 +1,313 @@
1
+ // Test cases for httpsig_from (HTTP to TABM)
2
+ export const cases_from = [
3
+ // 1. Simple message with body
4
+ {
5
+ "content-type": "text/plain",
6
+ body: "Hello World",
7
+ },
8
+
9
+ // 2. Message with headers only
10
+ {
11
+ "x-custom-header": "value",
12
+ "content-length": "0",
13
+ },
14
+
15
+ // 3. Message with inline body key
16
+ {
17
+ "inline-body-key": "data",
18
+ body: "Some data content",
19
+ },
20
+
21
+ // 4. Multipart message with single part
22
+ {
23
+ "content-type": 'multipart/form-data; boundary="simple-boundary"',
24
+ body: `--simple-boundary\r\ncontent-disposition: form-data;name="field1"\r\n\r\nvalue1\r\n--simple-boundary--`,
25
+ },
26
+
27
+ // 5. Multipart with inline part
28
+ {
29
+ "content-type": 'multipart/form-data; boundary="inline-boundary"',
30
+ body: `--inline-boundary\r\ncontent-disposition: inline\r\n\r\nInline content\r\n--inline-boundary--`,
31
+ },
32
+
33
+ // 6. Multipart with nested structure
34
+ {
35
+ "content-type": 'multipart/form-data; boundary="nested-boundary"',
36
+ body: `--nested-boundary\r\ncontent-disposition: form-data;name="user/name"\r\n\r\nJohn\r\n--nested-boundary\r\ncontent-disposition: form-data;name="user/email"\r\n\r\njohn@example.com\r\n--nested-boundary--`,
37
+ },
38
+
39
+ // 7. Message with grouped IDs
40
+ {
41
+ "ao-ids":
42
+ 'id1XYZ01234567890123456789012345678901234567="value1", id2ABC01234567890123456789012345678901234567="value2"',
43
+ "regular-header": "value",
44
+ },
45
+
46
+ // 8. Multipart with headers in parts
47
+ {
48
+ "content-type": 'multipart/form-data; boundary="header-boundary"',
49
+ body: `--header-boundary\r\ncontent-disposition: form-data;name="data"\r\ncontent-type: application/json\r\n\r\n{"key": "value"}\r\n--header-boundary--`,
50
+ },
51
+
52
+ // 9. Empty body message
53
+ {
54
+ "content-type": "text/plain",
55
+ "x-empty": "true",
56
+ },
57
+
58
+ // 10. Multipart with body keys
59
+ {
60
+ "content-type": 'multipart/form-data; boundary="keys-boundary"',
61
+ "body-keys": "user, config",
62
+ body: `--keys-boundary\r\ncontent-disposition: form-data;name="user"\r\n\r\nJohn Doe\r\n--keys-boundary\r\ncontent-disposition: form-data;name="config"\r\n\r\nsettings\r\n--keys-boundary--`,
63
+ },
64
+
65
+ // 11. Message with special characters
66
+ {
67
+ "x-special": 'Hello "World"',
68
+ body: "Line1\nLine2\r\nLine3",
69
+ },
70
+
71
+ // 12. Deep nested multipart
72
+ {
73
+ "content-type": 'multipart/form-data; boundary="deep-boundary"',
74
+ body: `--deep-boundary\r\ncontent-disposition: form-data;name="a/b/c"\r\n\r\ndeep value\r\n--deep-boundary--`,
75
+ },
76
+
77
+ // 13. Mixed case headers (should normalize)
78
+ {
79
+ "Content-Type": "text/html",
80
+ "X-Custom-Header": "value",
81
+ body: "<html></html>",
82
+ },
83
+
84
+ // 14. Multipart with empty parts
85
+ {
86
+ "content-type": 'multipart/form-data; boundary="empty-boundary"',
87
+ body: `--empty-boundary\r\ncontent-disposition: form-data;name="empty"\r\n\r\n\r\n--empty-boundary\r\ncontent-disposition: form-data;name="not-empty"\r\n\r\nvalue\r\n--empty-boundary--`,
88
+ },
89
+
90
+ // 15. Unicode content
91
+ {
92
+ "content-type": "text/plain; charset=utf-8",
93
+ body: "Hello 世界 🎉",
94
+ },
95
+
96
+ // 16. Multipart with sub-messages
97
+ {
98
+ "content-type": 'multipart/form-data; boundary="sub-boundary"',
99
+ body: `--sub-boundary\r\ncontent-disposition: form-data;name="message"\r\ncontent-type: text/plain\r\nx-meta: data\r\n\r\nMessage body\r\n--sub-boundary--`,
100
+ },
101
+
102
+ // 17. Complex headers structure
103
+ {
104
+ "x-array": "[1,2,3]",
105
+ "x-object": '{"key":"value"}',
106
+ "x-boolean": "true",
107
+ body: "content",
108
+ },
109
+
110
+ // 18. Multipart with various dispositions
111
+ {
112
+ "content-type": 'multipart/form-data; boundary="disp-boundary"',
113
+ body: `--disp-boundary\r\ncontent-disposition: inline\r\n\r\nInline data\r\n--disp-boundary\r\ncontent-disposition: form-data;name="attachment"\r\n\r\nAttachment data\r\n--disp-boundary--`,
114
+ },
115
+
116
+ // 19. Long header value (near threshold)
117
+ {
118
+ "x-long": "a".repeat(4000),
119
+ "x-short": "short value",
120
+ },
121
+
122
+ // 20. Complete multipart form
123
+ {
124
+ "content-type": 'multipart/form-data; boundary="form-boundary"',
125
+ body: `--form-boundary\r\ncontent-disposition: form-data;name="user/profile/name"\r\n\r\nAlice\r\n--form-boundary\r\ncontent-disposition: form-data;name="user/profile/age"\r\n\r\n30\r\n--form-boundary\r\ncontent-disposition: form-data;name="user/settings/theme"\r\n\r\ndark\r\n--form-boundary\r\ncontent-disposition: form-data;name="metadata"\r\ncontent-type: application/json\r\n\r\n{"created": "2024-01-01"}\r\n--form-boundary--`,
126
+ },
127
+ ]
128
+
129
+ // Test cases for httpsig_to (TABM to HTTP)
130
+ export const cases_to = [
131
+ // 1. Simple message with body
132
+ {
133
+ message: "Hello World",
134
+ body: "Main content",
135
+ },
136
+
137
+ // 2. Headers only message
138
+ {
139
+ "x-custom-header": "value",
140
+ "content-length": "0",
141
+ },
142
+
143
+ // 3. Message with data as inline key
144
+ {
145
+ data: "Some data content",
146
+ "x-header": "value",
147
+ },
148
+
149
+ // 4. Nested structure (should become multipart)
150
+ {
151
+ user: {
152
+ name: "John",
153
+ email: "john@example.com",
154
+ },
155
+ config: "settings",
156
+ },
157
+
158
+ // 5. Message with IDs to group
159
+ {
160
+ id1XYZ01234567890123456789012345678901234567: "value1",
161
+ id2ABC01234567890123456789012345678901234567: "value2",
162
+ "regular-key": "value",
163
+ },
164
+
165
+ // 6. Deep nested structure
166
+ {
167
+ a: {
168
+ b: {
169
+ c: "deep value",
170
+ },
171
+ },
172
+ },
173
+
174
+ // 7. Mixed content types
175
+ {
176
+ text: "plain text",
177
+ data: {
178
+ json: '{"key": "value"}',
179
+ number: "123",
180
+ },
181
+ },
182
+
183
+ // 8. Long values (exceeding header limit)
184
+ {
185
+ short: "short value",
186
+ long: "x".repeat(5000),
187
+ },
188
+
189
+ // 9. Empty values
190
+ {
191
+ empty: "",
192
+ nonempty: "value",
193
+ nested: {
194
+ empty: "",
195
+ },
196
+ },
197
+
198
+ // 10. Special characters
199
+ {
200
+ special: 'Hello "World"',
201
+ multiline: "Line1\nLine2",
202
+ unicode: "Hello 世界",
203
+ },
204
+
205
+ // 11. Array-like structure
206
+ {
207
+ items: {
208
+ 0: "first",
209
+ 1: "second",
210
+ 2: "third",
211
+ },
212
+ },
213
+
214
+ // 12. Complex nested with body
215
+ {
216
+ metadata: {
217
+ version: "1.0",
218
+ created: "2024-01-01",
219
+ },
220
+ body: "Main document content",
221
+ config: {
222
+ enabled: "true",
223
+ },
224
+ },
225
+
226
+ // 13. Keys requiring normalization
227
+ {
228
+ Content_Type: "text/html",
229
+ X_Custom_Header: "value",
230
+ normal_key: "value",
231
+ },
232
+
233
+ // 14. Structure with inline-body-key
234
+ {
235
+ "inline-body-key": "content",
236
+ content: "This is the main content",
237
+ meta: "data",
238
+ },
239
+
240
+ // 15. Unicode in keys and values
241
+ {
242
+ greeting: "Hello 世界",
243
+ "emoji_🎉": "celebration",
244
+ },
245
+
246
+ // 16. Deeply nested with mixed types
247
+ {
248
+ app: {
249
+ name: "MyApp",
250
+ config: {
251
+ port: "3000",
252
+ features: {
253
+ auth: "enabled",
254
+ cache: "disabled",
255
+ },
256
+ },
257
+ },
258
+ },
259
+
260
+ // 17. Boolean and numeric strings
261
+ {
262
+ enabled: "true",
263
+ count: "42",
264
+ rate: "3.14",
265
+ },
266
+
267
+ // 18. Single body value (should not create multipart)
268
+ {
269
+ body: "Just a simple body content",
270
+ },
271
+
272
+ // 19. Complex form-like structure
273
+ {
274
+ form: {
275
+ user: {
276
+ name: "Alice",
277
+ email: "alice@example.com",
278
+ },
279
+ preferences: {
280
+ theme: "dark",
281
+ notifications: "on",
282
+ },
283
+ },
284
+ },
285
+
286
+ // 20. Large nested structure
287
+ {
288
+ users: {
289
+ alice: {
290
+ profile: {
291
+ name: "Alice Smith",
292
+ age: "30",
293
+ },
294
+ settings: {
295
+ theme: "dark",
296
+ },
297
+ },
298
+ bob: {
299
+ profile: {
300
+ name: "Bob Jones",
301
+ age: "25",
302
+ },
303
+ settings: {
304
+ theme: "light",
305
+ },
306
+ },
307
+ },
308
+ system: {
309
+ version: "2.0",
310
+ status: "active",
311
+ },
312
+ },
313
+ ]
@@ -0,0 +1,222 @@
1
+ // Test cases for structured_from (TABM to native)
2
+ // NOTE: Simplified to match HB's dev_codec_structured behavior.
3
+ // The structured codec applies type conversions and removes ao-types.
4
+ export const cases_from = [
5
+ // 1. Simple string value without type
6
+ {
7
+ message: "Hello World",
8
+ },
9
+
10
+ // 2. Simple nested object without types
11
+ {
12
+ user: {
13
+ name: "John",
14
+ city: "NYC",
15
+ },
16
+ },
17
+
18
+ // 3. Unicode in values
19
+ {
20
+ greeting: "Hello 世界",
21
+ emoji: "🎉",
22
+ },
23
+
24
+ // 4. Multiple string values
25
+ {
26
+ first: "one",
27
+ second: "two",
28
+ third: "three",
29
+ },
30
+
31
+ // 5. Deeply nested strings
32
+ {
33
+ level1: {
34
+ level2: {
35
+ level3: {
36
+ value: "deep",
37
+ },
38
+ },
39
+ },
40
+ },
41
+
42
+ // 6. Special characters in values
43
+ {
44
+ message: "Hello, World!",
45
+ json: '{"key": "value"}',
46
+ },
47
+
48
+ // 7. Keys with special characters
49
+ {
50
+ "special-key": "value",
51
+ another_key: "data",
52
+ },
53
+
54
+ // 8. Multiple nested levels
55
+ {
56
+ app: {
57
+ name: "MyApp",
58
+ version: "1.0.0",
59
+ config: {
60
+ env: "production",
61
+ region: "us-east",
62
+ },
63
+ },
64
+ },
65
+
66
+ // 9. Path-like keys
67
+ {
68
+ path: "/api/users",
69
+ method: "GET",
70
+ },
71
+
72
+ // 10. Long string values
73
+ {
74
+ description: "This is a longer text value that spans multiple words.",
75
+ },
76
+ ]
77
+
78
+ // Test cases for structured_to (native to TABM)
79
+ export const cases_to = [
80
+ // 1. Simple string value
81
+ {
82
+ message: "Hello World",
83
+ },
84
+
85
+ // 2. Integer value
86
+ {
87
+ count: 42,
88
+ },
89
+
90
+ // 3. Boolean values
91
+ {
92
+ enabled: true,
93
+ disabled: false,
94
+ },
95
+
96
+ // 4. Empty values
97
+ {
98
+ "empty-string": "",
99
+ "empty-list": [],
100
+ "empty-object": {},
101
+ },
102
+
103
+ // 5. Nested object
104
+ {
105
+ user: {
106
+ name: "John",
107
+ age: 30,
108
+ },
109
+ },
110
+
111
+ // 6. List of strings
112
+ {
113
+ tags: ["first", "second", "third"],
114
+ },
115
+
116
+ // 7. Mixed list
117
+ {
118
+ values: [1, true, "text"],
119
+ },
120
+
121
+ // 8. List of objects
122
+ {
123
+ items: [{ name: "Item 1" }, { name: "Item 2" }],
124
+ },
125
+
126
+ // 9. Complex nested structure
127
+ {
128
+ app: {
129
+ name: "MyApp",
130
+ version: "1.0.0",
131
+ config: {
132
+ port: 3000,
133
+ debug: true,
134
+ },
135
+ },
136
+ },
137
+
138
+ // 10. Null value
139
+ {
140
+ nullable: null,
141
+ },
142
+
143
+ // 11. Float value
144
+ {
145
+ price: 19.99,
146
+ },
147
+
148
+ // 12. Strings with special characters
149
+ {
150
+ messages: ['Hello "World"', "Line1\\Line2"],
151
+ },
152
+
153
+ // 13. Multiple empty types with regular value
154
+ {
155
+ a: "",
156
+ b: [],
157
+ c: {},
158
+ d: "not empty",
159
+ },
160
+
161
+ // 14. Unicode in values
162
+ {
163
+ greeting: "Hello 世界",
164
+ emoji: "🎉",
165
+ },
166
+
167
+ // 15. Deeply nested with mixed types
168
+ {
169
+ level1: {
170
+ level2: {
171
+ level3: {
172
+ value: 42,
173
+ },
174
+ },
175
+ },
176
+ },
177
+
178
+ // 16. List with various types
179
+ {
180
+ mixed: ["", "value", 123, true, null],
181
+ },
182
+
183
+ // 17. All primitive types
184
+ {
185
+ int: 123,
186
+ float: 45.67,
187
+ bool: true,
188
+ null: null,
189
+ string: "text",
190
+ },
191
+
192
+ // 18. Keys requiring encoding
193
+ {
194
+ "special-key": "value",
195
+ another_key: 123,
196
+ },
197
+
198
+ // 19. Complex list of mixed types
199
+ {
200
+ data: [100, 3.14, false, "plain string"],
201
+ },
202
+
203
+ // 20. Large structure with various types
204
+ {
205
+ users: [
206
+ {
207
+ id: 1,
208
+ name: "Alice",
209
+ active: true,
210
+ score: 95.5,
211
+ tags: ["admin", "user"],
212
+ },
213
+ {
214
+ id: 2,
215
+ name: "Bob",
216
+ active: false,
217
+ score: 87.3,
218
+ tags: ["user"],
219
+ },
220
+ ],
221
+ },
222
+ ]