shelving 1.86.1 → 1.86.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.
- package/constraint/Constraints.js +3 -2
- package/constraint/QueryConstraints.d.ts +1 -1
- package/constraint/QueryConstraints.js +8 -8
- package/error/ThroughError.js +1 -1
- package/markup/index.d.ts +1 -0
- package/markup/index.js +1 -0
- package/markup/options.d.ts +1 -1
- package/markup/regexp.d.ts +2 -2
- package/markup/render.js +19 -20
- package/markup/rule.d.ts +80 -0
- package/markup/rule.js +63 -0
- package/markup/rules.d.ts +17 -67
- package/markup/rules.js +88 -160
- package/package.json +17 -17
- package/react/useItem.js +2 -2
- package/react/useQuery.js +2 -2
- package/schema/NumberSchema.js +4 -4
- package/update/ArrayUpdate.d.ts +2 -1
- package/update/ArrayUpdate.js +4 -3
- package/update/DataUpdate.js +3 -2
- package/update/DictionaryUpdate.js +4 -3
- package/util/class.d.ts +1 -1
- package/util/clone.js +4 -3
- package/util/data.d.ts +0 -7
- package/util/data.js +1 -19
- package/util/date.d.ts +1 -1
- package/util/debug.d.ts +1 -0
- package/util/debug.js +5 -5
- package/util/equal.js +6 -3
- package/util/hydrate.d.ts +1 -1
- package/util/hydrate.js +2 -2
- package/util/object.d.ts +13 -0
- package/util/object.js +30 -4
- package/util/regexp.d.ts +0 -1
- package/util/serialise.js +2 -2
- package/util/source.js +2 -2
- package/util/string.js +3 -3
- package/util/template.js +9 -9
package/markup/rules.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable import/export */
|
|
2
2
|
import { getRegExp } from "../util/regexp.js";
|
|
3
|
-
import { formatURL, getOptionalURL } from "../util/url.js";
|
|
4
3
|
import { getBlockRegExp, getLineRegExp, BLOCK_REGEXP, LINE_REGEXP, WordRegExp } from "./regexp.js";
|
|
4
|
+
import { LinkRegExpMarkupRule, NamedRegExpMarkupRule, RegExpMarkupRule } from "./rule.js";
|
|
5
5
|
/** React security symbol — see https://github.com/facebook/react/pull/4832 */
|
|
6
6
|
const $$typeof = Symbol.for("react.element");
|
|
7
7
|
/**
|
|
@@ -10,18 +10,13 @@ const $$typeof = Symbol.for("react.element");
|
|
|
10
10
|
* - Same as Markdown syntax.
|
|
11
11
|
* - Markdown's underline syntax is not supported (for simplification).
|
|
12
12
|
*/
|
|
13
|
-
export const HEADING_RULE = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
props: { children: heading.trim() },
|
|
21
|
-
}),
|
|
22
|
-
contexts: ["block"],
|
|
23
|
-
subcontext: "inline",
|
|
24
|
-
};
|
|
13
|
+
export const HEADING_RULE = new NamedRegExpMarkupRule(getLineRegExp(`(?<prefix>#{1,6}) +(?<heading>${LINE_REGEXP.source})`), ({ prefix, heading }) => ({
|
|
14
|
+
type: `h${prefix.length}`,
|
|
15
|
+
key: null,
|
|
16
|
+
ref: null,
|
|
17
|
+
$$typeof,
|
|
18
|
+
props: { children: heading.trim() },
|
|
19
|
+
}), ["block"], "inline");
|
|
25
20
|
/**
|
|
26
21
|
* Separator (horizontal rule / thematic break).
|
|
27
22
|
* - Same as Markdown syntax but also allows `•` bullet character (in addition to `-` dash, `+` plus, `*` asterisk, `_` underscore).
|
|
@@ -29,17 +24,13 @@ export const HEADING_RULE = {
|
|
|
29
24
|
* - Character must be the same every time (can't mix)
|
|
30
25
|
* - Might have infinite number of spaces between the characters.
|
|
31
26
|
*/
|
|
32
|
-
export const SEPARATOR_RULE = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
props: {},
|
|
40
|
-
}),
|
|
41
|
-
contexts: ["block"],
|
|
42
|
-
};
|
|
27
|
+
export const SEPARATOR_RULE = new RegExpMarkupRule(getLineRegExp("([-*•+_=])(?: *\\1){2,}"), () => ({
|
|
28
|
+
type: "hr",
|
|
29
|
+
key: null,
|
|
30
|
+
ref: null,
|
|
31
|
+
$$typeof,
|
|
32
|
+
props: {},
|
|
33
|
+
}), ["block"]);
|
|
43
34
|
/**
|
|
44
35
|
* Unordered list.
|
|
45
36
|
* - Roughly the same syntax as Markdown (might be some differences with indenting).
|
|
@@ -50,18 +41,13 @@ export const SEPARATOR_RULE = {
|
|
|
50
41
|
const UNORDERED_PREFIX = "[-*•+] +";
|
|
51
42
|
const UNORDERED_SPLIT = new RegExp(`(?:^|\n)+${UNORDERED_PREFIX}`, "g");
|
|
52
43
|
const UNORDERED_INDENT = /^\t/gm;
|
|
53
|
-
export const UNORDERED_RULE = {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
props: { children: list.split(UNORDERED_SPLIT).filter(Boolean).map(_mapUnordered) },
|
|
61
|
-
}),
|
|
62
|
-
contexts: ["block", "list"],
|
|
63
|
-
subcontext: "list",
|
|
64
|
-
};
|
|
44
|
+
export const UNORDERED_RULE = new NamedRegExpMarkupRule(getBlockRegExp(`(?<list>${UNORDERED_PREFIX}${BLOCK_REGEXP.source})`), ({ list }) => ({
|
|
45
|
+
type: "ul",
|
|
46
|
+
key: null,
|
|
47
|
+
ref: null,
|
|
48
|
+
$$typeof,
|
|
49
|
+
props: { children: list.split(UNORDERED_SPLIT).filter(Boolean).map(_mapUnordered) },
|
|
50
|
+
}), ["block", "list"], "list");
|
|
65
51
|
const _mapUnordered = (item, key) => ({
|
|
66
52
|
type: "li",
|
|
67
53
|
key,
|
|
@@ -77,18 +63,13 @@ const _mapUnordered = (item, key) => ({
|
|
|
77
63
|
const ORDERED_PREFIX = "[1-9][0-9]{0,8}[.):] +"; // Number for a numbered list, e.g. `1.` or `2)` or `3:`
|
|
78
64
|
const ORDERED_SPLIT = new RegExp(`\n+(?=${ORDERED_PREFIX})`, "g");
|
|
79
65
|
const ORDERED_INDENT = UNORDERED_INDENT;
|
|
80
|
-
export const ORDERED_RULE = {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
props: { children: list.split(ORDERED_SPLIT).map(_mapOrdered) },
|
|
88
|
-
}),
|
|
89
|
-
contexts: ["block", "list"],
|
|
90
|
-
subcontext: "list",
|
|
91
|
-
};
|
|
66
|
+
export const ORDERED_RULE = new NamedRegExpMarkupRule(getBlockRegExp(`(?<list>${ORDERED_PREFIX}${BLOCK_REGEXP.source})`), ({ list }) => ({
|
|
67
|
+
type: "ol",
|
|
68
|
+
key: null,
|
|
69
|
+
ref: null,
|
|
70
|
+
$$typeof,
|
|
71
|
+
props: { children: list.split(ORDERED_SPLIT).map(_mapOrdered) },
|
|
72
|
+
}), ["block", "list"], "list");
|
|
92
73
|
const _mapOrdered = (item, key) => ({
|
|
93
74
|
type: "li",
|
|
94
75
|
key,
|
|
@@ -110,18 +91,13 @@ const _mapOrdered = (item, key) => ({
|
|
|
110
91
|
*/
|
|
111
92
|
const BLOCKQUOTE_PREFIX = "> *";
|
|
112
93
|
const BLOCKQUOTE_INDENT = new RegExp(`^${BLOCKQUOTE_PREFIX}`, "gm");
|
|
113
|
-
export const BLOCKQUOTE_RULE = {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
props: { children: quote.replace(BLOCKQUOTE_INDENT, "") },
|
|
121
|
-
}),
|
|
122
|
-
contexts: ["block", "list"],
|
|
123
|
-
subcontext: "block",
|
|
124
|
-
};
|
|
94
|
+
export const BLOCKQUOTE_RULE = new NamedRegExpMarkupRule(getLineRegExp(`(?<quote>${BLOCKQUOTE_PREFIX}${LINE_REGEXP.source}(?:\n${BLOCKQUOTE_PREFIX}${LINE_REGEXP.source})*)`), ({ quote }) => ({
|
|
95
|
+
type: "blockquote",
|
|
96
|
+
key: null,
|
|
97
|
+
ref: null,
|
|
98
|
+
$$typeof,
|
|
99
|
+
props: { children: quote.replace(BLOCKQUOTE_INDENT, "") },
|
|
100
|
+
}), ["block", "list"], "block");
|
|
125
101
|
/**
|
|
126
102
|
* Fenced code blocks
|
|
127
103
|
* - Same as Markdown syntax.
|
|
@@ -129,62 +105,42 @@ export const BLOCKQUOTE_RULE = {
|
|
|
129
105
|
* - If there's no closing fence the code block will run to the end of the current string.
|
|
130
106
|
* - Markdown-style four-space indent syntax is not supported (only fenced code, since it's easier to use).
|
|
131
107
|
*/
|
|
132
|
-
export const FENCED_CODE_RULE =
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
props: { title: (title === null || title === void 0 ? void 0 : title.trim()) || undefined, children: code.trim() },
|
|
147
|
-
},
|
|
108
|
+
export const FENCED_CODE_RULE = new NamedRegExpMarkupRule(
|
|
109
|
+
// Matcher has its own end that only stops when it reaches a matching closing fence or the end of the string.
|
|
110
|
+
getLineRegExp(`(?<wrap>\`{3,}|~{3,}) *(?<title>${LINE_REGEXP.source})\n(?<code>${BLOCK_REGEXP.source})`, `(?:\n\\k<wrap>|$)`), ({ title, code }) => ({
|
|
111
|
+
type: "pre",
|
|
112
|
+
key: null,
|
|
113
|
+
ref: null,
|
|
114
|
+
$$typeof,
|
|
115
|
+
props: {
|
|
116
|
+
children: {
|
|
117
|
+
type: "code",
|
|
118
|
+
key: null,
|
|
119
|
+
ref: null,
|
|
120
|
+
$$typeof,
|
|
121
|
+
props: { title: (title === null || title === void 0 ? void 0 : title.trim()) || undefined, children: code.trim() },
|
|
148
122
|
},
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
priority: 10, // Higher priority than other blocks so e.g. lists inside fenced code don't become lists.
|
|
152
|
-
};
|
|
123
|
+
},
|
|
124
|
+
}), ["block", "list"], null, 10);
|
|
153
125
|
/**
|
|
154
126
|
* Paragraph.
|
|
155
127
|
* - When ordering rules, paragraph should go after other "block" context elements (because it has a very generous capture).
|
|
156
128
|
*/
|
|
157
|
-
export const PARAGRAPH_RULE = {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
129
|
+
export const PARAGRAPH_RULE = new NamedRegExpMarkupRule(getBlockRegExp(`(?<paragraph>${BLOCK_REGEXP.source})`), ({ paragraph }) => ({
|
|
130
|
+
type: `p`,
|
|
131
|
+
key: null,
|
|
132
|
+
ref: null,
|
|
133
|
+
$$typeof,
|
|
134
|
+
props: { children: paragraph.trim() },
|
|
135
|
+
}), ["block"], "inline", -10);
|
|
136
|
+
/** Render function for URL and LINK rules. */
|
|
137
|
+
export function renderLinkRule({ href, title }, { rel }) {
|
|
138
|
+
return {
|
|
139
|
+
type: "a",
|
|
161
140
|
key: null,
|
|
162
141
|
ref: null,
|
|
163
142
|
$$typeof,
|
|
164
|
-
props: { children:
|
|
165
|
-
}),
|
|
166
|
-
contexts: ["block"],
|
|
167
|
-
subcontext: "inline",
|
|
168
|
-
priority: -10, // Lower precedence than other blocks so it matches last and paragraphs can be broken by other blocks.
|
|
169
|
-
};
|
|
170
|
-
/**
|
|
171
|
-
* Function that checks a link against the schemas allowed by rendering.
|
|
172
|
-
* - Used by `URL_RULE~ and `LINK_RULE`
|
|
173
|
-
* - Validates that the link is a valid URL (using `getOptionalURL()` to resolve relative links relative to `options.url`).
|
|
174
|
-
* - Validates that the link's URL scheme is in the `options.schemes` whitelist (defaults to `http` and `https`).
|
|
175
|
-
* - Generates a default title for the link using `formatURL()` (e.g. `shax.com/my/dir`).
|
|
176
|
-
*/
|
|
177
|
-
export function getLinkMatcher(regexp) {
|
|
178
|
-
return (input, { schemes, url: base }) => {
|
|
179
|
-
const match = regexp.exec(input);
|
|
180
|
-
if (match) {
|
|
181
|
-
const { 0: first, index, groups } = match;
|
|
182
|
-
const { href, title } = groups;
|
|
183
|
-
const url = getOptionalURL(href, base);
|
|
184
|
-
if (url && schemes.includes(url.protocol)) {
|
|
185
|
-
return { 0: first, index, groups: { href: url.href, title: (title === null || title === void 0 ? void 0 : title.trim()) || formatURL(url) } };
|
|
186
|
-
}
|
|
187
|
-
}
|
|
143
|
+
props: { children: title, href, rel },
|
|
188
144
|
};
|
|
189
145
|
}
|
|
190
146
|
/**
|
|
@@ -195,18 +151,7 @@ export function getLinkMatcher(regexp) {
|
|
|
195
151
|
* - For security only schemes that appear in `options.schemes` will match (defaults to `http:` and `https:`).
|
|
196
152
|
*/
|
|
197
153
|
export const URL_REGEXP = getRegExp(/(?<href>[a-z]+:[-$_@.&!*,=;/#?:%a-zA-Z0-9]+)(?: +(?:\((?<title>[^)]*?)\)))?/);
|
|
198
|
-
export const URL_RULE =
|
|
199
|
-
match: getLinkMatcher(URL_REGEXP),
|
|
200
|
-
render: ({ href, title }, { rel }) => ({
|
|
201
|
-
type: "a",
|
|
202
|
-
key: null,
|
|
203
|
-
ref: null,
|
|
204
|
-
$$typeof,
|
|
205
|
-
props: { children: title, href, rel },
|
|
206
|
-
}),
|
|
207
|
-
contexts: ["inline", "list"],
|
|
208
|
-
subcontext: "link",
|
|
209
|
-
};
|
|
154
|
+
export const URL_RULE = new LinkRegExpMarkupRule(URL_REGEXP, renderLinkRule, ["inline", "list"], "link");
|
|
210
155
|
/**
|
|
211
156
|
* Markdown-style link.
|
|
212
157
|
* - Link in standard Markdown format, e.g. `[Google Maps](http://google.com/maps)`
|
|
@@ -216,10 +161,7 @@ export const URL_RULE = {
|
|
|
216
161
|
* - For security only `http://` or `https://` links will work (if invalid the unparsed text will be returned).
|
|
217
162
|
*/
|
|
218
163
|
export const LINK_REGEXP = getRegExp(/\[(?<title>[^\]]*?)\]\((?<href>[^)]*?)\)/);
|
|
219
|
-
export const LINK_RULE =
|
|
220
|
-
...URL_RULE,
|
|
221
|
-
match: getLinkMatcher(LINK_REGEXP),
|
|
222
|
-
};
|
|
164
|
+
export const LINK_RULE = new LinkRegExpMarkupRule(LINK_REGEXP, renderLinkRule, ["inline", "list"], "link");
|
|
223
165
|
/**
|
|
224
166
|
* Inline code.
|
|
225
167
|
* - Text surrounded by one or more "`" backtick tilde characters.
|
|
@@ -227,18 +169,13 @@ export const LINK_RULE = {
|
|
|
227
169
|
* - Closing characters must exactly match opening characters.
|
|
228
170
|
* - Same as Markdown syntax.
|
|
229
171
|
*/
|
|
230
|
-
export const CODE_RULE = {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
props: { children: code },
|
|
238
|
-
}),
|
|
239
|
-
contexts: ["inline", "list"],
|
|
240
|
-
priority: 10, // Higher priority than e.g. `strong` or `em` (from CommonMark spec: "Code span backticks have higher precedence than any other inline constructs except HTML tags and autolinks.")
|
|
241
|
-
};
|
|
172
|
+
export const CODE_RULE = new NamedRegExpMarkupRule(new RegExp(`(?<wrap>\`+)(?<code>${BLOCK_REGEXP.source})\\k<wrap>`), ({ code }) => ({
|
|
173
|
+
type: "code",
|
|
174
|
+
key: null,
|
|
175
|
+
ref: null,
|
|
176
|
+
$$typeof,
|
|
177
|
+
props: { children: code },
|
|
178
|
+
}), ["inline", "list"], null, 10);
|
|
242
179
|
/**
|
|
243
180
|
* Inline strong, emphasis, insert, delete, highlight.
|
|
244
181
|
* - Inline strong text wrapped in one or more `*` asterisks.
|
|
@@ -253,18 +190,14 @@ export const CODE_RULE = {
|
|
|
253
190
|
* - Different to Markdown: strong is always surrounded by `*asterisks*` and emphasis is always surrounded by `_underscores_` (strong isn't 'double emphasis').
|
|
254
191
|
*/
|
|
255
192
|
const INLINE_CHARS = { "-": "del", "~": "del", "+": "ins", "*": "strong", "_": "em", "=": "mark", ":": "mark" }; // Hyphen must be first so it works when we use the keys as a character class.
|
|
256
|
-
export const INLINE_RULE = {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}),
|
|
265
|
-
contexts: ["inline", "list", "link"],
|
|
266
|
-
subcontext: "inline",
|
|
267
|
-
};
|
|
193
|
+
export const INLINE_RULE = new NamedRegExpMarkupRule(new WordRegExp(`(?<wrap>(?<char>[${Object.keys(INLINE_CHARS).join("")}])+)(?<text>(?!\\k<char>)\\S|(?!\\k<char>)\\S[\\s\\S]*?(?!\\k<char>)\\S)\\k<wrap>`), // prettier-ignore
|
|
194
|
+
({ char, text }) => ({
|
|
195
|
+
type: INLINE_CHARS[char],
|
|
196
|
+
key: null,
|
|
197
|
+
ref: null,
|
|
198
|
+
$$typeof,
|
|
199
|
+
props: { children: text },
|
|
200
|
+
}), ["inline", "list", "link"], "inline");
|
|
268
201
|
/**
|
|
269
202
|
* Hard linebreak (`<br />` tag).
|
|
270
203
|
* - Any line break in a paragraph will become a hard `<br />` tag.
|
|
@@ -273,18 +206,13 @@ export const INLINE_RULE = {
|
|
|
273
206
|
* - This is more intuitive (a linebreak becomes a linebreak is isn't silently ignored).
|
|
274
207
|
* - This works better with textareas that wrap text (since manually breaking up long lines is no longer necessary).
|
|
275
208
|
*/
|
|
276
|
-
export const LINEBREAK_RULE = {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
props: {},
|
|
284
|
-
}),
|
|
285
|
-
contexts: ["inline", "list", "link"],
|
|
286
|
-
subcontext: "inline",
|
|
287
|
-
};
|
|
209
|
+
export const LINEBREAK_RULE = new RegExpMarkupRule(/\n/, () => ({
|
|
210
|
+
type: "br",
|
|
211
|
+
key: null,
|
|
212
|
+
ref: null,
|
|
213
|
+
$$typeof,
|
|
214
|
+
props: {},
|
|
215
|
+
}), ["inline", "list", "link"], "inline");
|
|
288
216
|
/**
|
|
289
217
|
* All markup rules.
|
|
290
218
|
* - Syntax parsed by `renderMarkup()` is defined entirely by the list of rules (i.e. not by code).
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"state-management",
|
|
12
12
|
"query-builder"
|
|
13
13
|
],
|
|
14
|
-
"version": "1.86.
|
|
14
|
+
"version": "1.86.2",
|
|
15
15
|
"repository": "https://github.com/dhoulb/shelving",
|
|
16
16
|
"author": "Dave Houlbrooke <dave@shax.com>",
|
|
17
17
|
"license": "0BSD",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"sideEffects": false,
|
|
44
44
|
"engineStrict": true,
|
|
45
45
|
"engines": {
|
|
46
|
-
"node": ">=
|
|
46
|
+
"node": ">=16.0.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"fix": "npm run fix:prettier && npm run fix:eslint",
|
|
@@ -64,26 +64,26 @@
|
|
|
64
64
|
"build:jest": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config=jest.config.build.cjs"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@google-cloud/firestore": "^6.4.
|
|
68
|
-
"@types/jest": "^29.
|
|
69
|
-
"@types/react": "^18.0.
|
|
70
|
-
"@types/react-dom": "^18.0.
|
|
71
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
72
|
-
"@typescript-eslint/parser": "^5.
|
|
73
|
-
"dpdm": "^3.
|
|
74
|
-
"esbuild": "^0.15.
|
|
67
|
+
"@google-cloud/firestore": "^6.4.2",
|
|
68
|
+
"@types/jest": "^29.4.0",
|
|
69
|
+
"@types/react": "^18.0.27",
|
|
70
|
+
"@types/react-dom": "^18.0.10",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "^5.49.0",
|
|
72
|
+
"@typescript-eslint/parser": "^5.49.0",
|
|
73
|
+
"dpdm": "^3.11.0",
|
|
74
|
+
"esbuild": "^0.15.18",
|
|
75
75
|
"esbuild-jest": "^0.5.0",
|
|
76
|
-
"eslint": "^8.
|
|
77
|
-
"eslint-config-prettier": "^8.
|
|
78
|
-
"eslint-plugin-import": "^2.
|
|
76
|
+
"eslint": "^8.33.0",
|
|
77
|
+
"eslint-config-prettier": "^8.6.0",
|
|
78
|
+
"eslint-plugin-import": "^2.27.5",
|
|
79
79
|
"eslint-plugin-prettier": "^4.0.0",
|
|
80
|
-
"firebase": "^9.
|
|
81
|
-
"jest": "^29.
|
|
80
|
+
"firebase": "^9.16.0",
|
|
81
|
+
"jest": "^29.4.1",
|
|
82
82
|
"jest-ts-webcompat-resolver": "^1.0.0",
|
|
83
|
-
"prettier": "^2.8.
|
|
83
|
+
"prettier": "^2.8.3",
|
|
84
84
|
"react": "^18.1.0",
|
|
85
85
|
"react-dom": "^18.1.0",
|
|
86
|
-
"typescript": "^4.9.
|
|
86
|
+
"typescript": "^4.9.4"
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
89
|
"@google-cloud/firestore": ">=4.0.0",
|
package/react/useItem.js
CHANGED
|
@@ -18,9 +18,9 @@ export class ItemState extends State {
|
|
|
18
18
|
return !!this.value;
|
|
19
19
|
}
|
|
20
20
|
constructor(ref) {
|
|
21
|
-
var _a;
|
|
22
21
|
const { db, collection, id } = ref;
|
|
23
|
-
const
|
|
22
|
+
const cache = getOptionalSource(CacheProvider, db.provider);
|
|
23
|
+
const table = cache === null || cache === void 0 ? void 0 : cache.memory.getTable(collection);
|
|
24
24
|
const time = table ? table.getItemTime(id) : null;
|
|
25
25
|
const isCached = typeof time === "number";
|
|
26
26
|
super(table && isCached ? table.getItem(id) : State.NOVALUE, table ? new LazyDeferredSequence(() => this.from(table.getCachedItemSequence(id))) : undefined);
|
package/react/useQuery.js
CHANGED
|
@@ -38,9 +38,9 @@ export class QueryState extends State {
|
|
|
38
38
|
return this.value.length;
|
|
39
39
|
}
|
|
40
40
|
constructor(ref) {
|
|
41
|
-
var _a;
|
|
42
41
|
const { db, collection, limit } = ref;
|
|
43
|
-
const
|
|
42
|
+
const cache = getOptionalSource(CacheProvider, db.provider);
|
|
43
|
+
const table = cache === null || cache === void 0 ? void 0 : cache.memory.getTable(collection);
|
|
44
44
|
const time = table ? table.getQueryTime(ref) : null;
|
|
45
45
|
const isCached = typeof time === "number";
|
|
46
46
|
super(table && isCached ? table.getQuery(ref) : State.NOVALUE, table ? new LazyDeferredSequence(() => this.from(table.getCachedQuerySequence(ref))) : undefined);
|
package/schema/NumberSchema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getOptionalNumber, roundStep } from "../util/number.js";
|
|
1
|
+
import { formatNumber, getOptionalNumber, roundStep } from "../util/number.js";
|
|
2
2
|
import { InvalidFeedback } from "../feedback/InvalidFeedback.js";
|
|
3
3
|
import { Schema } from "./Schema.js";
|
|
4
4
|
import { OPTIONAL } from "./OptionalSchema.js";
|
|
@@ -17,9 +17,9 @@ export class NumberSchema extends Schema {
|
|
|
17
17
|
throw new InvalidFeedback("Must be number", { value: unsafeValue });
|
|
18
18
|
const safeNumber = typeof this.step === "number" ? roundStep(unsafeNumber, this.step) : unsafeNumber;
|
|
19
19
|
if (typeof this.max === "number" && safeNumber > this.max)
|
|
20
|
-
throw new InvalidFeedback(`Maximum ${this.max}`, { value: safeNumber });
|
|
20
|
+
throw new InvalidFeedback(`Maximum ${formatNumber(this.max)}`, { value: safeNumber });
|
|
21
21
|
if (typeof this.min === "number" && safeNumber < this.min)
|
|
22
|
-
throw new InvalidFeedback(`Minimum ${this.min}`, { value: safeNumber });
|
|
22
|
+
throw new InvalidFeedback(`Minimum ${formatNumber(this.min)}`, { value: safeNumber });
|
|
23
23
|
return safeNumber;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -28,6 +28,6 @@ export const NUMBER = new NumberSchema({});
|
|
|
28
28
|
/** Valid number, e.g. `2048.12345` or `0` zero, or `null` */
|
|
29
29
|
export const OPTIONAL_NUMBER = OPTIONAL(NUMBER);
|
|
30
30
|
/** Valid integer number, e.g. `2048` or `0` zero. */
|
|
31
|
-
export const INTEGER = new NumberSchema({ step: 1, min: Number.MIN_SAFE_INTEGER, max: Number.
|
|
31
|
+
export const INTEGER = new NumberSchema({ step: 1, min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER });
|
|
32
32
|
/** Valid integer number, e.g. `2048` or `0` zero, or `null` */
|
|
33
33
|
export const OPTIONAL_INTEGER = OPTIONAL(INTEGER);
|
package/update/ArrayUpdate.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ArraySchema } from "../schema/ArraySchema.js";
|
|
1
2
|
import { ImmutableArray } from "../util/array.js";
|
|
2
3
|
import { Validator } from "../util/validate.js";
|
|
3
4
|
import { Update } from "./Update.js";
|
|
@@ -15,5 +16,5 @@ export declare class ArrayUpdate<T> extends Update<ImmutableArray<T>> {
|
|
|
15
16
|
/** Return an array update with an additional item marked for deletion. */
|
|
16
17
|
delete(...deletes: T[]): this;
|
|
17
18
|
transform(arr?: ImmutableArray<T>): ImmutableArray<T>;
|
|
18
|
-
validate(validator: Validator<ImmutableArray<T>>): this;
|
|
19
|
+
validate(validator: ArraySchema<T> | Validator<ImmutableArray<T>>): this;
|
|
19
20
|
}
|
package/update/ArrayUpdate.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ArraySchema } from "../schema/ArraySchema.js";
|
|
2
2
|
import { withArrayItems, omitArrayItems } from "../util/array.js";
|
|
3
|
+
import { getPrototype } from "../util/object.js";
|
|
3
4
|
import { validateArray } from "../util/validate.js";
|
|
4
5
|
import { Update } from "./Update.js";
|
|
5
6
|
/** Update that can be applied to an array to add/remove items. */
|
|
@@ -20,7 +21,7 @@ export class ArrayUpdate extends Update {
|
|
|
20
21
|
/** Return an array update with an additional item marked for addition. */
|
|
21
22
|
add(...adds) {
|
|
22
23
|
return {
|
|
23
|
-
__proto__:
|
|
24
|
+
__proto__: getPrototype(this),
|
|
24
25
|
...this,
|
|
25
26
|
adds: [...this.adds, ...adds],
|
|
26
27
|
};
|
|
@@ -28,7 +29,7 @@ export class ArrayUpdate extends Update {
|
|
|
28
29
|
/** Return an array update with an additional item marked for deletion. */
|
|
29
30
|
delete(...deletes) {
|
|
30
31
|
return {
|
|
31
|
-
__proto__:
|
|
32
|
+
__proto__: getPrototype(this),
|
|
32
33
|
...this,
|
|
33
34
|
deletes: [...this.deletes, ...deletes],
|
|
34
35
|
};
|
|
@@ -42,7 +43,7 @@ export class ArrayUpdate extends Update {
|
|
|
42
43
|
if (!(validator instanceof ArraySchema))
|
|
43
44
|
return super.validate(validator);
|
|
44
45
|
return {
|
|
45
|
-
__proto__:
|
|
46
|
+
__proto__: getPrototype(this),
|
|
46
47
|
...this,
|
|
47
48
|
adds: validateArray(this.adds, validator.items),
|
|
48
49
|
deletes: validateArray(this.deletes, validator.items),
|
package/update/DataUpdate.js
CHANGED
|
@@ -3,6 +3,7 @@ import { InvalidFeedback } from "../feedback/InvalidFeedback.js";
|
|
|
3
3
|
import { DataSchema } from "../schema/DataSchema.js";
|
|
4
4
|
import { getDataProps } from "../util/data.js";
|
|
5
5
|
import { isNullish } from "../util/null.js";
|
|
6
|
+
import { getPrototype } from "../util/object.js";
|
|
6
7
|
import { transformObject } from "../util/transform.js";
|
|
7
8
|
import { validate } from "../util/validate.js";
|
|
8
9
|
import { Update } from "./Update.js";
|
|
@@ -49,7 +50,7 @@ export class DataUpdate extends Update {
|
|
|
49
50
|
if (isNullish(key))
|
|
50
51
|
return this;
|
|
51
52
|
return {
|
|
52
|
-
__proto__:
|
|
53
|
+
__proto__: getPrototype(this),
|
|
53
54
|
...this,
|
|
54
55
|
updates: { ...this.updates, [key]: value },
|
|
55
56
|
};
|
|
@@ -63,7 +64,7 @@ export class DataUpdate extends Update {
|
|
|
63
64
|
if (!(validator instanceof DataSchema))
|
|
64
65
|
return super.validate(validator);
|
|
65
66
|
return {
|
|
66
|
-
__proto__:
|
|
67
|
+
__proto__: getPrototype(this),
|
|
67
68
|
...this,
|
|
68
69
|
updates: validateUpdates(this.updates, validator.props),
|
|
69
70
|
};
|
|
@@ -4,6 +4,7 @@ import { DictionarySchema } from "../schema/DictionarySchema.js";
|
|
|
4
4
|
import { validate } from "../util/validate.js";
|
|
5
5
|
import { InvalidFeedback } from "../feedback/InvalidFeedback.js";
|
|
6
6
|
import { isFeedback } from "../feedback/Feedback.js";
|
|
7
|
+
import { getPrototype } from "../util/object.js";
|
|
7
8
|
import { Update } from "./Update.js";
|
|
8
9
|
import { Delete, DELETE } from "./Delete.js";
|
|
9
10
|
/** Update that can be applied to a dictionary object to add/remove/update its entries. */
|
|
@@ -25,7 +26,7 @@ export class DictionaryUpdate extends Update {
|
|
|
25
26
|
if (isNullish(key))
|
|
26
27
|
return this;
|
|
27
28
|
return {
|
|
28
|
-
__proto__:
|
|
29
|
+
__proto__: getPrototype(this),
|
|
29
30
|
...this,
|
|
30
31
|
updates: { ...this.updates, [key]: value },
|
|
31
32
|
};
|
|
@@ -35,7 +36,7 @@ export class DictionaryUpdate extends Update {
|
|
|
35
36
|
if (isNullish(key))
|
|
36
37
|
return this;
|
|
37
38
|
return {
|
|
38
|
-
__proto__:
|
|
39
|
+
__proto__: getPrototype(this),
|
|
39
40
|
...this,
|
|
40
41
|
updates: { ...this.updates, [key]: DELETE },
|
|
41
42
|
};
|
|
@@ -49,7 +50,7 @@ export class DictionaryUpdate extends Update {
|
|
|
49
50
|
if (!(validator instanceof DictionarySchema))
|
|
50
51
|
return super.validate(validator);
|
|
51
52
|
return {
|
|
52
|
-
__proto__:
|
|
53
|
+
__proto__: getPrototype(this),
|
|
53
54
|
...this,
|
|
54
55
|
updates: Object.fromEntries(_validateDictionaryUpdates(this.updates, validator.items)),
|
|
55
56
|
};
|
package/util/class.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export type Constructor<T, A extends Arguments> = new (...args: A) => T;
|
|
|
4
4
|
/** Any function arguments (designed for use with `extends Arguments` guards). */
|
|
5
5
|
export type AnyConstructor = new (...args: any) => any;
|
|
6
6
|
/** Class prototype that can be used with `instanceof` (string name, as per `Function`, and a prototype field matching the object). */
|
|
7
|
-
export type Class<T = unknown> = Function & {
|
|
7
|
+
export type Class<T = unknown> = Omit<Function, "prototype"> & {
|
|
8
8
|
prototype: T;
|
|
9
9
|
};
|
|
10
10
|
/** Is a given value a class constructor? */
|
package/util/clone.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { isArray } from "./array.js";
|
|
2
2
|
import { isData } from "./data.js";
|
|
3
3
|
import { mapArray, mapObject } from "./transform.js";
|
|
4
|
+
import { getPrototype } from "./object.js";
|
|
4
5
|
/** Does an object implement `Cloneable` */
|
|
5
|
-
export const isCloneable = (v) => isData(v) && typeof v.
|
|
6
|
+
export const isCloneable = (v) => isData(v) && typeof v.clone === "function";
|
|
6
7
|
/** Shallow clone a value. */
|
|
7
8
|
export const shallowClone = (value) => value;
|
|
8
9
|
/** Deep clone a value. */
|
|
@@ -20,7 +21,7 @@ export function cloneArray(input, recursor = shallowClone) {
|
|
|
20
21
|
if (isCloneable(input))
|
|
21
22
|
return input.clone();
|
|
22
23
|
const output = mapArray(input, recursor);
|
|
23
|
-
Object.setPrototypeOf(output,
|
|
24
|
+
Object.setPrototypeOf(output, getPrototype(input));
|
|
24
25
|
return output;
|
|
25
26
|
}
|
|
26
27
|
/** Clone an object. */
|
|
@@ -28,6 +29,6 @@ export function cloneObject(input, recursor = shallowClone) {
|
|
|
28
29
|
if (isCloneable(input))
|
|
29
30
|
return input.clone();
|
|
30
31
|
const output = mapObject(input, recursor);
|
|
31
|
-
Object.setPrototypeOf(input,
|
|
32
|
+
Object.setPrototypeOf(input, getPrototype(input));
|
|
32
33
|
return output;
|
|
33
34
|
}
|
package/util/data.d.ts
CHANGED
|
@@ -24,13 +24,6 @@ export declare function getData<T extends Data>(result: OptionalData<T>): T;
|
|
|
24
24
|
/** Get the props of a data object. */
|
|
25
25
|
export declare function getDataProps<T extends Data>(data: T): ImmutableArray<DataProp<T>>;
|
|
26
26
|
export declare function getDataProps<T extends Data>(data: T | Partial<T>): ImmutableArray<DataProp<T>>;
|
|
27
|
-
/**
|
|
28
|
-
* Format a data object as a string.
|
|
29
|
-
* - Use the custom `.toString()` function if it exists (don't use built in `Object.prototype.toString` because it's useless.
|
|
30
|
-
* - Use `.title` or `.name` or `.id` if they exist and are strings.
|
|
31
|
-
* - Use `Object` otherwise.
|
|
32
|
-
*/
|
|
33
|
-
export declare function formatData(data: Data): string;
|
|
34
27
|
/** Type that represents an empty data object. */
|
|
35
28
|
export type EmptyData = {
|
|
36
29
|
readonly [K in never]: never;
|
package/util/data.js
CHANGED
|
@@ -13,25 +13,7 @@ export function getData(result) {
|
|
|
13
13
|
export function getDataProps(data) {
|
|
14
14
|
return Object.entries(data);
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Format a data object as a string.
|
|
18
|
-
* - Use the custom `.toString()` function if it exists (don't use built in `Object.prototype.toString` because it's useless.
|
|
19
|
-
* - Use `.title` or `.name` or `.id` if they exist and are strings.
|
|
20
|
-
* - Use `Object` otherwise.
|
|
21
|
-
*/
|
|
22
|
-
export function formatData(data) {
|
|
23
|
-
const { toString, name, title, id } = data;
|
|
24
|
-
if (typeof toString === "function" && toString !== Object.prototype.toString)
|
|
25
|
-
return data.toString();
|
|
26
|
-
if (typeof name === "string")
|
|
27
|
-
return name;
|
|
28
|
-
if (typeof title === "string")
|
|
29
|
-
return title;
|
|
30
|
-
if (typeof id === "string")
|
|
31
|
-
return id;
|
|
32
|
-
return "Object";
|
|
33
|
-
}
|
|
34
16
|
/** An empty object. */
|
|
35
|
-
export const EMPTY_DATA = {};
|
|
17
|
+
export const EMPTY_DATA = { __proto__: null };
|
|
36
18
|
/** Function that returns an an empty object. */
|
|
37
19
|
export const getEmptyData = () => EMPTY_DATA;
|
package/util/date.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export declare const getYMD: (possible?: PossibleDate) => string;
|
|
|
35
35
|
/** List of day-of-week strings. */
|
|
36
36
|
export declare const days: readonly ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
|
|
37
37
|
/** Type listing day-of-week strings. */
|
|
38
|
-
export type Day = typeof days[number];
|
|
38
|
+
export type Day = (typeof days)[number];
|
|
39
39
|
/** Convert a `Date` instance to a day-of-week string like "monday" */
|
|
40
40
|
export declare const getDay: (target?: PossibleDate) => Day;
|
|
41
41
|
/** Get a Date representing exactly midnight of the specified date. */
|