@remoteoss/json-schema-form 0.6.6-beta.0 → 0.6.6-dev.20231026142809

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/CHANGELOG.md CHANGED
@@ -1,13 +1,3 @@
1
- #### 0.6.6-beta.0 (2023-10-17)
2
-
3
- ##### Chores
4
-
5
- - **github:** Add template for issues and pull requests ([#45](https://github.com/remoteoss/json-schema-form/pull/45)) ([621e3338](https://github.com/remoteoss/json-schema-form/commit/621e33389638541e771d2229c91655e430ea7ec4))
6
-
7
- ##### Bug Fixes
8
-
9
- - allow 0 in const validation ([#48](https://github.com/remoteoss/json-schema-form/pull/48)) ([cde19fc9](https://github.com/remoteoss/json-schema-form/commit/cde19fc960c4eacdde476ddcdd8c650a4ff5ce96))
10
-
11
1
  #### 0.6.5-beta.0 (2023-09-18)
12
2
 
13
3
  ##### Changes
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2023 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.6.6-beta.0
5
- Generated: Tue, 17 Oct 2023 13:38:25 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.6.6-dev.20231026142809
5
+ Generated: Thu, 26 Oct 2023 14:28:35 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -472,13 +472,34 @@ var yupSchemas = {
472
472
  if (value === "") {
473
473
  return void 0;
474
474
  }
475
- if (options?.includes(null)) {
475
+ if (options?.some((option) => option.value === null)) {
476
476
  return value;
477
477
  }
478
478
  return value === null ? void 0 : value;
479
- }).oneOf(options, ({ value }) => {
480
- return `The option ${JSON.stringify(value)} is not valid.`;
481
- }),
479
+ }).test(
480
+ /*
481
+ Custom test determines if the value either:
482
+ - Matches a specific option by value
483
+ - Matches a pattern
484
+ If the option is undefined do not test, to allow for optional fields.
485
+ */
486
+ "matchesOptionOrPattern",
487
+ ({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
488
+ (value) => {
489
+ if (value === void 0) {
490
+ return true;
491
+ }
492
+ const exactMatch = options.some((option) => option.value === value);
493
+ if (exactMatch) {
494
+ return true;
495
+ }
496
+ const patternMatch = options.some((option) => option.pattern?.test(value));
497
+ if (patternMatch) {
498
+ return true;
499
+ }
500
+ return false;
501
+ }
502
+ ),
482
503
  date: ({ minDate, maxDate }) => {
483
504
  let dateString = (0, import_yup.string)().nullable().transform((value) => {
484
505
  if (value === "") {
@@ -536,12 +557,15 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
536
557
  }
537
558
  var getJsonTypeInArray = (jsonType) => Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
538
559
  var getOptions = (field) => {
539
- const allValues = field.options?.map((option) => option.value);
560
+ const allValues = field.options?.map((option) => ({
561
+ value: option.value,
562
+ pattern: option.pattern ? new RegExp(option.pattern) : null
563
+ }));
540
564
  const isOptionalWithNull = Array.isArray(field.jsonType) && // @TODO should also check the "oneOf" directly looking for "null"
541
565
  // option but we don't have direct access at this point.
542
566
  // Otherwise the JSON Schema validator will fail as explained in PR#18
543
567
  field.jsonType.includes("null");
544
- return isOptionalWithNull ? [...allValues, null] : allValues;
568
+ return isOptionalWithNull ? [...allValues, { option: null }] : allValues;
545
569
  };
546
570
  var getYupSchema = ({ inputType, ...field }) => {
547
571
  const jsonType = getJsonTypeInArray(field.jsonType);
@@ -701,7 +725,7 @@ function buildYupSchema(field, config, logic) {
701
725
  if (propertyFields.accept) {
702
726
  validators.push(withFileFormat);
703
727
  }
704
- if (typeof propertyFields.const !== "undefined") {
728
+ if (propertyFields.const) {
705
729
  validators.push(withConst);
706
730
  }
707
731
  if (propertyFields.jsonLogicValidations) {
@@ -1330,11 +1354,10 @@ function extractParametersFromNode(schemaNode) {
1330
1354
  const node = (0, import_omit.default)(schemaNode, ["x-jsf-presentation", "presentation"]);
1331
1355
  const description = presentation?.description || node.description;
1332
1356
  const statementDescription = containsHTML(presentation.statement?.description) ? wrapWithSpan(presentation.statement.description, { class: "jsf-statement" }) : presentation.statement?.description;
1333
- const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" ? { value: node.const } : {};
1334
1357
  return (0, import_omitBy.default)(
1335
1358
  {
1336
1359
  const: node.const,
1337
- ...value,
1360
+ ...node.const && node.default ? { value: node.const } : {},
1338
1361
  label: node.title,
1339
1362
  readOnly: node.readOnly,
1340
1363
  ...node.deprecated && {
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2023 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.6.6-beta.0
5
- Generated: Tue, 17 Oct 2023 13:38:25 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.6.6-dev.20231026142809
5
+ Generated: Thu, 26 Oct 2023 14:28:35 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -436,13 +436,34 @@ var yupSchemas = {
436
436
  if (value === "") {
437
437
  return void 0;
438
438
  }
439
- if (options?.includes(null)) {
439
+ if (options?.some((option) => option.value === null)) {
440
440
  return value;
441
441
  }
442
442
  return value === null ? void 0 : value;
443
- }).oneOf(options, ({ value }) => {
444
- return `The option ${JSON.stringify(value)} is not valid.`;
445
- }),
443
+ }).test(
444
+ /*
445
+ Custom test determines if the value either:
446
+ - Matches a specific option by value
447
+ - Matches a pattern
448
+ If the option is undefined do not test, to allow for optional fields.
449
+ */
450
+ "matchesOptionOrPattern",
451
+ ({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
452
+ (value) => {
453
+ if (value === void 0) {
454
+ return true;
455
+ }
456
+ const exactMatch = options.some((option) => option.value === value);
457
+ if (exactMatch) {
458
+ return true;
459
+ }
460
+ const patternMatch = options.some((option) => option.pattern?.test(value));
461
+ if (patternMatch) {
462
+ return true;
463
+ }
464
+ return false;
465
+ }
466
+ ),
446
467
  date: ({ minDate, maxDate }) => {
447
468
  let dateString = string().nullable().transform((value) => {
448
469
  if (value === "") {
@@ -500,12 +521,15 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
500
521
  }
501
522
  var getJsonTypeInArray = (jsonType) => Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
502
523
  var getOptions = (field) => {
503
- const allValues = field.options?.map((option) => option.value);
524
+ const allValues = field.options?.map((option) => ({
525
+ value: option.value,
526
+ pattern: option.pattern ? new RegExp(option.pattern) : null
527
+ }));
504
528
  const isOptionalWithNull = Array.isArray(field.jsonType) && // @TODO should also check the "oneOf" directly looking for "null"
505
529
  // option but we don't have direct access at this point.
506
530
  // Otherwise the JSON Schema validator will fail as explained in PR#18
507
531
  field.jsonType.includes("null");
508
- return isOptionalWithNull ? [...allValues, null] : allValues;
532
+ return isOptionalWithNull ? [...allValues, { option: null }] : allValues;
509
533
  };
510
534
  var getYupSchema = ({ inputType, ...field }) => {
511
535
  const jsonType = getJsonTypeInArray(field.jsonType);
@@ -665,7 +689,7 @@ function buildYupSchema(field, config, logic) {
665
689
  if (propertyFields.accept) {
666
690
  validators.push(withFileFormat);
667
691
  }
668
- if (typeof propertyFields.const !== "undefined") {
692
+ if (propertyFields.const) {
669
693
  validators.push(withConst);
670
694
  }
671
695
  if (propertyFields.jsonLogicValidations) {
@@ -1294,11 +1318,10 @@ function extractParametersFromNode(schemaNode) {
1294
1318
  const node = omit(schemaNode, ["x-jsf-presentation", "presentation"]);
1295
1319
  const description = presentation?.description || node.description;
1296
1320
  const statementDescription = containsHTML(presentation.statement?.description) ? wrapWithSpan(presentation.statement.description, { class: "jsf-statement" }) : presentation.statement?.description;
1297
- const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" ? { value: node.const } : {};
1298
1321
  return omitBy(
1299
1322
  {
1300
1323
  const: node.const,
1301
- ...value,
1324
+ ...node.const && node.default ? { value: node.const } : {},
1302
1325
  label: node.title,
1303
1326
  readOnly: node.readOnly,
1304
1327
  ...node.deprecated && {
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2023 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.6.6-beta.0
5
- Generated: Tue, 17 Oct 2023 13:38:25 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.6.6-dev.20231026142809
5
+ Generated: Thu, 26 Oct 2023 14:28:35 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -11790,13 +11790,34 @@ var yupSchemas = {
11790
11790
  if (value === "") {
11791
11791
  return void 0;
11792
11792
  }
11793
- if (options?.includes(null)) {
11793
+ if (options?.some((option) => option.value === null)) {
11794
11794
  return value;
11795
11795
  }
11796
11796
  return value === null ? void 0 : value;
11797
- }).oneOf(options, ({ value }) => {
11798
- return `The option ${JSON.stringify(value)} is not valid.`;
11799
- }),
11797
+ }).test(
11798
+ /*
11799
+ Custom test determines if the value either:
11800
+ - Matches a specific option by value
11801
+ - Matches a pattern
11802
+ If the option is undefined do not test, to allow for optional fields.
11803
+ */
11804
+ "matchesOptionOrPattern",
11805
+ ({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
11806
+ (value) => {
11807
+ if (value === void 0) {
11808
+ return true;
11809
+ }
11810
+ const exactMatch = options.some((option) => option.value === value);
11811
+ if (exactMatch) {
11812
+ return true;
11813
+ }
11814
+ const patternMatch = options.some((option) => option.pattern?.test(value));
11815
+ if (patternMatch) {
11816
+ return true;
11817
+ }
11818
+ return false;
11819
+ }
11820
+ ),
11800
11821
  date: ({ minDate, maxDate }) => {
11801
11822
  let dateString = StringSchema().nullable().transform((value) => {
11802
11823
  if (value === "") {
@@ -11854,12 +11875,15 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
11854
11875
  }
11855
11876
  var getJsonTypeInArray = (jsonType) => Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
11856
11877
  var getOptions = (field) => {
11857
- const allValues = field.options?.map((option) => option.value);
11878
+ const allValues = field.options?.map((option) => ({
11879
+ value: option.value,
11880
+ pattern: option.pattern ? new RegExp(option.pattern) : null
11881
+ }));
11858
11882
  const isOptionalWithNull = Array.isArray(field.jsonType) && // @TODO should also check the "oneOf" directly looking for "null"
11859
11883
  // option but we don't have direct access at this point.
11860
11884
  // Otherwise the JSON Schema validator will fail as explained in PR#18
11861
11885
  field.jsonType.includes("null");
11862
- return isOptionalWithNull ? [...allValues, null] : allValues;
11886
+ return isOptionalWithNull ? [...allValues, { option: null }] : allValues;
11863
11887
  };
11864
11888
  var getYupSchema = ({ inputType, ...field }) => {
11865
11889
  const jsonType = getJsonTypeInArray(field.jsonType);
@@ -12019,7 +12043,7 @@ function buildYupSchema(field, config, logic) {
12019
12043
  if (propertyFields.accept) {
12020
12044
  validators.push(withFileFormat);
12021
12045
  }
12022
- if (typeof propertyFields.const !== "undefined") {
12046
+ if (propertyFields.const) {
12023
12047
  validators.push(withConst);
12024
12048
  }
12025
12049
  if (propertyFields.jsonLogicValidations) {
@@ -12648,11 +12672,10 @@ function extractParametersFromNode(schemaNode) {
12648
12672
  const node = (0, import_omit.default)(schemaNode, ["x-jsf-presentation", "presentation"]);
12649
12673
  const description = presentation?.description || node.description;
12650
12674
  const statementDescription = containsHTML(presentation.statement?.description) ? wrapWithSpan(presentation.statement.description, { class: "jsf-statement" }) : presentation.statement?.description;
12651
- const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" ? { value: node.const } : {};
12652
12675
  return (0, import_omitBy.default)(
12653
12676
  {
12654
12677
  const: node.const,
12655
- ...value,
12678
+ ...node.const && node.default ? { value: node.const } : {},
12656
12679
  label: node.title,
12657
12680
  readOnly: node.readOnly,
12658
12681
  ...node.deprecated && {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remoteoss/json-schema-form",
3
- "version": "0.6.6-beta.0",
3
+ "version": "0.6.6-dev.20231026142809",
4
4
  "description": "Headless UI form powered by JSON Schemas",
5
5
  "author": "Remote.com <engineering@remote.com> (https://remote.com/)",
6
6
  "license": "MIT",
@@ -20,25 +20,6 @@ describe('validations: const', () => {
20
20
  expect(handleValidation({ ten_only: null }).formErrors).toBeUndefined();
21
21
  });
22
22
 
23
- it('Should work for when the number is 0', () => {
24
- const { handleValidation } = createHeadlessForm(
25
- {
26
- properties: {
27
- zero_only: { type: 'number', const: 0 },
28
- },
29
- },
30
- { strictInputType: false }
31
- );
32
- expect(handleValidation({}).formErrors).toEqual(undefined);
33
- expect(handleValidation({ zero_only: 1 }).formErrors).toEqual({
34
- zero_only: 'The only accepted value is 0.',
35
- });
36
- expect(handleValidation({ zero_only: 0 }).formErrors).toBeUndefined();
37
- // null is also considered valid until we fix @BUG RMT-518
38
- // Expectation: To fail with error "The only accepted value is 0."
39
- expect(handleValidation({ zero_only: null }).formErrors).toBeUndefined();
40
- });
41
-
42
23
  it('Should work for text', () => {
43
24
  const { handleValidation } = createHeadlessForm(
44
25
  {
@@ -115,45 +96,3 @@ describe('validations: const', () => {
115
96
  expect(fields[0]).toMatchObject({ value: 10, const: 10, default: 10 });
116
97
  });
117
98
  });
118
-
119
- describe('const/default with forced values', () => {
120
- it('Should work for when the number is 0', () => {
121
- const { fields, handleValidation } = createHeadlessForm(
122
- {
123
- properties: {
124
- zero_only: { type: 'number', const: 0, default: 0 },
125
- },
126
- },
127
- { strictInputType: false }
128
- );
129
- expect(handleValidation({}).formErrors).toEqual(undefined);
130
- expect(handleValidation({ zero_only: 1 }).formErrors).toEqual({
131
- zero_only: 'The only accepted value is 0.',
132
- });
133
- expect(fields[0]).toMatchObject({ value: 0, const: 0, default: 0 });
134
- expect(handleValidation({ zero_only: 0 }).formErrors).toBeUndefined();
135
- // null is also considered valid until we fix @BUG RMT-518
136
- // Expectation: To fail with error "The only accepted value is 0."
137
- expect(handleValidation({ zero_only: null }).formErrors).toBeUndefined();
138
- });
139
-
140
- it('Should work for number', () => {
141
- const { fields, handleValidation } = createHeadlessForm(
142
- {
143
- properties: {
144
- ten_only: { type: 'number', const: 10, default: 10 },
145
- },
146
- },
147
- { strictInputType: false }
148
- );
149
- expect(handleValidation({}).formErrors).toEqual(undefined);
150
- expect(handleValidation({ ten_only: 1 }).formErrors).toEqual({
151
- ten_only: 'The only accepted value is 10.',
152
- });
153
- expect(handleValidation({ ten_only: 10 }).formErrors).toBeUndefined();
154
- expect(fields[0]).toMatchObject({ value: 10, const: 10, default: 10 });
155
- // null is also considered valid until we fix @BUG RMT-518
156
- // Expectation: To fail with error "The only accepted value is 10."
157
- expect(handleValidation({ ten_only: null }).formErrors).toBeUndefined();
158
- });
159
- });
@@ -38,6 +38,7 @@ import {
38
38
  mockFileInput,
39
39
  mockRadioCardInput,
40
40
  mockRadioCardExpandableInput,
41
+ mockTelWithPattern,
41
42
  mockTextInput,
42
43
  mockTextInputDeprecated,
43
44
  mockNumberInput,
@@ -1442,6 +1443,51 @@ describe('createHeadlessForm', () => {
1442
1443
  });
1443
1444
  });
1444
1445
 
1446
+ it('supports oneOf pattern validation', () => {
1447
+ const result = createHeadlessForm(mockTelWithPattern);
1448
+
1449
+ expect(result).toMatchObject({
1450
+ fields: [
1451
+ {
1452
+ label: 'Phone number',
1453
+ name: 'phone_number',
1454
+ type: 'tel',
1455
+ required: false,
1456
+ options: [
1457
+ {
1458
+ label: 'Portugal',
1459
+ pattern: '^(\\+351)[0-9]{9,}$',
1460
+ },
1461
+ {
1462
+ label: 'United Kingdom (UK)',
1463
+ pattern: '^(\\+44)[0-9]{1,}$',
1464
+ },
1465
+ {
1466
+ label: 'Bolivia',
1467
+ pattern: '^(\\+591)[0-9]{9,}$',
1468
+ },
1469
+ {
1470
+ label: 'Canada',
1471
+ pattern: '^(\\+1)(206|224)[0-9]{1,}$',
1472
+ },
1473
+ {
1474
+ label: 'United States',
1475
+ pattern: '^(\\+1)[0-9]{1,}$',
1476
+ },
1477
+ ],
1478
+ },
1479
+ ],
1480
+ });
1481
+
1482
+ const fieldValidator = result.fields[0].schema;
1483
+
1484
+ expect(fieldValidator.isValidSync('+351123123123')).toBe(true);
1485
+ expect(() => fieldValidator.validateSync('+35100')).toThrowError(
1486
+ 'The option "+35100" is not valid.'
1487
+ );
1488
+ expect(fieldValidator.isValidSync(undefined)).toBe(true);
1489
+ });
1490
+
1445
1491
  describe('supports "fieldset" field type', () => {
1446
1492
  it('supports basic case', () => {
1447
1493
  const result = createHeadlessForm({
@@ -453,6 +453,46 @@ export const mockCheckboxInput = {
453
453
  type: 'string',
454
454
  };
455
455
 
456
+ export const mockTelWithPattern = {
457
+ properties: {
458
+ phone_number: {
459
+ title: 'Phone number',
460
+ description: 'Enter your telephone number',
461
+ type: 'string',
462
+ 'x-jsf-presentation': {
463
+ inputType: 'tel',
464
+ },
465
+ oneOf: [
466
+ {
467
+ title: 'Portugal',
468
+ pattern: '^(\\+351)[0-9]{9,}$',
469
+ 'x-jsf-presentation': { meta: { countryCode: '351' } },
470
+ },
471
+ {
472
+ title: 'United Kingdom (UK)',
473
+ pattern: '^(\\+44)[0-9]{1,}$',
474
+ 'x-jsf-presentation': { meta: { countryCode: '44' } },
475
+ },
476
+ {
477
+ title: 'Bolivia',
478
+ pattern: '^(\\+591)[0-9]{9,}$',
479
+ 'x-jsf-presentation': { meta: { countryCode: '591' } },
480
+ },
481
+ {
482
+ title: 'Canada',
483
+ pattern: '^(\\+1)(206|224)[0-9]{1,}$',
484
+ 'x-jsf-presentation': { meta: { countryCode: '1' } },
485
+ },
486
+ {
487
+ title: 'United States',
488
+ pattern: '^(\\+1)[0-9]{1,}$',
489
+ 'x-jsf-presentation': { meta: { countryCode: '1' } },
490
+ },
491
+ ],
492
+ },
493
+ },
494
+ };
495
+
456
496
  /**
457
497
  * Compose a schema with lower chance of human error
458
498
  * @param {Object} schema version