@prismicio/types-internal
Advanced tools
Comparing version 0.1.1 to 0.2.0
{ | ||
"name": "@prismicio/types-internal", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "Prismic types for Custom Types and Prismic Data", | ||
@@ -15,6 +15,6 @@ "keywords": [ | ||
"author": "Prismic <contact@prismic.io> (https://prismic.io)", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"main": "lib/index.js", | ||
"types": "lib/index.d.ts", | ||
"files": [ | ||
"dist", | ||
"lib", | ||
"src" | ||
@@ -31,30 +31,42 @@ ], | ||
"release:alpha:dry": "standard-version --release-as major --prerelease alpha --dry-run", | ||
"lint": "eslint --ext .js,.ts .", | ||
"unit": "nyc --reporter=lcovonly --reporter=text --exclude-after-remap=false ava", | ||
"size": "size-limit", | ||
"test": "npm run lint && npm run unit && npm run build && npm run size" | ||
"test": "jest --no-cache --silent=false --verbose=false", | ||
"eslint": "eslint . --cache --cache-location .caches/eslint --cache-strategy content --ext js,ts,tsx --max-warnings 0", | ||
"eslint-fix": "npm run eslint -- --fix", | ||
"preflight": "npm run prettier && npm run build && npm run eslint", | ||
"prettier": "prettier --check .", | ||
"prettier-write": "prettier --write ." | ||
}, | ||
"dependencies": { | ||
"fp-ts": "^2.11.8", | ||
"io-ts": "^2.2.16", | ||
"io-ts-types": "^0.5.16" | ||
"monocle-ts": "^2.3.11", | ||
"newtype-ts": "^0.3.5", | ||
"tslib": "^2.3.1" | ||
}, | ||
"devDependencies": { | ||
"@size-limit/preset-small-lib": "^7.0.5", | ||
"@relmify/jest-fp-ts": "^1.1.1", | ||
"@types/jest": "^27.4.0", | ||
"@typescript-eslint/eslint-plugin": "^5.8.1", | ||
"@typescript-eslint/parser": "^5.8.1", | ||
"ava": "^3.15.0", | ||
"eslint": "^8.6.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"eslint-plugin-tsdoc": "^0.2.14", | ||
"eslint": "8.6.0", | ||
"eslint-config-prettier": "8.3.0", | ||
"eslint-plugin-only-warn": "1.0.3", | ||
"eslint-plugin-simple-import-sort": "7.0.0", | ||
"eslint-plugin-storybook": "0.5.5", | ||
"fp-ts": "^2.11.8", | ||
"io-ts": "^2.2.16", | ||
"io-ts-types": "^0.5.16", | ||
"jest": "^27.5.1", | ||
"nyc": "^15.1.0", | ||
"prettier": "^2.5.1", | ||
"prettier-plugin-jsdoc": "^0.3.30", | ||
"siroc": "^0.16.0", | ||
"size-limit": "^7.0.5", | ||
"standard-version": "^9.3.2", | ||
"ts-eager": "^2.0.2", | ||
"ts-jest": "^27.1.3", | ||
"typescript": "^4.5.5" | ||
}, | ||
"peerDependencies": { | ||
"fp-ts": "^2.11.8", | ||
"io-ts": "^2.2.16", | ||
"io-ts-types": "^0.5.16" | ||
}, | ||
"engines": { | ||
@@ -61,0 +73,0 @@ "node": ">=12.7.0" |
@@ -13,3 +13,3 @@ <!-- | ||
# prismic-types-internal | ||
# @prismicio/types-internal | ||
@@ -42,3 +42,3 @@ [![npm version][npm-version-src]][npm-version-href] | ||
```bash | ||
npm install prismic-types-internal | ||
npm install @prismicio/types-internal | ||
``` | ||
@@ -95,19 +95,19 @@ | ||
[forum-question]: https://community.prismic.io | ||
[repo-bug-report]: https://github.com/prismicio/prismic-types-internal/issues/new?assignees=&labels=bug&template=bug_report.md&title= | ||
[repo-feature-request]: https://github.com/prismicio/prismic-types-internal/issues/new?assignees=&labels=enhancement&template=feature_request.md&title= | ||
[repo-pull-requests]: https://github.com/prismicio/prismic-types-internal/pulls | ||
[repo-bug-report]: https://github.com/prismicio/@prismicio/types-internal/issues/new?assignees=&labels=bug&template=bug_report.md&title= | ||
[repo-feature-request]: https://github.com/prismicio/@prismicio/types-internal/issues/new?assignees=&labels=enhancement&template=feature_request.md&title= | ||
[repo-pull-requests]: https://github.com/prismicio/@prismicio/types-internal/pulls | ||
<!-- Badges --> | ||
[npm-version-src]: https://img.shields.io/npm/v/prismic-types-internal/latest.svg | ||
[npm-version-href]: https://npmjs.com/package/prismic-types-internal | ||
[npm-downloads-src]: https://img.shields.io/npm/dm/prismic-types-internal.svg | ||
[npm-downloads-href]: https://npmjs.com/package/prismic-types-internal | ||
[npm-version-src]: https://img.shields.io/npm/v/@prismicio/types-internal/latest.svg | ||
[npm-version-href]: https://npmjs.com/package/@prismicio/types-internal | ||
[npm-downloads-src]: https://img.shields.io/npm/dm/@prismicio/types-internal.svg | ||
[npm-downloads-href]: https://npmjs.com/package/@prismicio/types-internal | ||
[github-actions-ci-src]: https://github.com/prismicio/prismic-types-internal/workflows/ci/badge.svg | ||
[github-actions-ci-href]: https://github.com/prismicio/prismic-types-internal/actions?query=workflow%3Aci | ||
[codecov-src]: https://img.shields.io/codecov/c/github/prismicio/prismic-types-internal.svg | ||
[codecov-href]: https://codecov.io/gh/prismicio/prismic-types-internal | ||
[codecov-src]: https://img.shields.io/codecov/c/github/prismicio/@prismicio/types-internal.svg | ||
[codecov-href]: https://codecov.io/gh/prismicio/@prismicio/types-internal | ||
[conventional-commits-src]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg | ||
[conventional-commits-href]: https://conventionalcommits.org | ||
[license-src]: https://img.shields.io/npm/l/prismic-types-internal.svg | ||
[license-href]: https://npmjs.com/package/prismic-types-internal | ||
[license-src]: https://img.shields.io/npm/l/@prismicio/types-internal.svg | ||
[license-href]: https://npmjs.com/package/@prismicio/types-internal |
@@ -1,51 +0,53 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../validators/StringOrNull' | ||
import { Either, right, left } from 'fp-ts/lib/Either' | ||
import { withFallback } from 'io-ts-types/lib/withFallback' | ||
import { Either, left, right } from "fp-ts/lib/Either" | ||
import * as t from "io-ts" | ||
import { withFallback } from "io-ts-types/lib/withFallback" | ||
import { Format } from './Format' | ||
import { DynamicWidget } from './widgets/Widget' | ||
import SharedSlice from './widgets/slices/SharedSlice' | ||
import { DynamicSlice } from './widgets/slices/Slice' | ||
import { DynamicSlices } from './widgets/slices/Slices' | ||
import WidgetTypes from './widgets/WidgetTypes' | ||
import SlicesTypes from './widgets/slices/SlicesTypes' | ||
import { StringOrNull } from "../validators" | ||
import { Format } from "./Format" | ||
import { | ||
DynamicSection, | ||
sectionReader, | ||
Sections, | ||
StaticSection, | ||
} from "./Section" | ||
import type SharedSlice from "./widgets/slices/SharedSlice" | ||
import type { DynamicSlice } from "./widgets/slices/Slice" | ||
import type { DynamicSlices } from "./widgets/slices/Slices" | ||
import SlicesTypes from "./widgets/slices/SlicesTypes" | ||
import type { DynamicWidget } from "./widgets/Widget" | ||
import WidgetTypes from "./widgets/WidgetTypes" | ||
import { StaticSection, DynamicSection, sectionReader, Sections } from './Section' | ||
class CustomTypeSlicesError extends Error { | ||
slices: Array<string> | ||
message: string | ||
slices: Array<string> | ||
override message: string | ||
constructor(slices: Array<string>) { | ||
super() | ||
this.slices = slices | ||
this.message = this._formatError(slices) | ||
} | ||
constructor(slices: Array<string>) { | ||
super() | ||
this.slices = slices | ||
this.message = this._formatError(slices) | ||
} | ||
_formatError(slicesRefs: Array<string>) { | ||
const slicesMsg = slicesRefs.map(ref => `\t - ${ref}`); | ||
return ( | ||
`The following slices doesn't exists in your Prismic repository: | ||
${slicesMsg.join('\n')} | ||
_formatError(slicesRefs: Array<string>) { | ||
const slicesMsg = slicesRefs.map((ref) => `\t - ${ref}`) | ||
return `The following slices doesn't exists in your Prismic repository: | ||
${slicesMsg.join("\n")} | ||
` | ||
) | ||
} | ||
} | ||
} | ||
function customTypeReader<F extends Format>(format: F) { | ||
return t.exact( | ||
t.intersection([ | ||
t.type({ | ||
id: t.string, | ||
label: StringOrNull, | ||
repeatable: withFallback(t.boolean, true), | ||
json: t.record(t.string, sectionReader(format)), | ||
status: withFallback(t.boolean, true) | ||
}), | ||
t.partial({ | ||
hash: t.string | ||
}) | ||
]) | ||
) | ||
return t.exact( | ||
t.intersection([ | ||
t.type({ | ||
id: t.string, | ||
label: StringOrNull, | ||
repeatable: withFallback(t.boolean, true), | ||
json: t.record(t.string, sectionReader(format)), | ||
status: withFallback(t.boolean, true), | ||
}), | ||
t.partial({ | ||
hash: t.string, | ||
}), | ||
]), | ||
) | ||
} | ||
@@ -60,84 +62,139 @@ | ||
function _retrieveSharedSlicesRef(customType: CustomType): Array<string> { | ||
const flattenWidgets: Array<[string, DynamicWidget]> = Object.entries(customType.json) | ||
.reduce((acc: Array<[string, DynamicWidget]>, [, section]: [string, DynamicSection]) => { | ||
const sectionWidgets: Array<[string, DynamicWidget]> = Object.entries(section) | ||
return acc.concat(sectionWidgets); | ||
}, []) | ||
const flattenWidgets: Array<[string, DynamicWidget]> = Object.entries( | ||
customType.json, | ||
).reduce( | ||
( | ||
acc: Array<[string, DynamicWidget]>, | ||
[, section]: [string, DynamicSection], | ||
) => { | ||
const sectionWidgets: Array<[string, DynamicWidget]> = | ||
Object.entries(section) | ||
return acc.concat(sectionWidgets) | ||
}, | ||
[], | ||
) | ||
const slicezones = flattenWidgets.filter(([, widget]: [string, DynamicWidget]) => widget.type === WidgetTypes.Slices) as Array<[string, DynamicSlices]> | ||
const slicezones = flattenWidgets.filter( | ||
([, widget]: [string, DynamicWidget]) => widget.type === WidgetTypes.Slices, | ||
) as Array<[string, DynamicSlices]> | ||
const allSharedRefs = slicezones.reduce((acc: Array<string>, [, slicezone]) => { | ||
const sharedRefs = Object.entries(slicezone.config && slicezone.config.choices ? slicezone.config.choices : {}) | ||
.filter(([, slice]: [string, DynamicSlice]) => slice.type === SlicesTypes.SharedSlice) | ||
.map(([key]) => key) | ||
return acc.concat(sharedRefs); | ||
}, []); | ||
const allSharedRefs = slicezones.reduce( | ||
(acc: Array<string>, [, slicezone]) => { | ||
const sharedRefs = Object.entries( | ||
slicezone.config && slicezone.config.choices | ||
? slicezone.config.choices | ||
: {}, | ||
) | ||
.filter( | ||
([, slice]: [string, DynamicSlice]) => | ||
slice.type === SlicesTypes.SharedSlice, | ||
) | ||
.map(([key]) => key) | ||
return acc.concat(sharedRefs) | ||
}, | ||
[], | ||
) | ||
return allSharedRefs | ||
return allSharedRefs | ||
} | ||
function _mapSharedSlicesRefs<A>(customType: CustomType): (mapFn: (ref: string) => A) => Array<A> { | ||
const refs = _retrieveSharedSlicesRef(customType) | ||
function _mapSharedSlicesRefs<A>( | ||
customType: CustomType, | ||
): (mapFn: (ref: string) => A) => Array<A> { | ||
const refs = _retrieveSharedSlicesRef(customType) | ||
return function(mapFn: (ref: string) => A): Array<A> { | ||
return refs.map(mapFn) | ||
} | ||
return function (mapFn: (ref: string) => A): Array<A> { | ||
return refs.map(mapFn) | ||
} | ||
} | ||
export function toStatic(customType: CustomType, sharedSlices: Map<string, SharedSlice>): StaticCustomType { | ||
const json = Object.entries(customType.json) | ||
.reduce((acc: { [key: string]: StaticSection }, [sectionKey, dynSection]: [string, DynamicSection]) => { | ||
return { ...acc, [sectionKey]: Sections.toStatic(dynSection, sharedSlices) }; | ||
}, {}) | ||
export function toStatic( | ||
customType: CustomType, | ||
sharedSlices: Map<string, SharedSlice>, | ||
): StaticCustomType { | ||
const json = Object.entries(customType.json).reduce( | ||
( | ||
acc: { [key: string]: StaticSection }, | ||
[sectionKey, dynSection]: [string, DynamicSection], | ||
) => { | ||
return { | ||
...acc, | ||
[sectionKey]: Sections.toStatic(dynSection, sharedSlices), | ||
} | ||
}, | ||
{}, | ||
) | ||
return { ...customType, json } as StaticCustomType; | ||
return { ...customType, json } as StaticCustomType | ||
} | ||
export function validateSlices(customType: CustomType, sharedSlices: Map<string, SharedSlice>): Either<CustomTypeSlicesError, CustomType> { | ||
const missingSlices = _mapSharedSlicesRefs<string | undefined>(customType)((ref: string) => { | ||
const slice: SharedSlice | undefined = sharedSlices.get(ref) | ||
const isMissing = !Boolean(slice) | ||
if(isMissing) return ref | ||
}).filter(Boolean) as Array<string> | ||
export function validateSlices( | ||
customType: CustomType, | ||
sharedSlices: Map<string, SharedSlice>, | ||
): Either<CustomTypeSlicesError, CustomType> { | ||
const missingSlices = _mapSharedSlicesRefs<string | undefined>(customType)( | ||
(ref: string) => { | ||
const slice: SharedSlice | undefined = sharedSlices.get(ref) | ||
const isMissing = !slice | ||
if (isMissing) return ref | ||
return | ||
}, | ||
).filter(Boolean) as Array<string> | ||
if(missingSlices.length > 0) return left(new CustomTypeSlicesError(missingSlices)) | ||
else return right(customType) | ||
if (missingSlices.length > 0) | ||
return left(new CustomTypeSlicesError(missingSlices)) | ||
else return right(customType) | ||
} | ||
export function collectWidgets(customType: CustomType, f:((ref: string, widget: DynamicWidget) => DynamicWidget|undefined)): CustomType { | ||
const json = Object.entries(customType.json) | ||
.reduce((acc, [sectionId, section]: [string, DynamicSection]) => { | ||
const updatedSection = Object | ||
.entries(section) | ||
.reduce((acc, [ref, widget]) => { | ||
const updatedWidget = f(ref, widget) | ||
if (!!updatedWidget) { | ||
return {...acc, [ref]: updatedWidget} | ||
} | ||
return acc; | ||
}, {}); | ||
return {...acc, [sectionId]: updatedSection}; | ||
}, {}); | ||
export function collectWidgets( | ||
customType: CustomType, | ||
f: (ref: string, widget: DynamicWidget) => DynamicWidget | undefined, | ||
): CustomType { | ||
const json = Object.entries(customType.json).reduce( | ||
(acc, [sectionId, section]: [string, DynamicSection]) => { | ||
const updatedSection = Object.entries(section).reduce( | ||
(acc, [ref, widget]) => { | ||
const updatedWidget = f(ref, widget) | ||
if (updatedWidget) { | ||
return { ...acc, [ref]: updatedWidget } | ||
} | ||
return acc | ||
}, | ||
{}, | ||
) | ||
return { ...acc, [sectionId]: updatedSection } | ||
}, | ||
{}, | ||
) | ||
return { ...customType, json }; | ||
return { ...customType, json } | ||
} | ||
export function filterMissingSharedSlices(customType: CustomType, sharedSlices: Map<string, SharedSlice>): CustomType { | ||
return collectWidgets(customType, (_widgetId, widget) => { | ||
if (widget.type === WidgetTypes.Slices) { | ||
if(!widget.config || !widget.config.choices) return widget | ||
export function filterMissingSharedSlices( | ||
customType: CustomType, | ||
sharedSlices: Map<string, SharedSlice>, | ||
): CustomType { | ||
return collectWidgets(customType, (_widgetId, widget) => { | ||
if (widget.type === WidgetTypes.Slices) { | ||
if (!widget.config || !widget.config.choices) return widget | ||
const choices = Object.entries(widget.config.choices) | ||
.reduce((acc, [ sliceId, sliceValue ]: [string, DynamicSlice]) => { | ||
if (sliceValue.type === SlicesTypes.SharedSlice && !sharedSlices.get(sliceId)) return acc | ||
return { ...acc, [sliceId]: sliceValue } | ||
}, {}) | ||
const choices = Object.entries(widget.config.choices).reduce( | ||
(acc, [sliceId, sliceValue]: [string, DynamicSlice]) => { | ||
if ( | ||
sliceValue.type === SlicesTypes.SharedSlice && | ||
!sharedSlices.get(sliceId) | ||
) | ||
return acc | ||
return { ...acc, [sliceId]: sliceValue } | ||
}, | ||
{}, | ||
) | ||
const config = { ...widget.config, choices } | ||
const config = { ...widget.config, choices } | ||
return {...widget, config } | ||
} | ||
return { ...widget, config } | ||
} | ||
return widget | ||
}) | ||
} | ||
return widget | ||
}) | ||
} |
export enum Format { | ||
Static = 'static', | ||
Dynamic = 'dynamic' | ||
} | ||
Static = "static", | ||
Dynamic = "dynamic", | ||
} |
@@ -1,4 +0,4 @@ | ||
export { Format } from './Format' | ||
export * as Section from './Section' | ||
export * as Widgets from './widgets' | ||
export * from './CustomType' | ||
export * from "./CustomType" | ||
export { Format } from "./Format" | ||
export * as Section from "./Section" | ||
export * as Widgets from "./widgets" |
@@ -1,9 +0,14 @@ | ||
import * as t from 'io-ts' | ||
import * as t from "io-ts" | ||
import { Format } from './Format' | ||
import { widgetReader, StaticWidget, DynamicWidget, Widgets } from './widgets/Widget' | ||
import SharedSlice from './widgets/slices/SharedSlice' | ||
import { Format } from "./Format" | ||
import type SharedSlice from "./widgets/slices/SharedSlice" | ||
import { | ||
DynamicWidget, | ||
StaticWidget, | ||
widgetReader, | ||
Widgets, | ||
} from "./widgets/Widget" | ||
export function sectionReader<F extends Format>(format: F) { | ||
return t.record(t.string, widgetReader(format)) | ||
return t.record(t.string, widgetReader(format)) | ||
} | ||
@@ -18,9 +23,17 @@ | ||
export const Sections = { | ||
toStatic(dynamic: DynamicSection, sharedSlices: Map<string, SharedSlice>): StaticSection { | ||
const section = Object.entries(dynamic) | ||
.reduce((acc: { [key: string]: StaticWidget }, [widgetKey, widget]: [string, DynamicWidget]) => { | ||
return {...acc, [widgetKey]: Widgets.toStatic(widget, sharedSlices)} | ||
}, {}) | ||
return section as StaticSection | ||
} | ||
} | ||
toStatic( | ||
dynamic: DynamicSection, | ||
sharedSlices: Map<string, SharedSlice>, | ||
): StaticSection { | ||
const section = Object.entries(dynamic).reduce( | ||
( | ||
acc: { [key: string]: StaticWidget }, | ||
[widgetKey, widget]: [string, DynamicWidget], | ||
) => { | ||
return { ...acc, [widgetKey]: Widgets.toStatic(widget, sharedSlices) } | ||
}, | ||
{}, | ||
) | ||
return section as StaticSection | ||
}, | ||
} |
@@ -1,12 +0,13 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../validators/StringOrNull' | ||
import WidgetTypes from './WidgetTypes' | ||
import NestableWidget from './nestable/NestableWidget' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../validators" | ||
import NestableWidget from "./nestable/NestableWidget" | ||
import WidgetTypes from "./WidgetTypes" | ||
const GroupConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
repeat: t.boolean, | ||
fields: t.record(t.string, NestableWidget) | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
repeat: t.boolean, | ||
fields: t.record(t.string, NestableWidget), | ||
}), | ||
) | ||
@@ -16,13 +17,13 @@ type GroupConfig = t.TypeOf<typeof GroupConfig> | ||
const Group = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Group) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
icon: t.string, | ||
description: t.string, | ||
config: GroupConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Group), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
icon: t.string, | ||
description: t.string, | ||
config: GroupConfig, | ||
}), | ||
]), | ||
) | ||
@@ -29,0 +30,0 @@ type Group = t.TypeOf<typeof Group> |
@@ -1,7 +0,7 @@ | ||
export * as Nestable from './nestable' | ||
export * as Shared from './shared' | ||
export * as Slices from './slices' | ||
export * as Widget from './Widget' | ||
export { default as Group } from './Group' | ||
export { default as UID } from './UID' | ||
export { default as WidgetTypes } from './WidgetTypes' | ||
export { default as Group } from "./Group" | ||
export * as Nestable from "./nestable" | ||
export * as Shared from "./shared" | ||
export * as Slices from "./slices" | ||
export { default as UID } from "./UID" | ||
export * as Widget from "./Widget" | ||
export { default as WidgetTypes } from "./WidgetTypes" |
@@ -1,12 +0,13 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const BooleanConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
default_value: t.boolean, | ||
placeholder_true: t.string, | ||
placeholder_false: t.string | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
default_value: t.boolean, | ||
placeholder_true: t.string, | ||
placeholder_false: t.string, | ||
}), | ||
) | ||
@@ -17,10 +18,10 @@ | ||
const BooleanField = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.BooleanField) | ||
}), | ||
t.partial({ | ||
config: BooleanConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.BooleanField), | ||
}), | ||
t.partial({ | ||
config: BooleanConfig, | ||
}), | ||
]), | ||
) | ||
@@ -30,3 +31,2 @@ | ||
export default BooleanField | ||
export default BooleanField |
@@ -1,10 +0,11 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const ColorConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
}), | ||
) | ||
@@ -14,11 +15,11 @@ type ColorConfig = t.TypeOf<typeof ColorConfig> | ||
const Color = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Color) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: ColorConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Color), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: ColorConfig, | ||
}), | ||
]), | ||
) | ||
@@ -25,0 +26,0 @@ type Color = t.TypeOf<typeof Color> |
@@ -1,11 +0,12 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const DateConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
default: t.string | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
default: t.string, | ||
}), | ||
) | ||
@@ -15,14 +16,14 @@ type DateConfig = t.TypeOf<typeof DateConfig> | ||
const Date = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Date) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: DateConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Date), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: DateConfig, | ||
}), | ||
]), | ||
) | ||
type Date = t.TypeOf<typeof Date> | ||
export default Date | ||
export default Date |
@@ -1,11 +0,12 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const EmbedConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
useAsTitle: t.boolean | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
useAsTitle: t.boolean, | ||
}), | ||
) | ||
@@ -15,14 +16,14 @@ type EmbedConfig = t.TypeOf<typeof EmbedConfig> | ||
const Embed = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Embed) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: EmbedConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Embed), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: EmbedConfig, | ||
}), | ||
]), | ||
) | ||
type Embed = t.TypeOf<typeof Embed> | ||
export default Embed | ||
export default Embed |
@@ -1,9 +0,10 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const GeoPointConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
}), | ||
) | ||
@@ -13,14 +14,14 @@ type GeoPointConfig = t.TypeOf<typeof GeoPointConfig> | ||
const GeoPoint = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.GeoPoint) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: GeoPointConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.GeoPoint), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: GeoPointConfig, | ||
}), | ||
]), | ||
) | ||
type GeoPoint = t.TypeOf<typeof GeoPoint> | ||
export default GeoPoint | ||
export default GeoPoint |
@@ -1,13 +0,14 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import ImageConstraint from '../shared/ImageConstraint' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import ImageConstraint from "../shared/ImageConstraint" | ||
import WidgetTypes from "../WidgetTypes" | ||
const Thumbnail = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
name: t.string | ||
}), | ||
ImageConstraint | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
name: t.string, | ||
}), | ||
ImageConstraint, | ||
]), | ||
) | ||
@@ -17,22 +18,21 @@ type Thumbnail = t.TypeOf<typeof Thumbnail> | ||
const ImageConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
constraint: ImageConstraint, | ||
thumbnails: t.array(Thumbnail) | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
constraint: ImageConstraint, | ||
thumbnails: t.array(Thumbnail), | ||
}), | ||
) | ||
type ImageConfig = t.TypeOf<typeof ImageConfig> | ||
const Image = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Image) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: ImageConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Image), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: ImageConfig, | ||
}), | ||
]), | ||
) | ||
@@ -39,0 +39,0 @@ type Image = t.TypeOf<typeof Image> |
@@ -1,15 +0,15 @@ | ||
export { default as BooleanField } from './BooleanField' | ||
export { default as Color } from './Color' | ||
export { default as Date } from './Date' | ||
export { default as GeoPoint } from './GeoPoint' | ||
export { default as Image } from './Image' | ||
export { default as IntegrationField } from './IntegrationField' | ||
export { default as Link } from './Link' | ||
export { default as NestableWidget } from './NestableWidget' | ||
export { default as Number } from './Number' | ||
export { default as Range } from './Range' | ||
export { default as RichText } from './RichText' | ||
export { default as Select } from './Select' | ||
export { default as Separator } from './Separator' | ||
export { default as Text } from './Text' | ||
export { default as Timestamp } from './Timestamp' | ||
export { default as BooleanField } from "./BooleanField" | ||
export { default as Color } from "./Color" | ||
export { default as Date } from "./Date" | ||
export { default as GeoPoint } from "./GeoPoint" | ||
export { default as Image } from "./Image" | ||
export { default as IntegrationField } from "./IntegrationField" | ||
export { default as Link } from "./Link" | ||
export { default as NestableWidget } from "./NestableWidget" | ||
export { default as Number } from "./Number" | ||
export { default as Range } from "./Range" | ||
export { default as RichText } from "./RichText" | ||
export { default as Select } from "./Select" | ||
export { default as Separator } from "./Separator" | ||
export { default as Text } from "./Text" | ||
export { default as Timestamp } from "./Timestamp" |
@@ -1,11 +0,12 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const IntegrationFieldConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
catalog: t.string | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
catalog: t.string, | ||
}), | ||
) | ||
@@ -15,11 +16,11 @@ type IntegrationFieldConfig = t.TypeOf<typeof IntegrationFieldConfig> | ||
const IntegrationField = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.IntegrationField) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: IntegrationFieldConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.IntegrationField), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: IntegrationFieldConfig, | ||
}), | ||
]), | ||
) | ||
@@ -26,0 +27,0 @@ type IntegrationField = t.TypeOf<typeof IntegrationField> |
@@ -1,69 +0,81 @@ | ||
import * as t from 'io-ts' | ||
import { withFallback } from 'io-ts-types/lib/withFallback' | ||
import { either } from 'fp-ts/lib/Either' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import { either } from "fp-ts/lib/Either" | ||
import * as t from "io-ts" | ||
import { withFallback } from "io-ts-types/lib/withFallback" | ||
const arrayString = (entries: string | string[] | { | ||
[x: string]: { | ||
name: string; | ||
}[]; | ||
} | null) => { | ||
if(entries instanceof Array) { | ||
const isValidEntries = entries.reduce((acc, l) => acc && typeof l === 'string', true) | ||
if(isValidEntries) return t.success(entries) | ||
} | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const arrayString = ( | ||
entries: | ||
| string | ||
| string[] | ||
| { | ||
[x: string]: { | ||
name: string | ||
}[] | ||
} | ||
| undefined, | ||
) => { | ||
if (entries instanceof Array) { | ||
const isValidEntries = entries.reduce( | ||
(acc, l) => acc && typeof l === "string", | ||
true, | ||
) | ||
if (isValidEntries) return t.success(entries) | ||
} | ||
return | ||
} | ||
const plainString = (entries: string | string[] | { | ||
[x: string]: { | ||
name: string; | ||
}[]; | ||
} | null) => { | ||
if(typeof entries === 'string') { | ||
return t.success([entries]) | ||
} | ||
const plainString = ( | ||
entries: | ||
| string | ||
| string[] | ||
| { | ||
[x: string]: { | ||
name: string | ||
}[] | ||
} | ||
| undefined, | ||
) => { | ||
if (typeof entries === "string") { | ||
return t.success([entries]) | ||
} | ||
return | ||
} | ||
const MasksArrayString = new t.Type<Array<string>, object, unknown>( | ||
'MasksArrayString', | ||
(u: unknown): u is any => { | ||
return u instanceof Array | ||
}, | ||
(u: unknown, context: t.Context) => { | ||
return either.chain( | ||
t.union([ | ||
t.array(t.string), | ||
t.string, | ||
]).validate(u, context), (masks) => { | ||
return ( | ||
arrayString(masks) || | ||
plainString(masks) || | ||
t.failure(u, context) | ||
) | ||
} | ||
) | ||
}, | ||
res => res | ||
"MasksArrayString", | ||
(u: unknown): u is Array<string> => { | ||
return u instanceof Array | ||
}, | ||
(u: unknown, context: t.Context) => { | ||
return either.chain( | ||
t.union([t.array(t.string), t.string]).validate(u, context), | ||
(masks) => { | ||
return arrayString(masks) || plainString(masks) || t.failure(u, context) | ||
}, | ||
) | ||
}, | ||
(res) => res, | ||
) | ||
const LinkConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
useAsTitle: t.boolean, | ||
placeholder: t.string, | ||
select: withFallback( | ||
t.union([ | ||
t.literal('media'), | ||
t.literal('document'), | ||
t.literal('web'), | ||
t.null | ||
]), | ||
null | ||
), | ||
customtypes: t.array(t.string), // `customtypes` and `masks` are alternatives | ||
masks: MasksArrayString, | ||
tags: MasksArrayString, | ||
allowTargetBlank: t.boolean | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
useAsTitle: t.boolean, | ||
placeholder: t.string, | ||
select: withFallback( | ||
t.union([ | ||
t.literal("media"), | ||
t.literal("document"), | ||
t.literal("web"), | ||
t.null, | ||
]), | ||
null, | ||
), | ||
customtypes: t.array(t.string), // `customtypes` and `masks` are alternatives | ||
masks: MasksArrayString, | ||
tags: MasksArrayString, | ||
allowTargetBlank: t.boolean, | ||
}), | ||
) | ||
@@ -73,11 +85,11 @@ type LinkConfig = t.TypeOf<typeof LinkConfig> | ||
const Link = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Link) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: LinkConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Link), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: LinkConfig, | ||
}), | ||
]), | ||
) | ||
@@ -84,0 +96,0 @@ type Link = t.TypeOf<typeof Link> |
@@ -1,35 +0,35 @@ | ||
import * as t from 'io-ts' | ||
import * as t from "io-ts" | ||
import Color from './Color' | ||
import BooleanField from './BooleanField' | ||
import Date from './Date' | ||
import Embed from './Embed' | ||
import GeoPoint from './GeoPoint' | ||
import Number from './Number' | ||
import Range from './Range' | ||
import RichText from './RichText' | ||
import Select from './Select' | ||
import Separator from './Separator' | ||
import Text from './Text' | ||
import Timestamp from './Timestamp' | ||
import Link from './Link' | ||
import Image from './Image' | ||
import IntegrationField from './IntegrationField' | ||
import BooleanField from "./BooleanField" | ||
import Color from "./Color" | ||
import Date from "./Date" | ||
import Embed from "./Embed" | ||
import GeoPoint from "./GeoPoint" | ||
import Image from "./Image" | ||
import IntegrationField from "./IntegrationField" | ||
import Link from "./Link" | ||
import Number from "./Number" | ||
import Range from "./Range" | ||
import RichText from "./RichText" | ||
import Select from "./Select" | ||
import Separator from "./Separator" | ||
import Text from "./Text" | ||
import Timestamp from "./Timestamp" | ||
const NestableWidget = t.union([ | ||
Color, | ||
BooleanField, | ||
Embed, | ||
GeoPoint, | ||
Date, | ||
Number, | ||
Range, | ||
RichText, | ||
Select, | ||
Separator, | ||
Text, | ||
Timestamp, | ||
Link, | ||
Image, | ||
IntegrationField | ||
Color, | ||
BooleanField, | ||
Embed, | ||
GeoPoint, | ||
Date, | ||
Number, | ||
Range, | ||
RichText, | ||
Select, | ||
Separator, | ||
Text, | ||
Timestamp, | ||
Link, | ||
Image, | ||
IntegrationField, | ||
]) | ||
@@ -39,2 +39,2 @@ | ||
export default NestableWidget | ||
export default NestableWidget |
@@ -1,14 +0,15 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import { NumberFromString } from 'io-ts-types/lib/NumberFromString' | ||
import * as t from "io-ts" | ||
import { NumberFromString } from "io-ts-types/lib/NumberFromString" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const NumberConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
min: t.union([t.number, NumberFromString]), | ||
max: t.union([t.number, NumberFromString]), | ||
step: t.union([t.number, NumberFromString]) | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
min: t.union([t.number, NumberFromString]), | ||
max: t.union([t.number, NumberFromString]), | ||
step: t.union([t.number, NumberFromString]), | ||
}), | ||
) | ||
@@ -18,14 +19,14 @@ type NumberConfig = t.TypeOf<typeof NumberConfig> | ||
const Number = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Number) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: NumberConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Number), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: NumberConfig, | ||
}), | ||
]), | ||
) | ||
type Number = t.TypeOf<typeof Number> | ||
export default Number | ||
export default Number |
@@ -1,14 +0,15 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import { NumberFromString } from 'io-ts-types/lib/NumberFromString' | ||
import * as t from "io-ts" | ||
import { NumberFromString } from "io-ts-types/lib/NumberFromString" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const RangeConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
min: t.union([t.number, NumberFromString]), | ||
max: t.union([t.number, NumberFromString]), | ||
step: t.union([t.number, NumberFromString]), | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
min: t.union([t.number, NumberFromString]), | ||
max: t.union([t.number, NumberFromString]), | ||
step: t.union([t.number, NumberFromString]), | ||
}), | ||
) | ||
@@ -18,14 +19,14 @@ type RangeConfig = t.TypeOf<typeof RangeConfig> | ||
const Range = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Range) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: RangeConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Range), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: RangeConfig, | ||
}), | ||
]), | ||
) | ||
type Range = t.TypeOf<typeof Range> | ||
export default Range | ||
export default Range |
@@ -1,144 +0,174 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import { either } from 'fp-ts/lib/Either' | ||
import WidgetTypes from '../WidgetTypes' | ||
import ImageConstraint from '../shared/ImageConstraint' | ||
import { either } from "fp-ts/lib/Either" | ||
import * as t from "io-ts" | ||
const DEFAULT_OPTION = 'paragraph' | ||
import { StringOrNull } from "../../../validators" | ||
import ImageConstraint from "../shared/ImageConstraint" | ||
import WidgetTypes from "../WidgetTypes" | ||
const DEFAULT_OPTION = "paragraph" | ||
const options = [ | ||
'heading1', | ||
'heading2', | ||
'heading3', | ||
'heading4', | ||
'heading5', | ||
'heading6', | ||
'paragraph', | ||
'strong', | ||
'em', | ||
'preformatted', | ||
'hyperlink', | ||
'image', | ||
'embed', | ||
'list-item', | ||
'o-list-item', | ||
'rtl' | ||
]; | ||
"heading1", | ||
"heading2", | ||
"heading3", | ||
"heading4", | ||
"heading5", | ||
"heading6", | ||
"paragraph", | ||
"strong", | ||
"em", | ||
"preformatted", | ||
"hyperlink", | ||
"image", | ||
"embed", | ||
"list-item", | ||
"o-list-item", | ||
"rtl", | ||
] | ||
const RichTextOptions = new t.Type<string, string, unknown>( | ||
'RichTextOptions', | ||
(u: unknown): u is string => typeof u === 'string', | ||
(u: unknown, context: t.Context) => { | ||
return either.chain( | ||
t.union([ | ||
t.string, | ||
t.null | ||
]).validate(u as unknown, context), (s: string | null) => { | ||
if(!s) return t.success(DEFAULT_OPTION) | ||
const entries = s.split(',').map((e: string) => e.trim()) | ||
const filtered = entries.filter(entry => options.includes(entry)) | ||
if(!filtered.length) return t.success(DEFAULT_OPTION) | ||
return t.success(filtered.join(',')) | ||
} | ||
); | ||
}, | ||
a => a | ||
"RichTextOptions", | ||
(u: unknown): u is string => typeof u === "string", | ||
(u: unknown, context: t.Context) => { | ||
return either.chain( | ||
t.union([t.string, t.null]).validate(u, context), | ||
(s: string | null) => { | ||
if (!s) return t.success(DEFAULT_OPTION) | ||
const entries = s.split(",").map((e: string) => e.trim()) | ||
const filtered = entries.filter((entry) => options.includes(entry)) | ||
if (!filtered.length) return t.success(DEFAULT_OPTION) | ||
return t.success(filtered.join(",")) | ||
}, | ||
) | ||
}, | ||
(a) => a, | ||
) | ||
const NoLabels = (labels: string | string[] | { | ||
[x: string]: { | ||
name: string; | ||
}[]; | ||
} | null) => { | ||
if(!labels) return t.success([]) | ||
const NoLabels = ( | ||
labels: | ||
| string | ||
| string[] | ||
| { | ||
[x: string]: { | ||
name: string | ||
}[] | ||
} | ||
| null, | ||
) => { | ||
if (!labels) return t.success([]) | ||
return | ||
} | ||
const LabelsAsObject = (labels: string | string[] | { | ||
[x: string]: { | ||
name: string; | ||
}[]; | ||
} | null) => { | ||
if(labels instanceof Object) { | ||
const labelsObj = labels as { [x: string]: { name: string }[] } | ||
// empty labels | ||
if(!Object.entries(labelsObj).length) return t.success([]) | ||
// weird case labels with empty key as parent | ||
if(labelsObj['']) { | ||
return t.success(labelsObj[''].map(l => l.name)) | ||
} | ||
const LabelsAsObject = ( | ||
labels: | ||
| string | ||
| string[] | ||
| { | ||
[x: string]: { | ||
name: string | ||
}[] | ||
} | ||
| null, | ||
) => { | ||
if (labels instanceof Object) { | ||
const labelsObj = labels as { [x: string]: { name: string }[] } | ||
const convertedObjectToArray = Object.entries(labelsObj) | ||
.reduce<ReadonlyArray<string>>((acc, [, labelsEntries]) => { | ||
return acc.concat(labelsEntries.map(l => l.name)) | ||
}, []) | ||
.filter(Boolean) | ||
// empty labels | ||
if (!Object.entries(labelsObj).length) return t.success([]) | ||
return t.success(convertedObjectToArray) | ||
} | ||
// weird case labels with empty key as parent | ||
if (labelsObj[""]) { | ||
return t.success(labelsObj[""].map((l) => l.name)) | ||
} | ||
const convertedObjectToArray = Object.entries(labelsObj) | ||
.reduce<ReadonlyArray<string>>((acc, [, labelsEntries]) => { | ||
return acc.concat(labelsEntries.map((l) => l.name)) | ||
}, []) | ||
.filter(Boolean) | ||
return t.success(convertedObjectToArray) | ||
} | ||
return | ||
} | ||
const LabelsAsArray = (labels: string | string[] | { | ||
[x: string]: { | ||
name: string; | ||
}[]; | ||
} | null) => { | ||
if(labels instanceof Array) { | ||
const isValidLabels = labels.reduce((acc, l) => acc && typeof l === 'string', true) | ||
if(isValidLabels) return t.success(labels) | ||
} | ||
const LabelsAsArray = ( | ||
labels: | ||
| string | ||
| string[] | ||
| { | ||
[x: string]: { | ||
name: string | ||
}[] | ||
} | ||
| null, | ||
) => { | ||
if (labels instanceof Array) { | ||
const isValidLabels = labels.reduce( | ||
(acc, l) => acc && typeof l === "string", | ||
true, | ||
) | ||
if (isValidLabels) return t.success(labels) | ||
} | ||
return | ||
} | ||
const LabelsAsString = (labels: string | string[] | { | ||
[x: string]: { | ||
name: string; | ||
}[]; | ||
} | null) => { | ||
if(typeof labels === 'string') { | ||
return t.success([labels]) | ||
} | ||
const LabelsAsString = ( | ||
labels: | ||
| string | ||
| string[] | ||
| { | ||
[x: string]: { | ||
name: string | ||
}[] | ||
} | ||
| null, | ||
) => { | ||
if (typeof labels === "string") { | ||
return t.success([labels]) | ||
} | ||
return | ||
} | ||
const RichTextLabels = new t.Type<Array<string>, object, unknown>( | ||
'RichTextLabels', | ||
(u: unknown): u is any => { | ||
return u instanceof Array | ||
}, | ||
(u: unknown, context: t.Context) => { | ||
const legacyValidator = t.record(t.string, t.array(t.record(t.literal("name"), t.string))) | ||
const validator = t.array(t.string) | ||
"RichTextLabels", | ||
(u: unknown): u is Array<string> => { | ||
return u instanceof Array | ||
}, | ||
(u: unknown, context: t.Context) => { | ||
const legacyValidator = t.record( | ||
t.string, | ||
t.array(t.record(t.literal("name"), t.string)), | ||
) | ||
const validator = t.array(t.string) | ||
return either.chain( | ||
t.union([ | ||
legacyValidator, | ||
validator, | ||
t.string, | ||
t.null, | ||
]).validate(u, context), (labels) => { | ||
return ( | ||
NoLabels(labels) || | ||
LabelsAsArray(labels) || | ||
LabelsAsObject(labels) || | ||
LabelsAsString(labels) || | ||
t.failure(u, context) | ||
) | ||
} | ||
) | ||
}, | ||
res => res | ||
return either.chain( | ||
t | ||
.union([legacyValidator, validator, t.string, t.null]) | ||
.validate(u, context), | ||
(labels) => { | ||
return ( | ||
NoLabels(labels) || | ||
LabelsAsArray(labels) || | ||
LabelsAsObject(labels) || | ||
LabelsAsString(labels) || | ||
t.failure(u, context) | ||
) | ||
}, | ||
) | ||
}, | ||
(res) => res, | ||
) | ||
const RichTextConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
useAsTitle: t.boolean, | ||
single: RichTextOptions, | ||
multi: RichTextOptions, | ||
imageConstraint: ImageConstraint, | ||
labels: RichTextLabels, | ||
allowTargetBlank: t.boolean | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
useAsTitle: t.boolean, | ||
single: RichTextOptions, | ||
multi: RichTextOptions, | ||
imageConstraint: ImageConstraint, | ||
labels: RichTextLabels, | ||
allowTargetBlank: t.boolean, | ||
}), | ||
) | ||
@@ -148,11 +178,11 @@ type RichTextConfig = t.TypeOf<typeof RichTextConfig> | ||
const RichText = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.RichText) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: RichTextConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.RichText), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: RichTextConfig, | ||
}), | ||
]), | ||
) | ||
@@ -159,0 +189,0 @@ type RichText = t.TypeOf<typeof RichText> |
@@ -1,15 +0,17 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import { StringFromBoolean } from '../../../validators/StringFromBoolean' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringFromNumber } from '../../../validators/StringFromNumber' | ||
import { | ||
StringFromBoolean, | ||
StringFromNumber, | ||
StringOrNull, | ||
} from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const SelectConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
default_value: t.string, | ||
options: t.array(t.union([t.string, StringFromNumber, StringFromBoolean])) | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
default_value: t.string, | ||
options: t.array(t.union([t.string, StringFromNumber, StringFromBoolean])), | ||
}), | ||
) | ||
@@ -19,11 +21,11 @@ type SelectConfig = t.TypeOf<typeof SelectConfig> | ||
const Select = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Select) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: SelectConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Select), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: SelectConfig, | ||
}), | ||
]), | ||
) | ||
@@ -33,2 +35,1 @@ type Select = t.TypeOf<typeof Select> | ||
export default Select | ||
@@ -1,9 +0,10 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const SeparatorConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
}), | ||
) | ||
@@ -13,10 +14,10 @@ type SeparatorConfig = t.TypeOf<typeof SeparatorConfig> | ||
const Separator = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Separator) | ||
}), | ||
t.partial({ | ||
config: SeparatorConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Separator), | ||
}), | ||
t.partial({ | ||
config: SeparatorConfig, | ||
}), | ||
]), | ||
) | ||
@@ -23,0 +24,0 @@ type Separator = t.TypeOf<typeof Separator> |
@@ -1,11 +0,12 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const TextConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
useAsTitle: t.boolean, | ||
placeholder: t.string | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
useAsTitle: t.boolean, | ||
placeholder: t.string, | ||
}), | ||
) | ||
@@ -15,11 +16,11 @@ type TextConfig = t.TypeOf<typeof TextConfig> | ||
const Text = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Text) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: TextConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Text), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: TextConfig, | ||
}), | ||
]), | ||
) | ||
@@ -26,0 +27,0 @@ type Text = t.TypeOf<typeof Text> |
@@ -1,11 +0,12 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import WidgetTypes from "../WidgetTypes" | ||
const TimestampConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
default: t.string | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
placeholder: t.string, | ||
default: t.string, | ||
}), | ||
) | ||
@@ -15,14 +16,14 @@ type TimestampConfig = t.TypeOf<typeof TimestampConfig> | ||
const Timestamp = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Timestamp) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: TimestampConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.Timestamp), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: TimestampConfig, | ||
}), | ||
]), | ||
) | ||
type Timestamp = t.TypeOf<typeof Timestamp> | ||
export default Timestamp | ||
export default Timestamp |
@@ -1,35 +0,37 @@ | ||
import * as t from 'io-ts' | ||
import { either } from 'fp-ts/lib/Either' | ||
import { IntFromString } from 'io-ts-types/lib/IntFromString' | ||
import { either } from "fp-ts/lib/Either" | ||
import * as t from "io-ts" | ||
import { IntFromString } from "io-ts-types/lib/IntFromString" | ||
import { IntFromNumber } from '../../../validators/IntFromNumber' | ||
import { IntFromPixels } from '../../../validators/IntFromPixels' | ||
import { IntFromNumber, IntFromPixels } from "../../../validators" | ||
const SideConstraint = new t.Type<number | null, any, unknown>( | ||
'SideConstraints', | ||
(u: unknown): u is any => { | ||
return !u || typeof u === 'number' | ||
}, | ||
(u: unknown, context: t.Context) => { | ||
return either.chain( | ||
t.union([ | ||
t.literal('auto'), | ||
t.literal(''), | ||
t.Int, | ||
IntFromString, | ||
IntFromNumber, | ||
IntFromPixels, | ||
t.null | ||
]).validate(u, context), (constraint) => { | ||
if(constraint === 'auto' || constraint === '') return t.success(null) | ||
return t.success(constraint) | ||
} | ||
) | ||
}, | ||
res => res | ||
const SideConstraint = new t.Type<number | null, unknown, unknown>( | ||
"SideConstraints", | ||
(u: unknown): u is number | null => { | ||
return !u || typeof u === "number" | ||
}, | ||
(u: unknown, context: t.Context) => { | ||
return either.chain( | ||
t | ||
.union([ | ||
t.literal("auto"), | ||
t.literal(""), | ||
t.Int, | ||
IntFromString, | ||
IntFromNumber, | ||
IntFromPixels, | ||
t.null, | ||
]) | ||
.validate(u, context), | ||
(constraint) => { | ||
if (constraint === "auto" || constraint === "") return t.success(null) | ||
return t.success(constraint) | ||
}, | ||
) | ||
}, | ||
(res) => res, | ||
) | ||
const ImageConstraint = t.partial({ | ||
width: SideConstraint, | ||
height: SideConstraint | ||
width: SideConstraint, | ||
height: SideConstraint, | ||
}) | ||
@@ -36,0 +38,0 @@ |
@@ -1,1 +0,1 @@ | ||
export { default as ImageConstraint } from './ImageConstraint' | ||
export { default as ImageConstraint } from "./ImageConstraint" |
@@ -1,11 +0,11 @@ | ||
import * as t from 'io-ts' | ||
import * as t from "io-ts" | ||
import SlicesTypes from './SlicesTypes' | ||
import { StringOrNull } from "../../../validators" | ||
import NestableWidget from "../nestable/NestableWidget" | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import SlicesTypes from "./SlicesTypes" | ||
const CompositeSliceConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
}), | ||
) | ||
@@ -15,19 +15,19 @@ type CompositeSliceConfig = t.TypeOf<typeof CompositeSliceConfig> | ||
const CompositeSlice = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(SlicesTypes.Slice) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
description: t.string, | ||
icon: t.string, | ||
display: t.string, | ||
'non-repeat': t.record(t.string, NestableWidget), | ||
repeat: t.record(t.string, NestableWidget), | ||
config: CompositeSliceConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(SlicesTypes.Slice), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
description: t.string, | ||
icon: t.string, | ||
display: t.string, | ||
"non-repeat": t.record(t.string, NestableWidget), | ||
repeat: t.record(t.string, NestableWidget), | ||
config: CompositeSliceConfig, | ||
}), | ||
]), | ||
) | ||
type CompositeSlice = t.TypeOf<typeof CompositeSlice> | ||
export default CompositeSlice | ||
export default CompositeSlice |
@@ -1,7 +0,7 @@ | ||
export { default as CompositeSlice } from './CompositeSlice' | ||
export { default as LegacySlice } from './LegacySlice' | ||
export { default as SharedSlice } from './SharedSlice' | ||
export { default as SharedSliceRef } from './SharedSliceRef' | ||
export { default as SlicesTypes } from './SlicesTypes' | ||
export * as Slice from './Slice' | ||
export * as SliceZone from './Slices' | ||
export { default as CompositeSlice } from "./CompositeSlice" | ||
export { default as LegacySlice } from "./LegacySlice" | ||
export { default as SharedSlice } from "./SharedSlice" | ||
export { default as SharedSliceRef } from "./SharedSliceRef" | ||
export * as Slice from "./Slice" | ||
export * as SliceZone from "./Slices" | ||
export { default as SlicesTypes } from "./SlicesTypes" |
@@ -1,15 +0,11 @@ | ||
import * as t from 'io-ts' | ||
import * as t from "io-ts" | ||
import UID from '../UID' | ||
import NestableWidget from '../nestable/NestableWidget' | ||
import Group from '../Group' | ||
import Group from "../Group" | ||
import NestableWidget from "../nestable/NestableWidget" | ||
import UID from "../UID" | ||
const LegacySlice = t.union([ | ||
UID, | ||
NestableWidget, | ||
Group | ||
]) | ||
const LegacySlice = t.union([UID, NestableWidget, Group]) | ||
type LegacySlice = t.TypeOf<typeof LegacySlice> | ||
export default LegacySlice | ||
export default LegacySlice |
@@ -1,24 +0,26 @@ | ||
import * as t from 'io-ts' | ||
import { withFallback } from 'io-ts-types/lib/withFallback' | ||
import NestableWidget from '../nestable/NestableWidget' | ||
import SlicesTypes from './SlicesTypes' | ||
import * as t from "io-ts" | ||
import { withFallback } from "io-ts-types/lib/withFallback" | ||
const IMAGE_PLACEHOLDER_URL = 'https://images.prismic.io/slice-machine/621a5ec4-0387-4bc5-9860-2dd46cbc07cd_default_ss.png?auto=compress,format' | ||
import NestableWidget from "../nestable/NestableWidget" | ||
import SlicesTypes from "./SlicesTypes" | ||
const IMAGE_PLACEHOLDER_URL = | ||
"https://images.prismic.io/slice-machine/621a5ec4-0387-4bc5-9860-2dd46cbc07cd_default_ss.png?auto=compress,format" | ||
const Variation = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
id: t.string, | ||
name: t.string, | ||
description: t.string, | ||
imageUrl: withFallback(t.string, IMAGE_PLACEHOLDER_URL), | ||
docURL: t.string, | ||
version: t.string | ||
}), | ||
t.partial({ | ||
display: t.string, | ||
primary: t.record(t.string, NestableWidget), | ||
items: t.record(t.string, NestableWidget) | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
id: t.string, | ||
name: t.string, | ||
description: t.string, | ||
imageUrl: withFallback(t.string, IMAGE_PLACEHOLDER_URL), | ||
docURL: t.string, | ||
version: t.string, | ||
}), | ||
t.partial({ | ||
display: t.string, | ||
primary: t.record(t.string, NestableWidget), | ||
items: t.record(t.string, NestableWidget), | ||
}), | ||
]), | ||
) | ||
@@ -29,13 +31,13 @@ | ||
const SharedSlice = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
id: t.string, | ||
type: t.literal(SlicesTypes.SharedSlice), | ||
name: t.string, | ||
variations: t.array(Variation) | ||
}), | ||
t.partial({ | ||
description: t.string | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
id: t.string, | ||
type: t.literal(SlicesTypes.SharedSlice), | ||
name: t.string, | ||
variations: t.array(Variation), | ||
}), | ||
t.partial({ | ||
description: t.string, | ||
}), | ||
]), | ||
) | ||
@@ -42,0 +44,0 @@ |
@@ -1,12 +0,12 @@ | ||
import * as t from 'io-ts' | ||
import * as t from "io-ts" | ||
import SlicesTypes from './SlicesTypes' | ||
import SlicesTypes from "./SlicesTypes" | ||
const SharedSliceRef = t.exact( | ||
t.type({ | ||
type: t.literal(SlicesTypes.SharedSlice) | ||
}) | ||
t.type({ | ||
type: t.literal(SlicesTypes.SharedSlice), | ||
}), | ||
) | ||
type SharedSliceRef = t.TypeOf<typeof SharedSliceRef> | ||
export default SharedSliceRef | ||
export default SharedSliceRef |
@@ -1,7 +0,7 @@ | ||
import SharedSlice from "./SharedSlice"; | ||
import CompositeSlice from "./CompositeSlice"; | ||
import LegacySlice from "./LegacySlice"; | ||
import SharedSliceRef from "./SharedSliceRef"; | ||
import type CompositeSlice from "./CompositeSlice" | ||
import type LegacySlice from "./LegacySlice" | ||
import type SharedSlice from "./SharedSlice" | ||
import type SharedSliceRef from "./SharedSliceRef" | ||
export type DynamicSlice = CompositeSlice | LegacySlice | SharedSliceRef | ||
export type StaticSlice = CompositeSlice | LegacySlice | SharedSlice |
@@ -1,28 +0,29 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../../validators/StringOrNull' | ||
import WidgetTypes from '../WidgetTypes' | ||
import { Format } from '../../Format' | ||
import LegacySlice from './LegacySlice' | ||
import CompositeSlice from './CompositeSlice' | ||
import SharedSliceRef from './SharedSliceRef' | ||
import SharedSlice from './SharedSlice' | ||
import SlicesTypes from './SlicesTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../../validators" | ||
import { Format } from "../../Format" | ||
import WidgetTypes from "../WidgetTypes" | ||
import CompositeSlice from "./CompositeSlice" | ||
import LegacySlice from "./LegacySlice" | ||
import SharedSlice from "./SharedSlice" | ||
import SharedSliceRef from "./SharedSliceRef" | ||
import SlicesTypes from "./SlicesTypes" | ||
const SlicesLabels = t.union([ | ||
t.record( | ||
t.string, | ||
t.array( | ||
t.exact( | ||
t.intersection([ | ||
t.type({ | ||
name: t.string | ||
}), | ||
t.partial({ | ||
display: t.string | ||
}) | ||
]) | ||
) | ||
) | ||
), | ||
t.null | ||
t.record( | ||
t.string, | ||
t.array( | ||
t.exact( | ||
t.intersection([ | ||
t.type({ | ||
name: t.string, | ||
}), | ||
t.partial({ | ||
display: t.string, | ||
}), | ||
]), | ||
), | ||
), | ||
), | ||
t.null, | ||
]) | ||
@@ -32,19 +33,27 @@ type SlicesLabels = t.TypeOf<typeof SlicesLabels> | ||
export function slicesConfigReader<F extends Format>(format: F) { | ||
return t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
labels: SlicesLabels, | ||
choices: t.record(t.string, t.union([ | ||
LegacySlice, | ||
CompositeSlice, | ||
(() => { | ||
switch(format) { | ||
case Format.Static: return SharedSlice | ||
case Format.Dynamic: return SharedSliceRef | ||
default: throw new Error(`Invalid Format Exception: ${format} doesn't exist`) | ||
} | ||
})() | ||
])) | ||
}) | ||
) | ||
return t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
labels: SlicesLabels, | ||
choices: t.record( | ||
t.string, | ||
t.union([ | ||
LegacySlice, | ||
CompositeSlice, | ||
(() => { | ||
switch (format) { | ||
case Format.Static: | ||
return SharedSlice | ||
case Format.Dynamic: | ||
return SharedSliceRef | ||
default: | ||
throw new Error( | ||
`Invalid Format Exception: ${format} doesn't exist`, | ||
) | ||
} | ||
})(), | ||
]), | ||
), | ||
}), | ||
) | ||
} | ||
@@ -58,30 +67,37 @@ export const StaticSlicesConfig = slicesConfigReader(Format.Static) | ||
const SlicesConfig = { | ||
toStatic(config: DynamicSlicesConfig, sharedSlices: Map<string, SharedSlice>): StaticSlicesConfig { | ||
const choices: {[key: string]: LegacySlice | CompositeSlice | SharedSlice } = Object.entries(config.choices || {}) | ||
.reduce((acc, [ref, slice]) => { | ||
if(slice.type === SlicesTypes.SharedSlice) { | ||
const sharedSlice = sharedSlices.get(ref) | ||
if(sharedSlice) return { ...acc, [ref]: sharedSlice } | ||
else return acc | ||
} else { | ||
return { ...acc, [ref]: slice } | ||
} | ||
}, {}) | ||
return { ...config, choices } as StaticSlicesConfig | ||
} | ||
toStatic( | ||
config: DynamicSlicesConfig, | ||
sharedSlices: Map<string, SharedSlice>, | ||
): StaticSlicesConfig { | ||
const choices: { | ||
[key: string]: LegacySlice | CompositeSlice | SharedSlice | ||
} = Object.entries(config.choices || {}).reduce((acc, [ref, slice]) => { | ||
if (slice.type === SlicesTypes.SharedSlice) { | ||
const sharedSlice = sharedSlices.get(ref) | ||
if (sharedSlice) return { ...acc, [ref]: sharedSlice } | ||
else return acc | ||
} else { | ||
return { ...acc, [ref]: slice } | ||
} | ||
}, {}) | ||
return { ...config, choices } as StaticSlicesConfig | ||
}, | ||
} | ||
export function slicesReader<F extends Format>(format: F) { | ||
return t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.union([t.literal(WidgetTypes.Slices), t.literal(WidgetTypes.LegacySlices)]) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: slicesConfigReader(format) | ||
}) | ||
]) | ||
) | ||
return t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.union([ | ||
t.literal(WidgetTypes.Slices), | ||
t.literal(WidgetTypes.LegacySlices), | ||
]), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: slicesConfigReader(format), | ||
}), | ||
]), | ||
) | ||
} | ||
@@ -96,8 +112,14 @@ | ||
export const Slices = { | ||
toStatic(slices: DynamicSlices, sharedSlices: Map<string, SharedSlice>): StaticSlices { | ||
if(!slices.config) return slices as StaticSlices | ||
else { | ||
return { ...slices, config: SlicesConfig.toStatic(slices.config, sharedSlices) } | ||
} | ||
} | ||
toStatic( | ||
slices: DynamicSlices, | ||
sharedSlices: Map<string, SharedSlice>, | ||
): StaticSlices { | ||
if (!slices.config) return slices as StaticSlices | ||
else { | ||
return { | ||
...slices, | ||
config: SlicesConfig.toStatic(slices.config, sharedSlices), | ||
} | ||
} | ||
}, | ||
} |
enum SlicesTypes { | ||
Slice = 'Slice', | ||
SharedSlice = 'SharedSlice' | ||
Slice = "Slice", | ||
SharedSlice = "SharedSlice", | ||
} | ||
export default SlicesTypes | ||
export default SlicesTypes |
@@ -1,11 +0,12 @@ | ||
import * as t from 'io-ts' | ||
import { StringOrNull } from '../../validators/StringOrNull' | ||
import WidgetTypes from './WidgetTypes' | ||
import * as t from "io-ts" | ||
import { StringOrNull } from "../../validators" | ||
import WidgetTypes from "./WidgetTypes" | ||
const UIDConfig = t.exact( | ||
t.partial({ | ||
label: StringOrNull, | ||
useAsTitle: t.boolean, | ||
placeholder: t.string | ||
}) | ||
t.partial({ | ||
label: StringOrNull, | ||
useAsTitle: t.boolean, | ||
placeholder: t.string, | ||
}), | ||
) | ||
@@ -15,11 +16,11 @@ type UIDConfig = t.TypeOf<typeof UIDConfig> | ||
const UID = t.exact( | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.UID) | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: UIDConfig | ||
}) | ||
]) | ||
t.intersection([ | ||
t.type({ | ||
type: t.literal(WidgetTypes.UID), | ||
}), | ||
t.partial({ | ||
fieldset: StringOrNull, | ||
config: UIDConfig, | ||
}), | ||
]), | ||
) | ||
@@ -26,0 +27,0 @@ type UID = t.TypeOf<typeof UID> |
@@ -1,18 +0,13 @@ | ||
import * as t from 'io-ts' | ||
import * as t from "io-ts" | ||
import UID from './UID' | ||
import NestableWidget from './nestable/NestableWidget' | ||
import { slicesReader, Slices } from './slices/Slices' | ||
import SharedSlice from './slices/SharedSlice' | ||
import { Format } from '../Format' | ||
import Group from './Group' | ||
import WidgetTypes from './WidgetTypes' | ||
import { Format } from "../Format" | ||
import Group from "./Group" | ||
import NestableWidget from "./nestable/NestableWidget" | ||
import type SharedSlice from "./slices/SharedSlice" | ||
import { Slices, slicesReader } from "./slices/Slices" | ||
import UID from "./UID" | ||
import WidgetTypes from "./WidgetTypes" | ||
export function widgetReader<F extends Format>(format: F){ | ||
return t.union([ | ||
UID, | ||
NestableWidget, | ||
Group, | ||
slicesReader(format) | ||
]) | ||
export function widgetReader<F extends Format>(format: F) { | ||
return t.union([UID, NestableWidget, Group, slicesReader(format)]) | ||
} | ||
@@ -25,10 +20,14 @@ export const StaticWidget = widgetReader(Format.Static) | ||
export const Widgets = { | ||
toStatic(widget: DynamicWidget, sharedSlices: Map<string, SharedSlice>): StaticWidget { | ||
switch(widget.type) { | ||
case WidgetTypes.Slices: return Slices.toStatic(widget, sharedSlices) | ||
default: return widget as StaticWidget | ||
} | ||
} | ||
} | ||
toStatic( | ||
widget: DynamicWidget, | ||
sharedSlices: Map<string, SharedSlice>, | ||
): StaticWidget { | ||
switch (widget.type) { | ||
case WidgetTypes.Slices: | ||
return Slices.toStatic(widget, sharedSlices) | ||
default: | ||
return widget as StaticWidget | ||
} | ||
}, | ||
} |
enum WidgetTypes { | ||
Text = 'Text', | ||
RichText = 'StructuredText', | ||
Color = 'Color', | ||
Image = 'Image', | ||
Date = 'Date', | ||
Timestamp = 'Timestamp', | ||
Number = 'Number', | ||
Range = 'Range', | ||
Select = 'Select', | ||
Link = 'Link', | ||
Embed = 'Embed', | ||
GeoPoint = 'GeoPoint', | ||
Separator = 'Separator', | ||
UID = 'UID', | ||
BooleanField = 'Boolean', | ||
IntegrationField = 'IntegrationFields', | ||
Group = 'Group', | ||
Slices = 'Slices', | ||
// Legacy type for slices | ||
LegacySlices = 'Choice' | ||
Text = "Text", | ||
RichText = "StructuredText", | ||
Color = "Color", | ||
Image = "Image", | ||
Date = "Date", | ||
Timestamp = "Timestamp", | ||
Number = "Number", | ||
Range = "Range", | ||
Select = "Select", | ||
Link = "Link", | ||
Embed = "Embed", | ||
GeoPoint = "GeoPoint", | ||
Separator = "Separator", | ||
UID = "UID", | ||
BooleanField = "Boolean", | ||
IntegrationField = "IntegrationFields", | ||
Group = "Group", | ||
Slices = "Slices", | ||
// Legacy type for slices | ||
LegacySlices = "Choice", | ||
} | ||
export default WidgetTypes | ||
export default WidgetTypes |
@@ -1,1 +0,3 @@ | ||
export * as CustomTypes from './customtypes' | ||
export * as CustomTypes from "./customtypes" | ||
export * as Documents from "./documents" | ||
export * as Validators from "./validators" |
@@ -1,24 +0,22 @@ | ||
import * as t from 'io-ts' | ||
import { pipe } from 'fp-ts/lib/pipeable' | ||
import { chain } from 'fp-ts/lib/Either' | ||
export interface IntFromNumberC extends t.Type<t.Int, number, unknown> {} | ||
/** | ||
* A codec that succeeds if a number can be parsed to an integer | ||
*/ | ||
export const IntFromNumber: IntFromNumberC = new t.Type<t.Int, number, unknown>( | ||
'IntFromNumber', | ||
t.Int.is, | ||
(u, c) => | ||
pipe( | ||
t.number.validate(u, c), | ||
chain(n => { | ||
if(t.Int.is(n)) return t.success(n) | ||
else { | ||
return t.success(Math.round(n) as t.Int) | ||
} | ||
}) | ||
), | ||
t.Int.encode | ||
) | ||
import { chain } from "fp-ts/Either" | ||
import { pipe } from "fp-ts/function" | ||
import * as t from "io-ts" | ||
export type IntFromNumberC = t.Type<t.Int, number, unknown> | ||
/** A codec that succeeds if a number can be parsed to an integer */ | ||
export default new t.Type<t.Int, number, unknown>( | ||
"IntFromNumber", | ||
t.Int.is, | ||
(u, c) => | ||
pipe( | ||
t.number.validate(u, c), | ||
chain((n) => { | ||
if (t.Int.is(n)) return t.success(n) | ||
else { | ||
return t.success(Math.round(n) as t.Int) | ||
} | ||
}), | ||
), | ||
t.Int.encode, | ||
) |
@@ -1,31 +0,32 @@ | ||
import * as t from 'io-ts' | ||
import { pipe } from 'fp-ts/lib/pipeable' | ||
import { chain } from 'fp-ts/lib/Either' | ||
import { chain } from "fp-ts/Either" | ||
import { pipe } from "fp-ts/function" | ||
import * as t from "io-ts" | ||
export interface IntFromPixelsC extends t.Type<t.Int, string, unknown> {} | ||
export type IntFromPixelsC = t.Type<t.Int, string, unknown> | ||
const PixelsRegex = /^([0-9]+)px$/ | ||
/** | ||
* A codec that succeeds if a string representing pixels (eg: "200px") can be parsed to an integer | ||
* A codec that succeeds if a string representing pixels (eg: "200px") can be | ||
* parsed to an integer | ||
*/ | ||
export const IntFromPixels: IntFromPixelsC = new t.Type<t.Int, string, unknown>( | ||
'IntFromPixels', | ||
t.Int.is, | ||
(u, c) => | ||
pipe( | ||
t.string.validate(u, c), | ||
chain(strPixels => { | ||
try { | ||
const matched = strPixels.match(PixelsRegex) | ||
if(!matched) return t.failure(u, c) | ||
else { | ||
const parsed = parseInt(matched[1]) as t.Int | ||
return t.success(parsed) | ||
} | ||
} catch { | ||
return t.failure(u, c) | ||
} | ||
}) | ||
), | ||
String | ||
) | ||
export default new t.Type<t.Int, string, unknown>( | ||
"IntFromPixels", | ||
t.Int.is, | ||
(u, c) => | ||
pipe( | ||
t.string.validate(u, c), | ||
chain((strPixels) => { | ||
try { | ||
const matched = strPixels.match(PixelsRegex) | ||
if (!matched) return t.failure(u, c) | ||
/* eslint-disable @typescript-eslint/no-non-null-assertion */ | ||
const parsed = parseInt(matched[1]!) as t.Int | ||
return t.success(parsed) | ||
} catch { | ||
return t.failure(u, c) | ||
} | ||
}), | ||
), | ||
String, | ||
) |
@@ -1,21 +0,19 @@ | ||
import * as t from 'io-ts' | ||
import { pipe } from 'fp-ts/lib/pipeable' | ||
import { chain } from 'fp-ts/lib/Either' | ||
import { chain } from "fp-ts/Either" | ||
import { pipe } from "fp-ts/function" | ||
import * as t from "io-ts" | ||
export interface StringFromBooleanC extends t.Type<string, string, unknown> {} | ||
export type StringFromBooleanC = t.Type<string, string, unknown> | ||
/** | ||
* A codec that validates a Boolean and convert it as a string | ||
*/ | ||
export const StringFromBoolean: StringFromBooleanC = new t.Type<string, string, unknown>( | ||
'StringFromInt', | ||
t.string.is, | ||
(u, c) => | ||
pipe( | ||
t.boolean.validate(u, c), | ||
chain(i => { | ||
return t.success(i.toString()) | ||
}) | ||
), | ||
i => i | ||
) | ||
/** A codec that validates a Boolean and convert it as a string */ | ||
export default new t.Type<string, string, unknown>( | ||
"StringFromInt", | ||
t.string.is, | ||
(u, c) => | ||
pipe( | ||
t.boolean.validate(u, c), | ||
chain((i) => { | ||
return t.success(i.toString()) | ||
}), | ||
), | ||
(i) => i, | ||
) |
@@ -1,21 +0,19 @@ | ||
import * as t from 'io-ts' | ||
import { pipe } from 'fp-ts/lib/pipeable' | ||
import { chain } from 'fp-ts/lib/Either' | ||
import { chain } from "fp-ts/Either" | ||
import { pipe } from "fp-ts/function" | ||
import * as t from "io-ts" | ||
export interface StringFromNumberC extends t.Type<string, string, unknown> {} | ||
export type StringFromNumberC = t.Type<string, string, unknown> | ||
/** | ||
* A codec that validates a number and convert it as a string | ||
*/ | ||
export const StringFromNumber: StringFromNumberC = new t.Type<string, string, unknown>( | ||
'StringFromInt', | ||
t.string.is, | ||
(u, c) => | ||
pipe( | ||
t.number.validate(u, c), | ||
chain(i => { | ||
return t.success(i.toString()) | ||
}) | ||
), | ||
i => i | ||
) | ||
/** A codec that validates a number and convert it as a string */ | ||
export default new t.Type<string, string, unknown>( | ||
"StringFromInt", | ||
t.string.is, | ||
(u, c) => | ||
pipe( | ||
t.number.validate(u, c), | ||
chain((i) => { | ||
return t.success(i.toString()) | ||
}), | ||
), | ||
(i) => i, | ||
) |
@@ -1,3 +0,5 @@ | ||
import * as t from 'io-ts' | ||
import * as t from "io-ts" | ||
export const StringOrNull = t.union([ t.string, t.null, t.undefined ]) | ||
import { nullable } from "./function" | ||
export default nullable(t.string) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1289230
245
25484
6
21
+ Addedmonocle-ts@^2.3.11
+ Addednewtype-ts@^0.3.5
+ Addedtslib@^2.3.1
+ Addedtslib@2.8.1(transitive)
- Removedfp-ts@^2.11.8
- Removedio-ts@^2.2.16
- Removedio-ts-types@^0.5.16