From e78948f36823d006bb27f96748581ecc89053ec4 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Fri, 29 Jul 2022 03:38:16 -0500 Subject: [PATCH 01/26] initial commit --- packages/editor/.eslintignore | 13 + packages/editor/.eslintrc.cjs | 20 + .../editor/.flatbread/schemas/author.yaml | 24 + .../.flatbread/schemas/override-test.yaml | 25 + .../schemas/post-category-blob.yaml | 21 + .../.flatbread/schemas/post-category.yaml | 23 + packages/editor/.flatbread/schemas/post.yaml | 21 + .../.flatbread/schemas/yaml-author.yaml | 23 + packages/editor/.gitignore | 8 + packages/editor/.npmrc | 1 + packages/editor/.prettierignore | 13 + packages/editor/.prettierrc | 6 + packages/editor/README.md | 38 + packages/editor/app.html | 12 + packages/editor/package.json | 44 + packages/editor/pnpm-lock.yaml | 1965 +++++++++++++++++ packages/editor/src/app.d.ts | 11 + packages/editor/src/app.html | 12 + packages/editor/src/hooks.ts | 43 + packages/editor/src/lib/JsonCrush.ts | 10 + packages/editor/src/lib/api.ts | 186 ++ packages/editor/src/lib/breadcrumbs.svelte | 51 + packages/editor/src/lib/config.ts | 66 + .../editor/src/lib/field-component.svelte | 17 + packages/editor/src/lib/fields/date.svelte | 14 + packages/editor/src/lib/fields/list.svelte | 36 + packages/editor/src/lib/fields/object.svelte | 34 + packages/editor/src/lib/fields/raw.svelte | 15 + packages/editor/src/lib/fields/string.svelte | 15 + packages/editor/src/lib/schemaStore.ts | 5 + packages/editor/src/routes/__layout.svelte | 77 + .../src/routes/collection/[name]/[id].svelte | 56 + .../src/routes/collection/[name]/index.svelte | 66 + .../src/routes/collection/[name]/new.svelte | 42 + packages/editor/src/routes/index.svelte | 20 + packages/editor/static/favicon.png | Bin 0 -> 1571 bytes packages/editor/svelte.config.js | 15 + packages/editor/tsconfig.json | 17 + packages/editor/vite.config.js | 8 + pnpm-lock.yaml | 788 ++++++- 40 files changed, 3820 insertions(+), 41 deletions(-) create mode 100644 packages/editor/.eslintignore create mode 100644 packages/editor/.eslintrc.cjs create mode 100644 packages/editor/.flatbread/schemas/author.yaml create mode 100644 packages/editor/.flatbread/schemas/override-test.yaml create mode 100644 packages/editor/.flatbread/schemas/post-category-blob.yaml create mode 100644 packages/editor/.flatbread/schemas/post-category.yaml create mode 100644 packages/editor/.flatbread/schemas/post.yaml create mode 100644 packages/editor/.flatbread/schemas/yaml-author.yaml create mode 100644 packages/editor/.gitignore create mode 100644 packages/editor/.npmrc create mode 100644 packages/editor/.prettierignore create mode 100644 packages/editor/.prettierrc create mode 100644 packages/editor/README.md create mode 100644 packages/editor/app.html create mode 100644 packages/editor/package.json create mode 100644 packages/editor/pnpm-lock.yaml create mode 100644 packages/editor/src/app.d.ts create mode 100644 packages/editor/src/app.html create mode 100644 packages/editor/src/hooks.ts create mode 100644 packages/editor/src/lib/JsonCrush.ts create mode 100644 packages/editor/src/lib/api.ts create mode 100644 packages/editor/src/lib/breadcrumbs.svelte create mode 100644 packages/editor/src/lib/config.ts create mode 100644 packages/editor/src/lib/field-component.svelte create mode 100644 packages/editor/src/lib/fields/date.svelte create mode 100644 packages/editor/src/lib/fields/list.svelte create mode 100644 packages/editor/src/lib/fields/object.svelte create mode 100644 packages/editor/src/lib/fields/raw.svelte create mode 100644 packages/editor/src/lib/fields/string.svelte create mode 100644 packages/editor/src/lib/schemaStore.ts create mode 100644 packages/editor/src/routes/__layout.svelte create mode 100644 packages/editor/src/routes/collection/[name]/[id].svelte create mode 100644 packages/editor/src/routes/collection/[name]/index.svelte create mode 100644 packages/editor/src/routes/collection/[name]/new.svelte create mode 100644 packages/editor/src/routes/index.svelte create mode 100644 packages/editor/static/favicon.png create mode 100644 packages/editor/svelte.config.js create mode 100644 packages/editor/tsconfig.json create mode 100644 packages/editor/vite.config.js diff --git a/packages/editor/.eslintignore b/packages/editor/.eslintignore new file mode 100644 index 00000000..38972655 --- /dev/null +++ b/packages/editor/.eslintignore @@ -0,0 +1,13 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/packages/editor/.eslintrc.cjs b/packages/editor/.eslintrc.cjs new file mode 100644 index 00000000..3ccf435f --- /dev/null +++ b/packages/editor/.eslintrc.cjs @@ -0,0 +1,20 @@ +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], + plugins: ['svelte3', '@typescript-eslint'], + ignorePatterns: ['*.cjs'], + overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], + settings: { + 'svelte3/typescript': () => require('typescript') + }, + parserOptions: { + sourceType: 'module', + ecmaVersion: 2020 + }, + env: { + browser: true, + es2017: true, + node: true + } +}; diff --git a/packages/editor/.flatbread/schemas/author.yaml b/packages/editor/.flatbread/schemas/author.yaml new file mode 100644 index 00000000..c5762bb7 --- /dev/null +++ b/packages/editor/.flatbread/schemas/author.yaml @@ -0,0 +1,24 @@ +label: Authors +name: allAuthors +description: Return a set of Authors +disabled: false +component: list +schema: + name: Author + kind: OBJECT + fields: + - {label: Name, name: name, disabled: false, component: string} + - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} + - {label: filename, name: _filename, disabled: true, component: string} + - {label: path, name: _path, disabled: true, component: string} + - {label: slug, name: _slug, disabled: true, component: string} + - {label: Date joined, name: date_joined, disabled: false, component: date} + - {label: Entity, name: entity, disabled: false, component: string} + - {label: Id, name: id, disabled: true, component: string} + - {label: content, name: _content, disabled: true, component: object} + - {label: Enjoys, name: enjoys, disabled: false, component: list} + - {label: Friend, name: friend, description: The Author referenced by this Author, disabled: false, component: object} + - {label: Skills, name: skills, disabled: false, component: object} + referenceField: name +meta: + hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/override-test.yaml b/packages/editor/.flatbread/schemas/override-test.yaml new file mode 100644 index 00000000..9a7c5a76 --- /dev/null +++ b/packages/editor/.flatbread/schemas/override-test.yaml @@ -0,0 +1,25 @@ +label: Override Tests +name: allOverrideTests +description: Return a set of OverrideTests +disabled: false +component: list +schema: + name: OverrideTest + kind: OBJECT + fields: + - {label: Title, name: title, disabled: false, component: string} + - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} + - {label: filename, name: _filename, disabled: true, component: string} + - {label: path, name: _path, disabled: true, component: string} + - {label: slug, name: _slug, disabled: true, component: string} + - {label: Id, name: id, disabled: true, component: string} + - {label: content, name: _content, disabled: true, component: object} + - {label: Array, name: array, disabled: false, component: list} + - {label: Array2, name: array2, disabled: false, component: list} + - {label: Array3, name: array3, disabled: false, component: list} + - {label: Deeply, name: deeply, disabled: false, component: object} + - {label: Image, name: image, disabled: false, component: object} + - {label: Image2, name: image2, disabled: false, component: object} + referenceField: title +meta: + hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/post-category-blob.yaml b/packages/editor/.flatbread/schemas/post-category-blob.yaml new file mode 100644 index 00000000..2746078c --- /dev/null +++ b/packages/editor/.flatbread/schemas/post-category-blob.yaml @@ -0,0 +1,21 @@ +label: Post Category Blobs +name: allPostCategoryBlobs +description: Return a set of PostCategoryBlobs +disabled: false +component: list +schema: + name: PostCategoryBlob + kind: OBJECT + fields: + - {label: Title, name: title, disabled: false, component: string} + - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} + - {label: filename, name: _filename, disabled: true, component: string} + - {label: path, name: _path, disabled: true, component: string} + - {label: slug, name: _slug, disabled: true, component: string} + - {label: Id, name: id, disabled: true, component: string} + - {label: Rating, name: rating, disabled: false, component: float} + - {label: content, name: _content, disabled: true, component: object} + - {label: Authors, name: authors, description: All Authors that are referenced by this PostCategoryBlob, disabled: false, component: list} + referenceField: title +meta: + hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/post-category.yaml b/packages/editor/.flatbread/schemas/post-category.yaml new file mode 100644 index 00000000..dda48b16 --- /dev/null +++ b/packages/editor/.flatbread/schemas/post-category.yaml @@ -0,0 +1,23 @@ +label: Post Categories +name: allPostCategories +description: Return a set of PostCategories +disabled: false +component: list +schema: + name: PostCategory + kind: OBJECT + fields: + - {label: Title, name: title, disabled: false, component: string} + - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} + - {label: filename, name: _filename, disabled: true, component: string} + - {label: path, name: _path, disabled: true, component: string} + - {label: slug, name: _slug, disabled: true, component: string} + - {label: Category, name: category, disabled: false, component: string} + - {label: Id, name: id, disabled: true, component: string} + - {label: Rating, name: rating, disabled: false, component: float} + - {label: Slug, name: slug, disabled: false, component: string} + - {label: content, name: _content, disabled: true, component: object} + - {label: Authors, name: authors, description: All Authors that are referenced by this PostCategory, disabled: false, component: list} + referenceField: title +meta: + hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/post.yaml b/packages/editor/.flatbread/schemas/post.yaml new file mode 100644 index 00000000..6aad712a --- /dev/null +++ b/packages/editor/.flatbread/schemas/post.yaml @@ -0,0 +1,21 @@ +label: Posts +name: allPosts +description: Return a set of Posts +disabled: false +component: list +schema: + name: Post + kind: OBJECT + fields: + - {label: Title, name: title, disabled: false, component: string} + - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} + - {label: filename, name: _filename, disabled: true, component: string} + - {label: path, name: _path, disabled: true, component: string} + - {label: slug, name: _slug, disabled: true, component: string} + - {label: Id, name: id, disabled: true, component: string} + - {label: Rating, name: rating, disabled: false, component: float} + - {label: content, name: _content, disabled: true, component: object} + - {label: Authors, name: authors, description: All Authors that are referenced by this Post, disabled: false, component: list} + referenceField: title +meta: + hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/yaml-author.yaml b/packages/editor/.flatbread/schemas/yaml-author.yaml new file mode 100644 index 00000000..fa513d36 --- /dev/null +++ b/packages/editor/.flatbread/schemas/yaml-author.yaml @@ -0,0 +1,23 @@ +label: Authors (Yaml) +name: allYamlAuthors +description: Return a set of YamlAuthors +disabled: false +component: list +schema: + name: YamlAuthor + kind: OBJECT + fields: + - {label: Name, name: name, disabled: false, component: string} + - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} + - {label: filename, name: _filename, disabled: true, component: string} + - {label: path, name: _path, disabled: true, component: string} + - {label: slug, name: _slug, disabled: true, component: string} + - {label: Date joined, name: date_joined, disabled: false, component: date} + - {label: Id, name: id, disabled: true, component: string} + - {label: content, name: _content, disabled: true, component: object} + - {label: Enjoys, name: enjoys, disabled: false, component: list} + - {label: Friend, name: friend, description: The YamlAuthor referenced by this YamlAuthor, disabled: false, component: object} + - {label: Skills, name: skills, disabled: false, component: object} + referenceField: name +meta: + hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.gitignore b/packages/editor/.gitignore new file mode 100644 index 00000000..f4401a32 --- /dev/null +++ b/packages/editor/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example diff --git a/packages/editor/.npmrc b/packages/editor/.npmrc new file mode 100644 index 00000000..b6f27f13 --- /dev/null +++ b/packages/editor/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/packages/editor/.prettierignore b/packages/editor/.prettierignore new file mode 100644 index 00000000..38972655 --- /dev/null +++ b/packages/editor/.prettierignore @@ -0,0 +1,13 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/packages/editor/.prettierrc b/packages/editor/.prettierrc new file mode 100644 index 00000000..ff2677ef --- /dev/null +++ b/packages/editor/.prettierrc @@ -0,0 +1,6 @@ +{ + "useTabs": true, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100 +} diff --git a/packages/editor/README.md b/packages/editor/README.md new file mode 100644 index 00000000..5c91169b --- /dev/null +++ b/packages/editor/README.md @@ -0,0 +1,38 @@ +# create-svelte + +Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). + +## Creating a project + +If you're seeing this, you've probably already done this step. Congrats! + +```bash +# create a new project in the current directory +npm create svelte@latest + +# create a new project in my-app +npm create svelte@latest my-app +``` + +## Developing + +Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: + +```bash +npm run dev + +# or start the server and open the app in a new browser tab +npm run dev -- --open +``` + +## Building + +To create a production version of your app: + +```bash +npm run build +``` + +You can preview the production build with `npm run preview`. + +> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/packages/editor/app.html b/packages/editor/app.html new file mode 100644 index 00000000..5b53ef7e --- /dev/null +++ b/packages/editor/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/editor/package.json b/packages/editor/package.json new file mode 100644 index 00000000..ce56e734 --- /dev/null +++ b/packages/editor/package.json @@ -0,0 +1,44 @@ +{ + "name": "@flatbread/editor", + "version": "0.0.1", + "types": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "package": "svelte-kit package", + "preview": "vite preview", + "prepare": "svelte-kit sync", + "check": "svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check --plugin-search-dir=. . && eslint .", + "format": "prettier --write --plugin-search-dir=. ." + }, + "devDependencies": { + "@sveltejs/adapter-auto": "next", + "@sveltejs/kit": "next", + "@typescript-eslint/eslint-plugin": "^5.31.0", + "@typescript-eslint/parser": "^5.31.0", + "eslint": "^8.20.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-svelte3": "^4.0.0", + "prettier": "^2.7.1", + "prettier-plugin-svelte": "^2.7.0", + "sass": "^1.54.0", + "svelte": "^3.49.0", + "svelte-check": "^2.8.0", + "svelte-preprocess": "^4.10.7", + "tslib": "^2.4.0", + "typescript": "^4.7.4", + "vite": "^3.0.3" + }, + "type": "module", + "dependencies": { + "@picocss/pico": "^1.5.3", + "@types/js-yaml": "^4.0.5", + "@types/lodash-es": "^4.17.6", + "js-yaml": "^4.1.0", + "lodash-es": "^4.17.21", + "node-fetch": "^3.2.9", + "wretch": "^1.7.10" + } +} diff --git a/packages/editor/pnpm-lock.yaml b/packages/editor/pnpm-lock.yaml new file mode 100644 index 00000000..e4ec3143 --- /dev/null +++ b/packages/editor/pnpm-lock.yaml @@ -0,0 +1,1965 @@ +lockfileVersion: 5.4 + +specifiers: + '@sveltejs/adapter-auto': next + '@sveltejs/kit': next + '@typescript-eslint/eslint-plugin': ^5.27.0 + '@typescript-eslint/parser': ^5.27.0 + eslint: ^8.16.0 + eslint-config-prettier: ^8.3.0 + eslint-plugin-svelte3: ^4.0.0 + prettier: ^2.6.2 + prettier-plugin-svelte: ^2.7.0 + svelte: ^3.44.0 + svelte-check: ^2.7.1 + svelte-preprocess: ^4.10.6 + tslib: ^2.3.1 + typescript: ^4.7.4 + vite: ^3.0.0 + +devDependencies: + '@sveltejs/adapter-auto': 1.0.0-next.64 + '@sveltejs/kit': 1.0.0-next.396_svelte@3.49.0+vite@3.0.3 + '@typescript-eslint/eslint-plugin': 5.31.0_d5zwcxr4bwkhmuo464cb3a2puu + '@typescript-eslint/parser': 5.31.0_he2ccbldppg44uulnyq4rwocfa + eslint: 8.20.0 + eslint-config-prettier: 8.5.0_eslint@8.20.0 + eslint-plugin-svelte3: 4.0.0_piwa6j2njmnknm35bh3wz5v52y + prettier: 2.7.1 + prettier-plugin-svelte: 2.7.0_o3ioganyptcsrh6x4hnxvjkpqi + svelte: 3.49.0 + svelte-check: 2.8.0_svelte@3.49.0 + svelte-preprocess: 4.10.7_uslzfc62di2n2otc2tvfklnwji + tslib: 2.4.0 + typescript: 4.7.4 + vite: 3.0.3 + +packages: + + /@cloudflare/workers-types/3.14.1: + resolution: {integrity: sha512-B1/plF62pt+H2IJHvApK8fdOJAVsvojvacuac8x8s+JIyqbropMyqNqHTKLm3YD8ZFLGwYeFTudU+PQ7vGvBdA==} + dev: true + + /@eslint/eslintrc/1.3.0: + resolution: {integrity: sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.3.2 + globals: 13.17.0 + ignore: 5.2.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/config-array/0.9.5: + resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/object-schema/1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@iarna/toml/2.2.5: + resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + dev: true + + /@jridgewell/resolve-uri/3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec/1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + dev: true + + /@jridgewell/trace-mapping/0.3.14: + resolution: {integrity: sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@mapbox/node-pre-gyp/1.0.9: + resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==} + hasBin: true + dependencies: + detect-libc: 2.0.1 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.6.7 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.3.7 + tar: 6.1.11 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.13.0 + dev: true + + /@rollup/pluginutils/4.2.1: + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@sveltejs/adapter-auto/1.0.0-next.64: + resolution: {integrity: sha512-Q8DwcS6wl1GovzS9JJzaD/WL/Lfk1ur4nAF1HtmsUvZDpsPBVDqnK2AhYU4G3oFNiuHstrjAogMy5th8ptSFGw==} + dependencies: + '@sveltejs/adapter-cloudflare': 1.0.0-next.31 + '@sveltejs/adapter-netlify': 1.0.0-next.71 + '@sveltejs/adapter-vercel': 1.0.0-next.66 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@sveltejs/adapter-cloudflare/1.0.0-next.31: + resolution: {integrity: sha512-HhEFZP72GJ8AZGgFECKIiayDcLaAWi65pI0AnBfiNhCifYSlH/mPNWNVD4AWRDnXnH6XU+FLwhGDnIDwytTyYg==} + dependencies: + '@cloudflare/workers-types': 3.14.1 + esbuild: 0.14.50 + worktop: 0.8.0-next.14 + dev: true + + /@sveltejs/adapter-netlify/1.0.0-next.71: + resolution: {integrity: sha512-la1CGtWO1xul1L3zEoFAoc4EX2uxZjrZcOMS3tkKB8drxhbQsNbnTE6fmSSMFiZXhxaikczrBgQwqIaDkLTmZg==} + dependencies: + '@iarna/toml': 2.2.5 + esbuild: 0.14.50 + set-cookie-parser: 2.5.1 + tiny-glob: 0.2.9 + dev: true + + /@sveltejs/adapter-vercel/1.0.0-next.66: + resolution: {integrity: sha512-s3Hcxu9nCG/rR3C3cFbdQGjTa5W4K2kRcc6S5Xefx7itbrw+4v3KpO8ZPB6qM55XDwVxuG7260NMHVI6MUGmSA==} + dependencies: + '@vercel/nft': 0.21.0 + esbuild: 0.14.50 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@sveltejs/kit/1.0.0-next.396_svelte@3.49.0+vite@3.0.3: + resolution: {integrity: sha512-bKFpuzp9QxPkOIOEIeNeedvxEMORNqBPxUmoJXDP/Se7MrSfcxYiamjBcKrG+bgGNWmV39nD3EvUox+CXno/Ig==} + engines: {node: '>=16.9'} + hasBin: true + peerDependencies: + svelte: ^3.44.0 + vite: ^3.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte': 1.0.1_svelte@3.49.0+vite@3.0.3 + chokidar: 3.5.3 + sade: 1.8.1 + svelte: 3.49.0 + vite: 3.0.3 + transitivePeerDependencies: + - diff-match-patch + - supports-color + dev: true + + /@sveltejs/vite-plugin-svelte/1.0.1_svelte@3.49.0+vite@3.0.3: + resolution: {integrity: sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==} + engines: {node: ^14.18.0 || >= 16} + peerDependencies: + diff-match-patch: ^1.0.5 + svelte: ^3.44.0 + vite: ^3.0.0 + peerDependenciesMeta: + diff-match-patch: + optional: true + dependencies: + '@rollup/pluginutils': 4.2.1 + debug: 4.3.4 + deepmerge: 4.2.2 + kleur: 4.1.5 + magic-string: 0.26.2 + svelte: 3.49.0 + svelte-hmr: 0.14.12_svelte@3.49.0 + vite: 3.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@types/json-schema/7.0.11: + resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} + dev: true + + /@types/node/18.6.1: + resolution: {integrity: sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==} + dev: true + + /@types/pug/2.0.6: + resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} + dev: true + + /@types/sass/1.43.1: + resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} + dependencies: + '@types/node': 18.6.1 + dev: true + + /@typescript-eslint/eslint-plugin/5.31.0_d5zwcxr4bwkhmuo464cb3a2puu: + resolution: {integrity: sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/parser': 5.31.0_he2ccbldppg44uulnyq4rwocfa + '@typescript-eslint/scope-manager': 5.31.0 + '@typescript-eslint/type-utils': 5.31.0_he2ccbldppg44uulnyq4rwocfa + '@typescript-eslint/utils': 5.31.0_he2ccbldppg44uulnyq4rwocfa + debug: 4.3.4 + eslint: 8.20.0 + functional-red-black-tree: 1.0.1 + ignore: 5.2.0 + regexpp: 3.2.0 + semver: 7.3.7 + tsutils: 3.21.0_typescript@4.7.4 + typescript: 4.7.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser/5.31.0_he2ccbldppg44uulnyq4rwocfa: + resolution: {integrity: sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.31.0 + '@typescript-eslint/types': 5.31.0 + '@typescript-eslint/typescript-estree': 5.31.0_typescript@4.7.4 + debug: 4.3.4 + eslint: 8.20.0 + typescript: 4.7.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager/5.31.0: + resolution: {integrity: sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.31.0 + '@typescript-eslint/visitor-keys': 5.31.0 + dev: true + + /@typescript-eslint/type-utils/5.31.0_he2ccbldppg44uulnyq4rwocfa: + resolution: {integrity: sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/utils': 5.31.0_he2ccbldppg44uulnyq4rwocfa + debug: 4.3.4 + eslint: 8.20.0 + tsutils: 3.21.0_typescript@4.7.4 + typescript: 4.7.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types/5.31.0: + resolution: {integrity: sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree/5.31.0_typescript@4.7.4: + resolution: {integrity: sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.31.0 + '@typescript-eslint/visitor-keys': 5.31.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.3.7 + tsutils: 3.21.0_typescript@4.7.4 + typescript: 4.7.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils/5.31.0_he2ccbldppg44uulnyq4rwocfa: + resolution: {integrity: sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@types/json-schema': 7.0.11 + '@typescript-eslint/scope-manager': 5.31.0 + '@typescript-eslint/types': 5.31.0 + '@typescript-eslint/typescript-estree': 5.31.0_typescript@4.7.4 + eslint: 8.20.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0_eslint@8.20.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys/5.31.0: + resolution: {integrity: sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.31.0 + eslint-visitor-keys: 3.3.0 + dev: true + + /@vercel/nft/0.21.0: + resolution: {integrity: sha512-hFCAETfI5cG8l5iAiLhMC2bReC5K7SIybzrxGorv+eGspIbIFsVw7Vg85GovXm/LxA08pIDrAlrhR6GN36XB/Q==} + hasBin: true + dependencies: + '@mapbox/node-pre-gyp': 1.0.9 + acorn: 8.8.0 + async-sema: 3.1.1 + bindings: 1.5.0 + estree-walker: 2.0.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + micromatch: 4.0.5 + node-gyp-build: 4.5.0 + resolve-from: 5.0.0 + rollup-pluginutils: 2.8.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /abbrev/1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: true + + /acorn-jsx/5.3.2_acorn@8.8.0: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.0 + dev: true + + /acorn/8.8.0: + resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /agent-base/6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /ajv/6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /anymatch/3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /aproba/2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: true + + /are-we-there-yet/2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.0 + dev: true + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /async-sema/3.1.1: + resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bindings/1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + dependencies: + file-uri-to-path: 1.0.0 + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /buffer-crc32/0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: true + + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chokidar/3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /chownr/2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: true + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /color-support/1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + dev: true + + /console-control-strings/1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: true + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /deep-is/0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge/4.2.2: + resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} + engines: {node: '>=0.10.0'} + dev: true + + /delegates/1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: true + + /detect-indent/6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + + /detect-libc/2.0.1: + resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==} + engines: {node: '>=8'} + dev: true + + /dir-glob/3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine/3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /emoji-regex/8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /es6-promise/3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + dev: true + + /esbuild-android-64/0.14.50: + resolution: {integrity: sha512-H7iUEm7gUJHzidsBlFPGF6FTExazcgXL/46xxLo6i6bMtPim6ZmXyTccS8yOMpy6HAC6dPZ/JCQqrkkin69n6Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /esbuild-android-arm64/0.14.50: + resolution: {integrity: sha512-NFaoqEwa+OYfoYVpQWDMdKII7wZZkAjtJFo1WdnBeCYlYikvUhTnf2aPwPu5qEAw/ie1NYK0yn3cafwP+kP+OQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /esbuild-darwin-64/0.14.50: + resolution: {integrity: sha512-gDQsCvGnZiJv9cfdO48QqxkRV8oKAXgR2CGp7TdIpccwFdJMHf8hyIJhMW/05b/HJjET/26Us27Jx91BFfEVSA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /esbuild-darwin-arm64/0.14.50: + resolution: {integrity: sha512-36nNs5OjKIb/Q50Sgp8+rYW/PqirRiFN0NFc9hEvgPzNJxeJedktXwzfJSln4EcRFRh5Vz4IlqFRScp+aiBBzA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /esbuild-freebsd-64/0.14.50: + resolution: {integrity: sha512-/1pHHCUem8e/R86/uR+4v5diI2CtBdiWKiqGuPa9b/0x3Nwdh5AOH7lj+8823C6uX1e0ufwkSLkS+aFZiBCWxA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-freebsd-arm64/0.14.50: + resolution: {integrity: sha512-iKwUVMQztnPZe5pUYHdMkRc9aSpvoV1mkuHlCoPtxZA3V+Kg/ptpzkcSY+fKd0kuom+l6Rc93k0UPVkP7xoqrw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-32/0.14.50: + resolution: {integrity: sha512-sWUwvf3uz7dFOpLzYuih+WQ7dRycrBWHCdoXJ4I4XdMxEHCECd8b7a9N9u7FzT6XR2gHPk9EzvchQUtiEMRwqw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-64/0.14.50: + resolution: {integrity: sha512-u0PQxPhaeI629t4Y3EEcQ0wmWG+tC/LpP2K7yDFvwuPq0jSQ8SIN+ARNYfRjGW15O2we3XJvklbGV0wRuUCPig==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-arm/0.14.50: + resolution: {integrity: sha512-VALZq13bhmFJYFE/mLEb+9A0w5vo8z+YDVOWeaf9vOTrSC31RohRIwtxXBnVJ7YKLYfEMzcgFYf+OFln3Y0cWg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-arm64/0.14.50: + resolution: {integrity: sha512-ZyfoNgsTftD7Rp5S7La5auomKdNeB3Ck+kSKXC4pp96VnHyYGjHHXWIlcbH8i+efRn9brszo1/Thl1qn8RqmhQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-mips64le/0.14.50: + resolution: {integrity: sha512-ygo31Vxn/WrmjKCHkBoutOlFG5yM9J2UhzHb0oWD9O61dGg+Hzjz9hjf5cmM7FBhAzdpOdEWHIrVOg2YAi6rTw==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-ppc64le/0.14.50: + resolution: {integrity: sha512-xWCKU5UaiTUT6Wz/O7GKP9KWdfbsb7vhfgQzRfX4ahh5NZV4ozZ4+SdzYG8WxetsLy84UzLX3Pi++xpVn1OkFQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-riscv64/0.14.50: + resolution: {integrity: sha512-0+dsneSEihZTopoO9B6Z6K4j3uI7EdxBP7YSF5rTwUgCID+wHD3vM1gGT0m+pjCW+NOacU9kH/WE9N686FHAJg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-s390x/0.14.50: + resolution: {integrity: sha512-tVjqcu8o0P9H4StwbIhL1sQYm5mWATlodKB6dpEZFkcyTI8kfIGWiWcrGmkNGH2i1kBUOsdlBafPxR3nzp3TDA==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-netbsd-64/0.14.50: + resolution: {integrity: sha512-0R/glfqAQ2q6MHDf7YJw/TulibugjizBxyPvZIcorH0Mb7vSimdHy0XF5uCba5CKt+r4wjax1mvO9lZ4jiAhEg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-openbsd-64/0.14.50: + resolution: {integrity: sha512-7PAtmrR5mDOFubXIkuxYQ4bdNS6XCK8AIIHUiZxq1kL8cFIH5731jPcXQ4JNy/wbj1C9sZ8rzD8BIM80Tqk29w==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-sunos-64/0.14.50: + resolution: {integrity: sha512-gBxNY/wyptvD7PkHIYcq7se6SQEXcSC8Y7mE0FJB+CGgssEWf6vBPfTTZ2b6BWKnmaP6P6qb7s/KRIV5T2PxsQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-32/0.14.50: + resolution: {integrity: sha512-MOOe6J9cqe/iW1qbIVYSAqzJFh0p2LBLhVUIWdMVnNUNjvg2/4QNX4oT4IzgDeldU+Bym9/Tn6+DxvUHJXL5Zw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-64/0.14.50: + resolution: {integrity: sha512-r/qE5Ex3w1jjGv/JlpPoWB365ldkppUlnizhMxJgojp907ZF1PgLTuW207kgzZcSCXyquL9qJkMsY+MRtaZ5yQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-arm64/0.14.50: + resolution: {integrity: sha512-EMS4lQnsIe12ZyAinOINx7eq2mjpDdhGZZWDwPZE/yUTN9cnc2Ze/xUTYIAyaJqrqQda3LnDpADKpvLvol6ENQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild/0.14.50: + resolution: {integrity: sha512-SbC3k35Ih2IC6trhbMYW7hYeGdjPKf9atTKwBUHqMCYFZZ9z8zhuvfnZihsnJypl74FjiAKjBRqFkBkAd0rS/w==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + esbuild-android-64: 0.14.50 + esbuild-android-arm64: 0.14.50 + esbuild-darwin-64: 0.14.50 + esbuild-darwin-arm64: 0.14.50 + esbuild-freebsd-64: 0.14.50 + esbuild-freebsd-arm64: 0.14.50 + esbuild-linux-32: 0.14.50 + esbuild-linux-64: 0.14.50 + esbuild-linux-arm: 0.14.50 + esbuild-linux-arm64: 0.14.50 + esbuild-linux-mips64le: 0.14.50 + esbuild-linux-ppc64le: 0.14.50 + esbuild-linux-riscv64: 0.14.50 + esbuild-linux-s390x: 0.14.50 + esbuild-netbsd-64: 0.14.50 + esbuild-openbsd-64: 0.14.50 + esbuild-sunos-64: 0.14.50 + esbuild-windows-32: 0.14.50 + esbuild-windows-64: 0.14.50 + esbuild-windows-arm64: 0.14.50 + dev: true + + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier/8.5.0_eslint@8.20.0: + resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.20.0 + dev: true + + /eslint-plugin-svelte3/4.0.0_piwa6j2njmnknm35bh3wz5v52y: + resolution: {integrity: sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==} + peerDependencies: + eslint: '>=8.0.0' + svelte: ^3.2.0 + dependencies: + eslint: 8.20.0 + svelte: 3.49.0 + dev: true + + /eslint-scope/5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope/7.1.1: + resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-utils/3.0.0_eslint@8.20.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.20.0 + eslint-visitor-keys: 2.1.0 + dev: true + + /eslint-visitor-keys/2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint-visitor-keys/3.3.0: + resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint/8.20.0: + resolution: {integrity: sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint/eslintrc': 1.3.0 + '@humanwhocodes/config-array': 0.9.5 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.1.1 + eslint-utils: 3.0.0_eslint@8.20.0 + eslint-visitor-keys: 3.3.0 + espree: 9.3.2 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 6.0.2 + globals: 13.17.0 + ignore: 5.2.0 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + regexpp: 3.2.0 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + v8-compile-cache: 2.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree/9.3.2: + resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.0 + acorn-jsx: 5.3.2_acorn@8.8.0 + eslint-visitor-keys: 3.3.0 + dev: true + + /esquery/1.4.0: + resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse/4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse/4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse/5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker/0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + dev: true + + /estree-walker/2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob/3.2.11: + resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein/2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq/1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache/6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /file-uri-to-path/1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + dev: true + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /flat-cache/3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.6 + rimraf: 3.0.2 + dev: true + + /flatted/3.2.6: + resolution: {integrity: sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==} + dev: true + + /fs-minipass/2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.4 + dev: true + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /functional-red-black-tree/1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + dev: true + + /gauge/3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: true + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent/6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals/13.17.0: + resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalyzer/0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + dev: true + + /globby/11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.11 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globrex/0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + dev: true + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-unicode/2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /https-proxy-agent/5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /ignore/5.2.0: + resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} + engines: {node: '>= 4'} + dev: true + + /import-fresh/3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-core-module/2.9.0: + resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} + dependencies: + has: 1.0.3 + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point/3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify/1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /kleur/4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: true + + /levn/0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lodash.merge/4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /magic-string/0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /magic-string/0.26.2: + resolution: {integrity: sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==} + engines: {node: '>=12'} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /make-dir/3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: true + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /min-indent/1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: true + + /minipass/3.3.4: + resolution: {integrity: sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: true + + /minizlib/2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.4 + yallist: 4.0.0 + dev: true + + /mkdirp/0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.6 + dev: true + + /mkdirp/1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mri/1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: true + + /mrmime/1.0.1: + resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} + engines: {node: '>=10'} + dev: true + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /nanoid/3.3.4: + resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /natural-compare/1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /node-fetch/2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + + /node-gyp-build/4.5.0: + resolution: {integrity: sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==} + hasBin: true + dev: true + + /nopt/5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npmlog/5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + dev: true + + /object-assign/4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator/0.9.1: + resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + dev: true + + /parent-module/1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-type/4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /postcss/8.4.14: + resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /prelude-ls/1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-plugin-svelte/2.7.0_o3ioganyptcsrh6x4hnxvjkpqi: + resolution: {integrity: sha512-fQhhZICprZot2IqEyoiUYLTRdumULGRvw0o4dzl5jt0jfzVWdGqeYW27QTWAeXhoupEZJULmNoH3ueJwUWFLIA==} + peerDependencies: + prettier: ^1.16.4 || ^2.0.0 + svelte: ^3.2.0 + dependencies: + prettier: 2.7.1 + svelte: 3.49.0 + dev: true + + /prettier/2.7.1: + resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /punycode/2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + dev: true + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp/3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /regexparam/2.0.1: + resolution: {integrity: sha512-zRgSaYemnNYxUv+/5SeoHI0eJIgTL/A2pUtXUPLHQxUldagouJ9p+K6IbIZ/JiQuCEv2E2B1O11SjVQy3aMCkw==} + engines: {node: '>=8'} + dev: true + + /regexpp/3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from/5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.9.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf/2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup-pluginutils/2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + dependencies: + estree-walker: 0.6.1 + dev: true + + /rollup/2.77.1: + resolution: {integrity: sha512-GhutNJrvTYD6s1moo+kyq7lD9DeR5HDyXo4bDFlDSkepC9kVKY+KK/NSZFzCmeXeia3kEzVuToQmHRdugyZHxw==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /sade/1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + dependencies: + mri: 1.2.0 + dev: true + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /sander/0.5.1: + resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} + dependencies: + es6-promise: 3.3.1 + graceful-fs: 4.2.10 + mkdirp: 0.5.6 + rimraf: 2.7.1 + dev: true + + /semver/6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + dev: true + + /semver/7.3.7: + resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /set-blocking/2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /set-cookie-parser/2.5.1: + resolution: {integrity: sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==} + dev: true + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /sorcery/0.10.0: + resolution: {integrity: sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==} + hasBin: true + dependencies: + buffer-crc32: 0.2.13 + minimist: 1.2.6 + sander: 0.5.1 + sourcemap-codec: 1.4.8 + dev: true + + /source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /sourcemap-codec/1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + dev: true + + /string-width/4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-indent/3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments/3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /svelte-check/2.8.0_svelte@3.49.0: + resolution: {integrity: sha512-HRL66BxffMAZusqe5I5k26mRWQ+BobGd9Rxm3onh7ZVu0nTk8YTKJ9vu3LVPjUGLU9IX7zS+jmwPVhJYdXJ8vg==} + hasBin: true + peerDependencies: + svelte: ^3.24.0 + dependencies: + '@jridgewell/trace-mapping': 0.3.14 + chokidar: 3.5.3 + fast-glob: 3.2.11 + import-fresh: 3.3.0 + picocolors: 1.0.0 + sade: 1.8.1 + svelte: 3.49.0 + svelte-preprocess: 4.10.7_uslzfc62di2n2otc2tvfklnwji + typescript: 4.7.4 + transitivePeerDependencies: + - '@babel/core' + - coffeescript + - less + - node-sass + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + dev: true + + /svelte-hmr/0.14.12_svelte@3.49.0: + resolution: {integrity: sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + peerDependencies: + svelte: '>=3.19.0' + dependencies: + svelte: 3.49.0 + dev: true + + /svelte-preprocess/4.10.7_uslzfc62di2n2otc2tvfklnwji: + resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==} + engines: {node: '>= 9.11.2'} + requiresBuild: true + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + node-sass: '*' + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.55.0 + sugarss: ^2.0.0 + svelte: ^3.23.0 + typescript: ^3.9.5 || ^4.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + node-sass: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + dependencies: + '@types/pug': 2.0.6 + '@types/sass': 1.43.1 + detect-indent: 6.1.0 + magic-string: 0.25.9 + sorcery: 0.10.0 + strip-indent: 3.0.0 + svelte: 3.49.0 + typescript: 4.7.4 + dev: true + + /svelte/3.49.0: + resolution: {integrity: sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==} + engines: {node: '>= 8'} + dev: true + + /tar/6.1.11: + resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} + engines: {node: '>= 10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 3.3.4 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: true + + /text-table/0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /tiny-glob/0.2.9: + resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + dev: true + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /tr46/0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true + + /tslib/1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib/2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + dev: true + + /tsutils/3.21.0_typescript@4.7.4: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 4.7.4 + dev: true + + /type-check/0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest/0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /typescript/4.7.4: + resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.1.1 + dev: true + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /v8-compile-cache/2.3.0: + resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + dev: true + + /vite/3.0.3: + resolution: {integrity: sha512-sDIpIcl3mv1NUaSzZwiXGEy1ZoWwwC2vkxUHY6yiDacR6zf//ZFuBJrozO62gedpE43pmxnLATNR5IYUdAEkMQ==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + less: '*' + sass: '*' + stylus: '*' + terser: ^5.4.0 + peerDependenciesMeta: + less: + optional: true + sass: + optional: true + stylus: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.14.50 + postcss: 8.4.14 + resolve: 1.22.1 + rollup: 2.77.1 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /webidl-conversions/3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true + + /whatwg-url/5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wide-align/1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: true + + /word-wrap/1.2.3: + resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + engines: {node: '>=0.10.0'} + dev: true + + /worktop/0.8.0-next.14: + resolution: {integrity: sha512-RZgqHu1w/JcUdWOE/BUEAzarrUUHh39eWkLdX8XpA6MfgLJF6X5Vl26CV7/wcm4O/UpZvHMGJUtB9eYTqDjc9g==} + engines: {node: '>=12'} + dependencies: + mrmime: 1.0.1 + regexparam: 2.0.1 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true diff --git a/packages/editor/src/app.d.ts b/packages/editor/src/app.d.ts new file mode 100644 index 00000000..b28d8405 --- /dev/null +++ b/packages/editor/src/app.d.ts @@ -0,0 +1,11 @@ +/// + +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +// and what to do when importing types +declare namespace App { + // interface Locals {} + // interface Platform {} + // interface Session {} + // interface Stuff {} +} diff --git a/packages/editor/src/app.html b/packages/editor/src/app.html new file mode 100644 index 00000000..5b53ef7e --- /dev/null +++ b/packages/editor/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/editor/src/hooks.ts b/packages/editor/src/hooks.ts new file mode 100644 index 00000000..f370ff45 --- /dev/null +++ b/packages/editor/src/hooks.ts @@ -0,0 +1,43 @@ +import { getGqlTypes } from '$lib/api'; +import Config from './lib/config'; + +/** @type {import('@sveltejs/kit').GetSession} */ +export function getSession(event) { + return { + ...event.locals + }; +} + +/** @type {import('@sveltejs/kit').Handle} */ +export async function handle({ event, resolve }) { + if (event.url.pathname.startsWith('/custom')) { + return new Response('custom response'); + } + + const gqlTypes = await getGqlTypes(); + const queryTypes = new Map( + await Promise.all( + gqlTypes + .get('Query') + .fields.filter((field) => field.type.kind === 'LIST') + .map(async (field) => { + field.schema = gqlTypes.get(field.type.ofType.name); + field.label = field.name + .replace(/^all/, '') + .replace(/([A-Z])/g, ' $1') + .trim(); + return [field.name, await Config.get(field.name, field)]; + }) + ).then((collections) => collections.sort((a, b) => a[1].label.localeCompare(b[1].label))) + ); + + gqlTypes.set('Query', queryTypes); + + event.locals = { + gqlTypes, + queryTypes + }; + + const response = await resolve(event); + return response; +} diff --git a/packages/editor/src/lib/JsonCrush.ts b/packages/editor/src/lib/JsonCrush.ts new file mode 100644 index 00000000..4b3d63b0 --- /dev/null +++ b/packages/editor/src/lib/JsonCrush.ts @@ -0,0 +1,10 @@ +// import JSONCrush from 'jsoncrush'; + +// export default class JsonCrush { +// static crush(obj: any) { +// return encodeURIComponent(JSONCrush.crush(JSON.stringify(obj))); +// } +// static parse(str: string) { +// return JSON.parse(JSONCrush.uncrush(str)); +// } +// } diff --git a/packages/editor/src/lib/api.ts b/packages/editor/src/lib/api.ts new file mode 100644 index 00000000..d12232af --- /dev/null +++ b/packages/editor/src/lib/api.ts @@ -0,0 +1,186 @@ +import { get } from 'svelte/store'; +import wretch from 'wretch'; +import { getStores } from '$app/stores'; +import { capitalize } from 'lodash-es'; + +const api = wretch().url('http://localhost:5057/graphql'); + +export function getSession() { + return get(getStores().session); +} + +export async function getSchema() { + const schema = await api + .post({ + query: ` + query Schema { + __schema { + types { + name + kind + description + } + } + }` + }) + .json(); + return schema.data.__schema; +} + +export async function getCollectionFields(name: string) { + const schema = await api + .post({ + query: ` + query CollectionFields { + __type(name: "${name}") { + name + description + fields { + name + description + type { + kind + name + ofType { + name + kind + } + } + } + } + } + ` + }) + .json(); + return schema.data.__type; +} + +// __schema type Query has all queries in fields, fields of type list has all collections + +export async function getGqlTypes() { + const result = await api + .post({ + query: `query CollectionFields { + __schema { + types { + name + description + kind + fields { + name + description + type { + kind + name + ofType { + name + kind + } + } + } + } + } + }` + }) + .json(); + + const types = result.data.__schema.types; + return new Map(types.map((t) => [t.name, transformSchema(t)])); +} + +function getCollectionQuery(collectionName: string, gqlTypes, depth = Infinity, visited = {}) { + const collection = gqlTypes.get(collectionName); + + return collection.fields + .map((field) => { + if (field.type.kind === 'SCALAR' || field.type.ofType?.kind === 'SCALAR') return field.name; + const kind = field.type.kind === 'LIST' ? field.type.ofType.name : field.type.name; + depth--; + if (depth < 0) return ''; + if (visited[kind]) return ''; + visited[kind] = true; + return `${field.name} { ${getCollectionQuery(kind, gqlTypes, depth, visited)} }`; + }) + .join(' '); +} + +export function sanitizeGlobImport([key, value]: [string, any]) { + return [key.replace(/^.*\//, '').replace(/\..*$/, ''), value.default]; +} + +function getFilter(filter: any) { + if (!filter) return ''; + return `(filter: ${filter})`; +} + +interface QueryCollectionArgs { + query: string; + collection: string; + depth?: number; + filter?: any; +} + +export async function queryCollection(args: QueryCollectionArgs, gqlTypes) { + const query = `{ + ${args.query}${getFilter(args.filter)} { + ${getCollectionQuery(args.collection, gqlTypes, args.depth)} + } + } + `; + + const results = await api.post({ query }).json(); + return results.data[args.query]; +} + +export function getComponentType(type) { + const { kind, name } = type; + if (kind === 'SCALAR') return name.toLowerCase(); + return kind.toLowerCase(); +} + +// sort specific fields higher than the rest, in order +const fieldSortWeights = ['name', 'title']; + +function weightedSort(a: string, b: string) { + const aw = fieldSortWeights.indexOf(a); + const bw = fieldSortWeights.indexOf(b); + if (aw < 0 && bw < 0) return undefined; + return fieldSortWeights.length - aw - (fieldSortWeights.length - bw); +} + +export function transformSchema(schema) { + const fields = + schema.fields + ?.map((field) => { + return { + label: capitalize(field.name.replace(/_+/g, ' ')).trim(), + name: field.name, + description: field.description, + type: field.type, + disabled: field.name.startsWith('_') || field.name === 'id', + component: getComponentType(field.type) + }; + }) + .sort((a, b) => { + if (a.readOnly && !b.readOnly) return 1; + if (!a.readOnly && b.readOnly) return -1; + if (a.type.kind !== 'SCALAR' && b.type.kind === 'SCALAR') return 1; + if (a.type.kind === 'SCALAR' && b.type.kind !== 'SCALAR') return -1; + + return ( + weightedSort(a.name.toLowerCase(), b.name.toLowerCase()) ?? a.name.localeCompare(b.name) + ); + }) || []; + + const referenceField = + ['name', 'title'].find((fieldName) => fields.find((field) => field.name === fieldName)) ?? 'id'; + + + const result = { + ...schema, + referenceField, + fields + }; + + return result; +} diff --git a/packages/editor/src/lib/breadcrumbs.svelte b/packages/editor/src/lib/breadcrumbs.svelte new file mode 100644 index 00000000..86f1cad0 --- /dev/null +++ b/packages/editor/src/lib/breadcrumbs.svelte @@ -0,0 +1,51 @@ + + +
+ {#if allowBack} + c.path).path} + > + + + + + {/if} + {#each breadcrumbs as crumb} + {#if crumb.path} + {crumb.label} + {:else} + {crumb.label} + {/if} + {/each} +
+ + diff --git a/packages/editor/src/lib/config.ts b/packages/editor/src/lib/config.ts new file mode 100644 index 00000000..655789fc --- /dev/null +++ b/packages/editor/src/lib/config.ts @@ -0,0 +1,66 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { isEqual, mapValues, merge } from 'lodash-es'; +import yaml from 'js-yaml'; +import crypto from 'node:crypto'; + +function replacer(key, value) { + if (key === 'type') return undefined; + if (value === null) return undefined; + if (key === 'readOnly' && value === false) return undefined; + return value; +} + +export default class Config { + static getPath(schema) { + return path.resolve( + process.cwd(), + '.flatbread', + 'schemas', + `${schema.schema.name + .replace(/([A-Z])/g, '-$1') + .replace(/^\-/, '') + .toLowerCase()}.yaml` + ); + } + static async exists(schema: string) { + try { + return await fs.stat(this.getPath(schema)); + } catch (e) { + console.log('does not exist'); + return false; + } + } + + static async get(collectionName: string, schema) { + let existing; + let filePath = this.getPath(schema); + if (await this.exists(schema)) { + const file = await fs.readFile(filePath, 'utf-8'); + existing = yaml.load(file); + merge(schema, existing); + } else { + await fs.mkdir(path.dirname(filePath), { recursive: true }); + } + + const meta = schema.meta ?? {}; + schema.meta = undefined; + meta.hash = crypto.createHmac('sha1', String(schema)).digest('base64'); + schema.meta = meta; + + if (!isEqual(existing?.meta?.hash, schema?.meta?.hash)) { + console.log('writing config', collectionName); + + await fs.writeFile( + filePath, + yaml.dump(schema, { + flowLevel: 3, + replacer + }), + 'utf-8' + ); + } + + return schema; + } +} diff --git a/packages/editor/src/lib/field-component.svelte b/packages/editor/src/lib/field-component.svelte new file mode 100644 index 00000000..83509594 --- /dev/null +++ b/packages/editor/src/lib/field-component.svelte @@ -0,0 +1,17 @@ + + +{#if !field.hidden} + +{/if} diff --git a/packages/editor/src/lib/fields/date.svelte b/packages/editor/src/lib/fields/date.svelte new file mode 100644 index 00000000..8152ab1e --- /dev/null +++ b/packages/editor/src/lib/fields/date.svelte @@ -0,0 +1,14 @@ + + + diff --git a/packages/editor/src/lib/fields/list.svelte b/packages/editor/src/lib/fields/list.svelte new file mode 100644 index 00000000..dac8a4ce --- /dev/null +++ b/packages/editor/src/lib/fields/list.svelte @@ -0,0 +1,36 @@ + + +
+ {field.label} +
+
+
+ {#each items as value} +
+ +
+ {/each} +
+
+ + diff --git a/packages/editor/src/lib/fields/object.svelte b/packages/editor/src/lib/fields/object.svelte new file mode 100644 index 00000000..6523d8e8 --- /dev/null +++ b/packages/editor/src/lib/fields/object.svelte @@ -0,0 +1,34 @@ + + +{#if !inList}
{field.label}
+
+{/if} +{#each collection.fields as field} + {#if !field.hidden} + + {/if} +{/each} +{#if !inList} +
+{/if} diff --git a/packages/editor/src/lib/fields/raw.svelte b/packages/editor/src/lib/fields/raw.svelte new file mode 100644 index 00000000..d0b3b3ab --- /dev/null +++ b/packages/editor/src/lib/fields/raw.svelte @@ -0,0 +1,15 @@ + + + diff --git a/packages/editor/src/lib/fields/string.svelte b/packages/editor/src/lib/fields/string.svelte new file mode 100644 index 00000000..21f93dad --- /dev/null +++ b/packages/editor/src/lib/fields/string.svelte @@ -0,0 +1,15 @@ + + + diff --git a/packages/editor/src/lib/schemaStore.ts b/packages/editor/src/lib/schemaStore.ts new file mode 100644 index 00000000..29a3a8ba --- /dev/null +++ b/packages/editor/src/lib/schemaStore.ts @@ -0,0 +1,5 @@ +import { get, set } from 'lodash-es'; +import { writable } from 'svelte/store'; + +export const gqlTypesStore = writable(new Map()); +export const queryTypesStore = writable(new Map()); diff --git a/packages/editor/src/routes/__layout.svelte b/packages/editor/src/routes/__layout.svelte new file mode 100644 index 00000000..805f73d1 --- /dev/null +++ b/packages/editor/src/routes/__layout.svelte @@ -0,0 +1,77 @@ + + + + + diff --git a/packages/editor/src/routes/collection/[name]/[id].svelte b/packages/editor/src/routes/collection/[name]/[id].svelte new file mode 100644 index 00000000..af07a5a8 --- /dev/null +++ b/packages/editor/src/routes/collection/[name]/[id].svelte @@ -0,0 +1,56 @@ + + + + +
+ + +
+ {#each querySchema.schema.fields as field} + + {/each} + +
diff --git a/packages/editor/src/routes/collection/[name]/index.svelte b/packages/editor/src/routes/collection/[name]/index.svelte new file mode 100644 index 00000000..fcbf705c --- /dev/null +++ b/packages/editor/src/routes/collection/[name]/index.svelte @@ -0,0 +1,66 @@ + + + + +
+ + + + {#each visibleFields as field} + + {/each} + + {#each results as row} + location.assign(`/collection/${querySchema.name}/${row.id}`)} + > + {#each visibleFields as field} + + {/each} + + {/each} +
{field.label}
+ +
+
+ + diff --git a/packages/editor/src/routes/collection/[name]/new.svelte b/packages/editor/src/routes/collection/[name]/new.svelte new file mode 100644 index 00000000..af8622e6 --- /dev/null +++ b/packages/editor/src/routes/collection/[name]/new.svelte @@ -0,0 +1,42 @@ + + + + +
+ + +
+ {#each collection.fields as field} + + {/each} + +
diff --git a/packages/editor/src/routes/index.svelte b/packages/editor/src/routes/index.svelte new file mode 100644 index 00000000..ed0f8cb0 --- /dev/null +++ b/packages/editor/src/routes/index.svelte @@ -0,0 +1,20 @@ + + +
+

Welcome to Leaven

+ +
diff --git a/packages/editor/static/favicon.png b/packages/editor/static/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097 GIT binary patch literal 1571 zcmV+;2Hg3HP)Px)-AP12RCwC$UE6KzI1p6{F2N z1VK2vi|pOpn{~#djwYcWXTI_im_u^TJgMZ4JMOsSj!0ma>B?-(Hr@X&W@|R-$}W@Z zgj#$x=!~7LGqHW?IO8+*oE1MyDp!G=L0#^lUx?;!fXv@l^6SvTnf^ac{5OurzC#ZMYc20lI%HhX816AYVs1T3heS1*WaWH z%;x>)-J}YB5#CLzU@GBR6sXYrD>Vw(Fmt#|JP;+}<#6b63Ike{Fuo!?M{yEffez;| zp!PfsuaC)>h>-AdbnwN13g*1LowNjT5?+lFVd#9$!8Z9HA|$*6dQ8EHLu}U|obW6f z2%uGv?vr=KNq7YYa2Roj;|zooo<)lf=&2yxM@e`kM$CmCR#x>gI>I|*Ubr({5Y^rb zghxQU22N}F51}^yfDSt786oMTc!W&V;d?76)9KXX1 z+6Okem(d}YXmmOiZq$!IPk5t8nnS{%?+vDFz3BevmFNgpIod~R{>@#@5x9zJKEHLHv!gHeK~n)Ld!M8DB|Kfe%~123&Hz1Z(86nU7*G5chmyDe ziV7$pB7pJ=96hpxHv9rCR29%bLOXlKU<_13_M8x)6;P8E1Kz6G<&P?$P^%c!M5`2` zfY2zg;VK5~^>TJGQzc+33-n~gKt{{of8GzUkWmU110IgI0DLxRIM>0US|TsM=L|@F z0Bun8U!cRB7-2apz=y-7*UxOxz@Z0)@QM)9wSGki1AZ38ceG7Q72z5`i;i=J`ILzL z@iUO?SBBG-0cQuo+an4TsLy-g-x;8P4UVwk|D8{W@U1Zi z!M)+jqy@nQ$p?5tsHp-6J304Q={v-B>66$P0IDx&YT(`IcZ~bZfmn11#rXd7<5s}y zBi9eim&zQc0Dk|2>$bs0PnLmDfMP5lcXRY&cvJ=zKxI^f0%-d$tD!`LBf9^jMSYUA zI8U?CWdY@}cRq6{5~y+)#h1!*-HcGW@+gZ4B};0OnC~`xQOyH19z*TA!!BJ%9s0V3F?CAJ{hTd#*tf+ur-W9MOURF-@B77_-OshsY}6 zOXRY=5%C^*26z?l)1=$bz30!so5tfABdSYzO+H=CpV~aaUefmjvfZ3Ttu9W&W3Iu6 zROlh0MFA5h;my}8lB0tAV-Rvc2Zs_CCSJnx@d`**$idgy-iMob4dJWWw|21b4NB=LfsYp0Aeh{Ov)yztQi;eL4y5 zMi>8^SzKqk8~k?UiQK^^-5d8c%bV?$F8%X~czyiaKCI2=UH=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.3.2 + globals: 13.17.0 + ignore: 5.2.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /@graphql-tools/merge/8.3.0_graphql@16.5.0: resolution: {integrity: sha512-xRa7RAQok/0DD2YnjuqikMrr7dUAxTpdGtZ7BkvUUGhYs3B3p7reCAfvOVr1DJAqVToP7hdlMk+S5+Ylk+AaqA==} peerDependencies: @@ -862,6 +930,17 @@ packages: - supports-color dev: true + /@humanwhocodes/config-array/0.9.5: + resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + /@humanwhocodes/object-schema/1.2.1: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true @@ -1287,6 +1366,10 @@ packages: typescript: 4.7.4 dev: true + /@picocss/pico/1.5.3: + resolution: {integrity: sha512-ZdZOxjlmj0BkpGpYo/ODgAcFpqIgpAACqEmIgpFtxHkam06ITfUfcj9+mPcd+Ti8Dh0KCSvHpmSnJA3+tOStlQ==} + dev: false + /@protobufjs/aspromise/1.1.2: resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} dev: false @@ -1393,63 +1476,63 @@ packages: '@sinonjs/commons': 1.8.3 dev: true - /@sveltejs/adapter-auto/1.0.0-next.63: - resolution: {integrity: sha512-9KguXwROEJMyyoKrsizAilVSmtfWxEDn2Hbxk44SP8Kj5cgN7tFCxzbL2kmmqyV1CO1tOh5iNC2oWbyTfikXmw==} + /@sveltejs/adapter-auto/1.0.0-next.64: + resolution: {integrity: sha512-Q8DwcS6wl1GovzS9JJzaD/WL/Lfk1ur4nAF1HtmsUvZDpsPBVDqnK2AhYU4G3oFNiuHstrjAogMy5th8ptSFGw==} dependencies: - '@sveltejs/adapter-cloudflare': 1.0.0-next.30 - '@sveltejs/adapter-netlify': 1.0.0-next.70 - '@sveltejs/adapter-vercel': 1.0.0-next.65 + '@sveltejs/adapter-cloudflare': 1.0.0-next.31 + '@sveltejs/adapter-netlify': 1.0.0-next.71 + '@sveltejs/adapter-vercel': 1.0.0-next.66 transitivePeerDependencies: - encoding - supports-color dev: true - /@sveltejs/adapter-cloudflare/1.0.0-next.30: - resolution: {integrity: sha512-jIclgb58n3Uoo8TTudXSa7wmLP7Rn/ESLQS+zOUe0xsti5DG/eDhELTnSvkoSa2lJY21ym5rej/GSERRyeuBVw==} + /@sveltejs/adapter-cloudflare/1.0.0-next.31: + resolution: {integrity: sha512-HhEFZP72GJ8AZGgFECKIiayDcLaAWi65pI0AnBfiNhCifYSlH/mPNWNVD4AWRDnXnH6XU+FLwhGDnIDwytTyYg==} dependencies: '@cloudflare/workers-types': 3.14.1 - esbuild: 0.14.49 + esbuild: 0.14.51 worktop: 0.8.0-next.14 dev: true - /@sveltejs/adapter-netlify/1.0.0-next.70: - resolution: {integrity: sha512-lIXY6KIgIFBz4+mdvilx9Ny8oFV7T2iVTKLirJayoI/SqPWGAcxklvWvjGfS4QT8rS9pWKDaKRUQM4M/gl8LlA==} + /@sveltejs/adapter-netlify/1.0.0-next.71: + resolution: {integrity: sha512-la1CGtWO1xul1L3zEoFAoc4EX2uxZjrZcOMS3tkKB8drxhbQsNbnTE6fmSSMFiZXhxaikczrBgQwqIaDkLTmZg==} dependencies: '@iarna/toml': 2.2.5 - esbuild: 0.14.49 - set-cookie-parser: 2.5.0 + esbuild: 0.14.51 + set-cookie-parser: 2.5.1 tiny-glob: 0.2.9 dev: true - /@sveltejs/adapter-vercel/1.0.0-next.65: - resolution: {integrity: sha512-RV3HL7Ic7pGgIoBSHPwN1pBX96Km1X683oHImPHAKX9h/WOvJZ3bY5+IWNRcR8tx9rPB5gfMRg+msvPSBr3RVw==} + /@sveltejs/adapter-vercel/1.0.0-next.66: + resolution: {integrity: sha512-s3Hcxu9nCG/rR3C3cFbdQGjTa5W4K2kRcc6S5Xefx7itbrw+4v3KpO8ZPB6qM55XDwVxuG7260NMHVI6MUGmSA==} dependencies: - '@vercel/nft': 0.20.1 - esbuild: 0.14.49 + '@vercel/nft': 0.21.0 + esbuild: 0.14.51 transitivePeerDependencies: - encoding - supports-color dev: true - /@sveltejs/kit/1.0.0-next.392_svelte@3.49.0+vite@3.0.0: - resolution: {integrity: sha512-od4rDJ/Soq0I7mda7sTbAnNKERHSDEGNa7QBpLA859xgBkwC1JnEIymYOh9dm+hMyHhB0bUoRoaur0qxKLqOOw==} + /@sveltejs/kit/1.0.0-next.396_svelte@3.49.0+vite@3.0.3: + resolution: {integrity: sha512-bKFpuzp9QxPkOIOEIeNeedvxEMORNqBPxUmoJXDP/Se7MrSfcxYiamjBcKrG+bgGNWmV39nD3EvUox+CXno/Ig==} engines: {node: '>=16.9'} hasBin: true peerDependencies: svelte: ^3.44.0 vite: ^3.0.0 dependencies: - '@sveltejs/vite-plugin-svelte': 1.0.1_svelte@3.49.0+vite@3.0.0 + '@sveltejs/vite-plugin-svelte': 1.0.1_svelte@3.49.0+vite@3.0.3 chokidar: 3.5.3 sade: 1.8.1 svelte: 3.49.0 - vite: 3.0.0 + vite: 3.0.3_sass@1.54.0 transitivePeerDependencies: - diff-match-patch - supports-color dev: true - /@sveltejs/vite-plugin-svelte/1.0.1_svelte@3.49.0+vite@3.0.0: + /@sveltejs/vite-plugin-svelte/1.0.1_svelte@3.49.0+vite@3.0.3: resolution: {integrity: sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==} engines: {node: ^14.18.0 || >= 16} peerDependencies: @@ -1467,7 +1550,7 @@ packages: magic-string: 0.26.2 svelte: 3.49.0 svelte-hmr: 0.14.12_svelte@3.49.0 - vite: 3.0.0 + vite: 3.0.3_sass@1.54.0 transitivePeerDependencies: - supports-color dev: true @@ -1603,7 +1686,6 @@ packages: /@types/js-yaml/4.0.5: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} - dev: true /@types/json-schema/7.0.11: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} @@ -1617,11 +1699,9 @@ packages: resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==} dependencies: '@types/lodash': 4.14.182 - dev: true /@types/lodash/4.14.182: resolution: {integrity: sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==} - dev: true /@types/long/4.0.2: resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} @@ -1659,6 +1739,10 @@ packages: /@types/node/16.11.45: resolution: {integrity: sha512-3rKg/L5x0rofKuuUt5zlXzOnKyIHXmIu5R8A0TuNDMF2062/AOIDBciFIjToLEJ/9F9DzkHNot+BpNsMI1OLdQ==} + /@types/node/18.6.2: + resolution: {integrity: sha512-KcfkBq9H4PI6Vpu5B/KoPeuVDAbmi+2mDBqGPGUgoL7yXQtcWGu2vJWmmRkneWK3Rh0nIAX192Aa87AqKHYChQ==} + dev: true + /@types/parse5/6.0.3: resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} dev: false @@ -1698,7 +1782,7 @@ packages: /@types/sass/1.43.1: resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} dependencies: - '@types/node': 16.11.45 + '@types/node': 18.6.2 dev: true /@types/serialize-javascript/5.0.2: @@ -1757,6 +1841,33 @@ packages: - supports-color dev: true + /@typescript-eslint/eslint-plugin/5.31.0_d5zwcxr4bwkhmuo464cb3a2puu: + resolution: {integrity: sha512-VKW4JPHzG5yhYQrQ1AzXgVgX8ZAJEvCz0QI6mLRX4tf7rnFfh5D8SKm0Pq6w5PyNfAWJk6sv313+nEt3ohWMBQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/parser': 5.31.0_he2ccbldppg44uulnyq4rwocfa + '@typescript-eslint/scope-manager': 5.31.0 + '@typescript-eslint/type-utils': 5.31.0_he2ccbldppg44uulnyq4rwocfa + '@typescript-eslint/utils': 5.31.0_he2ccbldppg44uulnyq4rwocfa + debug: 4.3.4 + eslint: 8.20.0 + functional-red-black-tree: 1.0.1 + ignore: 5.2.0 + regexpp: 3.2.0 + semver: 7.3.7 + tsutils: 3.21.0_typescript@4.7.4 + typescript: 4.7.4 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/experimental-utils/4.33.0_hxadhbs2xogijvk7vq4t2azzbu: resolution: {integrity: sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==} engines: {node: ^10.12.0 || >=12.0.0} @@ -1795,6 +1906,26 @@ packages: - supports-color dev: true + /@typescript-eslint/parser/5.31.0_he2ccbldppg44uulnyq4rwocfa: + resolution: {integrity: sha512-UStjQiZ9OFTFReTrN+iGrC6O/ko9LVDhreEK5S3edmXgR396JGq7CoX2TWIptqt/ESzU2iRKXAHfSF2WJFcWHw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.31.0 + '@typescript-eslint/types': 5.31.0 + '@typescript-eslint/typescript-estree': 5.31.0_typescript@4.7.4 + debug: 4.3.4 + eslint: 8.20.0 + typescript: 4.7.4 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/scope-manager/4.33.0: resolution: {integrity: sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} @@ -1803,11 +1934,43 @@ packages: '@typescript-eslint/visitor-keys': 4.33.0 dev: true + /@typescript-eslint/scope-manager/5.31.0: + resolution: {integrity: sha512-8jfEzBYDBG88rcXFxajdVavGxb5/XKXyvWgvD8Qix3EEJLCFIdVloJw+r9ww0wbyNLOTYyBsR+4ALNGdlalLLg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.31.0 + '@typescript-eslint/visitor-keys': 5.31.0 + dev: true + + /@typescript-eslint/type-utils/5.31.0_he2ccbldppg44uulnyq4rwocfa: + resolution: {integrity: sha512-7ZYqFbvEvYXFn9ax02GsPcEOmuWNg+14HIf4q+oUuLnMbpJ6eHAivCg7tZMVwzrIuzX3QCeAOqKoyMZCv5xe+w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/utils': 5.31.0_he2ccbldppg44uulnyq4rwocfa + debug: 4.3.4 + eslint: 8.20.0 + tsutils: 3.21.0_typescript@4.7.4 + typescript: 4.7.4 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/types/4.33.0: resolution: {integrity: sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} dev: true + /@typescript-eslint/types/5.31.0: + resolution: {integrity: sha512-/f/rMaEseux+I4wmR6mfpM2wvtNZb1p9hAV77hWfuKc3pmaANp5dLAZSiE3/8oXTYTt3uV9KW5yZKJsMievp6g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /@typescript-eslint/typescript-estree/4.33.0_typescript@4.7.4: resolution: {integrity: sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==} engines: {node: ^10.12.0 || >=12.0.0} @@ -1829,6 +1992,45 @@ packages: - supports-color dev: true + /@typescript-eslint/typescript-estree/5.31.0_typescript@4.7.4: + resolution: {integrity: sha512-3S625TMcARX71wBc2qubHaoUwMEn+l9TCsaIzYI/ET31Xm2c9YQ+zhGgpydjorwQO9pLfR/6peTzS/0G3J/hDw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.31.0 + '@typescript-eslint/visitor-keys': 5.31.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.3.7 + tsutils: 3.21.0_typescript@4.7.4 + typescript: 4.7.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils/5.31.0_he2ccbldppg44uulnyq4rwocfa: + resolution: {integrity: sha512-kcVPdQS6VIpVTQ7QnGNKMFtdJdvnStkqS5LeALr4rcwx11G6OWb2HB17NMPnlRHvaZP38hL9iK8DdE9Fne7NYg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@types/json-schema': 7.0.11 + '@typescript-eslint/scope-manager': 5.31.0 + '@typescript-eslint/types': 5.31.0 + '@typescript-eslint/typescript-estree': 5.31.0_typescript@4.7.4 + eslint: 8.20.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0_eslint@8.20.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/visitor-keys/4.33.0: resolution: {integrity: sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} @@ -1837,15 +2039,24 @@ packages: eslint-visitor-keys: 2.1.0 dev: true - /@vercel/nft/0.20.1: - resolution: {integrity: sha512-hSLcr64KHOkcNiTAlv154K4p4faEFBwYIi2eIgu1QCDhB1qyQYvFuEhtw3eaapNjA4/7x/2jcclfCAjILua/ag==} + /@typescript-eslint/visitor-keys/5.31.0: + resolution: {integrity: sha512-ZK0jVxSjS4gnPirpVjXHz7mgdOsZUHzNYSfTw2yPa3agfbt9YfqaBiBZFSSxeBWnpWkzCxTfUpnzA3Vily/CSg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.31.0 + eslint-visitor-keys: 3.3.0 + dev: true + + /@vercel/nft/0.21.0: + resolution: {integrity: sha512-hFCAETfI5cG8l5iAiLhMC2bReC5K7SIybzrxGorv+eGspIbIFsVw7Vg85GovXm/LxA08pIDrAlrhR6GN36XB/Q==} hasBin: true dependencies: '@mapbox/node-pre-gyp': 1.0.9 - acorn: 8.7.1 + acorn: 8.8.0 + async-sema: 3.1.1 bindings: 1.5.0 estree-walker: 2.0.2 - glob: 7.1.6 + glob: 7.2.3 graceful-fs: 4.2.10 micromatch: 4.0.5 node-gyp-build: 4.5.0 @@ -1887,6 +2098,14 @@ packages: acorn: 7.4.1 dev: true + /acorn-jsx/5.3.2_acorn@8.8.0: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.0 + dev: true + /acorn-node/1.8.2: resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==} dependencies: @@ -1917,6 +2136,12 @@ packages: hasBin: true dev: true + /acorn/8.8.0: + resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + /agent-base/6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -2204,6 +2429,10 @@ packages: retry: 0.13.1 dev: false + /async-sema/3.1.1: + resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} + dev: true + /async/3.2.4: resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} dev: true @@ -2896,6 +3125,11 @@ packages: array-find-index: 1.0.2 dev: true + /data-uri-to-buffer/4.0.0: + resolution: {integrity: sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==} + engines: {node: '>= 12'} + dev: false + /data-urls/2.0.0: resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} engines: {node: '>=10'} @@ -3199,6 +3433,15 @@ packages: dev: true optional: true + /esbuild-android-64/0.14.51: + resolution: {integrity: sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /esbuild-android-arm64/0.13.15: resolution: {integrity: sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==} cpu: [arm64] @@ -3216,6 +3459,15 @@ packages: dev: true optional: true + /esbuild-android-arm64/0.14.51: + resolution: {integrity: sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /esbuild-darwin-64/0.13.15: resolution: {integrity: sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==} cpu: [x64] @@ -3233,6 +3485,15 @@ packages: dev: true optional: true + /esbuild-darwin-64/0.14.51: + resolution: {integrity: sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /esbuild-darwin-arm64/0.13.15: resolution: {integrity: sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==} cpu: [arm64] @@ -3250,6 +3511,15 @@ packages: dev: true optional: true + /esbuild-darwin-arm64/0.14.51: + resolution: {integrity: sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /esbuild-freebsd-64/0.13.15: resolution: {integrity: sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==} cpu: [x64] @@ -3267,6 +3537,15 @@ packages: dev: true optional: true + /esbuild-freebsd-64/0.14.51: + resolution: {integrity: sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /esbuild-freebsd-arm64/0.13.15: resolution: {integrity: sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==} cpu: [arm64] @@ -3284,6 +3563,15 @@ packages: dev: true optional: true + /esbuild-freebsd-arm64/0.14.51: + resolution: {integrity: sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /esbuild-linux-32/0.13.15: resolution: {integrity: sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==} cpu: [ia32] @@ -3301,6 +3589,15 @@ packages: dev: true optional: true + /esbuild-linux-32/0.14.51: + resolution: {integrity: sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /esbuild-linux-64/0.13.15: resolution: {integrity: sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==} cpu: [x64] @@ -3318,6 +3615,15 @@ packages: dev: true optional: true + /esbuild-linux-64/0.14.51: + resolution: {integrity: sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /esbuild-linux-arm/0.13.15: resolution: {integrity: sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==} cpu: [arm] @@ -3335,6 +3641,15 @@ packages: dev: true optional: true + /esbuild-linux-arm/0.14.51: + resolution: {integrity: sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /esbuild-linux-arm64/0.13.15: resolution: {integrity: sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==} cpu: [arm64] @@ -3352,6 +3667,15 @@ packages: dev: true optional: true + /esbuild-linux-arm64/0.14.51: + resolution: {integrity: sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /esbuild-linux-mips64le/0.13.15: resolution: {integrity: sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==} cpu: [mips64el] @@ -3369,6 +3693,15 @@ packages: dev: true optional: true + /esbuild-linux-mips64le/0.14.51: + resolution: {integrity: sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /esbuild-linux-ppc64le/0.13.15: resolution: {integrity: sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==} cpu: [ppc64] @@ -3386,6 +3719,15 @@ packages: dev: true optional: true + /esbuild-linux-ppc64le/0.14.51: + resolution: {integrity: sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /esbuild-linux-riscv64/0.14.49: resolution: {integrity: sha512-h66ORBz+Dg+1KgLvzTVQEA1LX4XBd1SK0Fgbhhw4akpG/YkN8pS6OzYI/7SGENiN6ao5hETRDSkVcvU9NRtkMQ==} engines: {node: '>=12'} @@ -3395,6 +3737,15 @@ packages: dev: true optional: true + /esbuild-linux-riscv64/0.14.51: + resolution: {integrity: sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /esbuild-linux-s390x/0.14.49: resolution: {integrity: sha512-DhrUoFVWD+XmKO1y7e4kNCqQHPs6twz6VV6Uezl/XHYGzM60rBewBF5jlZjG0nCk5W/Xy6y1xWeopkrhFFM0sQ==} engines: {node: '>=12'} @@ -3404,6 +3755,15 @@ packages: dev: true optional: true + /esbuild-linux-s390x/0.14.51: + resolution: {integrity: sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /esbuild-netbsd-64/0.13.15: resolution: {integrity: sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==} cpu: [x64] @@ -3421,6 +3781,15 @@ packages: dev: true optional: true + /esbuild-netbsd-64/0.14.51: + resolution: {integrity: sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /esbuild-openbsd-64/0.13.15: resolution: {integrity: sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==} cpu: [x64] @@ -3438,6 +3807,15 @@ packages: dev: true optional: true + /esbuild-openbsd-64/0.14.51: + resolution: {integrity: sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /esbuild-sunos-64/0.13.15: resolution: {integrity: sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==} cpu: [x64] @@ -3455,6 +3833,15 @@ packages: dev: true optional: true + /esbuild-sunos-64/0.14.51: + resolution: {integrity: sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /esbuild-windows-32/0.13.15: resolution: {integrity: sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==} cpu: [ia32] @@ -3472,6 +3859,15 @@ packages: dev: true optional: true + /esbuild-windows-32/0.14.51: + resolution: {integrity: sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /esbuild-windows-64/0.13.15: resolution: {integrity: sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==} cpu: [x64] @@ -3489,6 +3885,15 @@ packages: dev: true optional: true + /esbuild-windows-64/0.14.51: + resolution: {integrity: sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /esbuild-windows-arm64/0.13.15: resolution: {integrity: sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==} cpu: [arm64] @@ -3506,6 +3911,15 @@ packages: dev: true optional: true + /esbuild-windows-arm64/0.14.51: + resolution: {integrity: sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /esbuild/0.13.15: resolution: {integrity: sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==} hasBin: true @@ -3558,6 +3972,34 @@ packages: esbuild-windows-arm64: 0.14.49 dev: true + /esbuild/0.14.51: + resolution: {integrity: sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + esbuild-android-64: 0.14.51 + esbuild-android-arm64: 0.14.51 + esbuild-darwin-64: 0.14.51 + esbuild-darwin-arm64: 0.14.51 + esbuild-freebsd-64: 0.14.51 + esbuild-freebsd-arm64: 0.14.51 + esbuild-linux-32: 0.14.51 + esbuild-linux-64: 0.14.51 + esbuild-linux-arm: 0.14.51 + esbuild-linux-arm64: 0.14.51 + esbuild-linux-mips64le: 0.14.51 + esbuild-linux-ppc64le: 0.14.51 + esbuild-linux-riscv64: 0.14.51 + esbuild-linux-s390x: 0.14.51 + esbuild-netbsd-64: 0.14.51 + esbuild-openbsd-64: 0.14.51 + esbuild-sunos-64: 0.14.51 + esbuild-windows-32: 0.14.51 + esbuild-windows-64: 0.14.51 + esbuild-windows-arm64: 0.14.51 + dev: true + /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -3607,6 +4049,15 @@ packages: eslint: 7.32.0 dev: true + /eslint-config-prettier/8.5.0_eslint@8.20.0: + resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.20.0 + dev: true + /eslint-plugin-svelte3/3.4.1_k4rvtr32uzrs6rwp57u73ssa6q: resolution: {integrity: sha512-7p59WG8qV8L6wLdl4d/c3mdjkgVglQCdv5XOTk/iNPBKXuuV+Q0eFP5Wa6iJd/G2M1qR3BkLPEzaANOqKAZczw==} engines: {node: '>=10'} @@ -3618,6 +4069,16 @@ packages: svelte: 3.49.0 dev: true + /eslint-plugin-svelte3/4.0.0_piwa6j2njmnknm35bh3wz5v52y: + resolution: {integrity: sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==} + peerDependencies: + eslint: '>=8.0.0' + svelte: ^3.2.0 + dependencies: + eslint: 8.20.0 + svelte: 3.49.0 + dev: true + /eslint-scope/5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -3626,6 +4087,14 @@ packages: estraverse: 4.3.0 dev: true + /eslint-scope/7.1.1: + resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + /eslint-utils/2.1.0: resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} engines: {node: '>=6'} @@ -3643,6 +4112,16 @@ packages: eslint-visitor-keys: 2.1.0 dev: true + /eslint-utils/3.0.0_eslint@8.20.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.20.0 + eslint-visitor-keys: 2.1.0 + dev: true + /eslint-visitor-keys/1.3.0: resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} engines: {node: '>=4'} @@ -3653,6 +4132,11 @@ packages: engines: {node: '>=10'} dev: true + /eslint-visitor-keys/3.3.0: + resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /eslint/7.32.0: resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3702,6 +4186,50 @@ packages: - supports-color dev: true + /eslint/8.20.0: + resolution: {integrity: sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint/eslintrc': 1.3.0 + '@humanwhocodes/config-array': 0.9.5 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.1.1 + eslint-utils: 3.0.0_eslint@8.20.0 + eslint-visitor-keys: 3.3.0 + espree: 9.3.2 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 6.0.2 + globals: 13.17.0 + ignore: 5.2.0 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + regexpp: 3.2.0 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + v8-compile-cache: 2.3.0 + transitivePeerDependencies: + - supports-color + dev: true + /esno/0.16.3: resolution: {integrity: sha512-6slSBEV1lMKcX13DBifvnDFpNno5WXhw4j/ff7RI0y51BZiDqEe5dNhhjhIQ3iCOQuzsm2MbVzmwqbN78BBhPg==} hasBin: true @@ -3718,6 +4246,15 @@ packages: eslint-visitor-keys: 1.3.0 dev: true + /espree/9.3.2: + resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.0 + acorn-jsx: 5.3.2_acorn@8.8.0 + eslint-visitor-keys: 3.3.0 + dev: true + /esprima/4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} @@ -3940,6 +4477,14 @@ packages: bser: 2.1.1 dev: true + /fetch-blob/3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.2.1 + dev: false + /figures/3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -4052,6 +4597,13 @@ packages: engines: {node: '>=0.4.x'} dev: false + /formdata-polyfill/4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + dependencies: + fetch-blob: 3.2.0 + dev: false + /forwarded/0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -4204,6 +4756,17 @@ packages: path-is-absolute: 1.0.1 dev: true + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + /globals/11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -4216,6 +4779,13 @@ packages: type-fest: 0.20.2 dev: true + /globals/13.17.0: + resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + /globalyzer/0.1.0: resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} dev: true @@ -4559,6 +5129,10 @@ packages: engines: {node: '>= 4'} dev: true + /immutable/4.1.0: + resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==} + dev: true + /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -6056,6 +6630,11 @@ packages: resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} dev: true + /node-domexception/1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: false + /node-emoji/1.11.0: resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} dependencies: @@ -6073,6 +6652,15 @@ packages: dependencies: whatwg-url: 5.0.0 + /node-fetch/3.2.9: + resolution: {integrity: sha512-/2lI+DBecVvVm9tDhjziTVjo2wmTsSxSk58saUYP0P/fRJ3xxtfMDY24+CKTkfm0Dlhyn3CSXNL0SoRiCZ8Rzg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + data-uri-to-buffer: 4.0.0 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + dev: false + /node-gyp-build/4.5.0: resolution: {integrity: sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==} hasBin: true @@ -6535,6 +7123,16 @@ packages: svelte: 3.49.0 dev: true + /prettier-plugin-svelte/2.7.0_o3ioganyptcsrh6x4hnxvjkpqi: + resolution: {integrity: sha512-fQhhZICprZot2IqEyoiUYLTRdumULGRvw0o4dzl5jt0jfzVWdGqeYW27QTWAeXhoupEZJULmNoH3ueJwUWFLIA==} + peerDependencies: + prettier: ^1.16.4 || ^2.0.0 + svelte: ^3.2.0 + dependencies: + prettier: 2.7.1 + svelte: 3.49.0 + dev: true + /prettier/2.4.1: resolution: {integrity: sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==} engines: {node: '>=10.13.0'} @@ -6899,14 +7497,14 @@ packages: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true dependencies: - glob: 7.1.6 + glob: 7.2.3 dev: true /rimraf/3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: - glob: 7.1.6 + glob: 7.2.3 dev: true /rollup-pluginutils/2.8.2: @@ -6923,6 +7521,14 @@ packages: fsevents: 2.3.2 dev: true + /rollup/2.77.2: + resolution: {integrity: sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + /run-parallel/1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -6972,6 +7578,16 @@ packages: postcss: 8.4.14 dev: false + /sass/1.54.0: + resolution: {integrity: sha512-C4zp79GCXZfK0yoHZg+GxF818/aclhp9F48XBu/+bm9vXEVAYov9iU3FBVRMq3Hx3OA4jfKL+p2K9180mEh0xQ==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.1.0 + source-map-js: 1.0.2 + dev: true + /saxes/5.0.1: resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} engines: {node: '>=10'} @@ -7058,8 +7674,8 @@ packages: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true - /set-cookie-parser/2.5.0: - resolution: {integrity: sha512-cHMAtSXilfyBePduZEBVPTCftTQWz6ehWJD5YNUg4mqvRosrrjKbo4WS8JkB0/RxonMoohHm7cOGH60mDkRQ9w==} + /set-cookie-parser/2.5.1: + resolution: {integrity: sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==} dev: true /setprototypeof/1.2.0: @@ -7376,6 +7992,34 @@ packages: - sugarss dev: true + /svelte-check/2.8.0_sass@1.54.0+svelte@3.49.0: + resolution: {integrity: sha512-HRL66BxffMAZusqe5I5k26mRWQ+BobGd9Rxm3onh7ZVu0nTk8YTKJ9vu3LVPjUGLU9IX7zS+jmwPVhJYdXJ8vg==} + hasBin: true + peerDependencies: + svelte: ^3.24.0 + dependencies: + '@jridgewell/trace-mapping': 0.3.14 + chokidar: 3.5.3 + fast-glob: 3.2.11 + import-fresh: 3.3.0 + picocolors: 1.0.0 + sade: 1.8.1 + svelte: 3.49.0 + svelte-preprocess: 4.10.7_qqyngjnvpp2z5rj6eppfx7s47e + typescript: 4.7.4 + transitivePeerDependencies: + - '@babel/core' + - coffeescript + - less + - node-sass + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + dev: true + /svelte-hmr/0.14.12_svelte@3.49.0: resolution: {integrity: sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==} engines: {node: ^12.20 || ^14.13.1 || >= 16} @@ -7437,6 +8081,58 @@ packages: typescript: 4.7.4 dev: true + /svelte-preprocess/4.10.7_qqyngjnvpp2z5rj6eppfx7s47e: + resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==} + engines: {node: '>= 9.11.2'} + requiresBuild: true + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + node-sass: '*' + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.55.0 + sugarss: ^2.0.0 + svelte: ^3.23.0 + typescript: ^3.9.5 || ^4.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + node-sass: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + dependencies: + '@types/pug': 2.0.6 + '@types/sass': 1.43.1 + detect-indent: 6.1.0 + magic-string: 0.25.9 + sass: 1.54.0 + sorcery: 0.10.0 + strip-indent: 3.0.0 + svelte: 3.49.0 + typescript: 4.7.4 + dev: true + /svelte/3.49.0: resolution: {integrity: sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==} engines: {node: '>= 8'} @@ -8072,9 +8768,9 @@ packages: resolution: {integrity: sha512-6MTHB7J7HKILXTBTENhc378zrm75wWR+8ZHYKLVq02tsaXlnoGG8aFhZOtDWthNkGCNAcp31epAc/HiSzPwFbg==} dev: true - /vite/3.0.0: - resolution: {integrity: sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==} - engines: {node: '>=14.18.0'} + /vite/3.0.3_sass@1.54.0: + resolution: {integrity: sha512-sDIpIcl3mv1NUaSzZwiXGEy1ZoWwwC2vkxUHY6yiDacR6zf//ZFuBJrozO62gedpE43pmxnLATNR5IYUdAEkMQ==} + engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: less: '*' @@ -8091,10 +8787,11 @@ packages: terser: optional: true dependencies: - esbuild: 0.14.49 + esbuild: 0.14.51 postcss: 8.4.14 resolve: 1.22.1 - rollup: 2.77.0 + rollup: 2.77.2 + sass: 1.54.0 optionalDependencies: fsevents: 2.3.2 dev: true @@ -8122,6 +8819,11 @@ packages: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} dev: false + /web-streams-polyfill/3.2.1: + resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} + engines: {node: '>= 8'} + dev: false + /webidl-conversions/3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -8222,6 +8924,10 @@ packages: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true + /wretch/1.7.10: + resolution: {integrity: sha512-UgF2o63bZRsz3LoOxaxzAUdFdlIJzVYbCHHhQ+LNMSBD1FeFJn8ADaekopJclHUm6sN8Lhu0DQFGQloliS0Twg==} + dev: false + /write-file-atomic/3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} dependencies: From 4154b261acb6affdaad2cbc01f56bc868af41978 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Fri, 29 Jul 2022 18:58:44 -0500 Subject: [PATCH 02/26] wip --- .../editor/.flatbread/schemas/author.yaml | 36 ++++++++++++------- .../.flatbread/schemas/override-test.yaml | 32 ++++++++++------- .../schemas/post-category-blob.yaml | 30 +++++++++++----- .../.flatbread/schemas/post-category.yaml | 34 ++++++++++++------ packages/editor/.flatbread/schemas/post.yaml | 30 +++++++++++----- .../.flatbread/schemas/yaml-author.yaml | 34 ++++++++++++------ packages/editor/src/lib/api.ts | 28 ++++++++++----- .../editor/src/lib/field-component.svelte | 2 +- packages/editor/src/lib/fields/object.svelte | 11 ++++-- .../src/routes/collection/[name]/[id].svelte | 4 +-- packages/editor/tsconfig.json | 6 ++-- playground/src/routes/index.svelte | 4 +-- 12 files changed, 166 insertions(+), 85 deletions(-) diff --git a/packages/editor/.flatbread/schemas/author.yaml b/packages/editor/.flatbread/schemas/author.yaml index c5762bb7..cedf9a69 100644 --- a/packages/editor/.flatbread/schemas/author.yaml +++ b/packages/editor/.flatbread/schemas/author.yaml @@ -7,18 +7,30 @@ schema: name: Author kind: OBJECT fields: - - {label: Name, name: name, disabled: false, component: string} - - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} - - {label: filename, name: _filename, disabled: true, component: string} - - {label: path, name: _path, disabled: true, component: string} - - {label: slug, name: _slug, disabled: true, component: string} - - {label: Date joined, name: date_joined, disabled: false, component: date} - - {label: Entity, name: entity, disabled: false, component: string} - - {label: Id, name: id, disabled: true, component: string} - - {label: content, name: _content, disabled: true, component: object} - - {label: Enjoys, name: enjoys, disabled: false, component: list} - - {label: Friend, name: friend, description: The Author referenced by this Author, disabled: false, component: object} - - {label: Skills, name: skills, disabled: false, component: object} + - { label: Name, name: name, disabled: false, component: string } + - { + label: collection, + name: _collection, + description: The collection name, + disabled: true, + component: string + } + - { label: filename, name: _filename, hidden: true, disabled: true, component: string } + - { label: path, name: _path, disabled: true, component: string } + - { label: slug, name: _slug, disabled: true, component: string } + - { label: Date joined, name: date_joined, disabled: false, component: date } + - { label: Entity, name: entity, disabled: false, component: string } + - { label: Id, name: id, disabled: true, component: string } + - { label: content, hidden: true, name: _content, disabled: true, component: object } + - { label: Enjoys, name: enjoys, disabled: false, component: list } + - { + label: Friend, + name: friend, + description: The Author referenced by this Author, + disabled: false, + component: object + } + - { label: Skills, name: skills, disabled: false, component: object } referenceField: name meta: hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/override-test.yaml b/packages/editor/.flatbread/schemas/override-test.yaml index 9a7c5a76..4a5abf08 100644 --- a/packages/editor/.flatbread/schemas/override-test.yaml +++ b/packages/editor/.flatbread/schemas/override-test.yaml @@ -7,19 +7,25 @@ schema: name: OverrideTest kind: OBJECT fields: - - {label: Title, name: title, disabled: false, component: string} - - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} - - {label: filename, name: _filename, disabled: true, component: string} - - {label: path, name: _path, disabled: true, component: string} - - {label: slug, name: _slug, disabled: true, component: string} - - {label: Id, name: id, disabled: true, component: string} - - {label: content, name: _content, disabled: true, component: object} - - {label: Array, name: array, disabled: false, component: list} - - {label: Array2, name: array2, disabled: false, component: list} - - {label: Array3, name: array3, disabled: false, component: list} - - {label: Deeply, name: deeply, disabled: false, component: object} - - {label: Image, name: image, disabled: false, component: object} - - {label: Image2, name: image2, disabled: false, component: object} + - { label: Title, name: title, disabled: false, component: string } + - { + label: collection, + name: _collection, + description: The collection name, + disabled: true, + component: string + } + - { label: filename, name: _filename, disabled: true, component: string } + - { label: path, name: _path, disabled: true, component: string } + - { label: slug, name: _slug, disabled: true, component: string } + - { label: Id, name: id, disabled: true, component: string } + - { label: content, name: _content, disabled: true, component: object } + - { label: Array, name: array, disabled: false, component: list } + - { label: Array2, name: array2, disabled: false, component: list } + - { label: Array3, name: array3, disabled: false, component: list } + - { label: Deeply, name: deeply, disabled: false, component: object } + - { label: Image, name: image, disabled: false, component: object } + - { label: Image2, name: image2, disabled: false, component: object } referenceField: title meta: hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/post-category-blob.yaml b/packages/editor/.flatbread/schemas/post-category-blob.yaml index 2746078c..70b4277d 100644 --- a/packages/editor/.flatbread/schemas/post-category-blob.yaml +++ b/packages/editor/.flatbread/schemas/post-category-blob.yaml @@ -7,15 +7,27 @@ schema: name: PostCategoryBlob kind: OBJECT fields: - - {label: Title, name: title, disabled: false, component: string} - - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} - - {label: filename, name: _filename, disabled: true, component: string} - - {label: path, name: _path, disabled: true, component: string} - - {label: slug, name: _slug, disabled: true, component: string} - - {label: Id, name: id, disabled: true, component: string} - - {label: Rating, name: rating, disabled: false, component: float} - - {label: content, name: _content, disabled: true, component: object} - - {label: Authors, name: authors, description: All Authors that are referenced by this PostCategoryBlob, disabled: false, component: list} + - { label: Title, name: title, disabled: false, component: string } + - { + label: collection, + name: _collection, + description: The collection name, + disabled: true, + component: string + } + - { label: filename, name: _filename, disabled: true, component: string } + - { label: path, name: _path, disabled: true, component: string } + - { label: slug, name: _slug, disabled: true, component: string } + - { label: Id, name: id, disabled: true, component: string } + - { label: Rating, name: rating, disabled: false, component: float } + - { label: content, name: _content, disabled: true, component: object } + - { + label: Authors, + name: authors, + description: All Authors that are referenced by this PostCategoryBlob, + disabled: false, + component: list + } referenceField: title meta: hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/post-category.yaml b/packages/editor/.flatbread/schemas/post-category.yaml index dda48b16..9d0c4e01 100644 --- a/packages/editor/.flatbread/schemas/post-category.yaml +++ b/packages/editor/.flatbread/schemas/post-category.yaml @@ -7,17 +7,29 @@ schema: name: PostCategory kind: OBJECT fields: - - {label: Title, name: title, disabled: false, component: string} - - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} - - {label: filename, name: _filename, disabled: true, component: string} - - {label: path, name: _path, disabled: true, component: string} - - {label: slug, name: _slug, disabled: true, component: string} - - {label: Category, name: category, disabled: false, component: string} - - {label: Id, name: id, disabled: true, component: string} - - {label: Rating, name: rating, disabled: false, component: float} - - {label: Slug, name: slug, disabled: false, component: string} - - {label: content, name: _content, disabled: true, component: object} - - {label: Authors, name: authors, description: All Authors that are referenced by this PostCategory, disabled: false, component: list} + - { label: Title, name: title, disabled: false, component: string } + - { + label: collection, + name: _collection, + description: The collection name, + disabled: true, + component: string + } + - { label: filename, name: _filename, disabled: true, component: string } + - { label: path, name: _path, disabled: true, component: string } + - { label: slug, name: _slug, disabled: true, component: string } + - { label: Category, name: category, disabled: false, component: string } + - { label: Id, name: id, disabled: true, component: string } + - { label: Rating, name: rating, disabled: false, component: float } + - { label: Slug, name: slug, disabled: false, component: string } + - { label: content, name: _content, disabled: true, component: object } + - { + label: Authors, + name: authors, + description: All Authors that are referenced by this PostCategory, + disabled: false, + component: list + } referenceField: title meta: hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/post.yaml b/packages/editor/.flatbread/schemas/post.yaml index 6aad712a..ae99bb82 100644 --- a/packages/editor/.flatbread/schemas/post.yaml +++ b/packages/editor/.flatbread/schemas/post.yaml @@ -7,15 +7,27 @@ schema: name: Post kind: OBJECT fields: - - {label: Title, name: title, disabled: false, component: string} - - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} - - {label: filename, name: _filename, disabled: true, component: string} - - {label: path, name: _path, disabled: true, component: string} - - {label: slug, name: _slug, disabled: true, component: string} - - {label: Id, name: id, disabled: true, component: string} - - {label: Rating, name: rating, disabled: false, component: float} - - {label: content, name: _content, disabled: true, component: object} - - {label: Authors, name: authors, description: All Authors that are referenced by this Post, disabled: false, component: list} + - { label: Title, name: title, disabled: false, component: string } + - { + label: collection, + name: _collection, + description: The collection name, + disabled: true, + component: string + } + - { label: filename, name: _filename, disabled: true, component: string } + - { label: path, name: _path, disabled: true, component: string } + - { label: slug, name: _slug, disabled: true, component: string } + - { label: Id, name: id, disabled: true, component: string } + - { label: Rating, name: rating, disabled: false, component: float } + - { label: content, name: _content, disabled: true, component: object } + - { + label: Authors, + name: authors, + description: All Authors that are referenced by this Post, + disabled: false, + component: list + } referenceField: title meta: hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/.flatbread/schemas/yaml-author.yaml b/packages/editor/.flatbread/schemas/yaml-author.yaml index fa513d36..78351982 100644 --- a/packages/editor/.flatbread/schemas/yaml-author.yaml +++ b/packages/editor/.flatbread/schemas/yaml-author.yaml @@ -7,17 +7,29 @@ schema: name: YamlAuthor kind: OBJECT fields: - - {label: Name, name: name, disabled: false, component: string} - - {label: collection, name: _collection, description: The collection name, disabled: true, component: string} - - {label: filename, name: _filename, disabled: true, component: string} - - {label: path, name: _path, disabled: true, component: string} - - {label: slug, name: _slug, disabled: true, component: string} - - {label: Date joined, name: date_joined, disabled: false, component: date} - - {label: Id, name: id, disabled: true, component: string} - - {label: content, name: _content, disabled: true, component: object} - - {label: Enjoys, name: enjoys, disabled: false, component: list} - - {label: Friend, name: friend, description: The YamlAuthor referenced by this YamlAuthor, disabled: false, component: object} - - {label: Skills, name: skills, disabled: false, component: object} + - { label: Name, name: name, disabled: false, component: string } + - { + label: collection, + name: _collection, + description: The collection name, + disabled: true, + component: string + } + - { label: filename, name: _filename, disabled: true, component: string } + - { label: path, name: _path, disabled: true, component: string } + - { label: slug, name: _slug, disabled: true, component: string } + - { label: Date joined, name: date_joined, disabled: false, component: date } + - { label: Id, name: id, disabled: true, component: string } + - { label: content, name: _content, disabled: true, component: object } + - { label: Enjoys, name: enjoys, disabled: false, component: list } + - { + label: Friend, + name: friend, + description: The YamlAuthor referenced by this YamlAuthor, + disabled: false, + component: object + } + - { label: Skills, name: skills, disabled: false, component: object } referenceField: name meta: hash: AzBMdh85EQBjJKyBC4yODtR8loA= diff --git a/packages/editor/src/lib/api.ts b/packages/editor/src/lib/api.ts index d12232af..e426602c 100644 --- a/packages/editor/src/lib/api.ts +++ b/packages/editor/src/lib/api.ts @@ -1,7 +1,7 @@ -import { get } from 'svelte/store'; -import wretch from 'wretch'; import { getStores } from '$app/stores'; import { capitalize } from 'lodash-es'; +import { get } from 'svelte/store'; +import wretch from 'wretch'; const api = wretch().url('http://localhost:5057/graphql'); @@ -88,18 +88,29 @@ export async function getGqlTypes() { return new Map(types.map((t) => [t.name, transformSchema(t)])); } -function getCollectionQuery(collectionName: string, gqlTypes, depth = Infinity, visited = {}) { +interface GetCollectionQueryArgs { + visits: number; + visited: Record; + depth: number; + preventCycles: boolean; +} + +function getCollectionQuery( + collectionName: string, + gqlTypes, + { visits = 2, depth = Infinity, visited = {} }: GetCollectionQueryArgs +) { const collection = gqlTypes.get(collectionName); return collection.fields .map((field) => { if (field.type.kind === 'SCALAR' || field.type.ofType?.kind === 'SCALAR') return field.name; - const kind = field.type.kind === 'LIST' ? field.type.ofType.name : field.type.name; + const kind: string = field.type.kind === 'LIST' ? field.type.ofType.name : field.type.name; depth--; if (depth < 0) return ''; - if (visited[kind]) return ''; - visited[kind] = true; - return `${field.name} { ${getCollectionQuery(kind, gqlTypes, depth, visited)} }`; + if (visited[kind] > visits) return ''; + visited[kind] = (visited[kind] ?? 0) + 1; + return `${field.name} { ${getCollectionQuery(kind, gqlTypes, { depth, visited, visits })} }`; }) .join(' '); } @@ -123,7 +134,7 @@ interface QueryCollectionArgs { export async function queryCollection(args: QueryCollectionArgs, gqlTypes) { const query = `{ ${args.query}${getFilter(args.filter)} { - ${getCollectionQuery(args.collection, gqlTypes, args.depth)} + ${getCollectionQuery(args.collection, gqlTypes, { depth: args.depth })} } } `; @@ -175,7 +186,6 @@ export function transformSchema(schema) { const referenceField = ['name', 'title'].find((fieldName) => fields.find((field) => field.name === fieldName)) ?? 'id'; - const result = { ...schema, referenceField, diff --git a/packages/editor/src/lib/field-component.svelte b/packages/editor/src/lib/field-component.svelte index 83509594..e9995c17 100644 --- a/packages/editor/src/lib/field-component.svelte +++ b/packages/editor/src/lib/field-component.svelte @@ -10,7 +10,7 @@ {#if !field.hidden} diff --git a/packages/editor/src/lib/fields/object.svelte b/packages/editor/src/lib/fields/object.svelte index 6523d8e8..912f1abe 100644 --- a/packages/editor/src/lib/fields/object.svelte +++ b/packages/editor/src/lib/fields/object.svelte @@ -18,7 +18,6 @@ const gqlCollection = gqlTypes.get(field.type.ofType?.name ?? field.type.name); let collection = gqlCollection; - console.log({ field, collection, fieldComponents}) {#if !inList}
{field.label}
@@ -26,7 +25,15 @@ {/if} {#each collection.fields as field} {#if !field.hidden} - + {#if field.component === 'object' && value?.[field.name]} + + {:else} + + {/if} {/if} {/each} {#if !inList} diff --git a/packages/editor/src/routes/collection/[name]/[id].svelte b/packages/editor/src/routes/collection/[name]/[id].svelte index af07a5a8..a0ee46d9 100644 --- a/packages/editor/src/routes/collection/[name]/[id].svelte +++ b/packages/editor/src/routes/collection/[name]/[id].svelte @@ -32,8 +32,8 @@ import FieldComponent from '$lib/field-component.svelte'; import { get } from 'lodash-es'; - export let querySchema; - export let record; + export let querySchema: any; + export let record: any;
diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json index 430ed82c..51c4dc7d 100644 --- a/packages/editor/tsconfig.json +++ b/packages/editor/tsconfig.json @@ -10,8 +10,8 @@ "sourceMap": true, "strict": true, "paths": { - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"] - } + "$lib": ["src/lib"], + "$lib/*": ["src/lib/*"] + } } } diff --git a/playground/src/routes/index.svelte b/playground/src/routes/index.svelte index f0da4c50..94b0a570 100644 --- a/playground/src/routes/index.svelte +++ b/playground/src/routes/index.svelte @@ -87,9 +87,7 @@
-
+    
       
         {JSON.stringify(data, null, 2)}
       

From 352eba4a382c347cbe201704300850a6e887ef2c Mon Sep 17 00:00:00 2001
From: Adam Sparks 
Date: Sat, 30 Jul 2022 00:46:50 -0500
Subject: [PATCH 03/26] add field.description and redesign nesting pattern

---
 packages/editor/src/lib/fields/date.svelte    |  1 +
 packages/editor/src/lib/fields/list.svelte    | 31 ++++--------
 packages/editor/src/lib/fields/object.svelte  | 47 ++++++++++++-------
 packages/editor/src/lib/fields/raw.svelte     |  7 +++
 packages/editor/src/lib/fields/string.svelte  |  1 +
 packages/editor/src/routes/__layout.svelte    | 26 ++++++++++
 .../src/routes/collection/[name]/[id].svelte  |  4 +-
 .../src/routes/collection/[name]/index.svelte |  1 +
 packages/editor/src/routes/index.svelte       |  3 +-
 9 files changed, 79 insertions(+), 42 deletions(-)

diff --git a/packages/editor/src/lib/fields/date.svelte b/packages/editor/src/lib/fields/date.svelte
index 8152ab1e..6f669855 100644
--- a/packages/editor/src/lib/fields/date.svelte
+++ b/packages/editor/src/lib/fields/date.svelte
@@ -11,4 +11,5 @@
 		{value?.split('T')?.[0] ?? value}
 	{:else}
 	{/if}
+	{#if field.description}{field.description}{/if}
 
diff --git a/packages/editor/src/lib/fields/list.svelte b/packages/editor/src/lib/fields/list.svelte
index dac8a4ce..383a4461 100644
--- a/packages/editor/src/lib/fields/list.svelte
+++ b/packages/editor/src/lib/fields/list.svelte
@@ -12,25 +12,14 @@
 	const component = fieldComponents[getComponentType(field.type.ofType)];
 
 
-
- {field.label} -
-
-
- {#each items as value} -
- -
- {/each} +
+

{field.label}

+ {#if field.description}{field.description}{/if} +
+ {#each items as value} +
+ +
+ {/each} +
-
- - diff --git a/packages/editor/src/lib/fields/object.svelte b/packages/editor/src/lib/fields/object.svelte index 912f1abe..eb0f5cb0 100644 --- a/packages/editor/src/lib/fields/object.svelte +++ b/packages/editor/src/lib/fields/object.svelte @@ -1,5 +1,6 @@ -{#if !inList}
{field.label}
-
-{/if} -{#each collection.fields as field} - {#if !field.hidden} - {#if field.component === 'object' && value?.[field.name]} - - {:else} - - {/if} - {/if} -{/each} -{#if !inList} -
+ +{#if value} +
+

+ {#if !inList}{field.label}{:else}{get(value, collection.referenceField)}{/if} +

+ {#if !inList && field.description}{field.description}{/if} +
+ {#each collection.fields as field} + {#if !field.hidden} + {#if field.component === 'object'} + + {:else} + + {/if} + {/if} + {/each} + {#if !inList} + + {/if} +
+
{/if} diff --git a/packages/editor/src/lib/fields/raw.svelte b/packages/editor/src/lib/fields/raw.svelte index d0b3b3ab..3598dd8c 100644 --- a/packages/editor/src/lib/fields/raw.svelte +++ b/packages/editor/src/lib/fields/raw.svelte @@ -1,8 +1,14 @@ diff --git a/packages/editor/src/lib/fields/string.svelte b/packages/editor/src/lib/fields/string.svelte index 21f93dad..613b9c35 100644 --- a/packages/editor/src/lib/fields/string.svelte +++ b/packages/editor/src/lib/fields/string.svelte @@ -12,4 +12,5 @@ {:else} {/if} + {#if field.description}{field.description}{/if} diff --git a/packages/editor/src/routes/__layout.svelte b/packages/editor/src/routes/__layout.svelte index 805f73d1..6ae86b50 100644 --- a/packages/editor/src/routes/__layout.svelte +++ b/packages/editor/src/routes/__layout.svelte @@ -30,6 +30,32 @@ padding: 1.75rem 0; } + [data-field='object'], + [data-field='list'] { + margin-bottom: var(--spacing); + padding: var(--form-element-spacing-vertical) 0; + + .content { + margin: calc(var(--form-element-spacing-vertical)) 0; + padding-left: 1rem; + border-left: var(--border-width) solid var(--form-element-border-color); + } + } + + h1, + h2, + h3, + h4, + h5, + h6 { + + small { + display: block; + width: 100%; + margin-bottom: var(--spacing); + color: var(--muted-color); + } + } + /* Cyan Light scheme (Default) */ /* Can be forced with data-theme="light" */ [data-theme='light'], diff --git a/packages/editor/src/routes/collection/[name]/[id].svelte b/packages/editor/src/routes/collection/[name]/[id].svelte index a0ee46d9..ec10e50b 100644 --- a/packages/editor/src/routes/collection/[name]/[id].svelte +++ b/packages/editor/src/routes/collection/[name]/[id].svelte @@ -11,7 +11,7 @@ query: queryName, collection: querySchema.schema.name, filter: `{ id: { eq: "${params.id}" } }`, - depth: Infinity + visits: 2 }, gqlTypes ); @@ -47,7 +47,7 @@ ]} /> - +

Edit {querySchema.schema.label}

{#each querySchema.schema.fields as field} diff --git a/packages/editor/src/routes/collection/[name]/index.svelte b/packages/editor/src/routes/collection/[name]/index.svelte index fcbf705c..6888b929 100644 --- a/packages/editor/src/routes/collection/[name]/index.svelte +++ b/packages/editor/src/routes/collection/[name]/index.svelte @@ -4,6 +4,7 @@ export async function load({ params, url, session }) { const { gqlTypes, queryTypes } = session; const querySchema = queryTypes.get(params.name); + console.log({ queryTypes, params, querySchema}) const collection = querySchema.schema; const results = await queryCollection( { query: params.name, collection: collection.name }, diff --git a/packages/editor/src/routes/index.svelte b/packages/editor/src/routes/index.svelte index ed0f8cb0..97957db8 100644 --- a/packages/editor/src/routes/index.svelte +++ b/packages/editor/src/routes/index.svelte @@ -2,6 +2,7 @@ import { getSession } from '$lib/api'; const { gqlTypes, queryTypes } = getSession(); +
@@ -11,7 +12,7 @@
- {collection.label} + {collection.schema.pluralName}
From 876f72ec56e9faa20ea81dda928a633e961d7c92 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sat, 30 Jul 2022 00:48:15 -0500 Subject: [PATCH 04/26] target schema types with config instead of schema query list types --- .../editor/.flatbread/schemas/author.yaml | 90 +++++++++++-------- .../.flatbread/schemas/author_-skills.yaml | 23 +++++ .../.flatbread/schemas/author__content.yaml | 23 +++++ .../.flatbread/schemas/flatbread-image.yaml | 14 +++ .../.flatbread/schemas/override-test.yaml | 88 +++++++++++------- .../schemas/override-test_-array2.yaml | 11 +++ .../schemas/override-test_-array3.yaml | 12 +++ .../schemas/override-test_-array3_-obj.yaml | 11 +++ .../schemas/override-test_-deeply.yaml | 11 +++ .../schemas/override-test__content.yaml | 23 +++++ .../schemas/post-category-blob.yaml | 76 +++++++++------- .../schemas/post-category-blob__content.yaml | 23 +++++ .../.flatbread/schemas/post-category.yaml | 84 ++++++++++------- .../schemas/post-category__content.yaml | 23 +++++ packages/editor/.flatbread/schemas/post.yaml | 76 +++++++++------- .../.flatbread/schemas/post__content.yaml | 23 +++++ packages/editor/.flatbread/schemas/query.yaml | 62 +++++++++++++ .../.flatbread/schemas/yaml-author.yaml | 86 +++++++++++------- .../schemas/yaml-author_-skills.yaml | 26 ++++++ .../schemas/yaml-author__content.yaml | 20 +++++ packages/editor/src/hooks.ts | 35 ++++---- packages/editor/src/lib/api.ts | 70 +++++++++++---- packages/editor/src/lib/config.ts | 44 +++++---- packages/editor/src/lib/types.ts | 27 ++++++ .../src/routes/collection/[name]/index.svelte | 2 +- packages/editor/src/routes/index.svelte | 1 - 26 files changed, 731 insertions(+), 253 deletions(-) create mode 100644 packages/editor/.flatbread/schemas/author_-skills.yaml create mode 100644 packages/editor/.flatbread/schemas/author__content.yaml create mode 100644 packages/editor/.flatbread/schemas/flatbread-image.yaml create mode 100644 packages/editor/.flatbread/schemas/override-test_-array2.yaml create mode 100644 packages/editor/.flatbread/schemas/override-test_-array3.yaml create mode 100644 packages/editor/.flatbread/schemas/override-test_-array3_-obj.yaml create mode 100644 packages/editor/.flatbread/schemas/override-test_-deeply.yaml create mode 100644 packages/editor/.flatbread/schemas/override-test__content.yaml create mode 100644 packages/editor/.flatbread/schemas/post-category-blob__content.yaml create mode 100644 packages/editor/.flatbread/schemas/post-category__content.yaml create mode 100644 packages/editor/.flatbread/schemas/post__content.yaml create mode 100644 packages/editor/.flatbread/schemas/query.yaml create mode 100644 packages/editor/.flatbread/schemas/yaml-author_-skills.yaml create mode 100644 packages/editor/.flatbread/schemas/yaml-author__content.yaml create mode 100644 packages/editor/src/lib/types.ts diff --git a/packages/editor/.flatbread/schemas/author.yaml b/packages/editor/.flatbread/schemas/author.yaml index cedf9a69..aa20c193 100644 --- a/packages/editor/.flatbread/schemas/author.yaml +++ b/packages/editor/.flatbread/schemas/author.yaml @@ -1,36 +1,56 @@ -label: Authors -name: allAuthors -description: Return a set of Authors -disabled: false -component: list -schema: - name: Author - kind: OBJECT - fields: - - { label: Name, name: name, disabled: false, component: string } - - { - label: collection, - name: _collection, - description: The collection name, - disabled: true, - component: string - } - - { label: filename, name: _filename, hidden: true, disabled: true, component: string } - - { label: path, name: _path, disabled: true, component: string } - - { label: slug, name: _slug, disabled: true, component: string } - - { label: Date joined, name: date_joined, disabled: false, component: date } - - { label: Entity, name: entity, disabled: false, component: string } - - { label: Id, name: id, disabled: true, component: string } - - { label: content, hidden: true, name: _content, disabled: true, component: object } - - { label: Enjoys, name: enjoys, disabled: false, component: list } - - { - label: Friend, - name: friend, - description: The Author referenced by this Author, - disabled: false, - component: object - } - - { label: Skills, name: skills, disabled: false, component: object } - referenceField: name +name: Author +kind: OBJECT +fields: + - label: Name + name: name + component: string + - label: Date joined + name: date_joined + component: date + - label: Entity + name: entity + component: string + - label: Enjoys + name: enjoys + component: list + - label: Friend + name: friend + description: The Author referenced by this Author + component: object + collection: Author + - label: Skills + name: skills + component: object + collection: Author_Skills + - label: Collection + name: _collection + description: The collection name + disabled: true + component: string + - label: Filename + name: _filename + disabled: true + component: string + - label: Path + name: _path + disabled: true + component: string + - label: Slug + name: _slug + disabled: true + component: string + - label: Id + name: id + disabled: true + component: string + - label: Content + name: _content + disabled: true + component: object + collection: Author__content +component: object +label: Author +pluralName: Authors +referenceField: name meta: - hash: AzBMdh85EQBjJKyBC4yODtR8loA= + hash: dlkLX3IxInKIl7bN/QkwxR88AbM= diff --git a/packages/editor/.flatbread/schemas/author_-skills.yaml b/packages/editor/.flatbread/schemas/author_-skills.yaml new file mode 100644 index 00000000..32054e94 --- /dev/null +++ b/packages/editor/.flatbread/schemas/author_-skills.yaml @@ -0,0 +1,23 @@ +name: Author_Skills +kind: OBJECT +fields: + - label: Breathing + name: breathing + component: float + - label: Existence + name: existence + component: string + - label: Liquid consumption + name: liquid_consumption + component: float + - label: Sitting + name: sitting + component: float + - label: Sports + name: sports + component: float +component: object +label: Author_ Skills +referenceField: id +meta: + hash: Le/pUcMNDHHL/Kr+Bl3AvMJcKjc= diff --git a/packages/editor/.flatbread/schemas/author__content.yaml b/packages/editor/.flatbread/schemas/author__content.yaml new file mode 100644 index 00000000..43ce54cb --- /dev/null +++ b/packages/editor/.flatbread/schemas/author__content.yaml @@ -0,0 +1,23 @@ +name: Author__content +kind: OBJECT +fields: + - label: Excerpt + name: excerpt + description: A plaintext excerpt taken from the main content + component: string + - label: Html + name: html + description: The content as HTML + component: string + - label: Raw + name: raw + component: string + - label: Timetoread + name: timeToRead + description: How long (in minutes) it would take an average reader to read the main content. + component: int +component: object +label: Author__content +referenceField: id +meta: + hash: Ekj17d0uRy3TbJFYZ13muZOqoXk= diff --git a/packages/editor/.flatbread/schemas/flatbread-image.yaml b/packages/editor/.flatbread/schemas/flatbread-image.yaml new file mode 100644 index 00000000..82bbc1fa --- /dev/null +++ b/packages/editor/.flatbread/schemas/flatbread-image.yaml @@ -0,0 +1,14 @@ +name: FlatbreadImage +kind: OBJECT +fields: + - label: Alt + name: alt + component: string + - label: Src + name: src + component: string +component: object +label: Flatbread Image +referenceField: id +meta: + hash: EpGAkm9XU4WWm8xiJts2g8EEFLw= diff --git a/packages/editor/.flatbread/schemas/override-test.yaml b/packages/editor/.flatbread/schemas/override-test.yaml index 4a5abf08..34b95caf 100644 --- a/packages/editor/.flatbread/schemas/override-test.yaml +++ b/packages/editor/.flatbread/schemas/override-test.yaml @@ -1,31 +1,59 @@ -label: Override Tests -name: allOverrideTests -description: Return a set of OverrideTests -disabled: false -component: list -schema: - name: OverrideTest - kind: OBJECT - fields: - - { label: Title, name: title, disabled: false, component: string } - - { - label: collection, - name: _collection, - description: The collection name, - disabled: true, - component: string - } - - { label: filename, name: _filename, disabled: true, component: string } - - { label: path, name: _path, disabled: true, component: string } - - { label: slug, name: _slug, disabled: true, component: string } - - { label: Id, name: id, disabled: true, component: string } - - { label: content, name: _content, disabled: true, component: object } - - { label: Array, name: array, disabled: false, component: list } - - { label: Array2, name: array2, disabled: false, component: list } - - { label: Array3, name: array3, disabled: false, component: list } - - { label: Deeply, name: deeply, disabled: false, component: object } - - { label: Image, name: image, disabled: false, component: object } - - { label: Image2, name: image2, disabled: false, component: object } - referenceField: title +name: OverrideTest +kind: OBJECT +fields: + - label: Title + name: title + component: string + - label: Array + name: array + component: list + - label: Array2 + name: array2 + component: list + - label: Array3 + name: array3 + component: list + - label: Deeply + name: deeply + component: object + collection: OverrideTest_Deeply + - label: Image + name: image + component: object + collection: FlatbreadImage + - label: Image2 + name: image2 + component: object + collection: FlatbreadImage + - label: Collection + name: _collection + description: The collection name + disabled: true + component: string + - label: Filename + name: _filename + disabled: true + component: string + - label: Path + name: _path + disabled: true + component: string + - label: Slug + name: _slug + disabled: true + component: string + - label: Id + name: id + disabled: true + component: string + - label: Content + name: _content + disabled: true + component: object + collection: OverrideTest__content +component: object +label: Override Test +pluralName: Override Tests +referenceField: title meta: - hash: AzBMdh85EQBjJKyBC4yODtR8loA= + hash: 5ypFyuwxiEp6X/et6hB/fCB+sPg= diff --git a/packages/editor/.flatbread/schemas/override-test_-array2.yaml b/packages/editor/.flatbread/schemas/override-test_-array2.yaml new file mode 100644 index 00000000..5ea3578f --- /dev/null +++ b/packages/editor/.flatbread/schemas/override-test_-array2.yaml @@ -0,0 +1,11 @@ +name: OverrideTest_Array2 +kind: OBJECT +fields: + - label: Obj + name: obj + component: string +component: object +label: Override Test_ Array2 +referenceField: id +meta: + hash: LRXQYmbIu3bPgYYkLTLiF/REii8= diff --git a/packages/editor/.flatbread/schemas/override-test_-array3.yaml b/packages/editor/.flatbread/schemas/override-test_-array3.yaml new file mode 100644 index 00000000..d82a900b --- /dev/null +++ b/packages/editor/.flatbread/schemas/override-test_-array3.yaml @@ -0,0 +1,12 @@ +name: OverrideTest_Array3 +kind: OBJECT +fields: + - label: Obj + name: obj + component: object + collection: OverrideTest_Array3_Obj +component: object +label: Override Test_ Array3 +referenceField: id +meta: + hash: nPeV3CaN7bk4HRYvZ6M23I0psWU= diff --git a/packages/editor/.flatbread/schemas/override-test_-array3_-obj.yaml b/packages/editor/.flatbread/schemas/override-test_-array3_-obj.yaml new file mode 100644 index 00000000..d1097433 --- /dev/null +++ b/packages/editor/.flatbread/schemas/override-test_-array3_-obj.yaml @@ -0,0 +1,11 @@ +name: OverrideTest_Array3_Obj +kind: OBJECT +fields: + - label: Test + name: test + component: string +component: object +label: Override Test_ Array3_ Obj +referenceField: id +meta: + hash: cB+oN67t9u+4Jg3Z8dbENDnI6LA= diff --git a/packages/editor/.flatbread/schemas/override-test_-deeply.yaml b/packages/editor/.flatbread/schemas/override-test_-deeply.yaml new file mode 100644 index 00000000..9dc37258 --- /dev/null +++ b/packages/editor/.flatbread/schemas/override-test_-deeply.yaml @@ -0,0 +1,11 @@ +name: OverrideTest_Deeply +kind: OBJECT +fields: + - label: Nested + name: nested + component: string +component: object +label: Override Test_ Deeply +referenceField: id +meta: + hash: 8olmxrqF+7RQ4+snnCEexrAIduc= diff --git a/packages/editor/.flatbread/schemas/override-test__content.yaml b/packages/editor/.flatbread/schemas/override-test__content.yaml new file mode 100644 index 00000000..02ef1d01 --- /dev/null +++ b/packages/editor/.flatbread/schemas/override-test__content.yaml @@ -0,0 +1,23 @@ +name: OverrideTest__content +kind: OBJECT +fields: + - label: Excerpt + name: excerpt + description: A plaintext excerpt taken from the main content + component: string + - label: Html + name: html + description: The content as HTML + component: string + - label: Raw + name: raw + component: string + - label: Timetoread + name: timeToRead + description: How long (in minutes) it would take an average reader to read the main content. + component: int +component: object +label: Override Test__content +referenceField: id +meta: + hash: 27ZZI2RjWWSJII8r2YFZuoDXCN0= diff --git a/packages/editor/.flatbread/schemas/post-category-blob.yaml b/packages/editor/.flatbread/schemas/post-category-blob.yaml index 70b4277d..2a2cb867 100644 --- a/packages/editor/.flatbread/schemas/post-category-blob.yaml +++ b/packages/editor/.flatbread/schemas/post-category-blob.yaml @@ -1,33 +1,45 @@ -label: Post Category Blobs -name: allPostCategoryBlobs -description: Return a set of PostCategoryBlobs -disabled: false -component: list -schema: - name: PostCategoryBlob - kind: OBJECT - fields: - - { label: Title, name: title, disabled: false, component: string } - - { - label: collection, - name: _collection, - description: The collection name, - disabled: true, - component: string - } - - { label: filename, name: _filename, disabled: true, component: string } - - { label: path, name: _path, disabled: true, component: string } - - { label: slug, name: _slug, disabled: true, component: string } - - { label: Id, name: id, disabled: true, component: string } - - { label: Rating, name: rating, disabled: false, component: float } - - { label: content, name: _content, disabled: true, component: object } - - { - label: Authors, - name: authors, - description: All Authors that are referenced by this PostCategoryBlob, - disabled: false, - component: list - } - referenceField: title +name: PostCategoryBlob +kind: OBJECT +fields: + - label: Title + name: title + component: string + - label: Rating + name: rating + component: float + - label: Authors + name: authors + description: All Authors that are referenced by this PostCategoryBlob + component: list + - label: Collection + name: _collection + description: The collection name + disabled: true + component: string + - label: Filename + name: _filename + disabled: true + component: string + - label: Path + name: _path + disabled: true + component: string + - label: Slug + name: _slug + disabled: true + component: string + - label: Id + name: id + disabled: true + component: string + - label: Content + name: _content + disabled: true + component: object + collection: PostCategoryBlob__content +component: object +label: Post Category Blob +pluralName: Post Category Blobs +referenceField: title meta: - hash: AzBMdh85EQBjJKyBC4yODtR8loA= + hash: Ai83SmxilqZ57WtHzourDiFyIqI= diff --git a/packages/editor/.flatbread/schemas/post-category-blob__content.yaml b/packages/editor/.flatbread/schemas/post-category-blob__content.yaml new file mode 100644 index 00000000..ab4fb9f4 --- /dev/null +++ b/packages/editor/.flatbread/schemas/post-category-blob__content.yaml @@ -0,0 +1,23 @@ +name: PostCategoryBlob__content +kind: OBJECT +fields: + - label: Excerpt + name: excerpt + description: A plaintext excerpt taken from the main content + component: string + - label: Html + name: html + description: The content as HTML + component: string + - label: Raw + name: raw + component: string + - label: Timetoread + name: timeToRead + description: How long (in minutes) it would take an average reader to read the main content. + component: int +component: object +label: Post Category Blob__content +referenceField: id +meta: + hash: MITSpn0srO5TZ3eq4Bk2NJADKt8= diff --git a/packages/editor/.flatbread/schemas/post-category.yaml b/packages/editor/.flatbread/schemas/post-category.yaml index 9d0c4e01..2db90154 100644 --- a/packages/editor/.flatbread/schemas/post-category.yaml +++ b/packages/editor/.flatbread/schemas/post-category.yaml @@ -1,35 +1,51 @@ -label: Post Categories -name: allPostCategories -description: Return a set of PostCategories -disabled: false -component: list -schema: - name: PostCategory - kind: OBJECT - fields: - - { label: Title, name: title, disabled: false, component: string } - - { - label: collection, - name: _collection, - description: The collection name, - disabled: true, - component: string - } - - { label: filename, name: _filename, disabled: true, component: string } - - { label: path, name: _path, disabled: true, component: string } - - { label: slug, name: _slug, disabled: true, component: string } - - { label: Category, name: category, disabled: false, component: string } - - { label: Id, name: id, disabled: true, component: string } - - { label: Rating, name: rating, disabled: false, component: float } - - { label: Slug, name: slug, disabled: false, component: string } - - { label: content, name: _content, disabled: true, component: object } - - { - label: Authors, - name: authors, - description: All Authors that are referenced by this PostCategory, - disabled: false, - component: list - } - referenceField: title +name: PostCategory +kind: OBJECT +fields: + - label: Title + name: title + component: string + - label: Category + name: category + component: string + - label: Rating + name: rating + component: float + - label: Slug + name: slug + component: string + - label: Authors + name: authors + description: All Authors that are referenced by this PostCategory + component: list + - label: Collection + name: _collection + description: The collection name + disabled: true + component: string + - label: Filename + name: _filename + disabled: true + component: string + - label: Path + name: _path + disabled: true + component: string + - label: Slug + name: _slug + disabled: true + component: string + - label: Id + name: id + disabled: true + component: string + - label: Content + name: _content + disabled: true + component: object + collection: PostCategory__content +component: object +label: Post Category +pluralName: Post Categories +referenceField: title meta: - hash: AzBMdh85EQBjJKyBC4yODtR8loA= + hash: tTodpqF2LjHylcNi24dgcAEUBU8= diff --git a/packages/editor/.flatbread/schemas/post-category__content.yaml b/packages/editor/.flatbread/schemas/post-category__content.yaml new file mode 100644 index 00000000..ef70c588 --- /dev/null +++ b/packages/editor/.flatbread/schemas/post-category__content.yaml @@ -0,0 +1,23 @@ +name: PostCategory__content +kind: OBJECT +fields: + - label: Excerpt + name: excerpt + description: A plaintext excerpt taken from the main content + component: string + - label: Html + name: html + description: The content as HTML + component: string + - label: Raw + name: raw + component: string + - label: Timetoread + name: timeToRead + description: How long (in minutes) it would take an average reader to read the main content. + component: int +component: object +label: Post Category__content +referenceField: id +meta: + hash: cnM5U561USPrGoU4WUWs70HAGnQ= diff --git a/packages/editor/.flatbread/schemas/post.yaml b/packages/editor/.flatbread/schemas/post.yaml index ae99bb82..6009f856 100644 --- a/packages/editor/.flatbread/schemas/post.yaml +++ b/packages/editor/.flatbread/schemas/post.yaml @@ -1,33 +1,45 @@ -label: Posts -name: allPosts -description: Return a set of Posts -disabled: false -component: list -schema: - name: Post - kind: OBJECT - fields: - - { label: Title, name: title, disabled: false, component: string } - - { - label: collection, - name: _collection, - description: The collection name, - disabled: true, - component: string - } - - { label: filename, name: _filename, disabled: true, component: string } - - { label: path, name: _path, disabled: true, component: string } - - { label: slug, name: _slug, disabled: true, component: string } - - { label: Id, name: id, disabled: true, component: string } - - { label: Rating, name: rating, disabled: false, component: float } - - { label: content, name: _content, disabled: true, component: object } - - { - label: Authors, - name: authors, - description: All Authors that are referenced by this Post, - disabled: false, - component: list - } - referenceField: title +name: Post +kind: OBJECT +fields: + - label: Title + name: title + component: string + - label: Rating + name: rating + component: float + - label: Authors + name: authors + description: All Authors that are referenced by this Post + component: list + - label: Collection + name: _collection + description: The collection name + disabled: true + component: string + - label: Filename + name: _filename + disabled: true + component: string + - label: Path + name: _path + disabled: true + component: string + - label: Slug + name: _slug + disabled: true + component: string + - label: Id + name: id + disabled: true + component: string + - label: Content + name: _content + disabled: true + component: object + collection: Post__content +component: object +label: Post +pluralName: Posts +referenceField: title meta: - hash: AzBMdh85EQBjJKyBC4yODtR8loA= + hash: d9VGXKIqhYJ4VJsotazpymTVmjQ= diff --git a/packages/editor/.flatbread/schemas/post__content.yaml b/packages/editor/.flatbread/schemas/post__content.yaml new file mode 100644 index 00000000..9eaaa2c9 --- /dev/null +++ b/packages/editor/.flatbread/schemas/post__content.yaml @@ -0,0 +1,23 @@ +name: Post__content +kind: OBJECT +fields: + - label: Excerpt + name: excerpt + description: A plaintext excerpt taken from the main content + component: string + - label: Html + name: html + description: The content as HTML + component: string + - label: Raw + name: raw + component: string + - label: Timetoread + name: timeToRead + description: How long (in minutes) it would take an average reader to read the main content. + component: int +component: object +label: Post__content +referenceField: id +meta: + hash: PEXY65G7pFIKFXYZcpUoqMDLNqs= diff --git a/packages/editor/.flatbread/schemas/query.yaml b/packages/editor/.flatbread/schemas/query.yaml new file mode 100644 index 00000000..ee30b27f --- /dev/null +++ b/packages/editor/.flatbread/schemas/query.yaml @@ -0,0 +1,62 @@ +name: Query +kind: OBJECT +fields: + - label: Allauthors + name: allAuthors + description: Return a set of Authors + component: list + - label: Alloverridetests + name: allOverrideTests + description: Return a set of OverrideTests + component: list + - label: Allpostcategories + name: allPostCategories + description: Return a set of PostCategories + component: list + - label: Allpostcategoryblobs + name: allPostCategoryBlobs + description: Return a set of PostCategoryBlobs + component: list + - label: Allposts + name: allPosts + description: Return a set of Posts + component: list + - label: Allyamlauthors + name: allYamlAuthors + description: Return a set of YamlAuthors + component: list + - label: Author + name: Author + description: Find one Author by its ID + component: object + collection: Author + - label: Overridetest + name: OverrideTest + description: Find one OverrideTest by its ID + component: object + collection: OverrideTest + - label: Post + name: Post + description: Find one Post by its ID + component: object + collection: Post + - label: Postcategory + name: PostCategory + description: Find one PostCategory by its ID + component: object + collection: PostCategory + - label: Postcategoryblob + name: PostCategoryBlob + description: Find one PostCategoryBlob by its ID + component: object + collection: PostCategoryBlob + - label: Yamlauthor + name: YamlAuthor + description: Find one YamlAuthor by its ID + component: object + collection: YamlAuthor +component: object +label: Query +referenceField: id +meta: + hash: LZ9Md7LOMyUIwXPnBmhnxofM5bE= diff --git a/packages/editor/.flatbread/schemas/yaml-author.yaml b/packages/editor/.flatbread/schemas/yaml-author.yaml index 78351982..9f444f8f 100644 --- a/packages/editor/.flatbread/schemas/yaml-author.yaml +++ b/packages/editor/.flatbread/schemas/yaml-author.yaml @@ -1,35 +1,53 @@ -label: Authors (Yaml) -name: allYamlAuthors -description: Return a set of YamlAuthors -disabled: false -component: list -schema: - name: YamlAuthor - kind: OBJECT - fields: - - { label: Name, name: name, disabled: false, component: string } - - { - label: collection, - name: _collection, - description: The collection name, - disabled: true, - component: string - } - - { label: filename, name: _filename, disabled: true, component: string } - - { label: path, name: _path, disabled: true, component: string } - - { label: slug, name: _slug, disabled: true, component: string } - - { label: Date joined, name: date_joined, disabled: false, component: date } - - { label: Id, name: id, disabled: true, component: string } - - { label: content, name: _content, disabled: true, component: object } - - { label: Enjoys, name: enjoys, disabled: false, component: list } - - { - label: Friend, - name: friend, - description: The YamlAuthor referenced by this YamlAuthor, - disabled: false, - component: object - } - - { label: Skills, name: skills, disabled: false, component: object } - referenceField: name +name: YamlAuthor +kind: OBJECT +fields: + - label: Name + name: name + component: string + - label: Date joined + name: date_joined + component: date + - label: Enjoys + name: enjoys + component: list + - label: Friend + name: friend + description: The YamlAuthor referenced by this YamlAuthor + component: object + collection: YamlAuthor + - label: Skills + name: skills + component: object + collection: YamlAuthor_Skills + - label: Collection + name: _collection + description: The collection name + disabled: true + component: string + - label: Filename + name: _filename + disabled: true + component: string + - label: Path + name: _path + disabled: true + component: string + - label: Slug + name: _slug + disabled: true + component: string + - label: Id + name: id + disabled: true + component: string + - label: Content + name: _content + disabled: true + component: object + collection: YamlAuthor__content +component: object +label: Yaml Author +pluralName: Authors (Yaml) +referenceField: name meta: - hash: AzBMdh85EQBjJKyBC4yODtR8loA= + hash: g0Rr4CZt9guOrAgv0PrNOnIhjdg= diff --git a/packages/editor/.flatbread/schemas/yaml-author_-skills.yaml b/packages/editor/.flatbread/schemas/yaml-author_-skills.yaml new file mode 100644 index 00000000..ad535d48 --- /dev/null +++ b/packages/editor/.flatbread/schemas/yaml-author_-skills.yaml @@ -0,0 +1,26 @@ +name: YamlAuthor_Skills +kind: OBJECT +fields: + - label: Breathing + name: breathing + component: float + - label: Cat pat + name: cat_pat + component: float + - label: Existence + name: existence + component: string + - label: Liquid consumption + name: liquid_consumption + component: float + - label: Sitting + name: sitting + component: float + - label: Sports + name: sports + component: float +component: object +label: Yaml Author_ Skills +referenceField: id +meta: + hash: EraBF4GYQg2wjaeu4MEoihjMDtU= diff --git a/packages/editor/.flatbread/schemas/yaml-author__content.yaml b/packages/editor/.flatbread/schemas/yaml-author__content.yaml new file mode 100644 index 00000000..c01112df --- /dev/null +++ b/packages/editor/.flatbread/schemas/yaml-author__content.yaml @@ -0,0 +1,20 @@ +name: YamlAuthor__content +kind: OBJECT +fields: + - label: Excerpt + name: excerpt + description: A plaintext excerpt taken from the main content + component: string + - label: Html + name: html + description: The content as HTML + component: string + - label: Timetoread + name: timeToRead + description: How long (in minutes) it would take an average reader to read the main content. + component: int +component: object +label: Yaml Author__content +referenceField: id +meta: + hash: jiauBo7x7XYpRnBd6AjHP6Gd1Dk= diff --git a/packages/editor/src/hooks.ts b/packages/editor/src/hooks.ts index f370ff45..c69c31f6 100644 --- a/packages/editor/src/hooks.ts +++ b/packages/editor/src/hooks.ts @@ -1,4 +1,4 @@ -import { getGqlTypes } from '$lib/api'; +import { getGqlTypes, getNameFromLabel } from '$lib/api'; import Config from './lib/config'; /** @type {import('@sveltejs/kit').GetSession} */ @@ -14,22 +14,23 @@ export async function handle({ event, resolve }) { return new Response('custom response'); } - const gqlTypes = await getGqlTypes(); - const queryTypes = new Map( - await Promise.all( - gqlTypes - .get('Query') - .fields.filter((field) => field.type.kind === 'LIST') - .map(async (field) => { - field.schema = gqlTypes.get(field.type.ofType.name); - field.label = field.name - .replace(/^all/, '') - .replace(/([A-Z])/g, ' $1') - .trim(); - return [field.name, await Config.get(field.name, field)]; - }) - ).then((collections) => collections.sort((a, b) => a[1].label.localeCompare(b[1].label))) - ); + // TODO: figure out how to expose config for sub objects like Author_Skills + // maybe merge these types into the parent type under sub types? + // maybe transform all __schema.types into their own schema instead of targeting type Query + + // transform gqlTypes first, then attach schemas + + const { gqlTypes, queryListFields } = await getGqlTypes(); + + const queryTypesList = queryListFields + .map((field) => { + field.schema = gqlTypes.get(field.type.ofType.name); + field.label = getNameFromLabel(field.name); + return [field.name, field]; + }) + .sort((a, b) => a[1].schema.pluralName.localeCompare(b[1].schema.pluralName)); + + const queryTypes = new Map(queryTypesList); gqlTypes.set('Query', queryTypes); diff --git a/packages/editor/src/lib/api.ts b/packages/editor/src/lib/api.ts index e426602c..b8868b28 100644 --- a/packages/editor/src/lib/api.ts +++ b/packages/editor/src/lib/api.ts @@ -1,7 +1,9 @@ import { getStores } from '$app/stores'; -import { capitalize } from 'lodash-es'; +import { capitalize, keyBy } from 'lodash-es'; import { get } from 'svelte/store'; import wretch from 'wretch'; +import type { Field, GqlField, GqlSchema } from '$lib/types'; +import Config from './config'; const api = wretch().url('http://localhost:5057/graphql'); @@ -84,15 +86,32 @@ export async function getGqlTypes() { }) .json(); - const types = result.data.__schema.types; - return new Map(types.map((t) => [t.name, transformSchema(t)])); + const types: GqlSchema[] = result.data.__schema.types; + const queryListFields = (types.find((t) => t.name === 'Query') as GqlSchema).fields.filter( + (t) => t.type.kind === 'LIST' + ); + const querySchema = keyBy(queryListFields, 'type.ofType.name'); + + console.log(querySchema); + + const gqlTypes = await Promise.all( + types.map(async (t) => { + const shouldConfig = !t.name.startsWith('__') && t.kind === 'OBJECT'; + const schema = transformSchema(t, querySchema); + return [t.name, shouldConfig ? await Config.get(t.name, schema) : schema]; + }) + ); + + return { + gqlTypes: new Map(gqlTypes), + queryListFields + }; } interface GetCollectionQueryArgs { - visits: number; - visited: Record; - depth: number; - preventCycles: boolean; + visits?: number; + visited?: Record; + depth?: number; } function getCollectionQuery( @@ -102,6 +121,8 @@ function getCollectionQuery( ) { const collection = gqlTypes.get(collectionName); + console.log({ collection, collectionName }); + return collection.fields .map((field) => { if (field.type.kind === 'SCALAR' || field.type.ofType?.kind === 'SCALAR') return field.name; @@ -124,21 +145,20 @@ function getFilter(filter: any) { return `(filter: ${filter})`; } -interface QueryCollectionArgs { +interface QueryCollectionArgs extends GetCollectionQueryArgs { query: string; collection: string; - depth?: number; filter?: any; } export async function queryCollection(args: QueryCollectionArgs, gqlTypes) { + const { collection, filter, ...rest } = args; const query = `{ ${args.query}${getFilter(args.filter)} { - ${getCollectionQuery(args.collection, gqlTypes, { depth: args.depth })} + ${getCollectionQuery(args.collection, gqlTypes, rest)} } } `; - const results = await api.post({ query }).json(); return results.data[args.query]; } @@ -149,6 +169,14 @@ export function getComponentType(type) { return kind.toLowerCase(); } +export function getNameFromLabel(label?: string) { + if (!label) return undefined; + return label + .replace(/^all/, '') + .replace(/([A-Z])/g, ' $1') + .trim(); +} + // sort specific fields higher than the rest, in order const fieldSortWeights = ['name', 'title']; @@ -159,22 +187,23 @@ function weightedSort(a: string, b: string) { return fieldSortWeights.length - aw - (fieldSortWeights.length - bw); } -export function transformSchema(schema) { - const fields = +export function transformSchema(schema: GqlSchema, querySchemaFieldMap: Record) { + const fields: Field[] = schema.fields - ?.map((field) => { + ?.map((field: GqlField) => { return { - label: capitalize(field.name.replace(/_+/g, ' ')).trim(), + label: capitalize(field.name.replace(/_+/g, ' ').trim()), name: field.name, description: field.description, type: field.type, disabled: field.name.startsWith('_') || field.name === 'id', - component: getComponentType(field.type) + component: getComponentType(field.type), + collection: field.type.kind === 'OBJECT' ? field.type.name : undefined }; }) - .sort((a, b) => { - if (a.readOnly && !b.readOnly) return 1; - if (!a.readOnly && b.readOnly) return -1; + .sort((a: Field, b: Field) => { + if (a.disabled && !b.disabled) return 1; + if (!a.disabled && b.disabled) return -1; if (a.type.kind !== 'SCALAR' && b.type.kind === 'SCALAR') return 1; if (a.type.kind === 'SCALAR' && b.type.kind !== 'SCALAR') return -1; @@ -188,6 +217,9 @@ export function transformSchema(schema) { const result = { ...schema, + component: schema.kind.toLowerCase(), + label: getNameFromLabel(schema.name), + pluralName: getNameFromLabel(querySchemaFieldMap[schema.name]?.name), referenceField, fields }; diff --git a/packages/editor/src/lib/config.ts b/packages/editor/src/lib/config.ts index 655789fc..719637e7 100644 --- a/packages/editor/src/lib/config.ts +++ b/packages/editor/src/lib/config.ts @@ -1,29 +1,32 @@ -import fs from 'node:fs/promises'; -import path from 'node:path'; -import { isEqual, mapValues, merge } from 'lodash-es'; import yaml from 'js-yaml'; +import { isArray, isEqual, keyBy, merge, mergeWith } from 'lodash-es'; import crypto from 'node:crypto'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import type { GqlSchema } from './types'; function replacer(key, value) { if (key === 'type') return undefined; if (value === null) return undefined; - if (key === 'readOnly' && value === false) return undefined; + if (key === 'disabled' && value === false) return undefined; return value; } +// TODO: capture + export default class Config { - static getPath(schema) { + static getPath(schema: GqlSchema) { return path.resolve( process.cwd(), '.flatbread', 'schemas', - `${schema.schema.name + `${schema.name .replace(/([A-Z])/g, '-$1') .replace(/^\-/, '') .toLowerCase()}.yaml` ); } - static async exists(schema: string) { + static async exists(schema: GqlSchema) { try { return await fs.stat(this.getPath(schema)); } catch (e) { @@ -32,33 +35,38 @@ export default class Config { } } - static async get(collectionName: string, schema) { + static async get(collectionName: string, schema: GqlSchema) { let existing; let filePath = this.getPath(schema); + + //if the file exists load it and merge the fresh graphql schema into it if (await this.exists(schema)) { const file = await fs.readFile(filePath, 'utf-8'); existing = yaml.load(file); - merge(schema, existing); + + schema = mergeWith(schema, existing, function (a, b) { + if (isArray(a)) { + const aMap = keyBy(a, 'name'); + return b.map((field) => { + return merge(aMap[field.name], field); + }); + } + }); } else { await fs.mkdir(path.dirname(filePath), { recursive: true }); } + // attach a meta tag and get an accurate hash for caching const meta = schema.meta ?? {}; schema.meta = undefined; - meta.hash = crypto.createHmac('sha1', String(schema)).digest('base64'); + meta.hash = crypto.createHmac('sha1', JSON.stringify(schema)).digest('base64'); schema.meta = meta; + // if the hash doesn't match the file hash, update it if (!isEqual(existing?.meta?.hash, schema?.meta?.hash)) { console.log('writing config', collectionName); - await fs.writeFile( - filePath, - yaml.dump(schema, { - flowLevel: 3, - replacer - }), - 'utf-8' - ); + await fs.writeFile(filePath, yaml.dump(schema, { flowLevel: 3, replacer }), 'utf-8'); } return schema; diff --git a/packages/editor/src/lib/types.ts b/packages/editor/src/lib/types.ts new file mode 100644 index 00000000..189bb3d6 --- /dev/null +++ b/packages/editor/src/lib/types.ts @@ -0,0 +1,27 @@ +interface GqlType { + kind: string; + name: string; +} + +export interface GqlField { + name: string; + description?: string; + type: GqlType & { ofType?: GqlType }; +} + +export interface GqlSchema { + name: string; + description?: string; + kind: string; + fields: GqlField[]; +} + +export interface Field { + label: string; + name: string; + type: GqlField['type']; + description?: string; + disabled?: boolean; + component: string; + collection?: string; +} diff --git a/packages/editor/src/routes/collection/[name]/index.svelte b/packages/editor/src/routes/collection/[name]/index.svelte index 6888b929..3e0a7fe3 100644 --- a/packages/editor/src/routes/collection/[name]/index.svelte +++ b/packages/editor/src/routes/collection/[name]/index.svelte @@ -4,7 +4,7 @@ export async function load({ params, url, session }) { const { gqlTypes, queryTypes } = session; const querySchema = queryTypes.get(params.name); - console.log({ queryTypes, params, querySchema}) + console.log({ queryTypes, params, querySchema }); const collection = querySchema.schema; const results = await queryCollection( { query: params.name, collection: collection.name }, diff --git a/packages/editor/src/routes/index.svelte b/packages/editor/src/routes/index.svelte index 97957db8..3f24d2d0 100644 --- a/packages/editor/src/routes/index.svelte +++ b/packages/editor/src/routes/index.svelte @@ -2,7 +2,6 @@ import { getSession } from '$lib/api'; const { gqlTypes, queryTypes } = getSession(); -
From 199d9822f4b928ba0410e01e9adf1785b8b172b2 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sat, 30 Jul 2022 01:20:21 -0500 Subject: [PATCH 05/26] put disabled fields in collapsible region at the bottom --- packages/editor/src/hooks.ts | 14 ++- packages/editor/src/lib/api.ts | 119 +++++------------- packages/editor/src/lib/fields/float.svelte | 16 +++ packages/editor/src/lib/fields/int.svelte | 16 +++ packages/editor/src/lib/fields/list.svelte | 3 +- packages/editor/src/lib/fields/object.svelte | 37 +++++- packages/editor/src/lib/schema.ts | 66 ++++++++++ packages/editor/src/lib/types.ts | 8 +- .../src/routes/collection/[name]/index.svelte | 6 + 9 files changed, 184 insertions(+), 101 deletions(-) create mode 100644 packages/editor/src/lib/fields/float.svelte create mode 100644 packages/editor/src/lib/fields/int.svelte create mode 100644 packages/editor/src/lib/schema.ts diff --git a/packages/editor/src/hooks.ts b/packages/editor/src/hooks.ts index c69c31f6..905dac49 100644 --- a/packages/editor/src/hooks.ts +++ b/packages/editor/src/hooks.ts @@ -1,5 +1,6 @@ -import { getGqlTypes, getNameFromLabel } from '$lib/api'; -import Config from './lib/config'; +import { getGqlTypes } from '$lib/api'; +import { getNameFromLabel } from '$lib/schema'; +import type { GqlQueryCollection, GqlSchema } from '$lib/types'; /** @type {import('@sveltejs/kit').GetSession} */ export function getSession(event) { @@ -23,10 +24,11 @@ export async function handle({ event, resolve }) { const { gqlTypes, queryListFields } = await getGqlTypes(); const queryTypesList = queryListFields - .map((field) => { - field.schema = gqlTypes.get(field.type.ofType.name); - field.label = getNameFromLabel(field.name); - return [field.name, field]; + .map<[string, GqlQueryCollection]>((field) => { + const newField = field as GqlQueryCollection; + newField.schema = gqlTypes.get(newField?.type?.ofType?.name as string) as GqlSchema; + newField.label = getNameFromLabel(newField.name); + return [field.name, newField]; }) .sort((a, b) => a[1].schema.pluralName.localeCompare(b[1].schema.pluralName)); diff --git a/packages/editor/src/lib/api.ts b/packages/editor/src/lib/api.ts index b8868b28..7113b42c 100644 --- a/packages/editor/src/lib/api.ts +++ b/packages/editor/src/lib/api.ts @@ -1,9 +1,10 @@ import { getStores } from '$app/stores'; -import { capitalize, keyBy } from 'lodash-es'; +import type { GqlSchema } from '$lib/types'; +import { keyBy } from 'lodash-es'; import { get } from 'svelte/store'; import wretch from 'wretch'; -import type { Field, GqlField, GqlSchema } from '$lib/types'; import Config from './config'; +import { transformSchema } from './schema'; const api = wretch().url('http://localhost:5057/graphql'); @@ -57,8 +58,6 @@ export async function getCollectionFields(name: string) { return schema.data.__type; } -// __schema type Query has all queries in fields, fields of type list has all collections - export async function getGqlTypes() { const result = await api .post({ @@ -92,10 +91,8 @@ export async function getGqlTypes() { ); const querySchema = keyBy(queryListFields, 'type.ofType.name'); - console.log(querySchema); - const gqlTypes = await Promise.all( - types.map(async (t) => { + types.map>(async (t) => { const shouldConfig = !t.name.startsWith('__') && t.kind === 'OBJECT'; const schema = transformSchema(t, querySchema); return [t.name, shouldConfig ? await Config.get(t.name, schema) : schema]; @@ -116,24 +113,30 @@ interface GetCollectionQueryArgs { function getCollectionQuery( collectionName: string, - gqlTypes, + gqlTypes: Map, { visits = 2, depth = Infinity, visited = {} }: GetCollectionQueryArgs -) { +): string { const collection = gqlTypes.get(collectionName); console.log({ collection, collectionName }); - return collection.fields - .map((field) => { - if (field.type.kind === 'SCALAR' || field.type.ofType?.kind === 'SCALAR') return field.name; - const kind: string = field.type.kind === 'LIST' ? field.type.ofType.name : field.type.name; - depth--; - if (depth < 0) return ''; - if (visited[kind] > visits) return ''; - visited[kind] = (visited[kind] ?? 0) + 1; - return `${field.name} { ${getCollectionQuery(kind, gqlTypes, { depth, visited, visits })} }`; - }) - .join(' '); + return ( + collection?.fields + .map((field) => { + if (field.type.kind === 'SCALAR' || field.type.ofType?.kind === 'SCALAR') return field.name; + const kind: string = field.type.kind === 'LIST' ? field.type.ofType.name : field.type.name; + depth--; + if (depth < 0) return ''; + if (visited[kind] > visits) return ''; + visited[kind] = (visited[kind] ?? 0) + 1; + return `${field.name} { ${getCollectionQuery(kind, gqlTypes, { + depth, + visited, + visits + })} }`; + }) + .join(' ') ?? '' + ); } export function sanitizeGlobImport([key, value]: [string, any]) { @@ -151,78 +154,14 @@ interface QueryCollectionArgs extends GetCollectionQueryArgs { filter?: any; } -export async function queryCollection(args: QueryCollectionArgs, gqlTypes) { - const { collection, filter, ...rest } = args; - const query = `{ - ${args.query}${getFilter(args.filter)} { - ${getCollectionQuery(args.collection, gqlTypes, rest)} +export async function queryCollection(args: QueryCollectionArgs, gqlTypes: Map) { + const { query, collection, filter, ...rest } = args; + const gqlQuery = `{ + ${query}${getFilter(filter)} { + ${getCollectionQuery(collection, gqlTypes, rest)} } } `; - const results = await api.post({ query }).json(); + const results = await api.post({ query: gqlQuery }).json(); return results.data[args.query]; } - -export function getComponentType(type) { - const { kind, name } = type; - if (kind === 'SCALAR') return name.toLowerCase(); - return kind.toLowerCase(); -} - -export function getNameFromLabel(label?: string) { - if (!label) return undefined; - return label - .replace(/^all/, '') - .replace(/([A-Z])/g, ' $1') - .trim(); -} - -// sort specific fields higher than the rest, in order -const fieldSortWeights = ['name', 'title']; - -function weightedSort(a: string, b: string) { - const aw = fieldSortWeights.indexOf(a); - const bw = fieldSortWeights.indexOf(b); - if (aw < 0 && bw < 0) return undefined; - return fieldSortWeights.length - aw - (fieldSortWeights.length - bw); -} - -export function transformSchema(schema: GqlSchema, querySchemaFieldMap: Record) { - const fields: Field[] = - schema.fields - ?.map((field: GqlField) => { - return { - label: capitalize(field.name.replace(/_+/g, ' ').trim()), - name: field.name, - description: field.description, - type: field.type, - disabled: field.name.startsWith('_') || field.name === 'id', - component: getComponentType(field.type), - collection: field.type.kind === 'OBJECT' ? field.type.name : undefined - }; - }) - .sort((a: Field, b: Field) => { - if (a.disabled && !b.disabled) return 1; - if (!a.disabled && b.disabled) return -1; - if (a.type.kind !== 'SCALAR' && b.type.kind === 'SCALAR') return 1; - if (a.type.kind === 'SCALAR' && b.type.kind !== 'SCALAR') return -1; - - return ( - weightedSort(a.name.toLowerCase(), b.name.toLowerCase()) ?? a.name.localeCompare(b.name) - ); - }) || []; - - const referenceField = - ['name', 'title'].find((fieldName) => fields.find((field) => field.name === fieldName)) ?? 'id'; - - const result = { - ...schema, - component: schema.kind.toLowerCase(), - label: getNameFromLabel(schema.name), - pluralName: getNameFromLabel(querySchemaFieldMap[schema.name]?.name), - referenceField, - fields - }; - - return result; -} diff --git a/packages/editor/src/lib/fields/float.svelte b/packages/editor/src/lib/fields/float.svelte new file mode 100644 index 00000000..87d0edf2 --- /dev/null +++ b/packages/editor/src/lib/fields/float.svelte @@ -0,0 +1,16 @@ + + + diff --git a/packages/editor/src/lib/fields/int.svelte b/packages/editor/src/lib/fields/int.svelte new file mode 100644 index 00000000..87d0edf2 --- /dev/null +++ b/packages/editor/src/lib/fields/int.svelte @@ -0,0 +1,16 @@ + + + diff --git a/packages/editor/src/lib/fields/list.svelte b/packages/editor/src/lib/fields/list.svelte index 383a4461..9f396f68 100644 --- a/packages/editor/src/lib/fields/list.svelte +++ b/packages/editor/src/lib/fields/list.svelte @@ -1,5 +1,6 @@ @@ -31,7 +34,7 @@ {#if !inList && field.description}{field.description}{/if}
- {#each collection.fields as field} + {#each editableFields as field} {#if !field.hidden} {#if field.component === 'object'} @@ -44,9 +47,37 @@ {/if} {/if} {/each} - {#if !inList} - + {#if disabledFields.length > 0} +
+ Show disabled fields +
+ {#each disabledFields as field} + {#if field.component === 'object'} + + {:else} + + {/if} + {/each} +
+
{/if}
{/if} + + diff --git a/packages/editor/src/lib/schema.ts b/packages/editor/src/lib/schema.ts new file mode 100644 index 00000000..b00fa4d5 --- /dev/null +++ b/packages/editor/src/lib/schema.ts @@ -0,0 +1,66 @@ +import { capitalize } from 'lodash-es'; +import type { Field, GqlField, GqlSchema, GqlType } from './types'; + +export function getComponentType(type: GqlType) { + const { kind, name } = type; + if (kind === 'SCALAR') return name.toLowerCase(); + return kind.toLowerCase(); +} + +export function getNameFromLabel(label?: string) { + if (!label) return undefined; + return label + .replace(/^all/, '') + .replace(/([A-Z])/g, ' $1') + .trim(); +} + +// sort specific fields higher than the rest, in order +const fieldSortWeights = ['name', 'title']; + +function weightedSort(a: string, b: string) { + const aw = fieldSortWeights.indexOf(a); + const bw = fieldSortWeights.indexOf(b); + if (aw < 0 && bw < 0) return undefined; + return fieldSortWeights.length - aw - (fieldSortWeights.length - bw); +} + +export function transformSchema(schema: GqlSchema, querySchemaFieldMap: Record) { + const fields: Field[] = + schema.fields + ?.map((field: GqlField) => { + return { + label: capitalize(field.name.replace(/_+/g, ' ').trim()), + name: field.name, + description: field.description, + type: field.type, + disabled: field.name.startsWith('_') || field.name === 'id', + component: getComponentType(field.type), + collection: field.type.kind === 'OBJECT' ? field.type.name : undefined + }; + }) + .sort((a: Field, b: Field) => { + if (a.disabled && !b.disabled) return 1; + if (!a.disabled && b.disabled) return -1; + if (a.type.kind !== 'SCALAR' && b.type.kind === 'SCALAR') return 1; + if (a.type.kind === 'SCALAR' && b.type.kind !== 'SCALAR') return -1; + + return ( + weightedSort(a.name.toLowerCase(), b.name.toLowerCase()) ?? a.name.localeCompare(b.name) + ); + }) || []; + + const referenceField = + ['name', 'title'].find((fieldName) => fields.find((field) => field.name === fieldName)) ?? 'id'; + + const result = { + ...schema, + component: schema.kind.toLowerCase(), + label: getNameFromLabel(schema.name), + pluralName: getNameFromLabel(querySchemaFieldMap[schema.name]?.name), + referenceField, + fields + }; + + return result; +} diff --git a/packages/editor/src/lib/types.ts b/packages/editor/src/lib/types.ts index 189bb3d6..a99442a2 100644 --- a/packages/editor/src/lib/types.ts +++ b/packages/editor/src/lib/types.ts @@ -1,4 +1,4 @@ -interface GqlType { +export interface GqlType { kind: string; name: string; } @@ -11,6 +11,7 @@ export interface GqlField { export interface GqlSchema { name: string; + pluralName: string; description?: string; kind: string; fields: GqlField[]; @@ -25,3 +26,8 @@ export interface Field { component: string; collection?: string; } + +export interface GqlQueryCollection extends GqlField { + schema: GqlSchema; + label?: string; +} diff --git a/packages/editor/src/routes/collection/[name]/index.svelte b/packages/editor/src/routes/collection/[name]/index.svelte index 3e0a7fe3..7323276d 100644 --- a/packages/editor/src/routes/collection/[name]/index.svelte +++ b/packages/editor/src/routes/collection/[name]/index.svelte @@ -50,6 +50,7 @@ {#each results as row} location.assign(`/collection/${querySchema.name}/${row.id}`)} > @@ -64,4 +65,9 @@
From 72b24015f3c6c8cfd79d20dbb9c0b50a1fee2089 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sun, 31 Jul 2022 18:14:32 -0500 Subject: [PATCH 06/26] add typings --- .../.flatbread/schemas/author_-skills.yaml | 2 +- .../.flatbread/schemas/author__content.yaml | 2 +- .../.flatbread/schemas/flatbread-image.yaml | 2 +- .../schemas/override-test_-array2.yaml | 2 +- .../schemas/override-test_-array3.yaml | 2 +- .../schemas/override-test_-array3_-obj.yaml | 2 +- .../schemas/override-test_-deeply.yaml | 2 +- .../schemas/override-test__content.yaml | 2 +- .../schemas/post-category-blob__content.yaml | 2 +- .../schemas/post-category__content.yaml | 2 +- .../.flatbread/schemas/post__content.yaml | 2 +- packages/editor/.flatbread/schemas/query.yaml | 2 +- .../.flatbread/schemas/yaml-author.yaml | 4 +-- .../schemas/yaml-author_-skills.yaml | 2 +- .../schemas/yaml-author__content.yaml | 2 +- packages/editor/src/hooks.ts | 10 +++--- packages/editor/src/lib/api.ts | 16 ++-------- packages/editor/src/lib/config.ts | 5 +-- packages/editor/src/lib/fields/list.svelte | 2 +- packages/editor/src/lib/fields/object.svelte | 22 +++++++++---- packages/editor/src/lib/schema.ts | 8 ++--- packages/editor/src/lib/schemaStore.ts | 1 - packages/editor/src/lib/types.ts | 32 +++++++++++++++---- packages/editor/src/lib/utils.ts | 11 +++++++ packages/editor/src/routes/__layout.svelte | 2 +- .../src/routes/collection/[name]/[id].svelte | 12 ++++--- .../src/routes/collection/[name]/index.svelte | 9 +++--- .../src/routes/collection/[name]/new.svelte | 9 ++++-- packages/editor/src/routes/index.svelte | 2 +- 29 files changed, 103 insertions(+), 70 deletions(-) create mode 100644 packages/editor/src/lib/utils.ts diff --git a/packages/editor/.flatbread/schemas/author_-skills.yaml b/packages/editor/.flatbread/schemas/author_-skills.yaml index 32054e94..0ac94631 100644 --- a/packages/editor/.flatbread/schemas/author_-skills.yaml +++ b/packages/editor/.flatbread/schemas/author_-skills.yaml @@ -20,4 +20,4 @@ component: object label: Author_ Skills referenceField: id meta: - hash: Le/pUcMNDHHL/Kr+Bl3AvMJcKjc= + hash: Blv5+KF1qwWNDdU3K6uCT40U6HU= diff --git a/packages/editor/.flatbread/schemas/author__content.yaml b/packages/editor/.flatbread/schemas/author__content.yaml index 43ce54cb..71bee953 100644 --- a/packages/editor/.flatbread/schemas/author__content.yaml +++ b/packages/editor/.flatbread/schemas/author__content.yaml @@ -20,4 +20,4 @@ component: object label: Author__content referenceField: id meta: - hash: Ekj17d0uRy3TbJFYZ13muZOqoXk= + hash: 8+fJdGTuCY8ij7xoqxZI8xCos80= diff --git a/packages/editor/.flatbread/schemas/flatbread-image.yaml b/packages/editor/.flatbread/schemas/flatbread-image.yaml index 82bbc1fa..0e147520 100644 --- a/packages/editor/.flatbread/schemas/flatbread-image.yaml +++ b/packages/editor/.flatbread/schemas/flatbread-image.yaml @@ -11,4 +11,4 @@ component: object label: Flatbread Image referenceField: id meta: - hash: EpGAkm9XU4WWm8xiJts2g8EEFLw= + hash: Nyxi7MGNUsy3mt1BsS8/YzdwNeQ= diff --git a/packages/editor/.flatbread/schemas/override-test_-array2.yaml b/packages/editor/.flatbread/schemas/override-test_-array2.yaml index 5ea3578f..d0dd0707 100644 --- a/packages/editor/.flatbread/schemas/override-test_-array2.yaml +++ b/packages/editor/.flatbread/schemas/override-test_-array2.yaml @@ -8,4 +8,4 @@ component: object label: Override Test_ Array2 referenceField: id meta: - hash: LRXQYmbIu3bPgYYkLTLiF/REii8= + hash: qKSJky1zrZ5je3dtuAaQug5kAeE= diff --git a/packages/editor/.flatbread/schemas/override-test_-array3.yaml b/packages/editor/.flatbread/schemas/override-test_-array3.yaml index d82a900b..68076539 100644 --- a/packages/editor/.flatbread/schemas/override-test_-array3.yaml +++ b/packages/editor/.flatbread/schemas/override-test_-array3.yaml @@ -9,4 +9,4 @@ component: object label: Override Test_ Array3 referenceField: id meta: - hash: nPeV3CaN7bk4HRYvZ6M23I0psWU= + hash: 34791d5i8uHnVwwh6lXB/MVzq4I= diff --git a/packages/editor/.flatbread/schemas/override-test_-array3_-obj.yaml b/packages/editor/.flatbread/schemas/override-test_-array3_-obj.yaml index d1097433..d3f89a4c 100644 --- a/packages/editor/.flatbread/schemas/override-test_-array3_-obj.yaml +++ b/packages/editor/.flatbread/schemas/override-test_-array3_-obj.yaml @@ -8,4 +8,4 @@ component: object label: Override Test_ Array3_ Obj referenceField: id meta: - hash: cB+oN67t9u+4Jg3Z8dbENDnI6LA= + hash: 7OMtizm7p4QC4GG9n5dL+L/uiM0= diff --git a/packages/editor/.flatbread/schemas/override-test_-deeply.yaml b/packages/editor/.flatbread/schemas/override-test_-deeply.yaml index 9dc37258..4ce06f18 100644 --- a/packages/editor/.flatbread/schemas/override-test_-deeply.yaml +++ b/packages/editor/.flatbread/schemas/override-test_-deeply.yaml @@ -8,4 +8,4 @@ component: object label: Override Test_ Deeply referenceField: id meta: - hash: 8olmxrqF+7RQ4+snnCEexrAIduc= + hash: JPYpOfi5x9JdHEush+FzeoW2Ybs= diff --git a/packages/editor/.flatbread/schemas/override-test__content.yaml b/packages/editor/.flatbread/schemas/override-test__content.yaml index 02ef1d01..e2748895 100644 --- a/packages/editor/.flatbread/schemas/override-test__content.yaml +++ b/packages/editor/.flatbread/schemas/override-test__content.yaml @@ -20,4 +20,4 @@ component: object label: Override Test__content referenceField: id meta: - hash: 27ZZI2RjWWSJII8r2YFZuoDXCN0= + hash: vuNQhfGHdxZdWDR+JoDUvw9iWoY= diff --git a/packages/editor/.flatbread/schemas/post-category-blob__content.yaml b/packages/editor/.flatbread/schemas/post-category-blob__content.yaml index ab4fb9f4..cf9d82e5 100644 --- a/packages/editor/.flatbread/schemas/post-category-blob__content.yaml +++ b/packages/editor/.flatbread/schemas/post-category-blob__content.yaml @@ -20,4 +20,4 @@ component: object label: Post Category Blob__content referenceField: id meta: - hash: MITSpn0srO5TZ3eq4Bk2NJADKt8= + hash: DeMt2PvrPKtARExIkIszULw0NlE= diff --git a/packages/editor/.flatbread/schemas/post-category__content.yaml b/packages/editor/.flatbread/schemas/post-category__content.yaml index ef70c588..df69bc4c 100644 --- a/packages/editor/.flatbread/schemas/post-category__content.yaml +++ b/packages/editor/.flatbread/schemas/post-category__content.yaml @@ -20,4 +20,4 @@ component: object label: Post Category__content referenceField: id meta: - hash: cnM5U561USPrGoU4WUWs70HAGnQ= + hash: 0WeMO01dh/WzfHFXy1myQ/oF5f0= diff --git a/packages/editor/.flatbread/schemas/post__content.yaml b/packages/editor/.flatbread/schemas/post__content.yaml index 9eaaa2c9..cc82d3e2 100644 --- a/packages/editor/.flatbread/schemas/post__content.yaml +++ b/packages/editor/.flatbread/schemas/post__content.yaml @@ -20,4 +20,4 @@ component: object label: Post__content referenceField: id meta: - hash: PEXY65G7pFIKFXYZcpUoqMDLNqs= + hash: KC6ZT6xj6NEQ80UolzqR3W8mJo8= diff --git a/packages/editor/.flatbread/schemas/query.yaml b/packages/editor/.flatbread/schemas/query.yaml index ee30b27f..471352d1 100644 --- a/packages/editor/.flatbread/schemas/query.yaml +++ b/packages/editor/.flatbread/schemas/query.yaml @@ -59,4 +59,4 @@ component: object label: Query referenceField: id meta: - hash: LZ9Md7LOMyUIwXPnBmhnxofM5bE= + hash: rXgvtTxZ7oy9+5ZQ+o+10pFOznc= diff --git a/packages/editor/.flatbread/schemas/yaml-author.yaml b/packages/editor/.flatbread/schemas/yaml-author.yaml index 9f444f8f..d87cf5a3 100644 --- a/packages/editor/.flatbread/schemas/yaml-author.yaml +++ b/packages/editor/.flatbread/schemas/yaml-author.yaml @@ -47,7 +47,7 @@ fields: collection: YamlAuthor__content component: object label: Yaml Author -pluralName: Authors (Yaml) +pluralName: Yaml Authors referenceField: name meta: - hash: g0Rr4CZt9guOrAgv0PrNOnIhjdg= + hash: M2rEU7eSlHf6OKNjxsTJlgZDg8M= diff --git a/packages/editor/.flatbread/schemas/yaml-author_-skills.yaml b/packages/editor/.flatbread/schemas/yaml-author_-skills.yaml index ad535d48..a7e19956 100644 --- a/packages/editor/.flatbread/schemas/yaml-author_-skills.yaml +++ b/packages/editor/.flatbread/schemas/yaml-author_-skills.yaml @@ -23,4 +23,4 @@ component: object label: Yaml Author_ Skills referenceField: id meta: - hash: EraBF4GYQg2wjaeu4MEoihjMDtU= + hash: MUOpWQ0pjfaKHhaaOYZsP7fQFsA= diff --git a/packages/editor/.flatbread/schemas/yaml-author__content.yaml b/packages/editor/.flatbread/schemas/yaml-author__content.yaml index c01112df..c5a39218 100644 --- a/packages/editor/.flatbread/schemas/yaml-author__content.yaml +++ b/packages/editor/.flatbread/schemas/yaml-author__content.yaml @@ -17,4 +17,4 @@ component: object label: Yaml Author__content referenceField: id meta: - hash: jiauBo7x7XYpRnBd6AjHP6Gd1Dk= + hash: JYC+GoUaXhIhwx/Fokj49mFJq6o= diff --git a/packages/editor/src/hooks.ts b/packages/editor/src/hooks.ts index 905dac49..95e76419 100644 --- a/packages/editor/src/hooks.ts +++ b/packages/editor/src/hooks.ts @@ -1,6 +1,6 @@ import { getGqlTypes } from '$lib/api'; import { getNameFromLabel } from '$lib/schema'; -import type { GqlQueryCollection, GqlSchema } from '$lib/types'; +import type { QueryCollection, GqlSchema, Schema } from '$lib/types'; /** @type {import('@sveltejs/kit').GetSession} */ export function getSession(event) { @@ -24,9 +24,9 @@ export async function handle({ event, resolve }) { const { gqlTypes, queryListFields } = await getGqlTypes(); const queryTypesList = queryListFields - .map<[string, GqlQueryCollection]>((field) => { - const newField = field as GqlQueryCollection; - newField.schema = gqlTypes.get(newField?.type?.ofType?.name as string) as GqlSchema; + .map<[string, QueryCollection]>((field) => { + const newField = field as QueryCollection; + newField.schema = gqlTypes.get(newField?.type?.ofType?.name as string) as Schema; newField.label = getNameFromLabel(newField.name); return [field.name, newField]; }) @@ -34,7 +34,7 @@ export async function handle({ event, resolve }) { const queryTypes = new Map(queryTypesList); - gqlTypes.set('Query', queryTypes); + // gqlTypes.set('Query', queryTypes); event.locals = { gqlTypes, diff --git a/packages/editor/src/lib/api.ts b/packages/editor/src/lib/api.ts index 7113b42c..47941bd9 100644 --- a/packages/editor/src/lib/api.ts +++ b/packages/editor/src/lib/api.ts @@ -1,17 +1,11 @@ -import { getStores } from '$app/stores'; -import type { GqlSchema } from '$lib/types'; +import type { GqlSchema, Schema } from '$lib/types'; import { keyBy } from 'lodash-es'; -import { get } from 'svelte/store'; import wretch from 'wretch'; import Config from './config'; import { transformSchema } from './schema'; const api = wretch().url('http://localhost:5057/graphql'); -export function getSession() { - return get(getStores().session); -} - export async function getSchema() { const schema = await api .post({ @@ -92,7 +86,7 @@ export async function getGqlTypes() { const querySchema = keyBy(queryListFields, 'type.ofType.name'); const gqlTypes = await Promise.all( - types.map>(async (t) => { + types.map>(async (t) => { const shouldConfig = !t.name.startsWith('__') && t.kind === 'OBJECT'; const schema = transformSchema(t, querySchema); return [t.name, shouldConfig ? await Config.get(t.name, schema) : schema]; @@ -118,8 +112,6 @@ function getCollectionQuery( ): string { const collection = gqlTypes.get(collectionName); - console.log({ collection, collectionName }); - return ( collection?.fields .map((field) => { @@ -139,10 +131,6 @@ function getCollectionQuery( ); } -export function sanitizeGlobImport([key, value]: [string, any]) { - return [key.replace(/^.*\//, '').replace(/\..*$/, ''), value.default]; -} - function getFilter(filter: any) { if (!filter) return ''; return `(filter: ${filter})`; diff --git a/packages/editor/src/lib/config.ts b/packages/editor/src/lib/config.ts index 719637e7..bb3610f1 100644 --- a/packages/editor/src/lib/config.ts +++ b/packages/editor/src/lib/config.ts @@ -3,11 +3,12 @@ import { isArray, isEqual, keyBy, merge, mergeWith } from 'lodash-es'; import crypto from 'node:crypto'; import fs from 'node:fs/promises'; import path from 'node:path'; -import type { GqlSchema } from './types'; +import type { GqlSchema, Schema } from './types'; function replacer(key, value) { if (key === 'type') return undefined; if (value === null) return undefined; + if (value === '') return undefined; if (key === 'disabled' && value === false) return undefined; return value; } @@ -35,7 +36,7 @@ export default class Config { } } - static async get(collectionName: string, schema: GqlSchema) { + static async get(collectionName: string, schema: Schema) { let existing; let filePath = this.getPath(schema); diff --git a/packages/editor/src/lib/fields/list.svelte b/packages/editor/src/lib/fields/list.svelte index 9f396f68..3853f8ad 100644 --- a/packages/editor/src/lib/fields/list.svelte +++ b/packages/editor/src/lib/fields/list.svelte @@ -1,5 +1,5 @@
diff --git a/packages/editor/src/routes/index.svelte b/packages/editor/src/routes/index.svelte index 3f24d2d0..ecb1caff 100644 --- a/packages/editor/src/routes/index.svelte +++ b/packages/editor/src/routes/index.svelte @@ -1,5 +1,5 @@ From ceb769755a9531dc47ecb26e1320a6edc3af928f Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Tue, 2 Aug 2022 23:54:04 -0500 Subject: [PATCH 07/26] wip --- .../src/generators/collectionMutations.ts | 36 ++++++ .../core/src/generators/collectionQueries.ts | 92 ++++++++++++++ packages/core/src/generators/schema.ts | 119 ++++-------------- packages/transformer-yaml/src/index.ts | 12 +- 4 files changed, 161 insertions(+), 98 deletions(-) create mode 100644 packages/core/src/generators/collectionMutations.ts create mode 100644 packages/core/src/generators/collectionQueries.ts diff --git a/packages/core/src/generators/collectionMutations.ts b/packages/core/src/generators/collectionMutations.ts new file mode 100644 index 00000000..a20ac161 --- /dev/null +++ b/packages/core/src/generators/collectionMutations.ts @@ -0,0 +1,36 @@ +import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose'; +import { LoadedFlatbreadConfig } from '../types'; + +export interface AddCollectionMutationsArgs { + name: string; + pluralName: string; + config: LoadedFlatbreadConfig; + objectComposer: ObjectTypeComposer; + schemaComposer: SchemaComposer; + allContentNodesJSON: Record; +} + +export default function addCollectionMutations( + args: AddCollectionMutationsArgs +) { + const { + name, + pluralName, + config, + objectComposer, + schemaComposer, + allContentNodesJSON, + } = args; + + schemaComposer.Mutation.addFields({ + [`upsert${name}`]: { + type: objectComposer, + args: { [name]: objectComposer.getInputType() }, + description: `Update or create a ${name}`, + async resolve(_, payload) { + console.dir({ payload }, { depth: Infinity }); + return payload; + }, + }, + }); +} diff --git a/packages/core/src/generators/collectionQueries.ts b/packages/core/src/generators/collectionQueries.ts new file mode 100644 index 00000000..98ddc1ce --- /dev/null +++ b/packages/core/src/generators/collectionQueries.ts @@ -0,0 +1,92 @@ +import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose'; +import resolveQueryArgs from '../resolvers/arguments'; + +import { + generateArgsForAllItemQuery, + generateArgsForManyItemQuery, + generateArgsForSingleItemQuery, +} from '../generators/arguments'; +import { cloneDeep } from 'lodash-es'; +import { EntryNode, LoadedFlatbreadConfig } from '../types'; + +export interface AddCollectionQueriesArgs { + name: string; + pluralName: string; + config: LoadedFlatbreadConfig; + objectComposer: ObjectTypeComposer; + schemaComposer: SchemaComposer; + allContentNodesJSON: Record; +} + +export default function addCollectionQueries(args: AddCollectionQueriesArgs) { + const { + name, + pluralName, + config, + objectComposer, + schemaComposer, + allContentNodesJSON, + } = args; + + const pluralTypeQueryName = 'all' + pluralName; + + objectComposer.addResolver({ + name: 'findById', + type: () => objectComposer, + description: `Find one ${name} by its ID`, + args: generateArgsForSingleItemQuery(), + resolve: (rp: Record) => + cloneDeep(allContentNodesJSON[name]).find( + (node: EntryNode) => node.id === rp.args.id + ), + }); + + objectComposer.addResolver({ + name: 'findMany', + type: () => [objectComposer], + description: `Find many ${pluralName} by their IDs`, + args: generateArgsForManyItemQuery(pluralName), + resolve: (rp: Record) => { + const idsToFind = rp.args.ids ?? []; + const matches = + cloneDeep(allContentNodesJSON[name])?.filter((node: EntryNode) => + idsToFind?.includes(node.id) + ) ?? []; + return resolveQueryArgs(matches, rp.args, config, { + type: { + name: name, + pluralName: pluralName, + pluralQueryName: pluralTypeQueryName, + }, + }); + }, + }); + + objectComposer.addResolver({ + name: 'all', + args: generateArgsForAllItemQuery(pluralName), + type: () => [objectComposer], + description: `Return a set of ${pluralName}`, + resolve: (rp: Record) => { + const nodes = cloneDeep(allContentNodesJSON[name]); + return resolveQueryArgs(nodes, rp.args, config, { + type: { + name: name, + pluralName: pluralName, + pluralQueryName: pluralTypeQueryName, + }, + }); + }, + }); + + schemaComposer.Query.addFields({ + /** + * Add find by ID to each content type + */ + [name]: objectComposer.getResolver('findById'), + /** + * Add find 'many' to each content type + */ + [pluralTypeQueryName]: objectComposer.getResolver('all'), + }); +} diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index d8f24283..2bf98494 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -1,28 +1,15 @@ import { schemaComposer } from 'graphql-compose'; import { composeWithJson } from 'graphql-compose-json'; -import { cloneDeep, defaultsDeep, merge } from 'lodash-es'; +import { defaultsDeep, merge } from 'lodash-es'; import plur from 'plur'; import { VFile } from 'vfile'; -import { - generateArgsForAllItemQuery, - generateArgsForManyItemQuery, - generateArgsForSingleItemQuery, -} from '../generators/arguments'; -import resolveQueryArgs from '../resolvers/arguments'; + import { cacheSchema, checkCacheForSchema } from '../cache/cache'; -import { - ConfigResult, - EntryNode, - LoadedFlatbreadConfig, - Transformer, -} from '../types'; -import { map } from '../utils/map'; +import { ConfigResult, LoadedFlatbreadConfig, Transformer } from '../types'; import { getFieldOverrides } from '../utils/fieldOverrides'; - -interface RootQueries { - maybeReturnsSingleItem: string[]; - maybeReturnsList: string[]; -} +import { map } from '../utils/map'; +import addCollectionMutations from './collectionMutations'; +import addCollectionQueries from './collectionQueries'; /** * Generates a GraphQL schema from content nodes. @@ -79,28 +66,19 @@ export async function generateSchema( ]) ); - /** - * @todo potentially able to remove this - **/ - let queries: RootQueries = { - maybeReturnsSingleItem: [], - maybeReturnsList: [], - }; - // Main builder loop - iterate through each content type and generate query resolvers + relationships for it - for (const [type, schema] of Object.entries(schemaArray)) { - const pluralType = plur(type, 2); - const pluralTypeQueryName = 'all' + pluralType; + for (const [name, objectComposer] of Object.entries(schemaArray)) { + const pluralName = plur(name, 2); // /// Global meta fields // - schema.addFields({ + objectComposer.addFields({ _collection: { type: 'String', description: 'The collection name', - resolve: () => type, + resolve: () => name, }, }); @@ -108,72 +86,23 @@ export async function generateSchema( /// Query resolvers // - schema.addResolver({ - name: 'findById', - type: () => schema, - description: `Find one ${type} by its ID`, - args: generateArgsForSingleItemQuery(), - resolve: (rp: Record) => - cloneDeep(allContentNodesJSON[type]).find( - (node: EntryNode) => node.id === rp.args.id - ), - }); - - schema.addResolver({ - name: 'findMany', - type: () => [schema], - description: `Find many ${pluralType} by their IDs`, - args: generateArgsForManyItemQuery(pluralType), - resolve: (rp: Record) => { - const idsToFind = rp.args.ids ?? []; - const matches = - cloneDeep(allContentNodesJSON[type])?.filter((node: EntryNode) => - idsToFind?.includes(node.id) - ) ?? []; - return resolveQueryArgs(matches, rp.args, config, { - type: { - name: type, - pluralName: pluralType, - pluralQueryName: pluralTypeQueryName, - }, - }); - }, - }); - - schema.addResolver({ - name: 'all', - args: generateArgsForAllItemQuery(pluralType), - type: () => [schema], - description: `Return a set of ${pluralType}`, - resolve: (rp: Record) => { - const nodes = cloneDeep(allContentNodesJSON[type]); - return resolveQueryArgs(nodes, rp.args, config, { - type: { - name: type, - pluralName: pluralType, - pluralQueryName: pluralTypeQueryName, - }, - }); - }, + addCollectionQueries({ + name, + pluralName, + objectComposer, + schemaComposer, + allContentNodesJSON, + config, }); - schemaComposer.Query.addFields({ - /** - * Add find by ID to each content type - */ - [type]: schema.getResolver('findById'), - /** - * Add find 'many' to each content type - */ - [pluralTypeQueryName]: schema.getResolver('all'), + addCollectionMutations({ + name, + pluralName, + objectComposer, + schemaComposer, + allContentNodesJSON, + config, }); - - /** - * Separate the queries by return type for later use when wrapping the query resolvers - * @todo potentially able to remove this - **/ - queries.maybeReturnsSingleItem.push(type); - queries.maybeReturnsList.push(pluralTypeQueryName); } // Create map of references on each content node diff --git a/packages/transformer-yaml/src/index.ts b/packages/transformer-yaml/src/index.ts index 859d8888..11cd1dc1 100644 --- a/packages/transformer-yaml/src/index.ts +++ b/packages/transformer-yaml/src/index.ts @@ -2,7 +2,7 @@ import yaml from 'js-yaml'; import type { YAMLException } from 'js-yaml'; import slugify from '@sindresorhus/slugify'; import type { EntryNode, TransformerPlugin } from '@flatbread/core'; -import type { VFile } from 'vfile'; +import { VFile } from 'vfile'; /** * Transforms a yaml file (content node) to JSON. @@ -32,15 +32,21 @@ export const parse = (input: VFile): EntryNode => { ); }; +function serialize(node: EntryNode): VFile { + const doc = yaml.dump(node); + return new VFile(doc); +} + /** - * Converts markdown files to meaningful data. + * Converts yaml files to meaningful data. * - * @returns Markdown parser, preknown GraphQL schema fragments, and an EntryNode inspector function. + * @returns yaml parser, preknown GraphQL schema fragments, and an EntryNode inspector function. */ const transformer: TransformerPlugin = () => { return { parse: (input: VFile): EntryNode => parse(input), inspect: (input: EntryNode) => String(input), + serialize, extensions: ['.yaml', '.yml'], }; }; From 9339af9d25a334787c846f3bb0e3ade849749ad5 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Thu, 4 Aug 2022 01:28:54 -0500 Subject: [PATCH 08/26] refactor collection metadata --- packages/core/src/generators/schema.ts | 22 +++++++---- packages/core/src/types.ts | 15 ++++---- packages/core/src/utils/initializeConfig.ts | 7 ++++ packages/source-filesystem/package.json | 1 + packages/source-filesystem/src/index.ts | 36 ++++++++++++------ packages/transformer-markdown/package.json | 1 - packages/transformer-markdown/src/index.ts | 8 +--- packages/transformer-yaml/package.json | 1 - packages/transformer-yaml/src/index.ts | 8 +--- .../src/tests/snapshots/index.test.ts.md | 3 -- .../src/tests/snapshots/index.test.ts.snap | Bin 539 -> 511 bytes playground/src/routes/index.svelte | 8 ++-- pnpm-lock.yaml | 18 ++++----- 13 files changed, 73 insertions(+), 55 deletions(-) diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 2bf98494..5fb11ddb 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -1,6 +1,6 @@ import { schemaComposer } from 'graphql-compose'; import { composeWithJson } from 'graphql-compose-json'; -import { defaultsDeep, merge } from 'lodash-es'; +import { defaultsDeep, get, merge } from 'lodash-es'; import plur from 'plur'; import { VFile } from 'vfile'; @@ -59,7 +59,17 @@ export async function generateSchema( defaultsDeep( {}, getFieldOverrides(collection, config), - ...nodes.map((node) => merge({}, node, preknownSchemaFragments)) + ...nodes.map((node) => + merge( + { + _flatbread: { + reference: get(node, node?._flatbread?.referenceField), + }, + }, + node, + preknownSchemaFragments + ) + ) ), { schemaComposer } ), @@ -170,11 +180,9 @@ const fetchPreknownSchemaFragments = ( function getTransformerExtensionMap(transformer: Transformer[]) { const transformerMap = new Map(); - transformer.forEach((t) => { - t.extensions.forEach((extension) => { - transformerMap.set(extension, t); - }); - }); + transformer.forEach((t) => + t.extensions.forEach((extension) => transformerMap.set(extension, t)) + ); return transformerMap; } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 82645f8f..43f74df3 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -23,13 +23,13 @@ export type ContentNode = BaseContentNode & { export interface FlatbreadConfig { source: Source; transformer?: Transformer | Transformer[]; - content: Content; + content: Partial[]; } export interface LoadedFlatbreadConfig { source: Source; transformer: Transformer[]; - content: Content; + content: CollectionEntry[]; loaded: { extensions: string[]; }; @@ -69,9 +69,8 @@ export type EntryNode = Record; */ export interface Source { initialize?: (flatbreadConfig: LoadedFlatbreadConfig) => void; - fetchByType?: (path: string) => Promise; fetch: ( - allContentTypes: Record[] + allContentTypes: CollectionEntry[] ) => Promise>; } @@ -93,12 +92,14 @@ export interface Override { } /** - * An array of content descriptions which can be used to retrieve content nodes. + * A collection entry which can be used to retrieve content nodes. * * This is paired with a `Source` (and, *optionally*, a `Transformer`) plugin. */ -export type Content = { +export interface CollectionEntry { collection: string; overrides?: Override[]; + referenceField: string; + [key: string]: any; -}[]; +} diff --git a/packages/core/src/utils/initializeConfig.ts b/packages/core/src/utils/initializeConfig.ts index c8540aed..bea2bd98 100644 --- a/packages/core/src/utils/initializeConfig.ts +++ b/packages/core/src/utils/initializeConfig.ts @@ -1,3 +1,5 @@ +import { defaultsDeep } from 'lodash-es'; +import { CollectionEntry } from '../../dist'; import { LoadedFlatbreadConfig, Transformer } from '../types'; export function initializeConfig(config: any): LoadedFlatbreadConfig { @@ -10,5 +12,10 @@ export function initializeConfig(config: any): LoadedFlatbreadConfig { .map((transformer: Transformer) => transformer.extensions || []) .flat(), }; + + config.content = config.content?.map((content: CollectionEntry) => + defaultsDeep(content, { referenceField: 'id' }) + ); + return config; } diff --git a/packages/source-filesystem/package.json b/packages/source-filesystem/package.json index 58b8031a..4c5c7a1f 100644 --- a/packages/source-filesystem/package.json +++ b/packages/source-filesystem/package.json @@ -41,6 +41,7 @@ }, "devDependencies": { "@flatbread/core": "workspace:*", + "@sindresorhus/slugify": "^2.1.0", "@types/lodash-es": "4.17.6", "@types/node": "16.11.47", "tsup": "6.2.1", diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index 34a67f4c..0127aef0 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -1,7 +1,12 @@ -import { defaultsDeep } from 'lodash-es'; +import slugify from '@sindresorhus/slugify'; +import { defaultsDeep, merge } from 'lodash-es'; import { read } from 'to-vfile'; -import type { LoadedFlatbreadConfig, SourcePlugin } from '@flatbread/core'; +import type { + CollectionEntry, + LoadedFlatbreadConfig, + SourcePlugin, +} from '@flatbread/core'; import type { VFile } from 'vfile'; import type { FileNode, @@ -18,16 +23,27 @@ import gatherFileNodes from './utils/gatherFileNodes'; * @returns An array of content nodes */ async function getNodesFromDirectory( - path: string, + collectionEntry: CollectionEntry, config: InitializedSourceFilesystemConfig ): Promise { const { extensions } = config; - const nodes: FileNode[] = await gatherFileNodes(path, { extensions }); + const nodes: FileNode[] = await gatherFileNodes(collectionEntry.path, { + extensions, + }); return Promise.all( nodes.map(async (node: FileNode): Promise => { const file = await read(node.path); - file.data = node.data; + file.data = merge(node.data, { + _flatbread: { + referenceField: collectionEntry.referenceField, + collection: collectionEntry.collection, + filename: file.basename, + path: file.path, + slug: slugify(file.stem ?? ''), + }, + }); + return file; }) ); @@ -40,16 +56,16 @@ async function getNodesFromDirectory( * @returns */ async function getAllNodes( - allContentTypes: Record[], + allCollectionEntries: CollectionEntry[], config: InitializedSourceFilesystemConfig ): Promise> { const nodeEntries = await Promise.all( - allContentTypes.map( + allCollectionEntries.map( async (contentType): Promise> => new Promise(async (res) => res([ contentType.collection, - await getNodesFromDirectory(contentType.path, config), + await getNodesFromDirectory(contentType, config), ]) ) ) @@ -76,9 +92,7 @@ const source: SourcePlugin = (sourceConfig?: sourceFilesystemConfig) => { const { extensions } = flatbreadConfig.loaded; config = defaultsDeep(sourceConfig ?? {}, { extensions }); }, - fetchByType: (path: string) => getNodesFromDirectory(path, config), - fetch: (allContentTypes: Record[]) => - getAllNodes(allContentTypes, config), + fetch: (content: CollectionEntry[]) => getAllNodes(content, config), }; }; diff --git a/packages/transformer-markdown/package.json b/packages/transformer-markdown/package.json index 7cbbfd2c..995dc85a 100644 --- a/packages/transformer-markdown/package.json +++ b/packages/transformer-markdown/package.json @@ -35,7 +35,6 @@ "node": "^14.13.1 || >=16.0.0" }, "dependencies": { - "@sindresorhus/slugify": "^2.1.0", "graphql": "16.5.0", "gray-matter": "^4.0.3", "lodash-es": "^4.17.21", diff --git a/packages/transformer-markdown/src/index.ts b/packages/transformer-markdown/src/index.ts index e37ac9b9..03c9cbf9 100644 --- a/packages/transformer-markdown/src/index.ts +++ b/packages/transformer-markdown/src/index.ts @@ -1,10 +1,9 @@ import matter from 'gray-matter'; -import slugify from '@sindresorhus/slugify'; -import { html, excerpt, timeToRead } from './graphql/schema-helpers'; +import { excerpt, html, timeToRead } from './graphql/schema-helpers'; -import type { MarkdownTransformerConfig } from './types'; import type { EntryNode, TransformerPlugin } from '@flatbread/core'; import type { VFile } from 'vfile'; +import type { MarkdownTransformerConfig } from './types'; export * from './types'; @@ -20,9 +19,6 @@ export const parse = ( ): EntryNode => { const { data, content } = matter(String(input), config.grayMatter); return { - _filename: input.basename, - _path: input.path, - _slug: slugify(input.stem ?? ''), ...input.data, ...data, _content: { diff --git a/packages/transformer-yaml/package.json b/packages/transformer-yaml/package.json index 28a1dbb0..e9d5c70b 100644 --- a/packages/transformer-yaml/package.json +++ b/packages/transformer-yaml/package.json @@ -35,7 +35,6 @@ "node": "^14.13.1 || >=16.0.0" }, "dependencies": { - "@sindresorhus/slugify": "^2.1.0", "js-yaml": "^4.1.0" }, "devDependencies": { diff --git a/packages/transformer-yaml/src/index.ts b/packages/transformer-yaml/src/index.ts index 11cd1dc1..5d998d3f 100644 --- a/packages/transformer-yaml/src/index.ts +++ b/packages/transformer-yaml/src/index.ts @@ -1,7 +1,6 @@ -import yaml from 'js-yaml'; -import type { YAMLException } from 'js-yaml'; -import slugify from '@sindresorhus/slugify'; import type { EntryNode, TransformerPlugin } from '@flatbread/core'; +import type { YAMLException } from 'js-yaml'; +import yaml from 'js-yaml'; import { VFile } from 'vfile'; /** @@ -18,9 +17,6 @@ export const parse = (input: VFile): EntryNode => { if (typeof doc === 'object') { return { - _filename: input.basename, - _path: input.path, - _slug: slugify(input.stem ?? ''), ...input.data, ...doc, }; diff --git a/packages/transformer-yaml/src/tests/snapshots/index.test.ts.md b/packages/transformer-yaml/src/tests/snapshots/index.test.ts.md index 4174cf44..ee331630 100644 --- a/packages/transformer-yaml/src/tests/snapshots/index.test.ts.md +++ b/packages/transformer-yaml/src/tests/snapshots/index.test.ts.md @@ -9,9 +9,6 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 { - _filename: undefined, - _path: undefined, - _slug: '', date_joined: Date 2021-02-25 16:41:59 558ms UTC {}, enjoys: [ 'cats', diff --git a/packages/transformer-yaml/src/tests/snapshots/index.test.ts.snap b/packages/transformer-yaml/src/tests/snapshots/index.test.ts.snap index 8de1e400eadd826f0a4a14048d10672ce39d8d11..b68787a83d21e4d8818404a52cbd67211bfffa73 100644 GIT binary patch literal 511 zcmVKas?O6;o zWxIBR79WcU00000000ABQZaASP!N7+J4tD2lN6+Os{999C2m8Z8;F68rArwaUF?_k z68qWsUZiGV=*C}Qf->;~*x8UO^(QbeG4TVK5EnOgsV#l-y}R$-clX&><58T3Q@;GH zE!kLK?2z?CG=7FTYajg)GKKyelh_|qtceX~e4bjqyow^Uc;b9_RZA@%Sb^3HdA|~9 z!8^ex!8gHA!6RsPq4|0=(V+#X!cM27U|m5|!3Mw|AwC9IL8A+6BA|zpl#GswVju2` zO>HLWoE5aCu~TKoIcXD>NAIA=`!$L~cjW;0b*=0fOmuZPPR+cKKK);srxeE`y(Jgj zP8YU=UeMp|1-rrExc}tnpno)Ywl^3&eN(LLy_7Y;Sq8O zEx{?7GvA&Qm*41~Sr10JMyZ;!BIC8dJKXCX)>ti39A;>5InIwpy^Fpew%UZ1@2gD7 zEJjPIsc|=BdOM?N7^a42Nw#3zwuPv!%4BUdnRBD+zY1q*Zh3k8?>`HjV`~Zn0014c B@>>7^ literal 539 zcmV+$0_6QcRzVVR@Qmm zzR(X$OCO5}00000000AZQq6ADKoH)s*LIr{k^mBLK|XLpjS{z^&>Iq*kU&VefP|ur zy=gXCuZ?#jnq%L96P(MPr|1pw2%Na{3Ke75Hf1F&ee&#l-_GxzFXl3f*ZS-$H^NAM z`aqa4W-82Cp?S!{InyEzw=9+6LP##OV!2*sMxUK02{Y`i`^Y5$DL>eO&MW*+5eD%I z@eT1E@eAPrArBER5Vye}fd6{F;;{i}&3?a6pi5wvKo2#}9dHSF1K6FF$rVd^%mjC0l+?>=Wtnwznd#s?L_pl2-TV+D=q#{3GBYmz`*;ZQ-{Y4?TN}3}*9O(l~ z;)uU=#16Pc)3%lJFwNAqN_}xXwO$J;G4)-%==KM2FB(PT{ZX_ZO{U|=$A{zN$=zP=16.9'} hasBin: true requiresBuild: true @@ -5425,7 +5423,7 @@ packages: /lodash.deburr/4.1.0: resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==} - dev: false + dev: true /lodash.merge/4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} From 941031053b46ff2cd8adc9ed1aa5e57575af1e3a Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Thu, 4 Aug 2022 22:50:41 -0500 Subject: [PATCH 09/26] add more metadata to collection --- examples/sveltekit/src/routes/index.svelte | 10 ++++++---- packages/core/src/generators/schema.ts | 18 ++++++------------ packages/core/src/types.ts | 2 ++ packages/core/src/utils/initializeConfig.ts | 7 ++++++- packages/source-filesystem/src/index.ts | 6 ++++-- packages/transformer-markdown/src/index.ts | 2 ++ packages/transformer-yaml/src/index.ts | 2 ++ 7 files changed, 28 insertions(+), 19 deletions(-) diff --git a/examples/sveltekit/src/routes/index.svelte b/examples/sveltekit/src/routes/index.svelte index e9f7bdcb..2d894932 100644 --- a/examples/sveltekit/src/routes/index.svelte +++ b/examples/sveltekit/src/routes/index.svelte @@ -4,9 +4,9 @@ query PostCategory { allPostCategories (sortBy: "title", order: DESC) { _flatbread { - _filename - _collection - _slug + filename + collection + slug } id title @@ -20,7 +20,9 @@ timeToRead } authors { - _slug + _flatbread { + slug + } id name entity diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 5fb11ddb..57014ad3 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -59,17 +59,7 @@ export async function generateSchema( defaultsDeep( {}, getFieldOverrides(collection, config), - ...nodes.map((node) => - merge( - { - _flatbread: { - reference: get(node, node?._flatbread?.referenceField), - }, - }, - node, - preknownSchemaFragments - ) - ) + ...nodes.map((node) => merge({}, node, preknownSchemaFragments)) ), { schemaComposer } ), @@ -213,7 +203,11 @@ const optionallyTransformContentNodes = ( if (!transformer?.parse) { throw new Error(`no transformer found for ${node.path}`); } - return transformer.parse(node); + console.log({ transformer }); + const doc = transformer.parse(node); + doc._flatbread.transformedBy = transformer.id; + doc._flatbread.reference = get(doc, doc._flatbread.referenceField); + return doc; }); } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 43f74df3..7eab39fe 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -51,6 +51,7 @@ export interface Transformer { * @param input Node to transform */ parse?: (input: VFile) => EntryNode; + id?: string; preknownSchemaFragments?: () => Record; inspect: (input: EntryNode) => string; extensions: string[]; @@ -69,6 +70,7 @@ export type EntryNode = Record; */ export interface Source { initialize?: (flatbreadConfig: LoadedFlatbreadConfig) => void; + id?: string; fetch: ( allContentTypes: CollectionEntry[] ) => Promise>; diff --git a/packages/core/src/utils/initializeConfig.ts b/packages/core/src/utils/initializeConfig.ts index bf46b09e..de9ea718 100644 --- a/packages/core/src/utils/initializeConfig.ts +++ b/packages/core/src/utils/initializeConfig.ts @@ -2,6 +2,8 @@ import { cloneDeep, defaultsDeep } from 'lodash-es'; import { CollectionEntry } from '../types'; import { FlatbreadConfig, LoadedFlatbreadConfig, Transformer } from '../types'; import { toArray } from './arrayUtils'; +import { createHash } from 'crypto'; +import { anyToString } from './stringUtils'; /** * Processes a config object and returns a normalized version of it. @@ -10,7 +12,10 @@ export function initializeConfig( rawConfig: FlatbreadConfig ): LoadedFlatbreadConfig { const config = cloneDeep(rawConfig); - const transformer = toArray(config.transformer ?? []); + const transformer = toArray(config.transformer ?? []).map((t) => { + t.id = t.id ?? createHash('sha256').update(anyToString(t)).digest('hex'); + return t; + }); return { ...config, diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index 838d4e28..b167fc1a 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -1,12 +1,13 @@ import slugify from '@sindresorhus/slugify'; import { defaultsDeep, merge } from 'lodash-es'; import { read } from 'to-vfile'; - +import ownPackage from '../package.json'; import type { CollectionEntry, LoadedFlatbreadConfig, SourcePlugin, } from '@flatbread/core'; +import { relative } from 'path'; import type { VFile } from 'vfile'; import type { FileNode, @@ -39,8 +40,9 @@ async function getNodesFromDirectory( referenceField: collectionEntry.referenceField, collection: collectionEntry.collection, filename: file.basename, - path: file.path, + path: relative(process.cwd(), file.path), slug: slugify(file.stem ?? ''), + sourcedBy: ownPackage.name, }, }); diff --git a/packages/transformer-markdown/src/index.ts b/packages/transformer-markdown/src/index.ts index 590a3a7d..8db226a6 100644 --- a/packages/transformer-markdown/src/index.ts +++ b/packages/transformer-markdown/src/index.ts @@ -1,5 +1,6 @@ import matter from 'gray-matter'; import { excerpt, html, timeToRead } from './graphql/schema-helpers'; +import ownPackage from '../package.json'; import type { EntryNode, TransformerPlugin } from '@flatbread/core'; import type { VFile } from 'vfile'; @@ -41,6 +42,7 @@ export const transformer: TransformerPlugin = ( ); return { parse: (input: VFile): EntryNode => parse(input, config), + id: ownPackage.name, preknownSchemaFragments: () => ({ _content: { html: html(config), diff --git a/packages/transformer-yaml/src/index.ts b/packages/transformer-yaml/src/index.ts index 2ad8c1b0..4e897e5f 100644 --- a/packages/transformer-yaml/src/index.ts +++ b/packages/transformer-yaml/src/index.ts @@ -2,6 +2,7 @@ import type { EntryNode, TransformerPlugin } from '@flatbread/core'; import type { YAMLException } from 'js-yaml'; import yaml from 'js-yaml'; import { VFile } from 'vfile'; +import ownPackage from '../package.json'; /** * Transforms a yaml file (content node) to JSON. @@ -42,6 +43,7 @@ export const transformer: TransformerPlugin = () => { return { parse: (input: VFile): EntryNode => parse(input), inspect: (input: EntryNode) => String(input), + id: ownPackage.name, serialize, extensions: ['.yaml', '.yml'], }; From df774c0a36fe1582f6b316d35252a4f897713200 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Thu, 4 Aug 2022 22:57:11 -0500 Subject: [PATCH 10/26] add json assertsions --- packages/core/src/generators/schema.ts | 1 - packages/source-filesystem/src/index.ts | 2 +- packages/transformer-markdown/src/index.ts | 2 +- packages/transformer-yaml/src/index.ts | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 57014ad3..7d5ccdb1 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -203,7 +203,6 @@ const optionallyTransformContentNodes = ( if (!transformer?.parse) { throw new Error(`no transformer found for ${node.path}`); } - console.log({ transformer }); const doc = transformer.parse(node); doc._flatbread.transformedBy = transformer.id; doc._flatbread.reference = get(doc, doc._flatbread.referenceField); diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index b167fc1a..1e092a5f 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -1,7 +1,7 @@ import slugify from '@sindresorhus/slugify'; import { defaultsDeep, merge } from 'lodash-es'; import { read } from 'to-vfile'; -import ownPackage from '../package.json'; +import ownPackage from '../package.json' assert { type: 'json' }; import type { CollectionEntry, LoadedFlatbreadConfig, diff --git a/packages/transformer-markdown/src/index.ts b/packages/transformer-markdown/src/index.ts index 8db226a6..c81f8fe6 100644 --- a/packages/transformer-markdown/src/index.ts +++ b/packages/transformer-markdown/src/index.ts @@ -1,6 +1,6 @@ import matter from 'gray-matter'; import { excerpt, html, timeToRead } from './graphql/schema-helpers'; -import ownPackage from '../package.json'; +import ownPackage from '../package.json' assert { type: 'json' }; import type { EntryNode, TransformerPlugin } from '@flatbread/core'; import type { VFile } from 'vfile'; diff --git a/packages/transformer-yaml/src/index.ts b/packages/transformer-yaml/src/index.ts index 4e897e5f..570637d8 100644 --- a/packages/transformer-yaml/src/index.ts +++ b/packages/transformer-yaml/src/index.ts @@ -2,7 +2,7 @@ import type { EntryNode, TransformerPlugin } from '@flatbread/core'; import type { YAMLException } from 'js-yaml'; import yaml from 'js-yaml'; import { VFile } from 'vfile'; -import ownPackage from '../package.json'; +import ownPackage from '../package.json' assert { type: 'json' }; /** * Transforms a yaml file (content node) to JSON. From fdefe159644912433f53411529ed3936d07ffb78 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Fri, 5 Aug 2022 23:50:29 -0500 Subject: [PATCH 11/26] update mutations update file and memory :D, breaks ava watch --- .../src/generators/collectionMutations.ts | 34 ++++++++++++---- .../core/src/generators/collectionQueries.ts | 3 +- packages/core/src/generators/schema.ts | 40 +++++++++++++++++-- packages/core/src/providers/test/base.test.ts | 35 ++++++++++++++++ packages/core/src/types.ts | 13 ++++++ packages/flatbread/content/authors/me.md | 2 +- packages/source-filesystem/src/index.ts | 17 +++++++- packages/transformer-markdown/src/index.ts | 21 +++++++++- packages/transformer-yaml/src/index.ts | 8 +++- 9 files changed, 155 insertions(+), 18 deletions(-) diff --git a/packages/core/src/generators/collectionMutations.ts b/packages/core/src/generators/collectionMutations.ts index a20ac161..f320b629 100644 --- a/packages/core/src/generators/collectionMutations.ts +++ b/packages/core/src/generators/collectionMutations.ts @@ -1,5 +1,11 @@ import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose'; -import { LoadedFlatbreadConfig } from '../types'; +import { merge } from 'lodash-es'; +import { + CollectionContext, + EntryNode, + LoadedFlatbreadConfig, + Transformer, +} from '../types'; export interface AddCollectionMutationsArgs { name: string; @@ -7,7 +13,9 @@ export interface AddCollectionMutationsArgs { config: LoadedFlatbreadConfig; objectComposer: ObjectTypeComposer; schemaComposer: SchemaComposer; - allContentNodesJSON: Record; + updateCollectionRecord: ( + entry: EntryNode & { _flatbread: CollectionContext } + ) => Promise; } export default function addCollectionMutations( @@ -19,17 +27,29 @@ export default function addCollectionMutations( config, objectComposer, schemaComposer, - allContentNodesJSON, + updateCollectionRecord, } = args; schemaComposer.Mutation.addFields({ - [`upsert${name}`]: { + [`update${name}`]: { type: objectComposer, args: { [name]: objectComposer.getInputType() }, description: `Update or create a ${name}`, - async resolve(_, payload) { - console.dir({ payload }, { depth: Infinity }); - return payload; + async resolve(source, payload) { + // remove _flatbread to prevent injection + const { _flatbread, ...update } = source.author; + + const targetRecord = objectComposer + .getResolver('findById') + .resolve({ args: update }); + + // remove supplied key (might not be required) + delete update[targetRecord._flatbread.referenceField]; + const newRecord = merge(targetRecord, update); + + await updateCollectionRecord(newRecord); + + return newRecord; }, }, }); diff --git a/packages/core/src/generators/collectionQueries.ts b/packages/core/src/generators/collectionQueries.ts index 98ddc1ce..7fc94bd0 100644 --- a/packages/core/src/generators/collectionQueries.ts +++ b/packages/core/src/generators/collectionQueries.ts @@ -7,7 +7,7 @@ import { generateArgsForSingleItemQuery, } from '../generators/arguments'; import { cloneDeep } from 'lodash-es'; -import { EntryNode, LoadedFlatbreadConfig } from '../types'; +import { EntryNode, LoadedFlatbreadConfig, Transformer } from '../types'; export interface AddCollectionQueriesArgs { name: string; @@ -16,6 +16,7 @@ export interface AddCollectionQueriesArgs { objectComposer: ObjectTypeComposer; schemaComposer: SchemaComposer; allContentNodesJSON: Record; + transformersById: Record; } export default function addCollectionQueries(args: AddCollectionQueriesArgs) { diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 7d5ccdb1..61a582b4 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -1,11 +1,17 @@ import { schemaComposer } from 'graphql-compose'; import { composeWithJson } from 'graphql-compose-json'; -import { defaultsDeep, get, merge } from 'lodash-es'; +import { defaultsDeep, get, keyBy, merge } from 'lodash-es'; import plur from 'plur'; import { VFile } from 'vfile'; import { cacheSchema, checkCacheForSchema } from '../cache/cache'; -import { ConfigResult, LoadedFlatbreadConfig, Transformer } from '../types'; +import { + CollectionContext, + ConfigResult, + EntryNode, + LoadedFlatbreadConfig, + Transformer, +} from '../types'; import { getFieldOverrides } from '../utils/fieldOverrides'; import { map } from '../utils/map'; import addCollectionMutations from './collectionMutations'; @@ -66,6 +72,33 @@ export async function generateSchema( ]) ); + const transformersById = { + ...Object.fromEntries( + config.transformer.map((transformer) => [transformer.id, transformer]) + ), + // this will be the default for collections that aren't already `transformedBy` anything + undefined: config.transformer[0], + }; + + async function updateCollectionRecord( + entry: EntryNode & { _flatbread: CollectionContext } + ) { + const { _flatbread: ctx, ...record } = entry; + const file = await transformersById[ctx.transformedBy].serialize( + record, + ctx + ); + + await config?.source.put(file, ctx); + const index = allContentNodesJSON[ctx.collection].findIndex( + (c) => get(c, ctx.referenceField) === ctx.reference + ); + + // replace in memory representation of record + allContentNodesJSON[ctx.collection][index] = entry; + return entry; + } + // Main builder loop - iterate through each content type and generate query resolvers + relationships for it for (const [name, objectComposer] of Object.entries(schemaArray)) { const pluralName = plur(name, 2); @@ -91,6 +124,7 @@ export async function generateSchema( pluralName, objectComposer, schemaComposer, + transformersById, allContentNodesJSON, config, }); @@ -100,7 +134,7 @@ export async function generateSchema( pluralName, objectComposer, schemaComposer, - allContentNodesJSON, + updateCollectionRecord, config, }); } diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index f003d247..dc267fd7 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -58,3 +58,38 @@ test('relational filter query', async (t) => { t.snapshot(result); }); + +test('update collection record', async (t) => { + const flatbread = basicProject(); + const sitting = (Math.random() * 100) | 0; + const result: any = await flatbread.query({ + rootValue: { author: { id: '2a3e', skills: { sitting } } }, + source: ` + mutation UpdateAuthor($author: AuthorInput){ + updateAuthor(Author: $author) { + id + skills { + sitting + } + } + } + `, + }); + + t.is(result.data.updateAuthor.skills.sitting, sitting); + + const updated: any = await flatbread.query({ + source: ` + query { + Author(id: "2a3e") { + id + skills { + sitting + } + } + } + `, + }); + + t.is(updated.data.Author.skills.sitting, sitting); +}); diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 7eab39fe..ebf3aa9f 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -54,6 +54,7 @@ export interface Transformer { id?: string; preknownSchemaFragments?: () => Record; inspect: (input: EntryNode) => string; + serialize: (input: EntryNode, ctx: CollectionContext) => VFile; extensions: string[]; } @@ -71,6 +72,7 @@ export type EntryNode = Record; export interface Source { initialize?: (flatbreadConfig: LoadedFlatbreadConfig) => void; id?: string; + put: (source: VFile, ctx: CollectionContext) => Promise; fetch: ( allContentTypes: CollectionEntry[] ) => Promise>; @@ -93,6 +95,17 @@ export interface Override { ) => any; } +export interface CollectionContext { + referenceField: string; + collection: string; + filename: string; + path: string; + slug: string; + sourcedBy: string; + transformedBy: string; + reference: string; +} + /** * A collection entry which can be used to retrieve content nodes. * diff --git a/packages/flatbread/content/authors/me.md b/packages/flatbread/content/authors/me.md index 408dc67d..14448c1b 100644 --- a/packages/flatbread/content/authors/me.md +++ b/packages/flatbread/content/authors/me.md @@ -8,7 +8,7 @@ enjoys: - making this date_joined: 2021-02-25T16:41:59.558Z skills: - sitting: 204 + sitting: 23 breathing: 7.07 liquid_consumption: 100 existence: simulation diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index 1e092a5f..d5732c97 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -1,13 +1,14 @@ import slugify from '@sindresorhus/slugify'; import { defaultsDeep, merge } from 'lodash-es'; -import { read } from 'to-vfile'; +import { read, write } from 'to-vfile'; import ownPackage from '../package.json' assert { type: 'json' }; import type { + CollectionContext, CollectionEntry, LoadedFlatbreadConfig, SourcePlugin, } from '@flatbread/core'; -import { relative } from 'path'; +import { relative, resolve } from 'path'; import type { VFile } from 'vfile'; import type { FileNode, @@ -80,6 +81,17 @@ async function getAllNodes( return nodes; } +// TODO: _flatbread data should be extracted from plugins +// plugin should return a context object and be given the same context object back when saving, +// this context object will be saved internally under _flatbread[collectionId] + +async function put(source: VFile, ctx: CollectionContext) { + (source.basename = ctx.filename), + (source.path = resolve(process.cwd(), ctx.path)); + + await write(source); +} + /** * Source filesystem plugin for fetching flat-file content nodes from directories on disk. * @@ -95,6 +107,7 @@ export const source: SourcePlugin = (sourceConfig?: sourceFilesystemConfig) => { config = defaultsDeep(sourceConfig ?? {}, { extensions }); }, fetch: (content: CollectionEntry[]) => getAllNodes(content, config), + put, }; }; diff --git a/packages/transformer-markdown/src/index.ts b/packages/transformer-markdown/src/index.ts index c81f8fe6..bfd18cdb 100644 --- a/packages/transformer-markdown/src/index.ts +++ b/packages/transformer-markdown/src/index.ts @@ -2,8 +2,12 @@ import matter from 'gray-matter'; import { excerpt, html, timeToRead } from './graphql/schema-helpers'; import ownPackage from '../package.json' assert { type: 'json' }; -import type { EntryNode, TransformerPlugin } from '@flatbread/core'; -import type { VFile } from 'vfile'; +import type { + CollectionContext, + EntryNode, + TransformerPlugin, +} from '@flatbread/core'; +import { VFile } from 'vfile'; import type { MarkdownTransformerConfig } from './types'; export * from './types'; @@ -28,6 +32,17 @@ export const parse = ( }; }; +function serialize( + data: EntryNode, + ctx: CollectionContext, + config: MarkdownTransformerConfig +) { + const { _content, ...rest } = data; + const doc = matter.stringify(_content.raw, rest, config.grayMatter); + + return new VFile(doc); +} + /** * Converts markdown files to meaningful data. * @@ -51,6 +66,8 @@ export const transformer: TransformerPlugin = ( }, }), inspect: (input: EntryNode) => String(input), + serialize: (input: EntryNode, ctx: CollectionContext) => + serialize(input, ctx, config), extensions, }; }; diff --git a/packages/transformer-yaml/src/index.ts b/packages/transformer-yaml/src/index.ts index 570637d8..39dabeb7 100644 --- a/packages/transformer-yaml/src/index.ts +++ b/packages/transformer-yaml/src/index.ts @@ -1,4 +1,8 @@ -import type { EntryNode, TransformerPlugin } from '@flatbread/core'; +import type { + CollectionContext, + EntryNode, + TransformerPlugin, +} from '@flatbread/core'; import type { YAMLException } from 'js-yaml'; import yaml from 'js-yaml'; import { VFile } from 'vfile'; @@ -29,7 +33,7 @@ export const parse = (input: VFile): EntryNode => { ); }; -function serialize(node: EntryNode): VFile { +function serialize(node: EntryNode, ctx: CollectionContext): VFile { const doc = yaml.dump(node); return new VFile(doc); } From 978b1300d755e346d9c4a9e91cc5f6247b2882d7 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sat, 6 Aug 2022 03:17:29 -0500 Subject: [PATCH 12/26] isolate context based on plugin, major breaking changes --- packages/core/src/generators/schema.ts | 43 +++++++++++--- packages/core/src/types.ts | 26 ++++++--- packages/core/src/utils/createHash.ts | 6 ++ packages/core/src/utils/initializeConfig.ts | 6 +- packages/flatbread/content/authors/me.md | 2 +- packages/source-filesystem/src/index.ts | 57 ++++++++++--------- packages/transformer-markdown/src/index.ts | 10 ++-- packages/transformer-yaml/src/index.ts | 6 +- .../transformer-yaml/src/tests/index.test.ts | 4 +- 9 files changed, 107 insertions(+), 53 deletions(-) create mode 100644 packages/core/src/utils/createHash.ts diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 61a582b4..aec72f73 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -7,11 +7,14 @@ import { VFile } from 'vfile'; import { cacheSchema, checkCacheForSchema } from '../cache/cache'; import { CollectionContext, + CollectionEntry, ConfigResult, EntryNode, LoadedFlatbreadConfig, + Source, Transformer, } from '../types'; +import createHash from '../utils/createHash'; import { getFieldOverrides } from '../utils/fieldOverrides'; import { map } from '../utils/map'; import addCollectionMutations from './collectionMutations'; @@ -41,7 +44,27 @@ export async function generateSchema( config.source.initialize?.(config); // Invoke the content source resolver to retrieve the content nodes - const allContentNodes = await config.source.fetch(config.content); + let allContentNodes: Record = {}; + + const addRecord = + (source: Source) => + (collection: CollectionEntry, record: EntryNode, context: Ctx) => { + allContentNodes[collection.collection] = + allContentNodes[collection.collection] ?? []; + allContentNodes[collection.collection].push({ + record, + context: { + sourceContext: context, + sourcedBy: source.id, + collection: collection.collection, + referenceField: collection.referenceField ?? 'id', + }, + }); + }; + + await config.source.fetch(config.content, { + addRecord: addRecord(config.source), + }); // Transform the content nodes to the expected JSON format if needed const allContentNodesJSON = optionallyTransformContentNodes( @@ -81,15 +104,15 @@ export async function generateSchema( }; async function updateCollectionRecord( - entry: EntryNode & { _flatbread: CollectionContext } + entry: EntryNode & { _flatbread: any } ) { const { _flatbread: ctx, ...record } = entry; const file = await transformersById[ctx.transformedBy].serialize( record, - ctx + ctx.transformContext ); - await config?.source.put(file, ctx); + await config?.source.put(file, ctx.sourceContext); const index = allContentNodesJSON[ctx.collection].findIndex( (c) => get(c, ctx.referenceField) === ctx.reference ); @@ -232,14 +255,16 @@ const optionallyTransformContentNodes = ( * @todo if this becomes a performance bottleneck, consider overloading the source plugin API to accept a transform function so we can avoid mapping through the content nodes twice * */ - return map(allContentNodes, (node: VFile) => { - const transformer = transformerMap.get(node.extname); + return map(allContentNodes, (node: { record: VFile; context: any }) => { + const transformer = transformerMap.get(node.record.extname); if (!transformer?.parse) { - throw new Error(`no transformer found for ${node.path}`); + throw new Error(`no transformer found for ${node.record.path}`); } - const doc = transformer.parse(node); + const { record: doc, context } = transformer.parse(node.record); + doc._flatbread = node.context; doc._flatbread.transformedBy = transformer.id; - doc._flatbread.reference = get(doc, doc._flatbread.referenceField); + doc._flatbread.transformContext = context; + doc._flatbread.reference = get(doc, node.context.referenceField); return doc; }); } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index ebf3aa9f..f4234185 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -21,13 +21,13 @@ export type ContentNode = BaseContentNode & { * @todo This needs to be typed more strictly. */ export interface FlatbreadConfig { - source: Source; + source: Source; transformer?: Transformer | Transformer[]; content: Partial[]; } export interface LoadedFlatbreadConfig { - source: Source; + source: Source; transformer: Transformer[]; content: CollectionEntry[]; loaded: { @@ -69,16 +69,28 @@ export type EntryNode = Record; * The result of an invoked `Source` plugin which contains methods on how to retrieve content nodes in * their raw (if coupled with a `Transformer` plugin) or processed form. */ -export interface Source { + +export interface FlatbreadArgs { + addRecord( + collection: CollectionEntry, + record: EntryNode, + context: Context + ): void; +} + +export interface Source { initialize?: (flatbreadConfig: LoadedFlatbreadConfig) => void; id?: string; - put: (source: VFile, ctx: CollectionContext) => Promise; + put: (source: VFile, ctx: Context) => Promise; fetch: ( - allContentTypes: CollectionEntry[] - ) => Promise>; + allContentTypes: CollectionEntry[], + flatbread: FlatbreadArgs + ) => Promise; } -export type SourcePlugin = (sourceConfig?: Record) => Source; +export type SourcePlugin = ( + sourceConfig?: Record +) => Source; /** * An override can be used to declare a custom resolve for a field in content diff --git a/packages/core/src/utils/createHash.ts b/packages/core/src/utils/createHash.ts new file mode 100644 index 00000000..03190add --- /dev/null +++ b/packages/core/src/utils/createHash.ts @@ -0,0 +1,6 @@ +import { anyToString } from './stringUtils'; +import { createHash as createHashRaw } from 'crypto'; + +export default function createHash(content: any) { + return createHashRaw('sha256').update(anyToString(content)).digest('hex'); +} diff --git a/packages/core/src/utils/initializeConfig.ts b/packages/core/src/utils/initializeConfig.ts index de9ea718..6deabd29 100644 --- a/packages/core/src/utils/initializeConfig.ts +++ b/packages/core/src/utils/initializeConfig.ts @@ -2,7 +2,7 @@ import { cloneDeep, defaultsDeep } from 'lodash-es'; import { CollectionEntry } from '../types'; import { FlatbreadConfig, LoadedFlatbreadConfig, Transformer } from '../types'; import { toArray } from './arrayUtils'; -import { createHash } from 'crypto'; +import createHash from './createHash'; import { anyToString } from './stringUtils'; /** @@ -13,10 +13,12 @@ export function initializeConfig( ): LoadedFlatbreadConfig { const config = cloneDeep(rawConfig); const transformer = toArray(config.transformer ?? []).map((t) => { - t.id = t.id ?? createHash('sha256').update(anyToString(t)).digest('hex'); + t.id = t.id ?? createHash(t); return t; }); + config.source.id = config.source.id ?? createHash(config.source); + return { ...config, content: config.content?.map((content: Partial) => diff --git a/packages/flatbread/content/authors/me.md b/packages/flatbread/content/authors/me.md index 14448c1b..3bb4e738 100644 --- a/packages/flatbread/content/authors/me.md +++ b/packages/flatbread/content/authors/me.md @@ -8,7 +8,7 @@ enjoys: - making this date_joined: 2021-02-25T16:41:59.558Z skills: - sitting: 23 + sitting: 69 breathing: 7.07 liquid_consumption: 100 existence: simulation diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index d5732c97..60696483 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -5,6 +5,7 @@ import ownPackage from '../package.json' assert { type: 'json' }; import type { CollectionContext, CollectionEntry, + FlatbreadArgs, LoadedFlatbreadConfig, SourcePlugin, } from '@flatbread/core'; @@ -17,6 +18,12 @@ import type { } from './types'; import gatherFileNodes from './utils/gatherFileNodes'; +interface Context { + filename?: string; + path: string; + slug: string; +} + /** * Get nodes (files) from the directory * @@ -26,28 +33,23 @@ import gatherFileNodes from './utils/gatherFileNodes'; */ async function getNodesFromDirectory( collectionEntry: CollectionEntry, + { addRecord }: FlatbreadArgs, config: InitializedSourceFilesystemConfig -): Promise { +): Promise { const { extensions } = config; const nodes: FileNode[] = await gatherFileNodes(collectionEntry.path, { extensions, }); - return Promise.all( - nodes.map(async (node: FileNode): Promise => { - const file = await read(node.path); - file.data = merge(node.data, { - _flatbread: { - referenceField: collectionEntry.referenceField, - collection: collectionEntry.collection, - filename: file.basename, - path: relative(process.cwd(), file.path), - slug: slugify(file.stem ?? ''), - sourcedBy: ownPackage.name, - }, + await Promise.all( + nodes.map(async (node: FileNode): Promise => { + const doc = await read(node.path); + doc.data = node.data; + addRecord(collectionEntry, doc, { + filename: doc.basename, + path: relative(process.cwd(), doc.path), + slug: slugify(doc.stem ?? ''), }); - - return file; }) ); } @@ -60,15 +62,16 @@ async function getNodesFromDirectory( */ async function getAllNodes( allCollectionEntries: CollectionEntry[], + flatbread: FlatbreadArgs, config: InitializedSourceFilesystemConfig -): Promise> { +): Promise { const nodeEntries = await Promise.all( allCollectionEntries.map( async (contentType): Promise> => new Promise(async (res) => res([ contentType.collection, - await getNodesFromDirectory(contentType, config), + await getNodesFromDirectory(contentType, flatbread, config), ]) ) ) @@ -77,19 +80,19 @@ async function getAllNodes( const nodes = Object.fromEntries( nodeEntries as Iterable ); - - return nodes; } // TODO: _flatbread data should be extracted from plugins // plugin should return a context object and be given the same context object back when saving, // this context object will be saved internally under _flatbread[collectionId] -async function put(source: VFile, ctx: CollectionContext) { - (source.basename = ctx.filename), - (source.path = resolve(process.cwd(), ctx.path)); +async function put(doc: VFile, context: Context) { + doc.basename = context.filename; + doc.path = resolve(process.cwd(), context.path); - await write(source); + await write(doc); + + return { doc, context }; } /** @@ -98,7 +101,8 @@ async function put(source: VFile, ctx: CollectionContext) { * @param sourceConfig content types config * @returns A function that returns functions which fetch lists of nodes */ -export const source: SourcePlugin = (sourceConfig?: sourceFilesystemConfig) => { + +export function source(sourceConfig?: sourceFilesystemConfig) { let config: InitializedSourceFilesystemConfig; return { @@ -106,9 +110,10 @@ export const source: SourcePlugin = (sourceConfig?: sourceFilesystemConfig) => { const { extensions } = flatbreadConfig.loaded; config = defaultsDeep(sourceConfig ?? {}, { extensions }); }, - fetch: (content: CollectionEntry[]) => getAllNodes(content, config), + fetch: (content: CollectionEntry[], flatbread: FlatbreadArgs) => + getAllNodes(content, flatbread, config), put, }; -}; +} export default source; diff --git a/packages/transformer-markdown/src/index.ts b/packages/transformer-markdown/src/index.ts index bfd18cdb..77358696 100644 --- a/packages/transformer-markdown/src/index.ts +++ b/packages/transformer-markdown/src/index.ts @@ -24,10 +24,12 @@ export const parse = ( ): EntryNode => { const { data, content } = matter(String(input), config.grayMatter); return { - ...input.data, - ...data, - _content: { - raw: content, + record: { + ...input.data, + ...data, + _content: { + raw: content, + }, }, }; }; diff --git a/packages/transformer-yaml/src/index.ts b/packages/transformer-yaml/src/index.ts index 39dabeb7..b16cf861 100644 --- a/packages/transformer-yaml/src/index.ts +++ b/packages/transformer-yaml/src/index.ts @@ -22,8 +22,10 @@ export const parse = (input: VFile): EntryNode => { if (typeof doc === 'object') { return { - ...input.data, - ...doc, + record: { + ...input.data, + ...doc, + }, }; } throw new Error( diff --git a/packages/transformer-yaml/src/tests/index.test.ts b/packages/transformer-yaml/src/tests/index.test.ts index ba28b068..5246dee3 100644 --- a/packages/transformer-yaml/src/tests/index.test.ts +++ b/packages/transformer-yaml/src/tests/index.test.ts @@ -26,6 +26,6 @@ const transformer = Transformer(); test('it can parse a basic yaml file', async (t) => { const parse = transformer.parse as (input: VFile) => EntryNode; - const node = parse(testFile); - t.snapshot(node); + const { record } = parse(testFile); + t.snapshot(record); }); From b724de139fe634bfb46828239435d2fcf5b17fa8 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sat, 6 Aug 2022 13:05:24 -0500 Subject: [PATCH 13/26] comments --- examples/nextjs/flatbread.config.ts | 4 +- examples/sveltekit/flatbread.config.js | 14 ++-- examples/sveltekit/src/routes/index.svelte | 14 ++-- packages/core/src/cache/cache.ts | 14 +--- .../src/generators/collectionMutations.ts | 8 +-- .../core/src/generators/collectionQueries.ts | 6 +- packages/core/src/generators/schema.ts | 56 ++++++++-------- packages/core/src/providers/test/base.test.ts | 64 +++++++++---------- packages/core/src/types.ts | 19 ++++-- packages/core/src/utils/createHash.ts | 6 -- packages/core/src/utils/createShaHash.ts | 6 ++ packages/core/src/utils/fieldOverrides.ts | 20 +++--- packages/core/src/utils/initializeConfig.ts | 10 +-- .../src/utils/tests/fieldOverrides.test.ts | 5 +- packages/flatbread/content/authors/me.md | 2 +- packages/source-filesystem/src/index.ts | 14 ++-- 16 files changed, 136 insertions(+), 126 deletions(-) delete mode 100644 packages/core/src/utils/createHash.ts create mode 100644 packages/core/src/utils/createShaHash.ts diff --git a/examples/nextjs/flatbread.config.ts b/examples/nextjs/flatbread.config.ts index 3fc7dff0..0d8e76a5 100644 --- a/examples/nextjs/flatbread.config.ts +++ b/examples/nextjs/flatbread.config.ts @@ -17,14 +17,14 @@ const config = { content: [ { path: '../../packages/flatbread/content/posts', - collection: 'Post', + name: 'Post', refs: { authors: 'Author', }, }, { path: '../../packages/flatbread/content/authors', - collection: 'Author', + name: 'Author', refs: { friend: 'Author', }, diff --git a/examples/sveltekit/flatbread.config.js b/examples/sveltekit/flatbread.config.js index 39c65f27..8d9565db 100644 --- a/examples/sveltekit/flatbread.config.js +++ b/examples/sveltekit/flatbread.config.js @@ -19,28 +19,28 @@ export default defineConfig({ content: [ { path: 'content/markdown/posts', - collection: 'Post', + name: 'Post', refs: { authors: 'Author', }, }, { path: 'content/markdown/posts/[category]/[slug].md', - collection: 'PostCategory', + name: 'PostCategory', refs: { authors: 'Author', }, }, { path: 'content/markdown/posts/**/*.md', - collection: 'PostCategoryBlob', + name: 'PostCategoryBlob', refs: { authors: 'Author', }, }, { path: 'content/markdown/authors', - collection: 'Author', + name: 'Author', refs: { friend: 'Author', }, @@ -54,20 +54,18 @@ export default defineConfig({ }, { path: 'content/yaml/authors', - collection: 'YamlAuthor', + name: 'YamlAuthor', refs: { friend: 'YamlAuthor', }, }, { path: 'content/markdown/deeply-nested', - collection: 'OverrideTest', + name: 'OverrideTest', overrides: [ { field: 'deeply.nested', type: 'String', - test: undefined, - test2: null, resolve: (source) => String(source).toUpperCase(), }, { diff --git a/examples/sveltekit/src/routes/index.svelte b/examples/sveltekit/src/routes/index.svelte index 2d894932..53c0ffa9 100644 --- a/examples/sveltekit/src/routes/index.svelte +++ b/examples/sveltekit/src/routes/index.svelte @@ -3,10 +3,12 @@ const query = ` query PostCategory { allPostCategories (sortBy: "title", order: DESC) { - _flatbread { - filename + _metadata { + sourceContext { + filename + slug + } collection - slug } id title @@ -20,8 +22,10 @@ timeToRead } authors { - _flatbread { - slug + _metadata { + sourceContext { + slug + } } id name diff --git a/packages/core/src/cache/cache.ts b/packages/core/src/cache/cache.ts index 6d40d382..fe8fc54c 100644 --- a/packages/core/src/cache/cache.ts +++ b/packages/core/src/cache/cache.ts @@ -1,8 +1,7 @@ import { GraphQLSchema } from 'graphql'; import LRU from 'lru-cache'; -import { createHash } from 'node:crypto'; import { LoadedFlatbreadConfig } from '../types'; -import { anyToString } from '../utils/stringUtils'; +import createShaHash from '../utils/createShaHash'; type SchemaCacheKey = string; @@ -29,7 +28,7 @@ export function cacheSchema( config: LoadedFlatbreadConfig, schema: GraphQLSchema ) { - const schemaHashKey = getSchemaHash(config); + const schemaHashKey = createShaHash(config); cache.schema.set(schemaHashKey, schema); } @@ -39,13 +38,6 @@ export function cacheSchema( export function checkCacheForSchema( config: LoadedFlatbreadConfig ): GraphQLSchema | undefined { - const schemaHashKey = getSchemaHash(config); + const schemaHashKey = createShaHash(config); return cache.schema.get(schemaHashKey); } - -/** - * Generates a hash key for a given Flatbread config. - */ -export function getSchemaHash(config: LoadedFlatbreadConfig) { - return createHash('md5').update(anyToString(config)).digest('hex'); -} diff --git a/packages/core/src/generators/collectionMutations.ts b/packages/core/src/generators/collectionMutations.ts index f320b629..c3e4421a 100644 --- a/packages/core/src/generators/collectionMutations.ts +++ b/packages/core/src/generators/collectionMutations.ts @@ -14,7 +14,7 @@ export interface AddCollectionMutationsArgs { objectComposer: ObjectTypeComposer; schemaComposer: SchemaComposer; updateCollectionRecord: ( - entry: EntryNode & { _flatbread: CollectionContext } + entry: EntryNode & { _metadata: CollectionContext } ) => Promise; } @@ -36,15 +36,15 @@ export default function addCollectionMutations( args: { [name]: objectComposer.getInputType() }, description: `Update or create a ${name}`, async resolve(source, payload) { - // remove _flatbread to prevent injection - const { _flatbread, ...update } = source.author; + // remove _metadata to prevent injection + const { _metadata, ...update } = source.author; const targetRecord = objectComposer .getResolver('findById') .resolve({ args: update }); // remove supplied key (might not be required) - delete update[targetRecord._flatbread.referenceField]; + delete update[targetRecord._metadata.referenceField]; const newRecord = merge(targetRecord, update); await updateCollectionRecord(newRecord); diff --git a/packages/core/src/generators/collectionQueries.ts b/packages/core/src/generators/collectionQueries.ts index 7fc94bd0..b5cbabd2 100644 --- a/packages/core/src/generators/collectionQueries.ts +++ b/packages/core/src/generators/collectionQueries.ts @@ -37,8 +37,10 @@ export default function addCollectionQueries(args: AddCollectionQueriesArgs) { description: `Find one ${name} by its ID`, args: generateArgsForSingleItemQuery(), resolve: (rp: Record) => - cloneDeep(allContentNodesJSON[name]).find( - (node: EntryNode) => node.id === rp.args.id + cloneDeep( + allContentNodesJSON[name].find( + (node: EntryNode) => node.id === rp.args.id + ) ), }); diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index aec72f73..0da36681 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -1,20 +1,18 @@ import { schemaComposer } from 'graphql-compose'; import { composeWithJson } from 'graphql-compose-json'; -import { defaultsDeep, get, keyBy, merge } from 'lodash-es'; +import { defaultsDeep, get, merge } from 'lodash-es'; import plur from 'plur'; import { VFile } from 'vfile'; import { cacheSchema, checkCacheForSchema } from '../cache/cache'; import { - CollectionContext, - CollectionEntry, ConfigResult, EntryNode, + LoadedCollectionEntry, LoadedFlatbreadConfig, Source, Transformer, } from '../types'; -import createHash from '../utils/createHash'; import { getFieldOverrides } from '../utils/fieldOverrides'; import { map } from '../utils/map'; import addCollectionMutations from './collectionMutations'; @@ -48,18 +46,25 @@ export async function generateSchema( const addRecord = (source: Source) => - (collection: CollectionEntry, record: EntryNode, context: Ctx) => { - allContentNodes[collection.collection] = - allContentNodes[collection.collection] ?? []; - allContentNodes[collection.collection].push({ + ( + collection: LoadedCollectionEntry, + record: EntryNode, + context: Ctx + ) => { + allContentNodes[collection.name] = allContentNodes[collection.name] ?? []; + + const newRecord = { record, context: { sourceContext: context, sourcedBy: source.id, - collection: collection.collection, + collection: collection.name, referenceField: collection.referenceField ?? 'id', }, - }); + }; + + allContentNodes[collection.name].push(newRecord); + return newRecord; }; await config.source.fetch(config.content, { @@ -87,7 +92,7 @@ export async function generateSchema( collection, defaultsDeep( {}, - getFieldOverrides(collection, config), + getFieldOverrides(collection, config.content), ...nodes.map((node) => merge({}, node, preknownSchemaFragments)) ), { schemaComposer } @@ -103,14 +108,10 @@ export async function generateSchema( undefined: config.transformer[0], }; - async function updateCollectionRecord( - entry: EntryNode & { _flatbread: any } - ) { - const { _flatbread: ctx, ...record } = entry; - const file = await transformersById[ctx.transformedBy].serialize( - record, - ctx.transformContext - ); + async function updateCollectionRecord(entry: EntryNode & { _metadata: any }) { + const { _metadata: ctx, ...record } = entry; + const { serialize } = transformersById[ctx.transformedBy]; + const file = await serialize(record, ctx.transformContext); await config?.source.put(file, ctx.sourceContext); const index = allContentNodesJSON[ctx.collection].findIndex( @@ -163,8 +164,8 @@ export async function generateSchema( } // Create map of references on each content node - for (const { collection, refs } of config.content) { - const typeTC = schemaComposer.getOTC(collection); + for (const { name, refs } of config.content) { + const typeTC = schemaComposer.getOTC(name); if (!refs) continue; @@ -181,7 +182,7 @@ export async function generateSchema( description: `All ${plur( String(refType), 2 - )} that are referenced by this ${collection}`, + )} that are referenced by this ${name}`, resolver: () => refTypeTC.getResolver('findMany'), prepareArgs: { ids: (source) => source[refField], @@ -191,7 +192,7 @@ export async function generateSchema( } else { // If the reference field has a single node typeTC.addRelation(refField, { - description: `The ${refType} referenced by this ${collection}`, + description: `The ${refType} referenced by this ${name}`, resolver: () => refTypeTC.getResolver('findById'), prepareArgs: { id: (source) => source[refField], @@ -261,13 +262,14 @@ const optionallyTransformContentNodes = ( throw new Error(`no transformer found for ${node.record.path}`); } const { record: doc, context } = transformer.parse(node.record); - doc._flatbread = node.context; - doc._flatbread.transformedBy = transformer.id; - doc._flatbread.transformContext = context; - doc._flatbread.reference = get(doc, node.context.referenceField); + doc._metadata = node.context; + doc._metadata.transformedBy = transformer.id; + doc._metadata.transformContext = context; + doc._metadata.reference = get(doc, node.context.referenceField); return doc; }); } + // TODO: might need to map this to attach metadata here return allContentNodes; }; diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index dc267fd7..3a30499d 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -16,7 +16,7 @@ function basicProject() { content: [ { path: 'packages/flatbread/content/authors', - collection: 'Author', + name: 'Author', refs: { friend: 'Author', }, @@ -59,37 +59,37 @@ test('relational filter query', async (t) => { t.snapshot(result); }); -test('update collection record', async (t) => { - const flatbread = basicProject(); - const sitting = (Math.random() * 100) | 0; - const result: any = await flatbread.query({ - rootValue: { author: { id: '2a3e', skills: { sitting } } }, - source: ` - mutation UpdateAuthor($author: AuthorInput){ - updateAuthor(Author: $author) { - id - skills { - sitting - } - } - } - `, - }); +// test('update collection record', async (t) => { +// const flatbread = basicProject(); +// const sitting = (Math.random() * 100) | 0; +// const result: any = await flatbread.query({ +// rootValue: { author: { id: '2a3e', skills: { sitting } } }, +// source: ` +// mutation UpdateAuthor($author: AuthorInput){ +// updateAuthor(Author: $author) { +// id +// skills { +// sitting +// } +// } +// } +// `, +// }); - t.is(result.data.updateAuthor.skills.sitting, sitting); +// t.is(result.data.updateAuthor.skills.sitting, sitting); - const updated: any = await flatbread.query({ - source: ` - query { - Author(id: "2a3e") { - id - skills { - sitting - } - } - } - `, - }); +// const updated: any = await flatbread.query({ +// source: ` +// query { +// Author(id: "2a3e") { +// id +// skills { +// sitting +// } +// } +// } +// `, +// }); - t.is(updated.data.Author.skills.sitting, sitting); -}); +// t.is(updated.data.Author.skills.sitting, sitting); +// }); diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index f4234185..06332f36 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -23,13 +23,13 @@ export type ContentNode = BaseContentNode & { export interface FlatbreadConfig { source: Source; transformer?: Transformer | Transformer[]; - content: Partial[]; + content: CollectionEntry[]; } export interface LoadedFlatbreadConfig { source: Source; transformer: Transformer[]; - content: CollectionEntry[]; + content: LoadedCollectionEntry[]; loaded: { extensions: string[]; }; @@ -72,7 +72,7 @@ export type EntryNode = Record; export interface FlatbreadArgs { addRecord( - collection: CollectionEntry, + collection: LoadedCollectionEntry, record: EntryNode, context: Context ): void; @@ -83,7 +83,7 @@ export interface Source { id?: string; put: (source: VFile, ctx: Context) => Promise; fetch: ( - allContentTypes: CollectionEntry[], + allContentTypes: LoadedCollectionEntry[], flatbread: FlatbreadArgs ) => Promise; } @@ -123,10 +123,15 @@ export interface CollectionContext { * * This is paired with a `Source` (and, *optionally*, a `Transformer`) plugin. */ + export interface CollectionEntry { - collection: string; + name: string; + path: string; overrides?: Override[]; - referenceField: string; + refs?: Record; + referenceField?: string; +} - [key: string]: any; +export interface LoadedCollectionEntry extends CollectionEntry { + referenceField: string; } diff --git a/packages/core/src/utils/createHash.ts b/packages/core/src/utils/createHash.ts deleted file mode 100644 index 03190add..00000000 --- a/packages/core/src/utils/createHash.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { anyToString } from './stringUtils'; -import { createHash as createHashRaw } from 'crypto'; - -export default function createHash(content: any) { - return createHashRaw('sha256').update(anyToString(content)).digest('hex'); -} diff --git a/packages/core/src/utils/createShaHash.ts b/packages/core/src/utils/createShaHash.ts new file mode 100644 index 00000000..a194072a --- /dev/null +++ b/packages/core/src/utils/createShaHash.ts @@ -0,0 +1,6 @@ +import { anyToString } from './stringUtils'; +import { createHash } from 'crypto'; + +export default function createShaHash(content: any) { + return createHash('sha256').update(anyToString(content)).digest('hex'); +} diff --git a/packages/core/src/utils/fieldOverrides.ts b/packages/core/src/utils/fieldOverrides.ts index f3106bb9..5122ea14 100644 --- a/packages/core/src/utils/fieldOverrides.ts +++ b/packages/core/src/utils/fieldOverrides.ts @@ -1,20 +1,24 @@ -import { FlatbreadConfig, Override } from '../types'; import { get, set } from 'lodash-es'; +import { CollectionEntry } from '../../dist'; +import { Override } from '../types'; /** * Get an object containing functions nested in an object structure * aligning to the listed overrides in the config * - * @param collection the collection string referenced in the config - * @param config the flatbread config object + * @param collectionName the collection string referenced in the config + * @param entries the flatbread config object * @returns an object in the shape of the json schema */ -export function getFieldOverrides(collection: string, config: FlatbreadConfig) { - const content = config.content.find( - (content) => content.collection === collection +export function getFieldOverrides( + collectionName: string, + entries: CollectionEntry[] +) { + const collectionEntry = entries.find( + (entry) => entry.name === collectionName ); - if (!content?.overrides) return {}; - const overrides = content.overrides; + if (!collectionEntry?.overrides) return {}; + const overrides = collectionEntry.overrides; return overrides.reduce((fields: any, override: Override) => { const { field, type, ...rest } = override; diff --git a/packages/core/src/utils/initializeConfig.ts b/packages/core/src/utils/initializeConfig.ts index 6deabd29..f1b4f2e5 100644 --- a/packages/core/src/utils/initializeConfig.ts +++ b/packages/core/src/utils/initializeConfig.ts @@ -1,8 +1,8 @@ import { cloneDeep, defaultsDeep } from 'lodash-es'; -import { CollectionEntry } from '../types'; +import { LoadedCollectionEntry } from '../types'; import { FlatbreadConfig, LoadedFlatbreadConfig, Transformer } from '../types'; import { toArray } from './arrayUtils'; -import createHash from './createHash'; +import createShaHash from './createShaHash'; import { anyToString } from './stringUtils'; /** @@ -13,15 +13,15 @@ export function initializeConfig( ): LoadedFlatbreadConfig { const config = cloneDeep(rawConfig); const transformer = toArray(config.transformer ?? []).map((t) => { - t.id = t.id ?? createHash(t); + t.id = t.id ?? createShaHash(t); return t; }); - config.source.id = config.source.id ?? createHash(config.source); + config.source.id = config.source.id ?? createShaHash(config.source); return { ...config, - content: config.content?.map((content: Partial) => + content: config.content?.map((content: Partial) => defaultsDeep(content, { referenceField: 'id' }) ), transformer, diff --git a/packages/core/src/utils/tests/fieldOverrides.test.ts b/packages/core/src/utils/tests/fieldOverrides.test.ts index fca200ee..bb93fdf7 100644 --- a/packages/core/src/utils/tests/fieldOverrides.test.ts +++ b/packages/core/src/utils/tests/fieldOverrides.test.ts @@ -1,8 +1,9 @@ import test from 'ava'; +import { LoadedCollectionEntry } from '../../types'; import { getFieldOverrides } from '../fieldOverrides.js'; -function getProps(overrides: any[]): [string, any] { - return ['t', { content: [{ collection: 't', overrides }] }]; +function getProps(overrides: any[]): [string, LoadedCollectionEntry[]] { + return ['t', [{ name: 't', overrides, referenceField: 'id' }]]; } test('basic override', (t) => { diff --git a/packages/flatbread/content/authors/me.md b/packages/flatbread/content/authors/me.md index 3bb4e738..200f7328 100644 --- a/packages/flatbread/content/authors/me.md +++ b/packages/flatbread/content/authors/me.md @@ -8,7 +8,7 @@ enjoys: - making this date_joined: 2021-02-25T16:41:59.558Z skills: - sitting: 69 + sitting: 71 breathing: 7.07 liquid_consumption: 100 existence: simulation diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index 60696483..6f588963 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -4,7 +4,7 @@ import { read, write } from 'to-vfile'; import ownPackage from '../package.json' assert { type: 'json' }; import type { CollectionContext, - CollectionEntry, + LoadedCollectionEntry, FlatbreadArgs, LoadedFlatbreadConfig, SourcePlugin, @@ -32,7 +32,7 @@ interface Context { * @returns An array of content nodes */ async function getNodesFromDirectory( - collectionEntry: CollectionEntry, + collectionEntry: LoadedCollectionEntry, { addRecord }: FlatbreadArgs, config: InitializedSourceFilesystemConfig ): Promise { @@ -61,7 +61,7 @@ async function getNodesFromDirectory( * @returns */ async function getAllNodes( - allCollectionEntries: CollectionEntry[], + allCollectionEntries: LoadedCollectionEntry[], flatbread: FlatbreadArgs, config: InitializedSourceFilesystemConfig ): Promise { @@ -70,7 +70,7 @@ async function getAllNodes( async (contentType): Promise> => new Promise(async (res) => res([ - contentType.collection, + contentType.name, await getNodesFromDirectory(contentType, flatbread, config), ]) ) @@ -110,8 +110,10 @@ export function source(sourceConfig?: sourceFilesystemConfig) { const { extensions } = flatbreadConfig.loaded; config = defaultsDeep(sourceConfig ?? {}, { extensions }); }, - fetch: (content: CollectionEntry[], flatbread: FlatbreadArgs) => - getAllNodes(content, flatbread, config), + fetch: ( + content: LoadedCollectionEntry[], + flatbread: FlatbreadArgs + ) => getAllNodes(content, flatbread, config), put, }; } From 230970899bbc5308365e6f837070a68e9e9f237e Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sat, 6 Aug 2022 13:57:40 -0500 Subject: [PATCH 14/26] added sourceMemory to allow for testing without a filesystem --- packages/core/src/providers/test/base.test.ts | 70 ++++++++-------- packages/core/src/providers/test/mockData.ts | 75 ++++++++++++++++++ .../providers/test/snapshots/base.test.ts.md | 22 +++-- .../test/snapshots/base.test.ts.snap | Bin 470 -> 576 bytes packages/core/src/sources/base.ts | 51 ++++++++++++ packages/core/src/types.ts | 7 +- tsconfig.json | 4 + 7 files changed, 189 insertions(+), 40 deletions(-) create mode 100644 packages/core/src/providers/test/mockData.ts create mode 100644 packages/core/src/sources/base.ts diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index 3a30499d..9892b025 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -2,10 +2,14 @@ import test from 'ava'; import filesystem from '@flatbread/source-filesystem'; import markdownTransformer from '@flatbread/transformer-markdown'; import { FlatbreadProvider } from '../base'; +import { SourceMemory } from '../../sources/base'; +import { mockData } from './mockData'; + +const sourceMemory = new SourceMemory(mockData); function basicProject() { return new FlatbreadProvider({ - source: filesystem(), + source: sourceMemory, transformer: markdownTransformer({ markdown: { gfm: true, @@ -48,7 +52,7 @@ test('relational filter query', async (t) => { const result = await flatbread.query({ source: ` query AllAuthors { - allAuthors(filter: {friend: {name: {wildcard: "Anot*"}}}) { + allAuthors(filter: {friend: {name: {wildcard: "Ev*"}}}) { name enjoys } @@ -59,37 +63,37 @@ test('relational filter query', async (t) => { t.snapshot(result); }); -// test('update collection record', async (t) => { -// const flatbread = basicProject(); -// const sitting = (Math.random() * 100) | 0; -// const result: any = await flatbread.query({ -// rootValue: { author: { id: '2a3e', skills: { sitting } } }, -// source: ` -// mutation UpdateAuthor($author: AuthorInput){ -// updateAuthor(Author: $author) { -// id -// skills { -// sitting -// } -// } -// } -// `, -// }); +test('update collection record', async (t) => { + const flatbread = basicProject(); + const sitting = (Math.random() * 100) | 0; + const result: any = await flatbread.query({ + rootValue: { author: { id: '2a3e', skills: { sitting } } }, + source: ` + mutation UpdateAuthor($author: AuthorInput){ + updateAuthor(Author: $author) { + id + skills { + sitting + } + } + } + `, + }); -// t.is(result.data.updateAuthor.skills.sitting, sitting); + t.is(result.data.updateAuthor.skills.sitting, sitting); -// const updated: any = await flatbread.query({ -// source: ` -// query { -// Author(id: "2a3e") { -// id -// skills { -// sitting -// } -// } -// } -// `, -// }); + const updated: any = await flatbread.query({ + source: ` + query { + Author(id: "2a3e") { + id + skills { + sitting + } + } + } + `, + }); -// t.is(updated.data.Author.skills.sitting, sitting); -// }); + t.is(updated.data.Author.skills.sitting, sitting); +}); diff --git a/packages/core/src/providers/test/mockData.ts b/packages/core/src/providers/test/mockData.ts new file mode 100644 index 00000000..44180443 --- /dev/null +++ b/packages/core/src/providers/test/mockData.ts @@ -0,0 +1,75 @@ +import { VFile } from 'vfile'; + +export const mockData = { + Author: [ + new VFile({ + path: '/content/authors/eva.md', + extname: '.md', + value: `--- + id: 40s3 + name: Eva + entity: Cat + enjoys: + - sitting + - standing + - mow mow + - sleepy time + - attention + friend: 2a3e + image: eva.svg + date_joined: 2002-02-25T16:41:59.558Z + skills: + sitting: 100000 + breathing: 4.7 + liquid_consumption: 10 + existence: funky + sports: -200 +--- + `, + }), + new VFile({ + path: '/content/authors/tony.md', + extname: '.md', + value: `--- + name: Tony + id: 2a3e + friend: ab2c + enjoys: + - cats + - tea + - making this + date_joined: 2021-02-25T16:41:59.558Z + skills: + sitting: 71 + breathing: 7.07 + liquid_consumption: 100 + existence: simulation + sports: -2 + cat_pat: 1500 +--- + `, + }), + new VFile({ + path: '/content/authors/daes.md', + extname: '.md', + value: `--- + id: ab2c + name: Daes + entity: Human + enjoys: + - cats + - coffee + - design + friend: 40s3 + date_joined: 2021-04-22T16:41:59.558Z + skills: + sitting: 304 + breathing: 1.034234 + liquid_consumption: -100 + existence: etheral + sports: 3 +--- + `, + }), + ], +}; diff --git a/packages/core/src/providers/test/snapshots/base.test.ts.md b/packages/core/src/providers/test/snapshots/base.test.ts.md index b48e6771..5ca7858a 100644 --- a/packages/core/src/providers/test/snapshots/base.test.ts.md +++ b/packages/core/src/providers/test/snapshots/base.test.ts.md @@ -13,9 +13,13 @@ Generated by [AVA](https://avajs.dev). allAuthors: [ { enjoys: [ - 'apples', + 'sitting', + 'standing', + 'mow mow', + 'sleepy time', + 'attention', ], - name: 'Another User', + name: 'Eva', }, { enjoys: [ @@ -25,6 +29,14 @@ Generated by [AVA](https://avajs.dev). ], name: 'Tony', }, + { + enjoys: [ + 'cats', + 'coffee', + 'design', + ], + name: 'Daes', + }, ], }, } @@ -39,10 +51,10 @@ Generated by [AVA](https://avajs.dev). { enjoys: [ 'cats', - 'tea', - 'making this', + 'coffee', + 'design', ], - name: 'Tony', + name: 'Daes', }, ], }, diff --git a/packages/core/src/providers/test/snapshots/base.test.ts.snap b/packages/core/src/providers/test/snapshots/base.test.ts.snap index 950c7672817dab7f153879b50fbae21405ddc62d..61d815b009304b40952f4953def70e0acb14d36d 100644 GIT binary patch literal 576 zcmV-G0>Ax1RzV$?(}4Wvp;4D=Ti!~z>rB_xD|gcvI^vLc4AOl-VMdnU0}svrg|ee$#4_db8m&(Hg# zL6XH&^W+6uWfPnZq)~CSy@Pq7jFwwwl3DY3e>jv@-WOj4Ych903-}c}Un5+Eum|Ct z!6wEQpbWd+E`#$7fWZZT+eEwsfPfbdbL(_ygAoJ1So`*9;}XPM2PLE#M-awjRq6sCk-sQ3$({SoyQ zQQijj~qh@yUGvpJ*8?^>86mcG^s{Sw!#&;S+6>AZ`_rRVn&p;FD|8 zTGUo$+JAb>MuJ#cQ*$9K%9??8DyL*DvJ+)i5ewsNG(xQDg+nxItWP$7mSZBFPnkp` zl~~MA`wPJ9|MV}w4=DHktnEKu^v}Kl@q^Ak3B5D+yj+T_@OMiQJfK1(JR&@YKP|&Q O8}2VAm0!N#1pojV)(D0G literal 470 zcmV;{0V)1LRzVvL3gW;qU%xa)KRULESn45te&c&O z1I<(ek{^o*00000000BcQoByWKoGn=KN2MYCxQ=%sA!-7T8gw#AR#EI(8al6Cl@>M zT@;xPegFx+Ak=g;6o`U~f*$^ZijK93ox~_aAPOvvZoRuV-W|`dSr@+Dmgm=8xk~VM zok`cO_WC>sUFor|bbKYxhK&YO?1=gr$&u)RJkWJKw-8HUR>0h=x45kU(y&}E6IdVs z1Qr2yuyGkQ0!9V&h%Bb)VRn$Epff10CMXI_h+1Dcejpg|W~EC8S8FwK1l&$%DRv4XcQ4#D1nZ zmlYBqB6&lsX;b=X%PJwFY=MAFW@_){NeBY M0G9*XF@6L909BROMgRZ+ diff --git a/packages/core/src/sources/base.ts b/packages/core/src/sources/base.ts new file mode 100644 index 00000000..7d1cb857 --- /dev/null +++ b/packages/core/src/sources/base.ts @@ -0,0 +1,51 @@ +import { cloneDeep } from 'lodash-es'; +import { VFile } from 'vfile'; +import { + FlatbreadArgs, + LoadedCollectionEntry, + LoadedFlatbreadConfig, + Source, +} from '../types'; + +interface MemContext { + id: string; + collectionName: string; +} + +export class SourceMemory implements Source { + private data: Record = {}; + + public id = '@flatbread/sourceMemory'; + + constructor(data: Record) { + this.data = data; + } + + initialize(config: LoadedFlatbreadConfig) {} + + async fetch( + entries: LoadedCollectionEntry[], + { addRecord }: FlatbreadArgs + ) { + for (const entry of entries) { + if (!this.data[entry.name]) + throw new Error(`can't find collection ${entry.name}`); + for (const record of this.data[entry.name]) { + addRecord(entry, cloneDeep(record), { + id: record.path, + collectionName: entry.name, + }); + } + } + } + + async put(doc: VFile, context: MemContext) { + const record = this.data[context.collectionName].find( + (entry) => entry.path === context.id + ); + + record.value = doc; + + return { doc, context }; + } +} diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 06332f36..14526716 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -74,14 +74,17 @@ export interface FlatbreadArgs { addRecord( collection: LoadedCollectionEntry, record: EntryNode, - context: Context + context?: Context ): void; } export interface Source { initialize?: (flatbreadConfig: LoadedFlatbreadConfig) => void; id?: string; - put: (source: VFile, ctx: Context) => Promise; + put: ( + source: VFile, + ctx: Context + ) => Promise<{ doc: VFile; context: Context }>; fetch: ( allContentTypes: LoadedCollectionEntry[], flatbread: FlatbreadArgs diff --git a/tsconfig.json b/tsconfig.json index 2de15ee4..ed99ee0c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,5 +24,9 @@ ] } }, + //https://github.com/avajs/ava/discussions/3036#discussioncomment-2928239 + "ts-node": { + "transpileOnly": true + }, "exclude": ["**/dist/**", "**/node_modules/**"] } From 27912b96a837f7b9325a1ccbb8c622565104f8f6 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sat, 6 Aug 2022 14:44:35 -0500 Subject: [PATCH 15/26] sourceVirtual --- packages/core/src/providers/test/base.test.ts | 9 ++++----- packages/core/src/sources/{base.ts => virtual.ts} | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) rename packages/core/src/sources/{base.ts => virtual.ts} (94%) diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index 9892b025..a980104d 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -1,15 +1,14 @@ -import test from 'ava'; -import filesystem from '@flatbread/source-filesystem'; import markdownTransformer from '@flatbread/transformer-markdown'; +import test from 'ava'; +import { SourceVirtual } from '../../sources/virtual'; import { FlatbreadProvider } from '../base'; -import { SourceMemory } from '../../sources/base'; import { mockData } from './mockData'; -const sourceMemory = new SourceMemory(mockData); +const sourceVirtual = new SourceVirtual(mockData); function basicProject() { return new FlatbreadProvider({ - source: sourceMemory, + source: sourceVirtual, transformer: markdownTransformer({ markdown: { gfm: true, diff --git a/packages/core/src/sources/base.ts b/packages/core/src/sources/virtual.ts similarity index 94% rename from packages/core/src/sources/base.ts rename to packages/core/src/sources/virtual.ts index 7d1cb857..3fb4f439 100644 --- a/packages/core/src/sources/base.ts +++ b/packages/core/src/sources/virtual.ts @@ -12,7 +12,7 @@ interface MemContext { collectionName: string; } -export class SourceMemory implements Source { +export class SourceVirtual implements Source { private data: Record = {}; public id = '@flatbread/sourceMemory'; From a1fd32d62ee33285a39f58499dd76013800b8f72 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sun, 7 Aug 2022 03:37:31 -0500 Subject: [PATCH 16/26] disable star paths, add basic create mutations --- packages/core/package.json | 1 + .../src/generators/collectionMutations.ts | 35 +++++++++++++--- packages/core/src/generators/schema.ts | 42 ++++++++++++++----- packages/core/src/providers/test/base.test.ts | 38 ++++++++++++++++- packages/core/src/sources/virtual.ts | 12 ++++-- packages/core/src/types.ts | 5 ++- packages/source-filesystem/src/index.ts | 25 ++++------- .../src/utils/gatherFileNodes.ts | 2 +- .../src/utils/tests/gatherFileNodes.test.ts | 32 +++++++------- packages/transformer-markdown/src/index.ts | 2 +- pnpm-lock.yaml | 8 ++++ 11 files changed, 144 insertions(+), 58 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index b49d91f8..446e7d98 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -35,6 +35,7 @@ "lodash-es": "4.17.21", "lru-cache": "7.13.2", "matcher": "5.0.0", + "nanoid": "4.0.0", "plur": "5.1.0" }, "devDependencies": { diff --git a/packages/core/src/generators/collectionMutations.ts b/packages/core/src/generators/collectionMutations.ts index c3e4421a..d31c11e6 100644 --- a/packages/core/src/generators/collectionMutations.ts +++ b/packages/core/src/generators/collectionMutations.ts @@ -2,9 +2,9 @@ import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose'; import { merge } from 'lodash-es'; import { CollectionContext, + CollectionEntry, EntryNode, LoadedFlatbreadConfig, - Transformer, } from '../types'; export interface AddCollectionMutationsArgs { @@ -13,7 +13,9 @@ export interface AddCollectionMutationsArgs { config: LoadedFlatbreadConfig; objectComposer: ObjectTypeComposer; schemaComposer: SchemaComposer; + collectionEntry: CollectionEntry; updateCollectionRecord: ( + collection: CollectionEntry, entry: EntryNode & { _metadata: CollectionContext } ) => Promise; } @@ -28,16 +30,17 @@ export default function addCollectionMutations( objectComposer, schemaComposer, updateCollectionRecord, + collectionEntry, } = args; schemaComposer.Mutation.addFields({ [`update${name}`]: { type: objectComposer, - args: { [name]: objectComposer.getInputType() }, - description: `Update or create a ${name}`, + args: { [name]: objectComposer.getInputTypeComposer() }, + description: `Update a ${name}`, async resolve(source, payload) { // remove _metadata to prevent injection - const { _metadata, ...update } = source.author; + const { _metadata, ...update } = payload[name]; const targetRecord = objectComposer .getResolver('findById') @@ -47,10 +50,32 @@ export default function addCollectionMutations( delete update[targetRecord._metadata.referenceField]; const newRecord = merge(targetRecord, update); - await updateCollectionRecord(newRecord); + await updateCollectionRecord(collectionEntry, newRecord); return newRecord; }, }, + [`create${name}`]: { + type: objectComposer, + args: { + [name]: objectComposer + .getInputTypeComposer() + .clone(`${name}CreateInput`) + .removeField('id'), + }, + description: `Create a ${name}`, + async resolve(source, payload, args) { + const record = merge(payload[name], { + _metadata: { + referenceField: collectionEntry.referenceField ?? 'id', + collection: name, + transformedBy: collectionEntry?.defaultTransformer, + sourcedBy: collectionEntry?.defaultSource, + }, + }); + + return await updateCollectionRecord(collectionEntry, record); + }, + }, }); } diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 0da36681..81fdacfd 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -1,6 +1,7 @@ import { schemaComposer } from 'graphql-compose'; import { composeWithJson } from 'graphql-compose-json'; -import { defaultsDeep, get, merge } from 'lodash-es'; +import { defaultsDeep, get, merge, set } from 'lodash-es'; +import { nanoid } from 'nanoid'; import plur from 'plur'; import { VFile } from 'vfile'; @@ -12,6 +13,7 @@ import { LoadedFlatbreadConfig, Source, Transformer, + CollectionEntry, } from '../types'; import { getFieldOverrides } from '../utils/fieldOverrides'; import { map } from '../utils/map'; @@ -108,18 +110,33 @@ export async function generateSchema( undefined: config.transformer[0], }; - async function updateCollectionRecord(entry: EntryNode & { _metadata: any }) { - const { _metadata: ctx, ...record } = entry; - const { serialize } = transformersById[ctx.transformedBy]; + async function updateCollectionRecord( + collection: CollectionEntry, + entry: EntryNode & { _metadata: any } + ) { + const ctx = entry._metadata; + const { serialize, id: transformerId } = + transformersById[ctx.transformedBy]; + + if (ctx.reference) { + const index = allContentNodesJSON[ctx.collection].findIndex( + (c) => get(c, ctx.referenceField) === ctx.reference + ); + + if (index < 0) throw new Error('Failed to find record to update'); + // replace in memory representation of record + allContentNodesJSON[ctx.collection][index] = entry; + } else { + entry._metadata.reference = nanoid(); + set(entry, entry._metadata.referenceField, entry._metadata.reference); + entry._metadata.transformedBy = transformerId; + allContentNodesJSON[ctx.collection].push(entry); + } + + const { _metadata, ...record } = entry; const file = await serialize(record, ctx.transformContext); + await config?.source.put(file, ctx.sourceContext, ctx); - await config?.source.put(file, ctx.sourceContext); - const index = allContentNodesJSON[ctx.collection].findIndex( - (c) => get(c, ctx.referenceField) === ctx.reference - ); - - // replace in memory representation of record - allContentNodesJSON[ctx.collection][index] = entry; return entry; } @@ -143,6 +160,8 @@ export async function generateSchema( /// Query resolvers // + // TODO: add a new type of plugin that can add resolvers to each collection, they should be called here + addCollectionQueries({ name, pluralName, @@ -160,6 +179,7 @@ export async function generateSchema( schemaComposer, updateCollectionRecord, config, + collectionEntry: config.content.find((c) => c.name === name), }); } diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index a980104d..1da68c9e 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -66,7 +66,7 @@ test('update collection record', async (t) => { const flatbread = basicProject(); const sitting = (Math.random() * 100) | 0; const result: any = await flatbread.query({ - rootValue: { author: { id: '2a3e', skills: { sitting } } }, + variableValues: { author: { id: '2a3e', skills: { sitting } } }, source: ` mutation UpdateAuthor($author: AuthorInput){ updateAuthor(Author: $author) { @@ -96,3 +96,39 @@ test('update collection record', async (t) => { t.is(updated.data.Author.skills.sitting, sitting); }); + +test('create collection record', async (t) => { + const flatbread = basicProject(); + const sitting = 69; + const result: any = await flatbread.query({ + variableValues: { test: { skills: { sitting } } }, + source: ` + mutation CreateAuthor($test: AuthorCreateInput){ + createAuthor(Author: $test) { + id + skills { + sitting + } + } + } + `, + }); + + t.is(result.data.createAuthor.skills.sitting, sitting); + + const updated: any = await flatbread.query({ + variableValues: { id: result.data.createAuthor.id }, + source: ` + query QueryAuthor($id: String) { + Author(id: $id) { + id + skills { + sitting + } + } + } + `, + }); + + t.is(updated.data.Author.skills.sitting, sitting); +}); diff --git a/packages/core/src/sources/virtual.ts b/packages/core/src/sources/virtual.ts index 3fb4f439..59a7d404 100644 --- a/packages/core/src/sources/virtual.ts +++ b/packages/core/src/sources/virtual.ts @@ -39,12 +39,16 @@ export class SourceVirtual implements Source { } } - async put(doc: VFile, context: MemContext) { - const record = this.data[context.collectionName].find( - (entry) => entry.path === context.id + async put(doc: VFile, context: MemContext, parentContext: any) { + const record = this.data[parentContext.collection].find( + (entry) => entry.path === parentContext.reference ); - record.value = doc; + if (record) { + record.value = doc.value; + } else { + this.data[parentContext.collection].push(doc); + } return { doc, context }; } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 14526716..5b946902 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -83,7 +83,8 @@ export interface Source { id?: string; put: ( source: VFile, - ctx: Context + ctx: Context, + parentContext: any ) => Promise<{ doc: VFile; context: Context }>; fetch: ( allContentTypes: LoadedCollectionEntry[], @@ -133,6 +134,8 @@ export interface CollectionEntry { overrides?: Override[]; refs?: Record; referenceField?: string; + defaultTransformer?: string; + defaultSource?: string; } export interface LoadedCollectionEntry extends CollectionEntry { diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index 6f588963..efb5038a 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -1,15 +1,12 @@ -import slugify from '@sindresorhus/slugify'; -import { defaultsDeep, merge } from 'lodash-es'; -import { read, write } from 'to-vfile'; -import ownPackage from '../package.json' assert { type: 'json' }; import type { - CollectionContext, - LoadedCollectionEntry, FlatbreadArgs, + LoadedCollectionEntry, LoadedFlatbreadConfig, - SourcePlugin, } from '@flatbread/core'; +import slugify from '@sindresorhus/slugify'; +import { defaultsDeep } from 'lodash-es'; import { relative, resolve } from 'path'; +import { read, write } from 'to-vfile'; import type { VFile } from 'vfile'; import type { FileNode, @@ -65,7 +62,7 @@ async function getAllNodes( flatbread: FlatbreadArgs, config: InitializedSourceFilesystemConfig ): Promise { - const nodeEntries = await Promise.all( + await Promise.all( allCollectionEntries.map( async (contentType): Promise> => new Promise(async (res) => @@ -76,18 +73,10 @@ async function getAllNodes( ) ) ); - - const nodes = Object.fromEntries( - nodeEntries as Iterable - ); } -// TODO: _flatbread data should be extracted from plugins -// plugin should return a context object and be given the same context object back when saving, -// this context object will be saved internally under _flatbread[collectionId] - -async function put(doc: VFile, context: Context) { - doc.basename = context.filename; +async function put(doc: VFile, context: Context, parentContext: any) { + doc.basename = context?.filename ?? parentContext.reference; doc.path = resolve(process.cwd(), context.path); await write(doc); diff --git a/packages/source-filesystem/src/utils/gatherFileNodes.ts b/packages/source-filesystem/src/utils/gatherFileNodes.ts index 8f880636..c3201400 100644 --- a/packages/source-filesystem/src/utils/gatherFileNodes.ts +++ b/packages/source-filesystem/src/utils/gatherFileNodes.ts @@ -51,7 +51,7 @@ export default async function gatherFileNodes( ) ?? ['.md', '.mdx', '.markdown']; // gather all the globs in the path ( [capture-groups], **, *) - const [pathPrefix, ...globs] = path.split(/\/(?:\[|\*+)/); + const [pathPrefix, ...globs] = path.split(/\/(?:\[)/); // for each segment - gather names for capture groups // and calculate what to remove from matches ex: [name].md => remove .md from match diff --git a/packages/source-filesystem/src/utils/tests/gatherFileNodes.test.ts b/packages/source-filesystem/src/utils/tests/gatherFileNodes.test.ts index e9b2699c..67bc3134 100644 --- a/packages/source-filesystem/src/utils/tests/gatherFileNodes.test.ts +++ b/packages/source-filesystem/src/utils/tests/gatherFileNodes.test.ts @@ -32,20 +32,20 @@ test('basic case', async (t) => { t.snapshot(result2); }); -test('double level recursion', async (t) => { - const result = await gatherFileNodes('deeply/**/*.md', opts); - t.snapshot(result); -}); +// test('double level recursion', async (t) => { +// const result = await gatherFileNodes('deeply/**/*.md', opts); +// t.snapshot(result); +// }); test('double level recursion named', async (t) => { const result = await gatherFileNodes('deeply/[a]/[b].md', opts); t.snapshot(result); }); -test('single level recursion', async (t) => { - const result = await gatherFileNodes('./*.md', opts as any); - t.snapshot(result); -}); +// test('single level recursion', async (t) => { +// const result = await gatherFileNodes('./*.md', opts as any); +// t.snapshot(result); +// }); test('double level recursion named without parent directory', async (t) => { const result = await gatherFileNodes('./[genre]/[title].md', opts); @@ -57,15 +57,15 @@ test('single level named', async (t) => { t.snapshot(result); }); -test('double level first named', async (t) => { - const result = await gatherFileNodes('./[genre]/*.md', opts); - t.snapshot(result); -}); +// test('double level first named', async (t) => { +// const result = await gatherFileNodes('./[genre]/*.md', opts); +// t.snapshot(result); +// }); -test('double level second named', async (t) => { - const result = await gatherFileNodes('./**/[title].md', opts); - t.snapshot(result); -}); +// test('double level second named', async (t) => { +// const result = await gatherFileNodes('./**/[title].md', opts); +// t.snapshot(result); +// }); test('triple level', async (t) => { const result = await gatherFileNodes('./[random]/[name]/[title].md', opts); diff --git a/packages/transformer-markdown/src/index.ts b/packages/transformer-markdown/src/index.ts index 77358696..eb8dd087 100644 --- a/packages/transformer-markdown/src/index.ts +++ b/packages/transformer-markdown/src/index.ts @@ -40,7 +40,7 @@ function serialize( config: MarkdownTransformerConfig ) { const { _content, ...rest } = data; - const doc = matter.stringify(_content.raw, rest, config.grayMatter); + const doc = matter.stringify(_content?.raw ?? '', rest, config.grayMatter); return new VFile(doc); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ef1c28b..a19f7dfb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -152,6 +152,7 @@ importers: lodash-es: 4.17.21 lru-cache: 7.13.2 matcher: 5.0.0 + nanoid: 4.0.0 plur: 5.1.0 tsup: 6.2.1 typescript: 4.7.4 @@ -163,6 +164,7 @@ importers: lodash-es: 4.17.21 lru-cache: 7.13.2 matcher: 5.0.0 + nanoid: 4.0.0 plur: 5.1.0 devDependencies: '@types/lodash-es': 4.17.6 @@ -7210,6 +7212,12 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + /nanoid/4.0.0: + resolution: {integrity: sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==} + engines: {node: ^14 || ^16 || >=18} + hasBin: true + dev: false + /napi-build-utils/1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} From 22da94951017bfc8b345c09a247a3b5cc17b2efc Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sun, 7 Aug 2022 19:42:01 -0500 Subject: [PATCH 17/26] handle creating new records with variable paths --- examples/sveltekit/flatbread.config.js | 7 ---- packages/core/package.json | 2 + packages/core/src/generators/schema.ts | 24 +++++++---- packages/core/src/sources/virtual.ts | 2 +- packages/core/src/types.ts | 2 +- packages/core/src/utils/createUniqueId.ts | 9 +++++ packages/source-filesystem/src/index.test.ts | 40 +++++++++++++++++++ packages/source-filesystem/src/index.ts | 36 +++++++++++++++-- .../src/utils/gatherFileNodes.ts | 5 +++ packages/source-filesystem/tsup.config.ts | 2 +- pnpm-lock.yaml | 27 +++++++++---- 11 files changed, 127 insertions(+), 29 deletions(-) create mode 100644 packages/core/src/utils/createUniqueId.ts create mode 100644 packages/source-filesystem/src/index.test.ts diff --git a/examples/sveltekit/flatbread.config.js b/examples/sveltekit/flatbread.config.js index 8d9565db..30f03342 100644 --- a/examples/sveltekit/flatbread.config.js +++ b/examples/sveltekit/flatbread.config.js @@ -31,13 +31,6 @@ export default defineConfig({ authors: 'Author', }, }, - { - path: 'content/markdown/posts/**/*.md', - name: 'PostCategoryBlob', - refs: { - authors: 'Author', - }, - }, { path: 'content/markdown/authors', name: 'Author', diff --git a/packages/core/package.json b/packages/core/package.json index 446e7d98..c35ac2af 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -40,7 +40,9 @@ }, "devDependencies": { "@types/lodash-es": "4.17.6", + "@types/nanoid-dictionary": "4.2.0", "@types/node": "16.11.47", + "nanoid-dictionary": "4.3.0", "tsup": "6.2.1", "typescript": "4.7.4", "vfile": "5.3.4" diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 81fdacfd..39995e31 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -1,20 +1,20 @@ import { schemaComposer } from 'graphql-compose'; import { composeWithJson } from 'graphql-compose-json'; import { defaultsDeep, get, merge, set } from 'lodash-es'; -import { nanoid } from 'nanoid'; import plur from 'plur'; import { VFile } from 'vfile'; import { cacheSchema, checkCacheForSchema } from '../cache/cache'; import { + CollectionEntry, ConfigResult, EntryNode, LoadedCollectionEntry, LoadedFlatbreadConfig, Source, Transformer, - CollectionEntry, } from '../types'; +import { createUniqueId } from '../utils/createUniqueId'; import { getFieldOverrides } from '../utils/fieldOverrides'; import { map } from '../utils/map'; import addCollectionMutations from './collectionMutations'; @@ -115,8 +115,11 @@ export async function generateSchema( entry: EntryNode & { _metadata: any } ) { const ctx = entry._metadata; - const { serialize, id: transformerId } = - transformersById[ctx.transformedBy]; + const { + serialize, + extensions, + id: transformerId, + } = transformersById[ctx.transformedBy]; if (ctx.reference) { const index = allContentNodesJSON[ctx.collection].findIndex( @@ -127,15 +130,20 @@ export async function generateSchema( // replace in memory representation of record allContentNodesJSON[ctx.collection][index] = entry; } else { - entry._metadata.reference = nanoid(); + entry._metadata.reference = createUniqueId(); set(entry, entry._metadata.referenceField, entry._metadata.reference); entry._metadata.transformedBy = transformerId; + entry._metadata.extension = extensions?.[0]; allContentNodesJSON[ctx.collection].push(entry); } const { _metadata, ...record } = entry; const file = await serialize(record, ctx.transformContext); - await config?.source.put(file, ctx.sourceContext, ctx); + await config?.source.put(file, ctx.sourceContext, { + parentContext: ctx, + collection, + record, + }); return entry; } @@ -179,7 +187,9 @@ export async function generateSchema( schemaComposer, updateCollectionRecord, config, - collectionEntry: config.content.find((c) => c.name === name), + collectionEntry: config.content.find( + (c) => c.name === name + ) as CollectionEntry, }); } diff --git a/packages/core/src/sources/virtual.ts b/packages/core/src/sources/virtual.ts index 59a7d404..d2be745a 100644 --- a/packages/core/src/sources/virtual.ts +++ b/packages/core/src/sources/virtual.ts @@ -39,7 +39,7 @@ export class SourceVirtual implements Source { } } - async put(doc: VFile, context: MemContext, parentContext: any) { + async put(doc: VFile, context: MemContext, { parentContext }: any) { const record = this.data[parentContext.collection].find( (entry) => entry.path === parentContext.reference ); diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 5b946902..e8ccf83f 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -84,7 +84,7 @@ export interface Source { put: ( source: VFile, ctx: Context, - parentContext: any + opts: { parentContext: any; collection: CollectionEntry; record: any } ) => Promise<{ doc: VFile; context: Context }>; fetch: ( allContentTypes: LoadedCollectionEntry[], diff --git a/packages/core/src/utils/createUniqueId.ts b/packages/core/src/utils/createUniqueId.ts new file mode 100644 index 00000000..2f68dbda --- /dev/null +++ b/packages/core/src/utils/createUniqueId.ts @@ -0,0 +1,9 @@ +import { customAlphabet } from 'nanoid'; +import { lowercase, numbers } from 'nanoid-dictionary'; + +const nanoid = customAlphabet(lowercase + numbers); + +export function createUniqueId() { + // only use lower case to avoid issues with windows ignoring case on filenames + return nanoid(); +} diff --git a/packages/source-filesystem/src/index.test.ts b/packages/source-filesystem/src/index.test.ts new file mode 100644 index 00000000..6af017b8 --- /dev/null +++ b/packages/source-filesystem/src/index.test.ts @@ -0,0 +1,40 @@ +import test from 'ava'; +import { createPath } from './index'; + +test('create path can correctly populate a path', (t) => { + const path = createPath( + { + name: 'Test', + path: '/[test]/[nested.test]/[blah].md', + }, + { + test: 'first', + nested: { + test: 'second-part', + }, + blah: 'blarghhh', + }, + { extension: '' } + ); + + t.is(path, '/first/second-part/blarghhh.md'); +}); + +test('create path can correctly populate a path without an extension', (t) => { + const path = createPath( + { + name: 'Test', + path: '/[test]/[nested.test]/[blah]', + }, + { + test: 'first', + nested: { + test: 'second-part', + }, + blah: 'blarghhh', + }, + { extension: '.md', reference: 'test-name', referenceField: 'id' } + ); + + t.is(path, '/first/second-part/blarghhh/test-name.md'); +}); diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index efb5038a..75e9c3c8 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -1,11 +1,12 @@ import type { + CollectionEntry, FlatbreadArgs, LoadedCollectionEntry, LoadedFlatbreadConfig, } from '@flatbread/core'; import slugify from '@sindresorhus/slugify'; -import { defaultsDeep } from 'lodash-es'; -import { relative, resolve } from 'path'; +import { defaultsDeep, get } from 'lodash-es'; +import path, { relative, resolve } from 'path'; import { read, write } from 'to-vfile'; import type { VFile } from 'vfile'; import type { @@ -75,9 +76,36 @@ async function getAllNodes( ); } -async function put(doc: VFile, context: Context, parentContext: any) { +export function createPath( + collection: CollectionEntry, + record: any, + parentContext: any +): string { + const partialPath = collection.path.replace( + /\[(.*?)\]/g, + (_: any, match: any) => get(record, match) + ); + + const filename = path.parse(partialPath); + + if (!filename.ext) { + return resolve( + partialPath, + parentContext.reference + parentContext.extension + ); + } + + return partialPath; +} + +async function put( + doc: VFile, + context: Context, + { parentContext, collection, record }: any +) { + const path = context?.path ?? createPath(collection, record, parentContext); doc.basename = context?.filename ?? parentContext.reference; - doc.path = resolve(process.cwd(), context.path); + doc.path = resolve(process.cwd(), path); await write(doc); diff --git a/packages/source-filesystem/src/utils/gatherFileNodes.ts b/packages/source-filesystem/src/utils/gatherFileNodes.ts index c3201400..a4bdf664 100644 --- a/packages/source-filesystem/src/utils/gatherFileNodes.ts +++ b/packages/source-filesystem/src/utils/gatherFileNodes.ts @@ -41,6 +41,11 @@ export default async function gatherFileNodes( path: string, { readDirectory = readDir, extensions }: GatherFileNodesOptions = {} ): Promise { + if (path.includes('*')) + throw new Error( + `* wildcards are not supported, only variable named paths like [example]\nPlease change path in config "${path}"` + ); + /** * Prepend a period to the extension if it doesn't have one. * If no extensions are provided, use the default ones. diff --git a/packages/source-filesystem/tsup.config.ts b/packages/source-filesystem/tsup.config.ts index 24b848e6..fa78cb57 100644 --- a/packages/source-filesystem/tsup.config.ts +++ b/packages/source-filesystem/tsup.config.ts @@ -4,7 +4,7 @@ export const tsup: Options = { splitting: false, sourcemap: true, clean: true, - entryPoints: ['src/*'], + entryPoints: ['src/index.ts'], format: ['esm'], target: 'esnext', dts: true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a19f7dfb..3f3f4d9b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,8 +106,8 @@ importers: svimg: 3.0.0 devDependencies: '@flatbread/transformer-yaml': link:../../packages/transformer-yaml - '@sveltejs/adapter-static': 1.0.0-next.38 - '@sveltejs/kit': 1.0.0-next.403_svelte@3.49.0+vite@3.0.4 + '@sveltejs/adapter-static': 1.0.0-next.39 + '@sveltejs/kit': 1.0.0-next.405_svelte@3.49.0+vite@3.0.4 '@typescript-eslint/eslint-plugin': 4.33.0_3ekaj7j3owlolnuhj3ykrb7u7i '@typescript-eslint/parser': 4.33.0_hxadhbs2xogijvk7vq4t2azzbu autoprefixer: 10.4.7_postcss@8.4.14 @@ -145,6 +145,7 @@ importers: packages/core: specifiers: '@types/lodash-es': 4.17.6 + '@types/nanoid-dictionary': 4.2.0 '@types/node': 16.11.47 graphql: 16.5.0 graphql-compose: 9.0.8 @@ -153,6 +154,7 @@ importers: lru-cache: 7.13.2 matcher: 5.0.0 nanoid: 4.0.0 + nanoid-dictionary: 4.3.0 plur: 5.1.0 tsup: 6.2.1 typescript: 4.7.4 @@ -168,7 +170,9 @@ importers: plur: 5.1.0 devDependencies: '@types/lodash-es': 4.17.6 + '@types/nanoid-dictionary': 4.2.0 '@types/node': 16.11.47 + nanoid-dictionary: 4.3.0 tsup: 6.2.1_typescript@4.7.4 typescript: 4.7.4 vfile: 5.3.4 @@ -1569,14 +1573,12 @@ packages: '@sinonjs/commons': 1.8.3 dev: true - /@sveltejs/adapter-static/1.0.0-next.38: - resolution: {integrity: sha512-O1b264K62E3OrUnsFxMjKn3CUJF50fxGcW0rWk8fa5kjzskPsSyTxS3jnWNryFaVJ3oSUtx57m4qFW43S1910Q==} - dependencies: - tiny-glob: 0.2.9 + /@sveltejs/adapter-static/1.0.0-next.39: + resolution: {integrity: sha512-EeD39H6iEe0UEKnKxLFTZFZpi/FcX5xfbAvsMQ+B09aDZccpQmkJBSIo+4kq1JsQGSjwi/+J3aE9bR67R6CIyQ==} dev: true - /@sveltejs/kit/1.0.0-next.403_svelte@3.49.0+vite@3.0.4: - resolution: {integrity: sha512-pKlmthl1SZkbx671Jp+LBoRne0vNzsjSgta9iRhqW/bt/0mx/IjlMd/NOeLuJGo30dAJdefrySoSamiaq47M/g==} + /@sveltejs/kit/1.0.0-next.405_svelte@3.49.0+vite@3.0.4: + resolution: {integrity: sha512-jHSa74F7k+hC+0fof75g/xm/+1M5sM66Qt6v8eLLMSgjkp36Lb5xOioBhbl6w0NYoE5xysLsBWuu+yHytfvCBA==} engines: {node: '>=16.9'} hasBin: true requiresBuild: true @@ -1588,6 +1590,7 @@ packages: chokidar: 3.5.3 sade: 1.8.1 svelte: 3.49.0 + tiny-glob: 0.2.9 vite: 3.0.4 transitivePeerDependencies: - diff-match-patch @@ -1806,6 +1809,10 @@ packages: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} dev: false + /@types/nanoid-dictionary/4.2.0: + resolution: {integrity: sha512-DyQddKC2AYsInXBMqKSwhom4gpouV8SF1smsCPSzR8hp20vZJ5o5Yxg7qXThCHwr/H6VMq01UArEGbF0q2FXig==} + dev: true + /@types/node/10.17.60: resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} dev: false @@ -7207,6 +7214,10 @@ packages: thenify-all: 1.6.0 dev: true + /nanoid-dictionary/4.3.0: + resolution: {integrity: sha512-Xw1+/QnRGWO1KJ0rLfU1xR85qXmAHyLbE3TUkklu9gOIDburP6CsUnLmTaNECGpBh5SHb2uPFmx0VT8UPyoeyw==} + dev: true + /nanoid/3.3.4: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} From f31e91fca08b9bf36736aa7aecc4ed9153f765de Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sun, 7 Aug 2022 20:06:05 -0500 Subject: [PATCH 18/26] remove nanoid-dictionary --- packages/core/package.json | 2 -- packages/core/src/utils/createUniqueId.ts | 5 ++--- pnpm-lock.yaml | 12 ------------ 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index c35ac2af..446e7d98 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -40,9 +40,7 @@ }, "devDependencies": { "@types/lodash-es": "4.17.6", - "@types/nanoid-dictionary": "4.2.0", "@types/node": "16.11.47", - "nanoid-dictionary": "4.3.0", "tsup": "6.2.1", "typescript": "4.7.4", "vfile": "5.3.4" diff --git a/packages/core/src/utils/createUniqueId.ts b/packages/core/src/utils/createUniqueId.ts index 2f68dbda..c860ed01 100644 --- a/packages/core/src/utils/createUniqueId.ts +++ b/packages/core/src/utils/createUniqueId.ts @@ -1,9 +1,8 @@ import { customAlphabet } from 'nanoid'; -import { lowercase, numbers } from 'nanoid-dictionary'; -const nanoid = customAlphabet(lowercase + numbers); +// only use lower case letters and numbers to avoid issues with windows ignoring case on filenames +const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789'); export function createUniqueId() { - // only use lower case to avoid issues with windows ignoring case on filenames return nanoid(); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3f3f4d9b..418fa204 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -145,7 +145,6 @@ importers: packages/core: specifiers: '@types/lodash-es': 4.17.6 - '@types/nanoid-dictionary': 4.2.0 '@types/node': 16.11.47 graphql: 16.5.0 graphql-compose: 9.0.8 @@ -154,7 +153,6 @@ importers: lru-cache: 7.13.2 matcher: 5.0.0 nanoid: 4.0.0 - nanoid-dictionary: 4.3.0 plur: 5.1.0 tsup: 6.2.1 typescript: 4.7.4 @@ -170,9 +168,7 @@ importers: plur: 5.1.0 devDependencies: '@types/lodash-es': 4.17.6 - '@types/nanoid-dictionary': 4.2.0 '@types/node': 16.11.47 - nanoid-dictionary: 4.3.0 tsup: 6.2.1_typescript@4.7.4 typescript: 4.7.4 vfile: 5.3.4 @@ -1809,10 +1805,6 @@ packages: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} dev: false - /@types/nanoid-dictionary/4.2.0: - resolution: {integrity: sha512-DyQddKC2AYsInXBMqKSwhom4gpouV8SF1smsCPSzR8hp20vZJ5o5Yxg7qXThCHwr/H6VMq01UArEGbF0q2FXig==} - dev: true - /@types/node/10.17.60: resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} dev: false @@ -7214,10 +7206,6 @@ packages: thenify-all: 1.6.0 dev: true - /nanoid-dictionary/4.3.0: - resolution: {integrity: sha512-Xw1+/QnRGWO1KJ0rLfU1xR85qXmAHyLbE3TUkklu9gOIDburP6CsUnLmTaNECGpBh5SHb2uPFmx0VT8UPyoeyw==} - dev: true - /nanoid/3.3.4: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} From e43f01c716cb4e9db5976740559de5a9f024c6d4 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Mon, 8 Aug 2022 01:02:26 -0500 Subject: [PATCH 19/26] cleanups, add required fields to resolvers, add upsert resolver --- .../src/generators/collectionMutations.ts | 102 +++++++++++++----- packages/core/src/generators/schema.ts | 29 +++-- packages/core/src/types.ts | 6 ++ packages/core/src/utils/initializeConfig.ts | 5 +- packages/flatbread/README.md | 4 + packages/source-filesystem/src/index.ts | 8 +- 6 files changed, 120 insertions(+), 34 deletions(-) diff --git a/packages/core/src/generators/collectionMutations.ts b/packages/core/src/generators/collectionMutations.ts index d31c11e6..13cd7ca4 100644 --- a/packages/core/src/generators/collectionMutations.ts +++ b/packages/core/src/generators/collectionMutations.ts @@ -1,9 +1,10 @@ import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose'; -import { merge } from 'lodash-es'; +import { get, merge } from 'lodash-es'; import { CollectionContext, CollectionEntry, EntryNode, + LoadedCollectionEntry, LoadedFlatbreadConfig, } from '../types'; @@ -13,7 +14,7 @@ export interface AddCollectionMutationsArgs { config: LoadedFlatbreadConfig; objectComposer: ObjectTypeComposer; schemaComposer: SchemaComposer; - collectionEntry: CollectionEntry; + collectionEntry: LoadedCollectionEntry; updateCollectionRecord: ( collection: CollectionEntry, entry: EntryNode & { _metadata: CollectionContext } @@ -33,27 +34,72 @@ export default function addCollectionMutations( collectionEntry, } = args; + async function update( + payload: Record, + existing: EntryNode + ) { + // remove _metadata to prevent injection + const { _metadata, ...update } = payload?.[name]; + + const targetRecord = objectComposer + .getResolver('findById') + .resolve({ args: update }); + + // remove supplied key (might not be required) + delete update[targetRecord._metadata.referenceField]; + const newRecord = merge(targetRecord, update); + + await updateCollectionRecord(collectionEntry, newRecord); + + return newRecord; + } + + async function create(source: unknown, payload: Record) { + collectionEntry.creationRequiredFields.forEach((field) => { + if (!payload[name].hasOwnProperty(field)) + throw new Error( + `field ${field} is required when creating a new ${name}` + ); + }); + + const record = merge(payload[name], { + _metadata: { + referenceField: collectionEntry.referenceField ?? 'id', + collection: name, + transformedBy: collectionEntry?.defaultTransformer, + sourcedBy: collectionEntry?.defaultSource, + } as CollectionContext, + }); + + return await updateCollectionRecord(collectionEntry, record); + } + schemaComposer.Mutation.addFields({ [`update${name}`]: { type: objectComposer, - args: { [name]: objectComposer.getInputTypeComposer() }, + args: { + [name]: objectComposer + .getInputTypeComposer() + .makeFieldNonNull(collectionEntry.creationRequiredFields), + }, description: `Update a ${name}`, - async resolve(source, payload) { - // remove _metadata to prevent injection - const { _metadata, ...update } = payload[name]; + async resolve(source: unknown, payload: Record) { + const { _metadata, ...args } = payload?.[name]; - const targetRecord = objectComposer + const existingRecord = objectComposer .getResolver('findById') - .resolve({ args: update }); - - // remove supplied key (might not be required) - delete update[targetRecord._metadata.referenceField]; - const newRecord = merge(targetRecord, update); - - await updateCollectionRecord(collectionEntry, newRecord); + .resolve({ args }); - return newRecord; + if (!existingRecord) + throw new Error( + `${name} with ${collectionEntry.referenceField} of ${get( + args, + collectionEntry.referenceField + )} not found` + ); + return update(payload, existingRecord); }, + update, }, [`create${name}`]: { type: objectComposer, @@ -61,20 +107,24 @@ export default function addCollectionMutations( [name]: objectComposer .getInputTypeComposer() .clone(`${name}CreateInput`) - .removeField('id'), + .removeField('id') + .makeFieldNonNull(collectionEntry.creationRequiredFields), }, description: `Create a ${name}`, - async resolve(source, payload, args) { - const record = merge(payload[name], { - _metadata: { - referenceField: collectionEntry.referenceField ?? 'id', - collection: name, - transformedBy: collectionEntry?.defaultTransformer, - sourcedBy: collectionEntry?.defaultSource, - }, - }); + resolve: create, + }, + [`upsert${name}`]: { + type: objectComposer, + args: { [name]: objectComposer.getInputTypeComposer() }, + async resolve(source: unknown, payload: Record) { + const { _metadata, ...args } = payload?.[name]; + + const existingRecord = objectComposer + .getResolver('findById') + .resolve({ args }); - return await updateCollectionRecord(collectionEntry, record); + if (existingRecord) return update(payload, existingRecord); + create(source, payload); }, }, }); diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 39995e31..34909ca2 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -46,8 +46,15 @@ export async function generateSchema( // Invoke the content source resolver to retrieve the content nodes let allContentNodes: Record = {}; + let collectionEntriesByName = Object.fromEntries( + config.content.map((collection: LoadedCollectionEntry) => [ + collection.name, + collection, + ]) + ); + const addRecord = - (source: Source) => + (sourceId: string) => ( collection: LoadedCollectionEntry, record: EntryNode, @@ -59,7 +66,7 @@ export async function generateSchema( record, context: { sourceContext: context, - sourcedBy: source.id, + sourcedBy: sourceId, collection: collection.name, referenceField: collection.referenceField ?? 'id', }, @@ -69,8 +76,20 @@ export async function generateSchema( return newRecord; }; + function addCreationRequiredFields( + collection: CollectionEntry, + fields: string[] + ): void { + if (!collectionEntriesByName[collection.name]) + throw new Error(`Couldn't find collection ${collection.name}`); + collectionEntriesByName?.[collection.name]?.creationRequiredFields?.push( + ...fields + ); + } + await config.source.fetch(config.content, { - addRecord: addRecord(config.source), + addRecord: addRecord(config.source.id as string), + addCreationRequiredFields, }); // Transform the content nodes to the expected JSON format if needed @@ -187,9 +206,7 @@ export async function generateSchema( schemaComposer, updateCollectionRecord, config, - collectionEntry: config.content.find( - (c) => c.name === name - ) as CollectionEntry, + collectionEntry: collectionEntriesByName[name], }); } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index e8ccf83f..a74209f9 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -76,6 +76,10 @@ export interface FlatbreadArgs { record: EntryNode, context?: Context ): void; + addCreationRequiredFields( + collection: LoadedCollectionEntry, + fields: string[] + ): void; } export interface Source { @@ -134,10 +138,12 @@ export interface CollectionEntry { overrides?: Override[]; refs?: Record; referenceField?: string; + creationRequiredFields?: string[]; defaultTransformer?: string; defaultSource?: string; } export interface LoadedCollectionEntry extends CollectionEntry { referenceField: string; + creationRequiredFields: string[]; } diff --git a/packages/core/src/utils/initializeConfig.ts b/packages/core/src/utils/initializeConfig.ts index f1b4f2e5..37f57d32 100644 --- a/packages/core/src/utils/initializeConfig.ts +++ b/packages/core/src/utils/initializeConfig.ts @@ -22,7 +22,10 @@ export function initializeConfig( return { ...config, content: config.content?.map((content: Partial) => - defaultsDeep(content, { referenceField: 'id' }) + defaultsDeep(content, { + referenceField: 'id', + creationRequiredFields: [], + }) ), transformer, loaded: { diff --git a/packages/flatbread/README.md b/packages/flatbread/README.md index 4b152a3e..4f6596f9 100644 --- a/packages/flatbread/README.md +++ b/packages/flatbread/README.md @@ -83,6 +83,10 @@ export default defineConfig({ { path: 'content/authors', collection: 'Author', + // the field to use as the primary key, 'id' by default + referenceField: 'id', + // a list of fields that are required when creating a new record (mostly used by plugins) + creationRequiredFields: [] refs: { friend: 'Author', }, diff --git a/packages/source-filesystem/src/index.ts b/packages/source-filesystem/src/index.ts index 75e9c3c8..b4787607 100644 --- a/packages/source-filesystem/src/index.ts +++ b/packages/source-filesystem/src/index.ts @@ -31,7 +31,7 @@ interface Context { */ async function getNodesFromDirectory( collectionEntry: LoadedCollectionEntry, - { addRecord }: FlatbreadArgs, + { addRecord, addCreationRequiredFields }: FlatbreadArgs, config: InitializedSourceFilesystemConfig ): Promise { const { extensions } = config; @@ -39,6 +39,12 @@ async function getNodesFromDirectory( extensions, }); + // collect all the variable path segments [like] [these] + const requiredFields = Array.from( + collectionEntry.path.matchAll(/\[(.*?)\]/g) + ).map((m) => m[1]); + addCreationRequiredFields(collectionEntry, requiredFields); + await Promise.all( nodes.map(async (node: FileNode): Promise => { const doc = await read(node.path); From a18ee39b6fac2492f88a85dc23dd71dd2d1c4cb9 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Thu, 11 Aug 2022 01:47:53 -0500 Subject: [PATCH 20/26] expose collectionResolvers to config --- examples/sveltekit/flatbread.config.js | 17 ++++++ .../src/generators/collectionMutations.ts | 53 +++++-------------- .../core/src/generators/collectionQueries.ts | 47 ++++++---------- packages/core/src/generators/schema.ts | 34 ++++++++---- packages/core/src/providers/test/base.test.ts | 42 +++++++++++++++ packages/core/src/types.ts | 19 +++++++ packages/core/src/utils/initializeConfig.ts | 1 + 7 files changed, 134 insertions(+), 79 deletions(-) diff --git a/examples/sveltekit/flatbread.config.js b/examples/sveltekit/flatbread.config.js index 30f03342..21a22d1e 100644 --- a/examples/sveltekit/flatbread.config.js +++ b/examples/sveltekit/flatbread.config.js @@ -16,6 +16,23 @@ const transformerConfig = { export default defineConfig({ source: sourceFilesystem(), transformer: [transformerMarkdown(transformerConfig), transformerYaml()], + + collectionResolvers: [ + function fakeResolver(schemaComposer, args) { + const { name } = args; + + schemaComposer.Query.addFields({ + [`fake${name}`]: { + type: 'String', + description: `fake resolver`, + resolve() { + return `fake ${name}!`; + }, + }, + }); + }, + ], + content: [ { path: 'content/markdown/posts', diff --git a/packages/core/src/generators/collectionMutations.ts b/packages/core/src/generators/collectionMutations.ts index 13cd7ca4..68edf422 100644 --- a/packages/core/src/generators/collectionMutations.ts +++ b/packages/core/src/generators/collectionMutations.ts @@ -1,38 +1,13 @@ import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose'; import { get, merge } from 'lodash-es'; -import { - CollectionContext, - CollectionEntry, - EntryNode, - LoadedCollectionEntry, - LoadedFlatbreadConfig, -} from '../types'; - -export interface AddCollectionMutationsArgs { - name: string; - pluralName: string; - config: LoadedFlatbreadConfig; - objectComposer: ObjectTypeComposer; - schemaComposer: SchemaComposer; - collectionEntry: LoadedCollectionEntry; - updateCollectionRecord: ( - collection: CollectionEntry, - entry: EntryNode & { _metadata: CollectionContext } - ) => Promise; -} +import { CollectionContext, CollectionResolverArgs, EntryNode } from '../types'; export default function addCollectionMutations( - args: AddCollectionMutationsArgs + schemaComposer: SchemaComposer, + args: CollectionResolverArgs ) { - const { - name, - pluralName, - config, - objectComposer, - schemaComposer, - updateCollectionRecord, - collectionEntry, - } = args; + const { name, objectTypeComposer, updateCollectionRecord, collectionEntry } = + args; async function update( payload: Record, @@ -41,7 +16,7 @@ export default function addCollectionMutations( // remove _metadata to prevent injection const { _metadata, ...update } = payload?.[name]; - const targetRecord = objectComposer + const targetRecord = objectTypeComposer .getResolver('findById') .resolve({ args: update }); @@ -76,9 +51,9 @@ export default function addCollectionMutations( schemaComposer.Mutation.addFields({ [`update${name}`]: { - type: objectComposer, + type: objectTypeComposer, args: { - [name]: objectComposer + [name]: objectTypeComposer .getInputTypeComposer() .makeFieldNonNull(collectionEntry.creationRequiredFields), }, @@ -86,7 +61,7 @@ export default function addCollectionMutations( async resolve(source: unknown, payload: Record) { const { _metadata, ...args } = payload?.[name]; - const existingRecord = objectComposer + const existingRecord = objectTypeComposer .getResolver('findById') .resolve({ args }); @@ -102,9 +77,9 @@ export default function addCollectionMutations( update, }, [`create${name}`]: { - type: objectComposer, + type: objectTypeComposer, args: { - [name]: objectComposer + [name]: objectTypeComposer .getInputTypeComposer() .clone(`${name}CreateInput`) .removeField('id') @@ -114,12 +89,12 @@ export default function addCollectionMutations( resolve: create, }, [`upsert${name}`]: { - type: objectComposer, - args: { [name]: objectComposer.getInputTypeComposer() }, + type: objectTypeComposer, + args: { [name]: objectTypeComposer.getInputTypeComposer() }, async resolve(source: unknown, payload: Record) { const { _metadata, ...args } = payload?.[name]; - const existingRecord = objectComposer + const existingRecord = objectTypeComposer .getResolver('findById') .resolve({ args }); diff --git a/packages/core/src/generators/collectionQueries.ts b/packages/core/src/generators/collectionQueries.ts index b5cbabd2..dd4fa887 100644 --- a/packages/core/src/generators/collectionQueries.ts +++ b/packages/core/src/generators/collectionQueries.ts @@ -1,39 +1,26 @@ -import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose'; import resolveQueryArgs from '../resolvers/arguments'; +import { SchemaComposer } from 'graphql-compose'; +import { cloneDeep } from 'lodash-es'; import { generateArgsForAllItemQuery, generateArgsForManyItemQuery, generateArgsForSingleItemQuery, } from '../generators/arguments'; -import { cloneDeep } from 'lodash-es'; -import { EntryNode, LoadedFlatbreadConfig, Transformer } from '../types'; - -export interface AddCollectionQueriesArgs { - name: string; - pluralName: string; - config: LoadedFlatbreadConfig; - objectComposer: ObjectTypeComposer; - schemaComposer: SchemaComposer; - allContentNodesJSON: Record; - transformersById: Record; -} +import { CollectionResolverArgs, EntryNode } from '../types'; -export default function addCollectionQueries(args: AddCollectionQueriesArgs) { - const { - name, - pluralName, - config, - objectComposer, - schemaComposer, - allContentNodesJSON, - } = args; +export default function addCollectionQueries( + schemaComposer: SchemaComposer, + args: CollectionResolverArgs & { allContentNodesJSON: Record } +) { + const { name, pluralName, config, objectTypeComposer, allContentNodesJSON } = + args; const pluralTypeQueryName = 'all' + pluralName; - objectComposer.addResolver({ + objectTypeComposer.addResolver({ name: 'findById', - type: () => objectComposer, + type: () => objectTypeComposer, description: `Find one ${name} by its ID`, args: generateArgsForSingleItemQuery(), resolve: (rp: Record) => @@ -44,9 +31,9 @@ export default function addCollectionQueries(args: AddCollectionQueriesArgs) { ), }); - objectComposer.addResolver({ + objectTypeComposer.addResolver({ name: 'findMany', - type: () => [objectComposer], + type: () => [objectTypeComposer], description: `Find many ${pluralName} by their IDs`, args: generateArgsForManyItemQuery(pluralName), resolve: (rp: Record) => { @@ -65,10 +52,10 @@ export default function addCollectionQueries(args: AddCollectionQueriesArgs) { }, }); - objectComposer.addResolver({ + objectTypeComposer.addResolver({ name: 'all', args: generateArgsForAllItemQuery(pluralName), - type: () => [objectComposer], + type: () => [objectTypeComposer], description: `Return a set of ${pluralName}`, resolve: (rp: Record) => { const nodes = cloneDeep(allContentNodesJSON[name]); @@ -86,10 +73,10 @@ export default function addCollectionQueries(args: AddCollectionQueriesArgs) { /** * Add find by ID to each content type */ - [name]: objectComposer.getResolver('findById'), + [name]: objectTypeComposer.getResolver('findById'), /** * Add find 'many' to each content type */ - [pluralTypeQueryName]: objectComposer.getResolver('all'), + [pluralTypeQueryName]: objectTypeComposer.getResolver('all'), }); } diff --git a/packages/core/src/generators/schema.ts b/packages/core/src/generators/schema.ts index 34909ca2..c787ccbf 100644 --- a/packages/core/src/generators/schema.ts +++ b/packages/core/src/generators/schema.ts @@ -168,14 +168,14 @@ export async function generateSchema( } // Main builder loop - iterate through each content type and generate query resolvers + relationships for it - for (const [name, objectComposer] of Object.entries(schemaArray)) { + for (const [name, objectTypeComposer] of Object.entries(schemaArray)) { const pluralName = plur(name, 2); // /// Global meta fields // - objectComposer.addFields({ + objectTypeComposer.addFields({ _collection: { type: 'String', description: 'The collection name', @@ -189,25 +189,39 @@ export async function generateSchema( // TODO: add a new type of plugin that can add resolvers to each collection, they should be called here - addCollectionQueries({ + const collectionEntry = collectionEntriesByName[name]; + + addCollectionQueries(schemaComposer, { name, pluralName, - objectComposer, - schemaComposer, - transformersById, allContentNodesJSON, + updateCollectionRecord, + objectTypeComposer, config, + collectionEntry, }); - addCollectionMutations({ + addCollectionMutations(schemaComposer, { name, pluralName, - objectComposer, - schemaComposer, + objectTypeComposer, updateCollectionRecord, config, - collectionEntry: collectionEntriesByName[name], + collectionEntry, }); + + await Promise.all( + config.collectionResolvers.map((collectionResolver) => + collectionResolver(schemaComposer, { + name, + pluralName, + objectTypeComposer, + updateCollectionRecord, + config, + collectionEntry, + }) + ) + ); } // Create map of references on each content node diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index 11823df2..3cec314b 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -3,6 +3,7 @@ import test from 'ava'; import { SourceVirtual } from '../../sources/virtual'; import { FlatbreadProvider } from '../base'; import { mockData } from './mockData'; +import { CollectionResolverArgs } from '../../types'; const sourceVirtual = new SourceVirtual(mockData); @@ -28,6 +29,47 @@ function basicProject() { }); } +test('create custom collection resolver', async (t) => { + const flatbread = await new FlatbreadProvider({ + source: sourceVirtual, + transformer: markdownTransformer({ + markdown: { + gfm: true, + externalLinks: true, + }, + }), + + collectionResolvers: [ + function fakeResolver(schemaComposer, args) { + const { name } = args; + + schemaComposer.Query.addFields({ + [`fake${name}`]: { + type: 'String', + description: `fake resolver`, + resolve() { + return `fake ${name}!`; + }, + }, + }); + }, + ], + + content: [ + { + path: 'examples/content/markdown/authors', + name: 'Author', + refs: { + friend: 'Author', + }, + }, + ], + }); + + const result: any = await flatbread.query({ source: `{ fakeAuthor }`}); + t.is(result.data.fakeAuthor, 'fake Author!'); +}); + test('basic query', async (t) => { const flatbread = basicProject(); diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index a74209f9..1f12ffbf 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -1,4 +1,5 @@ import { GraphQLFieldConfigArgumentMap, GraphQLInputType } from 'graphql'; +import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose'; import { Maybe } from 'graphql/jsutils/Maybe'; import type { VFile } from 'vfile'; @@ -24,12 +25,30 @@ export interface FlatbreadConfig { source: Source; transformer?: Transformer | Transformer[]; content: CollectionEntry[]; + collectionResolvers?: CollectionResolver[]; } +export interface CollectionResolverArgs { + name: string; + pluralName: string; + config: LoadedFlatbreadConfig; + objectTypeComposer: ObjectTypeComposer; + collectionEntry: LoadedCollectionEntry; + updateCollectionRecord: ( + collection: CollectionEntry, + entry: EntryNode & { _metadata: CollectionContext } + ) => Promise; +} + +export type CollectionResolver = (schemaComposer: SchemaComposer, + args: CollectionResolverArgs +) => void | Promise; + export interface LoadedFlatbreadConfig { source: Source; transformer: Transformer[]; content: LoadedCollectionEntry[]; + collectionResolvers: CollectionResolver[]; loaded: { extensions: string[]; }; diff --git a/packages/core/src/utils/initializeConfig.ts b/packages/core/src/utils/initializeConfig.ts index 37f57d32..de5ac3f9 100644 --- a/packages/core/src/utils/initializeConfig.ts +++ b/packages/core/src/utils/initializeConfig.ts @@ -21,6 +21,7 @@ export function initializeConfig( return { ...config, + collectionResolvers: config.collectionResolvers || [], content: config.content?.map((content: Partial) => defaultsDeep(content, { referenceField: 'id', From 259d9402f782dba231bf1c2f32530b09b15ef24b Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Thu, 11 Aug 2022 01:52:26 -0500 Subject: [PATCH 21/26] prettier --- packages/core/src/providers/test/base.test.ts | 2 +- packages/core/src/types.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index 3cec314b..0ca5ff82 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -66,7 +66,7 @@ test('create custom collection resolver', async (t) => { ], }); - const result: any = await flatbread.query({ source: `{ fakeAuthor }`}); + const result: any = await flatbread.query({ source: `{ fakeAuthor }` }); t.is(result.data.fakeAuthor, 'fake Author!'); }); diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 1f12ffbf..da36a2c4 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -40,7 +40,8 @@ export interface CollectionResolverArgs { ) => Promise; } -export type CollectionResolver = (schemaComposer: SchemaComposer, +export type CollectionResolver = ( + schemaComposer: SchemaComposer, args: CollectionResolverArgs ) => void | Promise; From fe429617a9dee8286b3514f87e937c7d07553865 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Thu, 11 Aug 2022 01:57:20 -0500 Subject: [PATCH 22/26] test husky --- packages/core/src/providers/test/base.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index 0ca5ff82..c365b7d9 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -17,6 +17,7 @@ function basicProject() { }, }), + content: [ { path: 'examples/content/markdown/authors', From 40f4c2682b93325a5ba75ec795041fb1f83d53e3 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Thu, 11 Aug 2022 01:59:06 -0500 Subject: [PATCH 23/26] test husky --- packages/core/src/providers/test/base.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/providers/test/base.test.ts b/packages/core/src/providers/test/base.test.ts index c365b7d9..0ca5ff82 100644 --- a/packages/core/src/providers/test/base.test.ts +++ b/packages/core/src/providers/test/base.test.ts @@ -17,7 +17,6 @@ function basicProject() { }, }), - content: [ { path: 'examples/content/markdown/authors', From 02bc50f73f319d4d538b70720284cf32060ebdec Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sat, 13 Aug 2022 01:37:33 -0500 Subject: [PATCH 24/26] remove stray arg --- packages/core/src/generators/collectionMutations.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/generators/collectionMutations.ts b/packages/core/src/generators/collectionMutations.ts index 68edf422..f66dab2f 100644 --- a/packages/core/src/generators/collectionMutations.ts +++ b/packages/core/src/generators/collectionMutations.ts @@ -74,7 +74,6 @@ export default function addCollectionMutations( ); return update(payload, existingRecord); }, - update, }, [`create${name}`]: { type: objectTypeComposer, From 1dfcff6cec8de3da1046e1280d42309f913e0c22 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Sat, 13 Aug 2022 03:01:56 -0500 Subject: [PATCH 25/26] update editor --- examples/content/markdown/authors/tony.md | 5 +- examples/sveltekit/flatbread.config.js | 2 +- .../editor/.flatbread/schemas/author.yaml | 23 +++--- .../.flatbread/schemas/author__metadata.yaml | 30 +++++++ .../author__metadata_-source-context.yaml | 17 ++++ .../.flatbread/schemas/flatbread-image.yaml | 14 ---- .../editor/.flatbread/schemas/mutation.yaml | 78 +++++++++++++++++++ .../.flatbread/schemas/override-test.yaml | 27 ++----- .../schemas/override-test__metadata.yaml | 30 +++++++ ...erride-test__metadata_-source-context.yaml | 17 ++++ .../schemas/post-category-blob.yaml | 45 ----------- .../schemas/post-category-blob__content.yaml | 23 ------ .../.flatbread/schemas/post-category.yaml | 19 ++--- .../schemas/post-category__metadata.yaml | 30 +++++++ ...st-category__metadata_-source-context.yaml | 17 ++++ packages/editor/.flatbread/schemas/post.yaml | 19 ++--- .../.flatbread/schemas/post__metadata.yaml | 30 +++++++ .../post__metadata_-source-context.yaml | 17 ++++ packages/editor/.flatbread/schemas/query.yaml | 31 +++++--- packages/editor/.flatbread/schemas/svimg.yaml | 33 ++++++++ .../.flatbread/schemas/yaml-author.yaml | 19 ++--- .../schemas/yaml-author__metadata.yaml | 30 +++++++ ...yaml-author__metadata_-source-context.yaml | 17 ++++ packages/editor/package.json | 1 + packages/editor/src/lib/api.ts | 2 + packages/editor/src/lib/config.ts | 19 ++++- packages/editor/src/lib/fields/svimg.svelte | 28 +++++++ packages/resolver-svimg/src/index.ts | 10 ++- pnpm-lock.yaml | 9 ++- 29 files changed, 464 insertions(+), 178 deletions(-) create mode 100644 packages/editor/.flatbread/schemas/author__metadata.yaml create mode 100644 packages/editor/.flatbread/schemas/author__metadata_-source-context.yaml delete mode 100644 packages/editor/.flatbread/schemas/flatbread-image.yaml create mode 100644 packages/editor/.flatbread/schemas/mutation.yaml create mode 100644 packages/editor/.flatbread/schemas/override-test__metadata.yaml create mode 100644 packages/editor/.flatbread/schemas/override-test__metadata_-source-context.yaml delete mode 100644 packages/editor/.flatbread/schemas/post-category-blob.yaml delete mode 100644 packages/editor/.flatbread/schemas/post-category-blob__content.yaml create mode 100644 packages/editor/.flatbread/schemas/post-category__metadata.yaml create mode 100644 packages/editor/.flatbread/schemas/post-category__metadata_-source-context.yaml create mode 100644 packages/editor/.flatbread/schemas/post__metadata.yaml create mode 100644 packages/editor/.flatbread/schemas/post__metadata_-source-context.yaml create mode 100644 packages/editor/.flatbread/schemas/svimg.yaml create mode 100644 packages/editor/.flatbread/schemas/yaml-author__metadata.yaml create mode 100644 packages/editor/.flatbread/schemas/yaml-author__metadata_-source-context.yaml create mode 100644 packages/editor/src/lib/fields/svimg.svelte diff --git a/examples/content/markdown/authors/tony.md b/examples/content/markdown/authors/tony.md index 416dd8ba..d96c0980 100644 --- a/examples/content/markdown/authors/tony.md +++ b/examples/content/markdown/authors/tony.md @@ -10,9 +10,10 @@ friend: 40s3 image: tony.svg date_joined: 2021-02-25T16:41:59.558Z skills: - sitting: 204 + sitting: 69 breathing: 7.07 - liquid_consumption: 100 + liquid_consumption: 420 existence: simulation sports: -2 --- + diff --git a/examples/sveltekit/flatbread.config.js b/examples/sveltekit/flatbread.config.js index 21a22d1e..e1af1d40 100644 --- a/examples/sveltekit/flatbread.config.js +++ b/examples/sveltekit/flatbread.config.js @@ -58,7 +58,7 @@ export default defineConfig({ createSvImgField('image', { inputDir: 'static/authorImages', outputDir: 'static/g', - srcGenerator: (path) => '/g/' + path, + srcGenerator: (path) => 'http://localhost:5174/g/' + path, }), ], }, diff --git a/packages/editor/.flatbread/schemas/author.yaml b/packages/editor/.flatbread/schemas/author.yaml index aa20c193..82f623ea 100644 --- a/packages/editor/.flatbread/schemas/author.yaml +++ b/packages/editor/.flatbread/schemas/author.yaml @@ -18,6 +18,10 @@ fields: description: The Author referenced by this Author component: object collection: Author + - label: Image + name: image + component: svimg + collection: Svimg - label: Skills name: skills component: object @@ -27,18 +31,6 @@ fields: description: The collection name disabled: true component: string - - label: Filename - name: _filename - disabled: true - component: string - - label: Path - name: _path - disabled: true - component: string - - label: Slug - name: _slug - disabled: true - component: string - label: Id name: id disabled: true @@ -48,9 +40,14 @@ fields: disabled: true component: object collection: Author__content + - label: Metadata + name: _metadata + disabled: true + component: object + collection: Author__metadata component: object label: Author pluralName: Authors referenceField: name meta: - hash: dlkLX3IxInKIl7bN/QkwxR88AbM= + hash: wJ/UxraDtoG3TPy2ZtymmKmFHJA= diff --git a/packages/editor/.flatbread/schemas/author__metadata.yaml b/packages/editor/.flatbread/schemas/author__metadata.yaml new file mode 100644 index 00000000..2e6fa2b0 --- /dev/null +++ b/packages/editor/.flatbread/schemas/author__metadata.yaml @@ -0,0 +1,30 @@ +name: Author__metadata +kind: OBJECT +fields: + - label: Collection + name: collection + component: string + - label: Reference + name: reference + component: string + - label: Referencefield + name: referenceField + component: string + - label: Sourcedby + name: sourcedBy + component: string + - label: Transformcontext + name: transformContext + component: json + - label: Transformedby + name: transformedBy + component: string + - label: Sourcecontext + name: sourceContext + component: object + collection: Author__metadata_SourceContext +component: object +label: Author__metadata +referenceField: id +meta: + hash: wy+YFVDu46TK+9c6m4ysZq+xhUU= diff --git a/packages/editor/.flatbread/schemas/author__metadata_-source-context.yaml b/packages/editor/.flatbread/schemas/author__metadata_-source-context.yaml new file mode 100644 index 00000000..74798173 --- /dev/null +++ b/packages/editor/.flatbread/schemas/author__metadata_-source-context.yaml @@ -0,0 +1,17 @@ +name: Author__metadata_SourceContext +kind: OBJECT +fields: + - label: Filename + name: filename + component: string + - label: Path + name: path + component: string + - label: Slug + name: slug + component: string +component: object +label: Author__metadata_ Source Context +referenceField: id +meta: + hash: gSsmwSPcdxtWn3jegimd00XqCo8= diff --git a/packages/editor/.flatbread/schemas/flatbread-image.yaml b/packages/editor/.flatbread/schemas/flatbread-image.yaml deleted file mode 100644 index 0e147520..00000000 --- a/packages/editor/.flatbread/schemas/flatbread-image.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: FlatbreadImage -kind: OBJECT -fields: - - label: Alt - name: alt - component: string - - label: Src - name: src - component: string -component: object -label: Flatbread Image -referenceField: id -meta: - hash: Nyxi7MGNUsy3mt1BsS8/YzdwNeQ= diff --git a/packages/editor/.flatbread/schemas/mutation.yaml b/packages/editor/.flatbread/schemas/mutation.yaml new file mode 100644 index 00000000..72a0f93f --- /dev/null +++ b/packages/editor/.flatbread/schemas/mutation.yaml @@ -0,0 +1,78 @@ +name: Mutation +kind: OBJECT +fields: + - label: Createauthor + name: createAuthor + description: Create a Author + component: object + collection: Author + - label: Createoverridetest + name: createOverrideTest + description: Create a OverrideTest + component: object + collection: OverrideTest + - label: Createpost + name: createPost + description: Create a Post + component: object + collection: Post + - label: Createpostcategory + name: createPostCategory + description: Create a PostCategory + component: object + collection: PostCategory + - label: Createyamlauthor + name: createYamlAuthor + description: Create a YamlAuthor + component: object + collection: YamlAuthor + - label: Updateauthor + name: updateAuthor + description: Update a Author + component: object + collection: Author + - label: Updateoverridetest + name: updateOverrideTest + description: Update a OverrideTest + component: object + collection: OverrideTest + - label: Updatepost + name: updatePost + description: Update a Post + component: object + collection: Post + - label: Updatepostcategory + name: updatePostCategory + description: Update a PostCategory + component: object + collection: PostCategory + - label: Updateyamlauthor + name: updateYamlAuthor + description: Update a YamlAuthor + component: object + collection: YamlAuthor + - label: Upsertauthor + name: upsertAuthor + component: object + collection: Author + - label: Upsertoverridetest + name: upsertOverrideTest + component: object + collection: OverrideTest + - label: Upsertpost + name: upsertPost + component: object + collection: Post + - label: Upsertpostcategory + name: upsertPostCategory + component: object + collection: PostCategory + - label: Upsertyamlauthor + name: upsertYamlAuthor + component: object + collection: YamlAuthor +component: object +label: Mutation +referenceField: id +meta: + hash: NhJ1i1yQcPoJu/n0bLd/kDItWXs= diff --git a/packages/editor/.flatbread/schemas/override-test.yaml b/packages/editor/.flatbread/schemas/override-test.yaml index 34b95caf..2f1bb080 100644 --- a/packages/editor/.flatbread/schemas/override-test.yaml +++ b/packages/editor/.flatbread/schemas/override-test.yaml @@ -17,31 +17,11 @@ fields: name: deeply component: object collection: OverrideTest_Deeply - - label: Image - name: image - component: object - collection: FlatbreadImage - - label: Image2 - name: image2 - component: object - collection: FlatbreadImage - label: Collection name: _collection description: The collection name disabled: true component: string - - label: Filename - name: _filename - disabled: true - component: string - - label: Path - name: _path - disabled: true - component: string - - label: Slug - name: _slug - disabled: true - component: string - label: Id name: id disabled: true @@ -51,9 +31,14 @@ fields: disabled: true component: object collection: OverrideTest__content + - label: Metadata + name: _metadata + disabled: true + component: object + collection: OverrideTest__metadata component: object label: Override Test pluralName: Override Tests referenceField: title meta: - hash: 5ypFyuwxiEp6X/et6hB/fCB+sPg= + hash: J7yZu464rDAR0+xgyPOQKdKdRH0= diff --git a/packages/editor/.flatbread/schemas/override-test__metadata.yaml b/packages/editor/.flatbread/schemas/override-test__metadata.yaml new file mode 100644 index 00000000..7625bde2 --- /dev/null +++ b/packages/editor/.flatbread/schemas/override-test__metadata.yaml @@ -0,0 +1,30 @@ +name: OverrideTest__metadata +kind: OBJECT +fields: + - label: Collection + name: collection + component: string + - label: Reference + name: reference + component: string + - label: Referencefield + name: referenceField + component: string + - label: Sourcedby + name: sourcedBy + component: string + - label: Transformcontext + name: transformContext + component: json + - label: Transformedby + name: transformedBy + component: string + - label: Sourcecontext + name: sourceContext + component: object + collection: OverrideTest__metadata_SourceContext +component: object +label: Override Test__metadata +referenceField: id +meta: + hash: KixWfqfskAAu42t6siU5TWzQ1Jg= diff --git a/packages/editor/.flatbread/schemas/override-test__metadata_-source-context.yaml b/packages/editor/.flatbread/schemas/override-test__metadata_-source-context.yaml new file mode 100644 index 00000000..aa9bd119 --- /dev/null +++ b/packages/editor/.flatbread/schemas/override-test__metadata_-source-context.yaml @@ -0,0 +1,17 @@ +name: OverrideTest__metadata_SourceContext +kind: OBJECT +fields: + - label: Filename + name: filename + component: string + - label: Path + name: path + component: string + - label: Slug + name: slug + component: string +component: object +label: Override Test__metadata_ Source Context +referenceField: id +meta: + hash: iYdBWS63mqNZRr7IFEPmfogd2tw= diff --git a/packages/editor/.flatbread/schemas/post-category-blob.yaml b/packages/editor/.flatbread/schemas/post-category-blob.yaml deleted file mode 100644 index 2a2cb867..00000000 --- a/packages/editor/.flatbread/schemas/post-category-blob.yaml +++ /dev/null @@ -1,45 +0,0 @@ -name: PostCategoryBlob -kind: OBJECT -fields: - - label: Title - name: title - component: string - - label: Rating - name: rating - component: float - - label: Authors - name: authors - description: All Authors that are referenced by this PostCategoryBlob - component: list - - label: Collection - name: _collection - description: The collection name - disabled: true - component: string - - label: Filename - name: _filename - disabled: true - component: string - - label: Path - name: _path - disabled: true - component: string - - label: Slug - name: _slug - disabled: true - component: string - - label: Id - name: id - disabled: true - component: string - - label: Content - name: _content - disabled: true - component: object - collection: PostCategoryBlob__content -component: object -label: Post Category Blob -pluralName: Post Category Blobs -referenceField: title -meta: - hash: Ai83SmxilqZ57WtHzourDiFyIqI= diff --git a/packages/editor/.flatbread/schemas/post-category-blob__content.yaml b/packages/editor/.flatbread/schemas/post-category-blob__content.yaml deleted file mode 100644 index cf9d82e5..00000000 --- a/packages/editor/.flatbread/schemas/post-category-blob__content.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: PostCategoryBlob__content -kind: OBJECT -fields: - - label: Excerpt - name: excerpt - description: A plaintext excerpt taken from the main content - component: string - - label: Html - name: html - description: The content as HTML - component: string - - label: Raw - name: raw - component: string - - label: Timetoread - name: timeToRead - description: How long (in minutes) it would take an average reader to read the main content. - component: int -component: object -label: Post Category Blob__content -referenceField: id -meta: - hash: DeMt2PvrPKtARExIkIszULw0NlE= diff --git a/packages/editor/.flatbread/schemas/post-category.yaml b/packages/editor/.flatbread/schemas/post-category.yaml index 2db90154..d0e2d9b6 100644 --- a/packages/editor/.flatbread/schemas/post-category.yaml +++ b/packages/editor/.flatbread/schemas/post-category.yaml @@ -22,18 +22,6 @@ fields: description: The collection name disabled: true component: string - - label: Filename - name: _filename - disabled: true - component: string - - label: Path - name: _path - disabled: true - component: string - - label: Slug - name: _slug - disabled: true - component: string - label: Id name: id disabled: true @@ -43,9 +31,14 @@ fields: disabled: true component: object collection: PostCategory__content + - label: Metadata + name: _metadata + disabled: true + component: object + collection: PostCategory__metadata component: object label: Post Category pluralName: Post Categories referenceField: title meta: - hash: tTodpqF2LjHylcNi24dgcAEUBU8= + hash: tcwprbAYH9iqUyH8YR9c7zBOdPI= diff --git a/packages/editor/.flatbread/schemas/post-category__metadata.yaml b/packages/editor/.flatbread/schemas/post-category__metadata.yaml new file mode 100644 index 00000000..165e3ac6 --- /dev/null +++ b/packages/editor/.flatbread/schemas/post-category__metadata.yaml @@ -0,0 +1,30 @@ +name: PostCategory__metadata +kind: OBJECT +fields: + - label: Collection + name: collection + component: string + - label: Reference + name: reference + component: string + - label: Referencefield + name: referenceField + component: string + - label: Sourcedby + name: sourcedBy + component: string + - label: Transformcontext + name: transformContext + component: json + - label: Transformedby + name: transformedBy + component: string + - label: Sourcecontext + name: sourceContext + component: object + collection: PostCategory__metadata_SourceContext +component: object +label: Post Category__metadata +referenceField: id +meta: + hash: ohMlDKpJ3ab37oMAGyO1/HM6c5c= diff --git a/packages/editor/.flatbread/schemas/post-category__metadata_-source-context.yaml b/packages/editor/.flatbread/schemas/post-category__metadata_-source-context.yaml new file mode 100644 index 00000000..be5d2d7c --- /dev/null +++ b/packages/editor/.flatbread/schemas/post-category__metadata_-source-context.yaml @@ -0,0 +1,17 @@ +name: PostCategory__metadata_SourceContext +kind: OBJECT +fields: + - label: Filename + name: filename + component: string + - label: Path + name: path + component: string + - label: Slug + name: slug + component: string +component: object +label: Post Category__metadata_ Source Context +referenceField: id +meta: + hash: C5VfOGT28XiLb1SnWyM/XJIEGfE= diff --git a/packages/editor/.flatbread/schemas/post.yaml b/packages/editor/.flatbread/schemas/post.yaml index 6009f856..effe61c5 100644 --- a/packages/editor/.flatbread/schemas/post.yaml +++ b/packages/editor/.flatbread/schemas/post.yaml @@ -16,18 +16,6 @@ fields: description: The collection name disabled: true component: string - - label: Filename - name: _filename - disabled: true - component: string - - label: Path - name: _path - disabled: true - component: string - - label: Slug - name: _slug - disabled: true - component: string - label: Id name: id disabled: true @@ -37,9 +25,14 @@ fields: disabled: true component: object collection: Post__content + - label: Metadata + name: _metadata + disabled: true + component: object + collection: Post__metadata component: object label: Post pluralName: Posts referenceField: title meta: - hash: d9VGXKIqhYJ4VJsotazpymTVmjQ= + hash: LllYynCtbVNDF8wA8Gj5NcR/ypY= diff --git a/packages/editor/.flatbread/schemas/post__metadata.yaml b/packages/editor/.flatbread/schemas/post__metadata.yaml new file mode 100644 index 00000000..2e31b39d --- /dev/null +++ b/packages/editor/.flatbread/schemas/post__metadata.yaml @@ -0,0 +1,30 @@ +name: Post__metadata +kind: OBJECT +fields: + - label: Collection + name: collection + component: string + - label: Reference + name: reference + component: string + - label: Referencefield + name: referenceField + component: string + - label: Sourcedby + name: sourcedBy + component: string + - label: Transformcontext + name: transformContext + component: json + - label: Transformedby + name: transformedBy + component: string + - label: Sourcecontext + name: sourceContext + component: object + collection: Post__metadata_SourceContext +component: object +label: Post__metadata +referenceField: id +meta: + hash: MkLyV6C1rG2QFAFpCQkQfgEZK7o= diff --git a/packages/editor/.flatbread/schemas/post__metadata_-source-context.yaml b/packages/editor/.flatbread/schemas/post__metadata_-source-context.yaml new file mode 100644 index 00000000..67cb5091 --- /dev/null +++ b/packages/editor/.flatbread/schemas/post__metadata_-source-context.yaml @@ -0,0 +1,17 @@ +name: Post__metadata_SourceContext +kind: OBJECT +fields: + - label: Filename + name: filename + component: string + - label: Path + name: path + component: string + - label: Slug + name: slug + component: string +component: object +label: Post__metadata_ Source Context +referenceField: id +meta: + hash: fGr5kTUqwaMCcB0DWKZtfsEGUhg= diff --git a/packages/editor/.flatbread/schemas/query.yaml b/packages/editor/.flatbread/schemas/query.yaml index 471352d1..2b2c6407 100644 --- a/packages/editor/.flatbread/schemas/query.yaml +++ b/packages/editor/.flatbread/schemas/query.yaml @@ -1,6 +1,26 @@ name: Query kind: OBJECT fields: + - label: Fakeauthor + name: fakeAuthor + description: fake resolver + component: string + - label: Fakeoverridetest + name: fakeOverrideTest + description: fake resolver + component: string + - label: Fakepost + name: fakePost + description: fake resolver + component: string + - label: Fakepostcategory + name: fakePostCategory + description: fake resolver + component: string + - label: Fakeyamlauthor + name: fakeYamlAuthor + description: fake resolver + component: string - label: Allauthors name: allAuthors description: Return a set of Authors @@ -13,10 +33,6 @@ fields: name: allPostCategories description: Return a set of PostCategories component: list - - label: Allpostcategoryblobs - name: allPostCategoryBlobs - description: Return a set of PostCategoryBlobs - component: list - label: Allposts name: allPosts description: Return a set of Posts @@ -45,11 +61,6 @@ fields: description: Find one PostCategory by its ID component: object collection: PostCategory - - label: Postcategoryblob - name: PostCategoryBlob - description: Find one PostCategoryBlob by its ID - component: object - collection: PostCategoryBlob - label: Yamlauthor name: YamlAuthor description: Find one YamlAuthor by its ID @@ -59,4 +70,4 @@ component: object label: Query referenceField: id meta: - hash: rXgvtTxZ7oy9+5ZQ+o+10pFOznc= + hash: iqYXAmXfI7xEPRotyw5ZH37w2L4= diff --git a/packages/editor/.flatbread/schemas/svimg.yaml b/packages/editor/.flatbread/schemas/svimg.yaml new file mode 100644 index 00000000..1c1ea54e --- /dev/null +++ b/packages/editor/.flatbread/schemas/svimg.yaml @@ -0,0 +1,33 @@ +name: Svimg +description: An Image Optimized by Svimg +kind: OBJECT +fields: + - label: Aspectratio + name: aspectratio + description: Aspect ratio of image + component: float + - label: Placeholder + name: placeholder + description: 'inline blurred placeholder image -- returns null if disabled via skipPlaceholder: true in config' + component: string + - label: Raw + name: raw + description: The raw value supplied from config + component: string + - label: Srcset + name: srcset + description: Responsive images and widths + component: string + - label: Srcsetavif + name: srcsetavif + description: 'Responsive Avif images and widths -- returns null if disabled via avif: false in config' + component: string + - label: Srcsetwebp + name: srcsetwebp + description: 'Responsive WebP images and widths -- returns null if disabled via webp: false in config' + component: string +component: object +label: Svimg +referenceField: id +meta: + hash: GnCxN+wFSZ8m4KacYt/7Yoaw/xk= diff --git a/packages/editor/.flatbread/schemas/yaml-author.yaml b/packages/editor/.flatbread/schemas/yaml-author.yaml index d87cf5a3..c3211d0f 100644 --- a/packages/editor/.flatbread/schemas/yaml-author.yaml +++ b/packages/editor/.flatbread/schemas/yaml-author.yaml @@ -24,18 +24,6 @@ fields: description: The collection name disabled: true component: string - - label: Filename - name: _filename - disabled: true - component: string - - label: Path - name: _path - disabled: true - component: string - - label: Slug - name: _slug - disabled: true - component: string - label: Id name: id disabled: true @@ -45,9 +33,14 @@ fields: disabled: true component: object collection: YamlAuthor__content + - label: Metadata + name: _metadata + disabled: true + component: object + collection: YamlAuthor__metadata component: object label: Yaml Author pluralName: Yaml Authors referenceField: name meta: - hash: M2rEU7eSlHf6OKNjxsTJlgZDg8M= + hash: 6Qoac76cYXfo2rmktr9sRMg7bbU= diff --git a/packages/editor/.flatbread/schemas/yaml-author__metadata.yaml b/packages/editor/.flatbread/schemas/yaml-author__metadata.yaml new file mode 100644 index 00000000..4cc57eb4 --- /dev/null +++ b/packages/editor/.flatbread/schemas/yaml-author__metadata.yaml @@ -0,0 +1,30 @@ +name: YamlAuthor__metadata +kind: OBJECT +fields: + - label: Collection + name: collection + component: string + - label: Reference + name: reference + component: string + - label: Referencefield + name: referenceField + component: string + - label: Sourcedby + name: sourcedBy + component: string + - label: Transformcontext + name: transformContext + component: json + - label: Transformedby + name: transformedBy + component: string + - label: Sourcecontext + name: sourceContext + component: object + collection: YamlAuthor__metadata_SourceContext +component: object +label: Yaml Author__metadata +referenceField: id +meta: + hash: 4Bt4Y6vbWdX6IdRXkAHRQnAaTbY= diff --git a/packages/editor/.flatbread/schemas/yaml-author__metadata_-source-context.yaml b/packages/editor/.flatbread/schemas/yaml-author__metadata_-source-context.yaml new file mode 100644 index 00000000..a5048ad0 --- /dev/null +++ b/packages/editor/.flatbread/schemas/yaml-author__metadata_-source-context.yaml @@ -0,0 +1,17 @@ +name: YamlAuthor__metadata_SourceContext +kind: OBJECT +fields: + - label: Filename + name: filename + component: string + - label: Path + name: path + component: string + - label: Slug + name: slug + component: string +component: object +label: Yaml Author__metadata_ Source Context +referenceField: id +meta: + hash: oysLojANVjgNVlOII6KL9GlsTYw= diff --git a/packages/editor/package.json b/packages/editor/package.json index ce56e734..958bedac 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -39,6 +39,7 @@ "js-yaml": "^4.1.0", "lodash-es": "^4.17.21", "node-fetch": "^3.2.9", + "svimg": "3.1.0", "wretch": "^1.7.10" } } diff --git a/packages/editor/src/lib/api.ts b/packages/editor/src/lib/api.ts index 47941bd9..f8fd2416 100644 --- a/packages/editor/src/lib/api.ts +++ b/packages/editor/src/lib/api.ts @@ -112,6 +112,8 @@ function getCollectionQuery( ): string { const collection = gqlTypes.get(collectionName); + // TODO: fields that exist in schema but not in graphql fail because they don't have field.type + return ( collection?.fields .map((field) => { diff --git a/packages/editor/src/lib/config.ts b/packages/editor/src/lib/config.ts index bb3610f1..5194ace9 100644 --- a/packages/editor/src/lib/config.ts +++ b/packages/editor/src/lib/config.ts @@ -14,6 +14,12 @@ function replacer(key, value) { } // TODO: capture +interface Field { + label: string; + name: string; + description: string; + component: string; +} export default class Config { static getPath(schema: GqlSchema) { @@ -47,10 +53,15 @@ export default class Config { schema = mergeWith(schema, existing, function (a, b) { if (isArray(a)) { - const aMap = keyBy(a, 'name'); - return b.map((field) => { - return merge(aMap[field.name], field); - }); + const aMap = new Map(a.map((a) => [a.name, a])); + return b + .map((field: Field) => { + const cur = aMap.get(field.name); + if (!cur) return; + aMap.delete(field.name); + return merge(cur, field); + }) + .concat(...aMap.values()); } }); } else { diff --git a/packages/editor/src/lib/fields/svimg.svelte b/packages/editor/src/lib/fields/svimg.svelte new file mode 100644 index 00000000..62ad22be --- /dev/null +++ b/packages/editor/src/lib/fields/svimg.svelte @@ -0,0 +1,28 @@ + + + diff --git a/packages/resolver-svimg/src/index.ts b/packages/resolver-svimg/src/index.ts index 27fd8284..f2008cb7 100644 --- a/packages/resolver-svimg/src/index.ts +++ b/packages/resolver-svimg/src/index.ts @@ -24,6 +24,9 @@ type Svimg { """Aspect ratio of image""" aspectratio: Float + + """The raw value supplied from config""" + raw: String }`; /** @@ -37,9 +40,12 @@ export function createSvImgField(field: string, config: Omit) { return { field, type: SVIMG_TYPE, - resolve(src: string) { + async resolve(src: string) { if (!src) return null; - return generateComponentAttributes({ queue, ...config, src }); + return { + ...(await generateComponentAttributes({ queue, ...config, src })), + raw: src, + }; }, }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d727a14c..310a99d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -196,6 +196,7 @@ importers: svelte: ^3.49.0 svelte-check: ^2.8.0 svelte-preprocess: ^4.10.7 + svimg: 3.1.0 tslib: ^2.4.0 typescript: ^4.7.4 vite: ^3.0.3 @@ -207,6 +208,7 @@ importers: js-yaml: 4.1.0 lodash-es: 4.17.21 node-fetch: 3.2.10 + svimg: 3.1.0 wretch: 1.7.10 devDependencies: '@sveltejs/adapter-auto': 1.0.0-next.64 @@ -1739,7 +1741,7 @@ packages: sade: 1.8.1 svelte: 3.49.0 tiny-glob: 0.2.9 - vite: 3.0.4 + vite: 3.0.4_sass@1.54.4 transitivePeerDependencies: - diff-match-patch - supports-color @@ -1763,7 +1765,7 @@ packages: magic-string: 0.26.2 svelte: 3.49.0 svelte-hmr: 0.14.12_svelte@3.49.0 - vite: 3.0.4 + vite: 3.0.4_sass@1.54.4 transitivePeerDependencies: - supports-color dev: true @@ -5682,7 +5684,7 @@ packages: dev: true /github-from-package/0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + resolution: {integrity: sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=} /github-slugger/1.4.0: resolution: {integrity: sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==} @@ -9719,7 +9721,6 @@ packages: p-queue: 6.6.2 sharp: 0.30.7 string-replace-async: 2.0.0 - dev: true /symbol-tree/3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} From c94f3be26e9eda88ac849709f755796d38017798 Mon Sep 17 00:00:00 2001 From: Adam Sparks Date: Tue, 16 Aug 2022 02:11:24 -0500 Subject: [PATCH 26/26] add header --- packages/editor/src/lib/header.svelte | 63 +++++++++++++++++++ packages/editor/src/lib/preferences.ts | 0 packages/editor/src/routes/__layout.svelte | 2 + .../src/routes/collection/[name]/[id].svelte | 7 ++- .../src/routes/collection/[name]/index.svelte | 19 +++--- .../src/routes/collection/[name]/new.svelte | 23 +++---- packages/editor/src/routes/index.svelte | 2 + 7 files changed, 96 insertions(+), 20 deletions(-) create mode 100644 packages/editor/src/lib/header.svelte create mode 100644 packages/editor/src/lib/preferences.ts diff --git a/packages/editor/src/lib/header.svelte b/packages/editor/src/lib/header.svelte new file mode 100644 index 00000000..45796419 --- /dev/null +++ b/packages/editor/src/lib/header.svelte @@ -0,0 +1,63 @@ + + + + + diff --git a/packages/editor/src/lib/preferences.ts b/packages/editor/src/lib/preferences.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/editor/src/routes/__layout.svelte b/packages/editor/src/routes/__layout.svelte index 82d4cdb7..cd84a705 100644 --- a/packages/editor/src/routes/__layout.svelte +++ b/packages/editor/src/routes/__layout.svelte @@ -2,9 +2,11 @@ import '@picocss/pico/css/pico.css'; +