turbo-stream 2.3.0 → 2.4.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.
package/dist/flatten.js CHANGED
@@ -26,7 +26,7 @@ function flatten(input) {
26
26
  }
27
27
  exports.flatten = flatten;
28
28
  function stringify(input, index) {
29
- const { deferred, plugins } = this;
29
+ const { deferred, plugins, postPlugins } = this;
30
30
  const str = this.stringified;
31
31
  const stack = [[input, index]];
32
32
  while (stack.length > 0) {
@@ -34,6 +34,7 @@ function stringify(input, index) {
34
34
  const partsForObj = (obj) => Object.keys(obj)
35
35
  .map((k) => `"_${flatten.call(this, k)}":${flatten.call(this, obj[k])}`)
36
36
  .join(",");
37
+ let error = null;
37
38
  switch (typeof input) {
38
39
  case "boolean":
39
40
  case "number":
@@ -45,9 +46,12 @@ function stringify(input, index) {
45
46
  break;
46
47
  case "symbol": {
47
48
  const keyFor = Symbol.keyFor(input);
48
- if (!keyFor)
49
- throw new Error("Cannot encode symbol unless created with Symbol.for()");
50
- str[index] = `["${utils_js_1.TYPE_SYMBOL}",${JSON.stringify(keyFor)}]`;
49
+ if (!keyFor) {
50
+ error = new Error("Cannot encode symbol unless created with Symbol.for()");
51
+ }
52
+ else {
53
+ str[index] = `["${utils_js_1.TYPE_SYMBOL}",${JSON.stringify(keyFor)}]`;
54
+ }
51
55
  break;
52
56
  }
53
57
  case "object": {
@@ -133,7 +137,7 @@ function stringify(input, index) {
133
137
  str[index] = `{${partsForObj(input)}}`;
134
138
  }
135
139
  else {
136
- throw new Error("Cannot encode object with prototype");
140
+ error = new Error("Cannot encode object with prototype");
137
141
  }
138
142
  }
139
143
  break;
@@ -159,10 +163,33 @@ function stringify(input, index) {
159
163
  }
160
164
  }
161
165
  if (!pluginHandled) {
162
- throw new Error("Cannot encode function or unexpected type");
166
+ error = new Error("Cannot encode function or unexpected type");
163
167
  }
164
168
  }
165
169
  }
170
+ if (error) {
171
+ let pluginHandled = false;
172
+ if (postPlugins) {
173
+ for (const plugin of postPlugins) {
174
+ const pluginResult = plugin(input);
175
+ if (Array.isArray(pluginResult)) {
176
+ pluginHandled = true;
177
+ const [pluginIdentifier, ...rest] = pluginResult;
178
+ str[index] = `[${JSON.stringify(pluginIdentifier)}`;
179
+ if (rest.length > 0) {
180
+ str[index] += `,${rest
181
+ .map((v) => flatten.call(this, v))
182
+ .join(",")}`;
183
+ }
184
+ str[index] += "]";
185
+ break;
186
+ }
187
+ }
188
+ }
189
+ if (!pluginHandled) {
190
+ throw error;
191
+ }
192
+ }
166
193
  }
167
194
  }
168
195
  const objectProtoNames = Object.getOwnPropertyNames(Object.prototype)
@@ -8,5 +8,6 @@ export declare function decode(readable: ReadableStream<Uint8Array>, options?: {
8
8
  }>;
9
9
  export declare function encode(input: unknown, options?: {
10
10
  plugins?: EncodePlugin[];
11
+ postPlugins?: EncodePlugin[];
11
12
  signal?: AbortSignal;
12
13
  }): ReadableStream<Uint8Array>;
@@ -107,13 +107,14 @@ async function decodeDeferred(reader) {
107
107
  }
108
108
  }
109
109
  function encode(input, options) {
110
- const { plugins, signal } = options ?? {};
110
+ const { plugins, postPlugins, signal } = options ?? {};
111
111
  const encoder = {
112
112
  deferred: {},
113
113
  index: 0,
114
114
  indices: new Map(),
115
115
  stringified: [],
116
116
  plugins,
117
+ postPlugins,
117
118
  signal,
118
119
  };
119
120
  const textEncoder = new TextEncoder();
@@ -72,12 +72,13 @@ function flatten(input) {
72
72
  return index;
73
73
  }
74
74
  function stringify(input, index) {
75
- const { deferred, plugins } = this;
75
+ const { deferred, plugins, postPlugins } = this;
76
76
  const str = this.stringified;
77
77
  const stack = [[input, index]];
78
78
  while (stack.length > 0) {
79
79
  const [input2, index2] = stack.pop();
80
80
  const partsForObj = (obj) => Object.keys(obj).map((k) => `"_${flatten.call(this, k)}":${flatten.call(this, obj[k])}`).join(",");
81
+ let error = null;
81
82
  switch (typeof input2) {
82
83
  case "boolean":
83
84
  case "number":
@@ -89,11 +90,13 @@ function stringify(input, index) {
89
90
  break;
90
91
  case "symbol": {
91
92
  const keyFor = Symbol.keyFor(input2);
92
- if (!keyFor)
93
- throw new Error(
93
+ if (!keyFor) {
94
+ error = new Error(
94
95
  "Cannot encode symbol unless created with Symbol.for()"
95
96
  );
96
- str[index2] = `["${TYPE_SYMBOL}",${JSON.stringify(keyFor)}]`;
97
+ } else {
98
+ str[index2] = `["${TYPE_SYMBOL}",${JSON.stringify(keyFor)}]`;
99
+ }
97
100
  break;
98
101
  }
99
102
  case "object": {
@@ -161,7 +164,7 @@ function stringify(input, index) {
161
164
  } else if (isPlainObject(input2)) {
162
165
  str[index2] = `{${partsForObj(input2)}}`;
163
166
  } else {
164
- throw new Error("Cannot encode object with prototype");
167
+ error = new Error("Cannot encode object with prototype");
165
168
  }
166
169
  }
167
170
  break;
@@ -185,9 +188,30 @@ function stringify(input, index) {
185
188
  }
186
189
  }
187
190
  if (!pluginHandled) {
188
- throw new Error("Cannot encode function or unexpected type");
191
+ error = new Error("Cannot encode function or unexpected type");
192
+ }
193
+ }
194
+ }
195
+ if (error) {
196
+ let pluginHandled = false;
197
+ if (postPlugins) {
198
+ for (const plugin of postPlugins) {
199
+ const pluginResult = plugin(input2);
200
+ if (Array.isArray(pluginResult)) {
201
+ pluginHandled = true;
202
+ const [pluginIdentifier, ...rest] = pluginResult;
203
+ str[index2] = `[${JSON.stringify(pluginIdentifier)}`;
204
+ if (rest.length > 0) {
205
+ str[index2] += `,${rest.map((v) => flatten.call(this, v)).join(",")}`;
206
+ }
207
+ str[index2] += "]";
208
+ break;
209
+ }
189
210
  }
190
211
  }
212
+ if (!pluginHandled) {
213
+ throw error;
214
+ }
191
215
  }
192
216
  }
193
217
  }
@@ -520,13 +544,14 @@ async function decodeDeferred(reader) {
520
544
  }
521
545
  }
522
546
  function encode(input, options) {
523
- const { plugins, signal } = options ?? {};
547
+ const { plugins, postPlugins, signal } = options ?? {};
524
548
  const encoder = {
525
549
  deferred: {},
526
550
  index: 0,
527
551
  indices: /* @__PURE__ */ new Map(),
528
552
  stringified: [],
529
553
  plugins,
554
+ postPlugins,
530
555
  signal
531
556
  };
532
557
  const textEncoder = new TextEncoder();
package/dist/utils.d.ts CHANGED
@@ -32,6 +32,7 @@ export interface ThisEncode {
32
32
  stringified: string[];
33
33
  deferred: Record<number, Promise<unknown>>;
34
34
  plugins?: EncodePlugin[];
35
+ postPlugins?: EncodePlugin[];
35
36
  signal?: AbortSignal;
36
37
  }
37
38
  export declare class Deferred<T = unknown> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turbo-stream",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "A streaming data transport format that aims to support built-in features such as Promises, Dates, RegExps, Maps, Sets and more.",
5
5
  "files": [
6
6
  "dist",
@@ -18,7 +18,7 @@
18
18
  "./package.json": "./package.json"
19
19
  },
20
20
  "scripts": {
21
- "build": "pnpm build:esm && pnpm build:cjs",
21
+ "build": "pnpm build:esm && pnpm build:cjs && cp ./dist/turbo-stream.mjs ./viewer/scripts/turbo-stream.js",
22
22
  "build:cjs": "tsc --outDir dist --project tsconfig.lib.json",
23
23
  "build:esm": "esbuild --bundle --platform=node --target=node16 --format=esm --outfile=dist/turbo-stream.mjs src/turbo-stream.ts",
24
24
  "test": "node --no-warnings --loader tsm --enable-source-maps --test-reporter tap --test src/*.spec.ts",