@valbuild/core 0.18.0 → 0.20.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.
Files changed (41) hide show
  1. package/dist/declarations/src/index.d.ts +4 -1
  2. package/dist/declarations/src/initSchema.d.ts +2 -2
  3. package/dist/declarations/src/patch/deref.d.ts +2 -1
  4. package/dist/declarations/src/patch/operation.d.ts +8 -0
  5. package/dist/declarations/src/schema/richtext.d.ts +7 -6
  6. package/dist/declarations/src/schema/string.d.ts +6 -3
  7. package/dist/declarations/src/selector/future/index.d.ts +3 -3
  8. package/dist/declarations/src/selector/index.d.ts +3 -3
  9. package/dist/declarations/src/source/future/remote.d.ts +2 -2
  10. package/dist/declarations/src/source/index.d.ts +3 -3
  11. package/dist/declarations/src/source/richtext.d.ts +70 -54
  12. package/dist/{index-4abf3a1f.esm.js → index-5d1ab97c.esm.js} +1 -1
  13. package/dist/{index-a9235737.esm.js → index-bccf1907.esm.js} +1 -1
  14. package/dist/{ops-a2a295f8.esm.js → ops-22b624eb.esm.js} +107 -35
  15. package/dist/{ops-f3015423.cjs.dev.js → ops-b0a33248.cjs.dev.js} +106 -33
  16. package/dist/{ops-0d09f8ee.cjs.prod.js → ops-def81fc3.cjs.prod.js} +106 -33
  17. package/dist/valbuild-core.cjs.dev.js +202 -104
  18. package/dist/valbuild-core.cjs.prod.js +202 -104
  19. package/dist/valbuild-core.esm.js +184 -106
  20. package/expr/dist/valbuild-core-expr.esm.js +2 -2
  21. package/package.json +4 -1
  22. package/patch/dist/valbuild-core-patch.cjs.dev.js +6 -1
  23. package/patch/dist/valbuild-core-patch.cjs.prod.js +6 -1
  24. package/patch/dist/valbuild-core-patch.esm.js +8 -3
  25. package/src/getSha256.ts +8 -0
  26. package/src/index.ts +21 -5
  27. package/src/module.ts +33 -2
  28. package/src/patch/deref.ts +14 -1
  29. package/src/patch/operation.ts +10 -0
  30. package/src/patch/parse.ts +1 -0
  31. package/src/patch/patch.ts +3 -0
  32. package/src/schema/richtext.ts +19 -73
  33. package/src/schema/string.ts +14 -4
  34. package/src/schema/validation.test.ts +2 -2
  35. package/src/selector/future/index.ts +8 -4
  36. package/src/selector/index.ts +4 -4
  37. package/src/source/future/remote.ts +2 -2
  38. package/src/source/index.ts +2 -2
  39. package/src/source/richtext.test.ts +178 -0
  40. package/src/source/richtext.ts +295 -89
  41. package/tsconfig.json +2 -1
@@ -1,7 +1,8 @@
1
- import { _ as _inherits, a as _createSuper, b as _classCallCheck, c as _createClass, d as _defineProperty, e as _typeof, S as Schema, G as GetSchema, g as getValPath, f as _slicedToArray, h as _objectSpread2, i as image, V as VAL_EXTENSION, j as file, k as isFile, F as FILE_REF_PROP, P as Path, l as GetSource, m as isSerializedVal, n as convertFileSource, o as getSchema, p as isVal } from './index-a9235737.esm.js';
2
- export { F as FILE_REF_PROP, q as GenericSelector, S as Schema, V as VAL_EXTENSION } from './index-a9235737.esm.js';
3
- import { c as createValPathOfItem, a as array, o as object, u as union, r as richtext$1, b as content, P as PatchError, n as newSelectorProxy, i as isSelector, g as getSource, d as resolvePath, s as splitModuleIdAndModulePath } from './ops-a2a295f8.esm.js';
4
- export { i as expr } from './index-4abf3a1f.esm.js';
1
+ import { _ as _inherits, a as _createSuper, b as _classCallCheck, c as _createClass, d as _defineProperty, e as _typeof, S as Schema, G as GetSchema, g as getValPath, i as image, V as VAL_EXTENSION, f as convertFileSource, h as file, j as _objectSpread2, k as _slicedToArray, l as isFile, F as FILE_REF_PROP, P as Path, m as GetSource, n as isSerializedVal, o as getSchema, p as isVal } from './index-bccf1907.esm.js';
2
+ export { F as FILE_REF_PROP, q as GenericSelector, S as Schema, V as VAL_EXTENSION } from './index-bccf1907.esm.js';
3
+ import { a as array, o as object, u as union, r as richtext$1, b as record, c as content, P as PatchError, n as newSelectorProxy, d as createValPathOfItem, i as isSelector, g as getSource, e as resolvePath, s as splitModuleIdAndModulePath } from './ops-22b624eb.esm.js';
4
+ import * as marked from 'marked';
5
+ export { i as expr } from './index-5d1ab97c.esm.js';
5
6
  import { _ as _createForOfIteratorHelper, i as isErr, a as isOk, e as err, o as ok, r as result } from './result-b96df128.esm.js';
6
7
 
7
8
  var NumberSchema = /*#__PURE__*/function (_Schema) {
@@ -65,10 +66,12 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
65
66
  function StringSchema(options) {
66
67
  var _this;
67
68
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
69
+ var isRaw = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
68
70
  _classCallCheck(this, StringSchema);
69
71
  _this = _super.call(this);
70
72
  _this.options = options;
71
73
  _this.opt = opt;
74
+ _this.isRaw = isRaw;
72
75
  return _this;
73
76
  }
74
77
  _createClass(StringSchema, [{
@@ -96,7 +99,12 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
96
99
  }, {
97
100
  key: "optional",
98
101
  value: function optional() {
99
- return new StringSchema(this.options, true);
102
+ return new StringSchema(this.options, true, this.isRaw);
103
+ }
104
+ }, {
105
+ key: "raw",
106
+ value: function raw() {
107
+ return new StringSchema(this.options, this.opt, true);
100
108
  }
101
109
  }, {
102
110
  key: "serialize",
@@ -104,7 +112,8 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
104
112
  return {
105
113
  type: "string",
106
114
  options: this.options,
107
- opt: this.opt
115
+ opt: this.opt,
116
+ raw: this.isRaw
108
117
  };
109
118
  }
110
119
  }]);
@@ -337,95 +346,6 @@ var keyOf = function keyOf(valModule) {
337
346
  return new KeyOfSchema(valModule);
338
347
  };
339
348
 
340
- var RecordSchema = /*#__PURE__*/function (_Schema) {
341
- _inherits(RecordSchema, _Schema);
342
- var _super = _createSuper(RecordSchema);
343
- function RecordSchema(item) {
344
- var _this;
345
- var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
346
- _classCallCheck(this, RecordSchema);
347
- _this = _super.call(this);
348
- _this.item = item;
349
- _this.opt = opt;
350
- return _this;
351
- }
352
- _createClass(RecordSchema, [{
353
- key: "validate",
354
- value: function validate(path, src) {
355
- var _this2 = this;
356
- var error = false;
357
- if (this.opt && (src === null || src === undefined)) {
358
- return false;
359
- }
360
- if (_typeof(src) !== "object") {
361
- return _defineProperty({}, path, [{
362
- message: "Expected 'object', got '".concat(_typeof(src), "'")
363
- }]);
364
- }
365
- if (Array.isArray(src)) {
366
- return _defineProperty({}, path, [{
367
- message: "Expected 'object', got 'array'"
368
- }]);
369
- }
370
- Object.entries(src).forEach(function (_ref3) {
371
- var _ref4 = _slicedToArray(_ref3, 2),
372
- key = _ref4[0],
373
- elem = _ref4[1];
374
- var subPath = createValPathOfItem(path, key);
375
- if (!subPath) {
376
- error = _this2.appendValidationError(error, path, "Internal error: could not create path at ".concat(!path && typeof path === "string" ? "<empty string>" : path, " at key ").concat(elem),
377
- // Should! never happen
378
- src);
379
- } else {
380
- var subError = _this2.item.validate(subPath, elem);
381
- if (subError && error) {
382
- error = _objectSpread2(_objectSpread2({}, subError), error);
383
- } else if (subError) {
384
- error = subError;
385
- }
386
- }
387
- });
388
- return error;
389
- }
390
- }, {
391
- key: "assert",
392
- value: function assert(src) {
393
- if (this.opt && (src === null || src === undefined)) {
394
- return true;
395
- }
396
- if (!src) {
397
- return false;
398
- }
399
- for (var _i = 0, _Object$entries = Object.entries(src); _i < _Object$entries.length; _i++) {
400
- var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
401
- _item = _Object$entries$_i[1];
402
- if (!this.item.assert(_item)) {
403
- return false;
404
- }
405
- }
406
- return _typeof(src) === "object" && !Array.isArray(src);
407
- }
408
- }, {
409
- key: "optional",
410
- value: function optional() {
411
- return new RecordSchema(this.item, true);
412
- }
413
- }, {
414
- key: "serialize",
415
- value: function serialize() {
416
- return {
417
- type: "record",
418
- item: this.item.serialize(),
419
- opt: this.opt
420
- };
421
- }
422
- }]);
423
- return RecordSchema;
424
- }(Schema);
425
- var record = function record(schema) {
426
- return new RecordSchema(schema);
427
- };
428
-
429
349
  // import type { F } from "ts-toolbelt";
430
350
  // import { i18n, I18n } from "./schema/future/i18n";
431
351
  // import { oneOf } from "./schema/future/oneOf";
@@ -451,18 +371,140 @@ function initSchema() {
451
371
  };
452
372
  }
453
373
 
454
- function richtext(data) {
455
- if (typeof data === "string") {
456
- var _ref;
457
- return _ref = {}, _defineProperty(_ref, VAL_EXTENSION, "richtext"), _defineProperty(_ref, "type", "root"), _defineProperty(_ref, "children", [{
458
- type: "paragraph",
459
- children: [{
460
- type: "text",
461
- text: data
462
- }]
463
- }]), _ref;
374
+ // export type FontFamily<O extends RichTextOptions> =
375
+ // O["fontFamily"] extends Record<string, unknown>
376
+ // ? `font-${keyof O["fontFamily"] & string}`
377
+ // : never;
378
+ // export type FontSize<O extends RichTextOptions> = O["fontSize"] extends Record<
379
+ // string,
380
+ // unknown
381
+ // >
382
+ // ? `text-${keyof O["fontSize"] & string}`
383
+ // : never;
384
+ // | FontFamily<O>
385
+ // | FontSize<O>;
386
+ // export type AnchorNode<O extends RichTextOptions> = never; // TODO:
387
+ // O["link"] extends true
388
+ // ? {
389
+ // tag: "a";
390
+ // href: string;
391
+ // children: [string];
392
+ // }
393
+ // : never;
394
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
395
+ // export type BlockQuoteNode<O extends RichTextOptions> =
396
+ // O["blockQuote"] extends true
397
+ // ? { tag: "blockquote"; children: [string] }
398
+ // : never;
399
+ // TODO: rename to RichTextSelector?
400
+ function parseTokens(tokens) {
401
+ return tokens.flatMap(function (token) {
402
+ if (token.type === "heading") {
403
+ return [{
404
+ tag: "h".concat(token.depth),
405
+ children: parseTokens(token.tokens ? token.tokens : [])
406
+ }];
407
+ }
408
+ if (token.type === "paragraph") {
409
+ return [{
410
+ tag: "p",
411
+ children: parseTokens(token.tokens ? token.tokens : [])
412
+ }];
413
+ }
414
+ if (token.type === "strong") {
415
+ return [{
416
+ tag: "span",
417
+ classes: ["bold"],
418
+ children: parseTokens(token.tokens ? token.tokens : [])
419
+ }];
420
+ }
421
+ if (token.type === "em") {
422
+ return [{
423
+ tag: "span",
424
+ classes: ["italic"],
425
+ children: parseTokens(token.tokens ? token.tokens : [])
426
+ }];
427
+ }
428
+ if (token.type === "del") {
429
+ return [{
430
+ tag: "span",
431
+ classes: ["line-through"],
432
+ children: parseTokens(token.tokens ? token.tokens : [])
433
+ }];
434
+ }
435
+ if (token.type === "text") {
436
+ return [token.text];
437
+ }
438
+ if (token.type === "list") {
439
+ return [{
440
+ tag: token.ordered ? "ol" : "ul",
441
+ children: parseTokens(token.items)
442
+ }];
443
+ }
444
+ if (token.type === "list_item") {
445
+ return [{
446
+ tag: "li",
447
+ children: parseTokens(token.tokens ? token.tokens : [])
448
+ }];
449
+ }
450
+ if (token.type === "space") {
451
+ return [];
452
+ }
453
+ if (token.type === "code") {
454
+ return [{
455
+ tag: "span",
456
+ classes: [],
457
+ children: [token.text]
458
+ }];
459
+ }
460
+ // console.error(
461
+ // `Could not parse markdown: unsupported token type: ${token.type}. Found: ${token.raw}`
462
+ // );
463
+ return [token.raw];
464
+ });
465
+ }
466
+
467
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
468
+ function nodeToTag(node) {
469
+ if (node[VAL_EXTENSION] === "file") {
470
+ return node;
464
471
  }
465
- return _objectSpread2(_objectSpread2({}, data), {}, _defineProperty({}, VAL_EXTENSION, "richtext"));
472
+ throw Error("Unexpected node: ".concat(JSON.stringify(node)));
473
+ }
474
+ function imgSrcToImgTag(imageSrc) {
475
+ var _imageSrc$metadata, _imageSrc$metadata2;
476
+ var converted = convertFileSource(imageSrc);
477
+ return {
478
+ tag: "img",
479
+ src: converted.url,
480
+ width: (_imageSrc$metadata = imageSrc.metadata) === null || _imageSrc$metadata === void 0 ? void 0 : _imageSrc$metadata.width,
481
+ height: (_imageSrc$metadata2 = imageSrc.metadata) === null || _imageSrc$metadata2 === void 0 ? void 0 : _imageSrc$metadata2.height
482
+ };
483
+ }
484
+ function convertRichTextSource(src) {
485
+ var _ref;
486
+ return _ref = {}, _defineProperty(_ref, VAL_EXTENSION, "richtext"), _defineProperty(_ref, "children", src.children.map(function (source) {
487
+ if (VAL_EXTENSION in source && source[VAL_EXTENSION] === "file") {
488
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
489
+ return imgSrcToImgTag(source);
490
+ }
491
+ return source;
492
+ })), _ref;
493
+ }
494
+ function richtext(templateStrings) {
495
+ var _ref2;
496
+ for (var _len = arguments.length, expr = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
497
+ expr[_key - 1] = arguments[_key];
498
+ }
499
+ return _ref2 = {}, _defineProperty(_ref2, VAL_EXTENSION, "richtext"), _defineProperty(_ref2, "children", templateStrings.flatMap(function (templateString, i) {
500
+ var lex = marked.lexer(templateString, {
501
+ gfm: true
502
+ });
503
+ if (expr[i]) {
504
+ return parseTokens(lex).concat(nodeToTag(expr[i]));
505
+ }
506
+ return parseTokens(lex);
507
+ })), _ref2;
466
508
  }
467
509
 
468
510
  // import { i18n, I18n } from "./source/future/i18n";
@@ -600,6 +642,14 @@ function derefPatch(patch, document, ops) {
600
642
  } else {
601
643
  dereferencedPatch.push(op);
602
644
  }
645
+ } else if (op.op === "file") {
646
+ if (op.path[0] !== "public") {
647
+ return err(new PatchError("Path must start with public"));
648
+ }
649
+ if (typeof op.value !== "string") {
650
+ return err(new PatchError("File operation must have a value that is typeof string. Found: ".concat(_typeof(op.value))));
651
+ }
652
+ fileUpdates["/".concat(op.path.join("/"))] = op.value;
603
653
  } else {
604
654
  var _maybeDerefRes = derefPath(op.path);
605
655
  if (isErr(_maybeDerefRes)) {
@@ -1093,6 +1143,32 @@ function _asyncToGenerator(fn) {
1093
1143
  };
1094
1144
  }
1095
1145
 
1146
+ var getSHA256Hash = /*#__PURE__*/function () {
1147
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(bits) {
1148
+ var hashBuffer, hashArray, hash;
1149
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
1150
+ while (1) switch (_context.prev = _context.next) {
1151
+ case 0:
1152
+ _context.next = 2;
1153
+ return crypto.subtle.digest("SHA-256", bits);
1154
+ case 2:
1155
+ hashBuffer = _context.sent;
1156
+ hashArray = Array.from(new Uint8Array(hashBuffer));
1157
+ hash = hashArray.map(function (item) {
1158
+ return item.toString(16).padStart(2, "0");
1159
+ }).join("");
1160
+ return _context.abrupt("return", hash);
1161
+ case 6:
1162
+ case "end":
1163
+ return _context.stop();
1164
+ }
1165
+ }, _callee);
1166
+ }));
1167
+ return function getSHA256Hash(_x) {
1168
+ return _ref.apply(this, arguments);
1169
+ };
1170
+ }();
1171
+
1096
1172
  // TODO: move this to internal, only reason this is here is that react, ui and server all depend on it
1097
1173
  var ValApi = /*#__PURE__*/function () {
1098
1174
  function ValApi(host) {
@@ -1202,6 +1278,7 @@ function _parse() {
1202
1278
 
1203
1279
  var Internal = {
1204
1280
  convertFileSource: convertFileSource,
1281
+ convertRichTextSource: convertRichTextSource,
1205
1282
  getSchema: getSchema,
1206
1283
  getValPath: getValPath,
1207
1284
  getVal: getVal,
@@ -1210,6 +1287,7 @@ var Internal = {
1210
1287
  splitModuleIdAndModulePath: splitModuleIdAndModulePath,
1211
1288
  isVal: isVal,
1212
1289
  createValPathOfItem: createValPathOfItem,
1290
+ getSHA256Hash: getSHA256Hash,
1213
1291
  createPatchJSONPath: function createPatchJSONPath(modulePath) {
1214
1292
  return "/".concat(modulePath.split(".").map(function (segment) {
1215
1293
  return JSON.parse(segment);
@@ -1,3 +1,3 @@
1
- export { e as evaluate, p as parse } from '../../dist/index-4abf3a1f.esm.js';
2
- export { C as Call, E as Expr, N as NilSym, s as StringLiteral, t as StringTemplate, r as Sym } from '../../dist/index-a9235737.esm.js';
1
+ export { e as evaluate, p as parse } from '../../dist/index-5d1ab97c.esm.js';
2
+ export { C as Call, E as Expr, N as NilSym, s as StringLiteral, t as StringTemplate, r as Sym } from '../../dist/index-bccf1907.esm.js';
3
3
  import '../../dist/result-b96df128.esm.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/core",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "private": false,
5
5
  "description": "Val - supercharged hard-coded content",
6
6
  "scripts": {
@@ -41,5 +41,8 @@
41
41
  },
42
42
  "devDependencies": {
43
43
  "ts-toolbelt": "^9.6.0"
44
+ },
45
+ "dependencies": {
46
+ "marked": "^9.0.3"
44
47
  }
45
48
  }
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var index = require('../../dist/index-a6e642dd.cjs.dev.js');
6
6
  var result = require('../../dist/result-48320acd.cjs.dev.js');
7
7
  var util = require('../../dist/util-b213092b.cjs.dev.js');
8
- var ops = require('../../dist/ops-f3015423.cjs.dev.js');
8
+ var ops = require('../../dist/ops-b0a33248.cjs.dev.js');
9
9
 
10
10
  function isNotRoot(path) {
11
11
  return result.isNonEmpty(path);
@@ -350,6 +350,7 @@ function isProperPathPrefix(prefix, path) {
350
350
  function parseOperation(operation) {
351
351
  var path = parseJSONPointer(operation.path);
352
352
  switch (operation.op) {
353
+ case "file":
353
354
  case "add":
354
355
  case "replace":
355
356
  case "test":
@@ -431,6 +432,10 @@ function apply(document, ops$1, op) {
431
432
  }
432
433
  return result.ok(document);
433
434
  }
435
+ case "file":
436
+ {
437
+ return result.err(new ops.PatchError("Cannot apply a file patch here"));
438
+ }
434
439
  }
435
440
  }
436
441
  function applyPatch(document, ops, patch) {
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var index = require('../../dist/index-8706c87e.cjs.prod.js');
6
6
  var result = require('../../dist/result-26f67b40.cjs.prod.js');
7
7
  var util = require('../../dist/util-030d8a1f.cjs.prod.js');
8
- var ops = require('../../dist/ops-0d09f8ee.cjs.prod.js');
8
+ var ops = require('../../dist/ops-def81fc3.cjs.prod.js');
9
9
 
10
10
  function isNotRoot(path) {
11
11
  return result.isNonEmpty(path);
@@ -350,6 +350,7 @@ function isProperPathPrefix(prefix, path) {
350
350
  function parseOperation(operation) {
351
351
  var path = parseJSONPointer(operation.path);
352
352
  switch (operation.op) {
353
+ case "file":
353
354
  case "add":
354
355
  case "replace":
355
356
  case "test":
@@ -431,6 +432,10 @@ function apply(document, ops$1, op) {
431
432
  }
432
433
  return result.ok(document);
433
434
  }
435
+ case "file":
436
+ {
437
+ return result.err(new ops.PatchError("Cannot apply a file patch here"));
438
+ }
434
439
  }
435
440
  }
436
441
  function applyPatch(document, ops, patch) {
@@ -1,8 +1,8 @@
1
- import { e as _typeof, f as _slicedToArray, c as _createClass, b as _classCallCheck, u as _toConsumableArray } from '../../dist/index-a9235737.esm.js';
1
+ import { e as _typeof, k as _slicedToArray, c as _createClass, b as _classCallCheck, u as _toConsumableArray } from '../../dist/index-bccf1907.esm.js';
2
2
  import { f as isNonEmpty, e as err, o as ok, m as map, g as flatMap, i as isErr, h as flatMapReduce, j as filterOrElse, k as mapErr, l as map$1, n as all, p as flatten, q as allT } from '../../dist/result-b96df128.esm.js';
3
3
  import { p as pipe } from '../../dist/util-18613e99.esm.js';
4
- import { P as PatchError, s as splitModuleIdAndModulePath } from '../../dist/ops-a2a295f8.esm.js';
5
- export { P as PatchError } from '../../dist/ops-a2a295f8.esm.js';
4
+ import { P as PatchError, s as splitModuleIdAndModulePath } from '../../dist/ops-22b624eb.esm.js';
5
+ export { P as PatchError } from '../../dist/ops-22b624eb.esm.js';
6
6
 
7
7
  function isNotRoot(path) {
8
8
  return isNonEmpty(path);
@@ -347,6 +347,7 @@ function isProperPathPrefix(prefix, path) {
347
347
  function parseOperation(operation) {
348
348
  var path = parseJSONPointer(operation.path);
349
349
  switch (operation.op) {
350
+ case "file":
350
351
  case "add":
351
352
  case "replace":
352
353
  case "test":
@@ -428,6 +429,10 @@ function apply(document, ops, op) {
428
429
  }
429
430
  return ok(document);
430
431
  }
432
+ case "file":
433
+ {
434
+ return err(new PatchError("Cannot apply a file patch here"));
435
+ }
431
436
  }
432
437
  }
433
438
  function applyPatch(document, ops, patch) {
@@ -0,0 +1,8 @@
1
+ export const getSHA256Hash = async (bits: Uint8Array) => {
2
+ const hashBuffer = await crypto.subtle.digest("SHA-256", bits);
3
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
4
+ const hash = hashArray
5
+ .map((item) => item.toString(16).padStart(2, "0"))
6
+ .join("");
7
+ return hash;
8
+ };
package/src/index.ts CHANGED
@@ -5,13 +5,25 @@ export type { ValModule, SerializedModule } from "./module";
5
5
  export type { SourceObject, SourcePrimitive, Source } from "./source";
6
6
  export type { FileSource } from "./source/file";
7
7
  export type {
8
- RichTextSource,
9
- RichText,
10
- TextNode,
11
- ParagraphNode,
8
+ AnyRichTextOptions,
9
+ Bold,
10
+ Classes,
12
11
  HeadingNode,
12
+ ImageNode,
13
+ Italic,
14
+ LineThrough,
13
15
  ListItemNode,
14
- ListNode,
16
+ OrderedListNode,
17
+ ParagraphNode,
18
+ RichText,
19
+ RichTextNode,
20
+ RichTextOptions,
21
+ RichTextSource,
22
+ RichTextSourceNode,
23
+ RootNode,
24
+ SourceNode,
25
+ SpanNode,
26
+ UnorderedListNode,
15
27
  } from "./source/richtext";
16
28
  export {
17
29
  type Val,
@@ -44,6 +56,8 @@ import { createValPathOfItem } from "./selector/SelectorProxy";
44
56
  import { getVal } from "./future/fetchVal";
45
57
  import { Json } from "./Json";
46
58
  import { SerializedSchema } from "./schema";
59
+ import { convertRichTextSource } from "./source/richtext";
60
+ import { getSHA256Hash } from "./getSha256";
47
61
  export { ValApi } from "./ValApi";
48
62
 
49
63
  export type ApiTreeResponse = {
@@ -68,6 +82,7 @@ export type ApiPatchResponse = Record<ModuleId, string[]>;
68
82
 
69
83
  const Internal = {
70
84
  convertFileSource,
85
+ convertRichTextSource,
71
86
  getSchema,
72
87
  getValPath,
73
88
  getVal,
@@ -76,6 +91,7 @@ const Internal = {
76
91
  splitModuleIdAndModulePath,
77
92
  isVal,
78
93
  createValPathOfItem,
94
+ getSHA256Hash,
79
95
  createPatchJSONPath: (modulePath: ModulePath) =>
80
96
  `/${modulePath
81
97
  .split(".")
package/src/module.ts CHANGED
@@ -21,7 +21,8 @@ import {
21
21
  SerializedImageSchema,
22
22
  } from "./schema/image";
23
23
  import { FileSource } from "./source/file";
24
- import { RichText } from "./source/richtext";
24
+ import { AnyRichTextOptions, RichText } from "./source/richtext";
25
+ import { RecordSchema, SerializedRecordSchema } from "./schema/record";
25
26
 
26
27
  const brand = Symbol("ValModule");
27
28
  export type ValModule<T extends SelectorSource> = SelectorOf<T> &
@@ -94,6 +95,15 @@ function isObjectSchema(
94
95
  );
95
96
  }
96
97
 
98
+ function isRecordSchema(
99
+ schema: Schema<SelectorSource> | SerializedSchema
100
+ ): schema is RecordSchema<Schema<SelectorSource>> | SerializedRecordSchema {
101
+ return (
102
+ schema instanceof RecordSchema ||
103
+ (typeof schema === "object" && "type" in schema && schema.type === "record")
104
+ );
105
+ }
106
+
97
107
  function isArraySchema(
98
108
  schema: Schema<SelectorSource> | SerializedSchema
99
109
  ): schema is ArraySchema<Schema<SelectorSource>> | SerializedArraySchema {
@@ -126,7 +136,7 @@ function isUnionSchema(
126
136
  function isRichTextSchema(
127
137
  schema: Schema<SelectorSource> | SerializedSchema
128
138
  ): schema is
129
- | Schema<RichText> // TODO: RichTextSchema
139
+ | Schema<RichText<AnyRichTextOptions>> // TODO: RichTextSchema
130
140
  | SerializedRichTextSchema {
131
141
  return (
132
142
  schema instanceof RichTextSchema ||
@@ -192,6 +202,27 @@ export function resolvePath(
192
202
  }
193
203
  resolvedSource = resolvedSource[part];
194
204
  resolvedSchema = resolvedSchema.item;
205
+ } else if (isRecordSchema(resolvedSchema)) {
206
+ if (typeof part !== "string") {
207
+ throw Error(
208
+ `Invalid path: record schema ${resolvedSchema} must have path: ${part} as string`
209
+ );
210
+ }
211
+ if (
212
+ typeof resolvedSource !== "object" &&
213
+ !Array.isArray(resolvedSource)
214
+ ) {
215
+ throw Error(
216
+ `Schema type error: expected source to be type of record, but got ${typeof resolvedSource}`
217
+ );
218
+ }
219
+ if (!resolvedSource[part]) {
220
+ throw Error(
221
+ `Invalid path: record source did not have key ${part} from path: ${path}`
222
+ );
223
+ }
224
+ resolvedSource = resolvedSource[part];
225
+ resolvedSchema = resolvedSchema.item;
195
226
  } else if (isObjectSchema(resolvedSchema)) {
196
227
  if (typeof resolvedSource !== "object") {
197
228
  throw Error(
@@ -3,6 +3,7 @@ import { result } from "../fp";
3
3
  import { isRemote, REMOTE_REF_PROP } from "../source/future/remote";
4
4
  import { Ops, PatchError } from "./ops";
5
5
  import { Patch } from "./patch";
6
+ import { Operation } from "./operation";
6
7
 
7
8
  function derefPath(
8
9
  path: string[]
@@ -41,7 +42,7 @@ export type DerefPatchResult = {
41
42
  };
42
43
 
43
44
  export function derefPatch<D, E>(
44
- patch: Patch,
45
+ patch: Operation[],
45
46
  document: D,
46
47
  ops: Ops<D, E>
47
48
  ): result.Result<DerefPatchResult, E | PatchError> {
@@ -107,6 +108,18 @@ export function derefPatch<D, E>(
107
108
  } else {
108
109
  dereferencedPatch.push(op);
109
110
  }
111
+ } else if (op.op === "file") {
112
+ if (op.path[0] !== "public") {
113
+ return result.err(new PatchError(`Path must start with public`));
114
+ }
115
+ if (typeof op.value !== "string") {
116
+ return result.err(
117
+ new PatchError(
118
+ `File operation must have a value that is typeof string. Found: ${typeof op.value}`
119
+ )
120
+ );
121
+ }
122
+ fileUpdates[`/${op.path.join("/")}`] = op.value;
110
123
  } else {
111
124
  const maybeDerefRes = derefPath(op.path);
112
125
  if (result.isErr(maybeDerefRes)) {
@@ -33,6 +33,11 @@ export type OperationJSON =
33
33
  op: "test";
34
34
  path: string;
35
35
  value: JSONValue;
36
+ }
37
+ | {
38
+ op: "file";
39
+ path: string;
40
+ value: JSONValue;
36
41
  };
37
42
 
38
43
  /**
@@ -71,4 +76,9 @@ export type Operation =
71
76
  op: "test";
72
77
  path: string[];
73
78
  value: JSONValue;
79
+ }
80
+ | {
81
+ op: "file";
82
+ path: string[];
83
+ value: JSONValue;
74
84
  };
@@ -95,6 +95,7 @@ export function parseOperation(
95
95
  const path = parseJSONPointer(operation.path);
96
96
 
97
97
  switch (operation.op) {
98
+ case "file":
98
99
  case "add":
99
100
  case "replace":
100
101
  case "test":
@@ -27,6 +27,9 @@ function apply<T, E>(
27
27
  }
28
28
  return result.ok(document);
29
29
  }
30
+ case "file": {
31
+ return result.err(new PatchError("Cannot apply a file patch here"));
32
+ }
30
33
  }
31
34
  }
32
35