turbo-stream 1.0.2 → 1.0.4

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/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A streaming data transport format that aims to support built-in features such as Promises, Dates, RegExps, Maps, Sets and more.
4
4
 
5
+ Decode runtime size: [![turbo-stream's badge](https://deno.bundlejs.com/badge?q=turbo-stream&badge=detailed&treeshake=%5B%7B+decode+%7D%5D)](https://bundlejs.com/?q=turbo-stream&treeshake=%5B%7B+decode+%7D%5D)
6
+
5
7
  ## Shout Out!
6
8
 
7
9
  Shout out to Rich Harris and his https://github.com/rich-harris/devalue project. Devalue has heavily influenced this project and portions
@@ -26,3 +28,4 @@ await decoded.done; // wait for the stream to finish
26
28
  ```
27
29
 
28
30
  Stackblitz: https://stackblitz.com/edit/stackblitz-starters-2wm7dh?file=index.js
31
+ React SSR Example: https://github.com/jacob-ebey/turbo-stream-react-example
package/dist/flatten.js CHANGED
@@ -1,6 +1,7 @@
1
- import { HOLE, NAN, NEGATIVE_INFINITY, NEGATIVE_ZERO, POSITIVE_INFINITY, TYPE_BIGINT, TYPE_DATE, TYPE_ERROR, TYPE_MAP, TYPE_NULL_OBJECT, TYPE_PROMISE, TYPE_REGEXP, TYPE_SET, TYPE_SYMBOL, UNDEFINED, } from "./utils.js";
1
+ import { HOLE, NAN, NEGATIVE_INFINITY, NEGATIVE_ZERO, POSITIVE_INFINITY, UNDEFINED, TYPE_BIGINT, TYPE_DATE, TYPE_ERROR, TYPE_MAP, TYPE_NULL_OBJECT, TYPE_PROMISE, TYPE_REGEXP, TYPE_SET, TYPE_SYMBOL, TYPE_URL, } from "./utils.js";
2
2
  export function flatten(input) {
3
- const existing = this.indicies.get(input);
3
+ const { indicies } = this;
4
+ const existing = indicies.get(input);
4
5
  if (existing)
5
6
  return existing;
6
7
  if (input === undefined)
@@ -14,12 +15,16 @@ export function flatten(input) {
14
15
  if (input === 0 && 1 / input < 0)
15
16
  return NEGATIVE_ZERO;
16
17
  const index = this.index++;
17
- this.indicies.set(input, index);
18
+ indicies.set(input, index);
18
19
  stringify.call(this, input, index);
19
20
  return index;
20
21
  }
21
22
  function stringify(input, index) {
23
+ const { deferred } = this;
22
24
  const str = this.stringified;
25
+ const partsForObj = (obj) => Object.keys(obj)
26
+ .map((k) => `${JSON.stringify(k)}:${flatten.call(this, obj[k])}`)
27
+ .join(",");
23
28
  switch (typeof input) {
24
29
  case "boolean":
25
30
  case "number":
@@ -50,6 +55,9 @@ function stringify(input, index) {
50
55
  else if (input instanceof Date) {
51
56
  str[index] = `["${TYPE_DATE}",${input.getTime()}]`;
52
57
  }
58
+ else if (input instanceof URL) {
59
+ str[index] = `["${TYPE_URL}",${JSON.stringify(input.href)}]`;
60
+ }
53
61
  else if (input instanceof RegExp) {
54
62
  str[index] = `["${TYPE_REGEXP}",${JSON.stringify(input.source)},${JSON.stringify(input.flags)}]`;
55
63
  }
@@ -65,7 +73,7 @@ function stringify(input, index) {
65
73
  }
66
74
  else if (input instanceof Promise) {
67
75
  str[index] = `["${TYPE_PROMISE}",${index}]`;
68
- this.deferred[index] = input;
76
+ deferred[index] = input;
69
77
  }
70
78
  else if (input instanceof Error) {
71
79
  str[index] = `["${TYPE_ERROR}",${JSON.stringify(input.message)}`;
@@ -75,17 +83,10 @@ function stringify(input, index) {
75
83
  str[index] += "]";
76
84
  }
77
85
  else if (Object.getPrototypeOf(input) === null) {
78
- str[index] = `["${TYPE_NULL_OBJECT}"`;
79
- const parts = [];
80
- for (const key in input)
81
- parts.push(`${JSON.stringify(key)}:${flatten.call(this, input[key])}`);
82
- str[index] += ",{" + parts.join(",") + "}]";
86
+ str[index] = `["${TYPE_NULL_OBJECT}",{${partsForObj(input)}}]`;
83
87
  }
84
88
  else if (isPlainObject(input)) {
85
- const parts = [];
86
- for (const key in input)
87
- parts.push(`${JSON.stringify(key)}:${flatten.call(this, input[key])}`);
88
- str[index] = "{" + parts.join(",") + "}";
89
+ str[index] = `{${partsForObj(input)}}`;
89
90
  }
90
91
  else {
91
92
  throw new Error("Cannot encode object with prototype");
@@ -1,6 +1,6 @@
1
1
  import { flatten } from "./flatten.js";
2
2
  import { unflatten } from "./unflatten.js";
3
- import { createLineSplittingTransform, Deferred, TYPE_PROMISE, TYPE_ERROR, } from "./utils.js";
3
+ import { Deferred, TYPE_ERROR, TYPE_PROMISE, createLineSplittingTransform, } from "./utils.js";
4
4
  export async function decode(readable) {
5
5
  const done = new Deferred();
6
6
  const reader = readable
package/dist/unflatten.js CHANGED
@@ -1,17 +1,18 @@
1
- import { Deferred, HOLE, NAN, NEGATIVE_INFINITY, NEGATIVE_ZERO, POSITIVE_INFINITY, TYPE_BIGINT, TYPE_DATE, TYPE_MAP, TYPE_PROMISE, TYPE_REGEXP, TYPE_SET, TYPE_SYMBOL, UNDEFINED, TYPE_ERROR, TYPE_NULL_OBJECT, } from "./utils.js";
1
+ import { Deferred, HOLE, NAN, NEGATIVE_INFINITY, NEGATIVE_ZERO, POSITIVE_INFINITY, UNDEFINED, TYPE_BIGINT, TYPE_DATE, TYPE_ERROR, TYPE_MAP, TYPE_NULL_OBJECT, TYPE_PROMISE, TYPE_REGEXP, TYPE_SET, TYPE_SYMBOL, TYPE_URL, } from "./utils.js";
2
2
  const globalObj = (typeof window !== "undefined"
3
3
  ? window
4
4
  : typeof globalThis !== "undefined"
5
5
  ? globalThis
6
6
  : undefined);
7
7
  export function unflatten(parsed) {
8
+ const { hydrated, values } = this;
8
9
  if (typeof parsed === "number")
9
10
  return hydrate.call(this, parsed);
10
11
  if (!Array.isArray(parsed) || !parsed.length)
11
12
  throw new SyntaxError();
12
- const startIndex = this.values.length;
13
- this.values.push(...parsed);
14
- this.hydrated.length = this.values.length;
13
+ const startIndex = values.length;
14
+ values.push(...parsed);
15
+ hydrated.length = values.length;
15
16
  return hydrate.call(this, startIndex);
16
17
  }
17
18
  function hydrate(index) {
@@ -35,15 +36,18 @@ function hydrate(index) {
35
36
  return (hydrated[index] = value);
36
37
  if (Array.isArray(value)) {
37
38
  if (typeof value[0] === "string") {
38
- switch (value[0]) {
39
+ const [type, b, c] = value;
40
+ switch (type) {
39
41
  case TYPE_DATE:
40
- return (hydrated[index] = new Date(value[1]));
42
+ return (hydrated[index] = new Date(b));
43
+ case TYPE_URL:
44
+ return (hydrated[index] = new URL(b));
41
45
  case TYPE_BIGINT:
42
- return (hydrated[index] = BigInt(value[1]));
46
+ return (hydrated[index] = BigInt(b));
43
47
  case TYPE_REGEXP:
44
- return (hydrated[index] = new RegExp(value[1], value[2]));
48
+ return (hydrated[index] = new RegExp(b, c));
45
49
  case TYPE_SYMBOL:
46
- return (hydrated[index] = Symbol.for(value[1]));
50
+ return (hydrated[index] = Symbol.for(b));
47
51
  case TYPE_SET:
48
52
  const set = new Set();
49
53
  hydrated[index] = set;
@@ -61,16 +65,16 @@ function hydrate(index) {
61
65
  console.log({ value });
62
66
  const obj = Object.create(null);
63
67
  hydrated[index] = obj;
64
- for (const key in value[1])
65
- obj[key] = hydrate.call(this, value[1][key]);
68
+ for (const key in b)
69
+ obj[key] = hydrate.call(this, b[key]);
66
70
  return obj;
67
71
  case TYPE_PROMISE:
68
- if (hydrated[value[1]]) {
69
- return (hydrated[index] = hydrated[value[1]]);
72
+ if (hydrated[b]) {
73
+ return (hydrated[index] = hydrated[b]);
70
74
  }
71
75
  else {
72
76
  const d = new Deferred();
73
- deferred[value[1]] = d;
77
+ deferred[b] = d;
74
78
  return (hydrated[index] = d.promise);
75
79
  }
76
80
  case TYPE_ERROR:
package/dist/utils.d.ts CHANGED
@@ -1,18 +1,19 @@
1
- export declare const UNDEFINED = -1;
2
1
  export declare const HOLE = -1;
3
2
  export declare const NAN = -2;
4
- export declare const POSITIVE_INFINITY = -3;
5
3
  export declare const NEGATIVE_INFINITY = -4;
6
4
  export declare const NEGATIVE_ZERO = -5;
5
+ export declare const POSITIVE_INFINITY = -3;
6
+ export declare const UNDEFINED = -1;
7
7
  export declare const TYPE_BIGINT = "B";
8
8
  export declare const TYPE_DATE = "D";
9
+ export declare const TYPE_ERROR = "E";
9
10
  export declare const TYPE_MAP = "M";
10
- export declare const TYPE_SET = "S";
11
- export declare const TYPE_REGEXP = "R";
12
- export declare const TYPE_SYMBOL = "Y";
13
11
  export declare const TYPE_NULL_OBJECT = "N";
14
12
  export declare const TYPE_PROMISE = "P";
15
- export declare const TYPE_ERROR = "E";
13
+ export declare const TYPE_REGEXP = "R";
14
+ export declare const TYPE_SET = "S";
15
+ export declare const TYPE_SYMBOL = "Y";
16
+ export declare const TYPE_URL = "U";
16
17
  export interface ThisDecode {
17
18
  values: unknown[];
18
19
  hydrated: unknown[];
package/dist/utils.js CHANGED
@@ -1,18 +1,19 @@
1
- export const UNDEFINED = -1;
2
1
  export const HOLE = -1;
3
2
  export const NAN = -2;
4
- export const POSITIVE_INFINITY = -3;
5
3
  export const NEGATIVE_INFINITY = -4;
6
4
  export const NEGATIVE_ZERO = -5;
5
+ export const POSITIVE_INFINITY = -3;
6
+ export const UNDEFINED = -1;
7
7
  export const TYPE_BIGINT = "B";
8
8
  export const TYPE_DATE = "D";
9
+ export const TYPE_ERROR = "E";
9
10
  export const TYPE_MAP = "M";
10
- export const TYPE_SET = "S";
11
- export const TYPE_REGEXP = "R";
12
- export const TYPE_SYMBOL = "Y";
13
11
  export const TYPE_NULL_OBJECT = "N";
14
12
  export const TYPE_PROMISE = "P";
15
- export const TYPE_ERROR = "E";
13
+ export const TYPE_REGEXP = "R";
14
+ export const TYPE_SET = "S";
15
+ export const TYPE_SYMBOL = "Y";
16
+ export const TYPE_URL = "U";
16
17
  export class Deferred {
17
18
  promise;
18
19
  resolve;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turbo-stream",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
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
  "type": "module",
6
6
  "files": [