From a0c5275aa5ac34160541180f3d1ed2a37934c4e6 Mon Sep 17 00:00:00 2001 From: Nikolaj Brask-Nielsen Date: Mon, 30 Dec 2024 15:19:11 +0100 Subject: [PATCH] docs: Update docs for v7 --- docs/astro.config.mjs | 97 +- docs/package.json | 6 +- docs/pnpm-lock.yaml | 1321 +++++++++-------- docs/src/content/config.ts | 5 +- docs/src/content/docs/overview.md | 1 + docs/src/content/docs/v7/extending/content.md | 291 ++++ docs/src/content/docs/v7/extending/media.md | 102 ++ docs/src/content/docs/v7/extending/member.md | 103 ++ .../v7/extending/properties/block-list.md | 109 ++ .../v7/extending/properties/custom-editor.md | 58 + .../v7/extending/properties/media-picker.md | 105 ++ .../docs/v7/extending/properties/overview.md | 49 + .../docs/v7/extending/properties/rich-text.md | 74 + .../docs/v7/extending/skybrud-redirects.md | 112 ++ .../content/docs/v7/extending/url-tracker.md | 288 ++++ .../docs/v7/fundamentals/getting-started.md | 146 ++ .../docs/v7/fundamentals/querying/content.md | 38 + .../docs/v7/fundamentals/querying/media.md | 36 + .../docs/v7/fundamentals/querying/members.md | 41 + .../v7/fundamentals/querying/properties.md | 74 + .../content/docs/v7/fundamentals/security.md | 313 ++++ docs/src/content/docs/v7/reference/content.md | 11 + .../docs/v7/reference/endpoint-options.md | 38 + docs/src/content/docs/v7/reference/media.md | 11 + docs/src/content/docs/v7/reference/member.md | 11 + docs/src/content/docs/v7/reference/options.md | 27 + .../content/docs/v7/reference/properties.md | 22 + docs/src/content/docs/v7/start.md | 72 + 28 files changed, 2916 insertions(+), 645 deletions(-) create mode 100644 docs/src/content/docs/v7/extending/content.md create mode 100644 docs/src/content/docs/v7/extending/media.md create mode 100644 docs/src/content/docs/v7/extending/member.md create mode 100644 docs/src/content/docs/v7/extending/properties/block-list.md create mode 100644 docs/src/content/docs/v7/extending/properties/custom-editor.md create mode 100644 docs/src/content/docs/v7/extending/properties/media-picker.md create mode 100644 docs/src/content/docs/v7/extending/properties/overview.md create mode 100644 docs/src/content/docs/v7/extending/properties/rich-text.md create mode 100644 docs/src/content/docs/v7/extending/skybrud-redirects.md create mode 100644 docs/src/content/docs/v7/extending/url-tracker.md create mode 100644 docs/src/content/docs/v7/fundamentals/getting-started.md create mode 100644 docs/src/content/docs/v7/fundamentals/querying/content.md create mode 100644 docs/src/content/docs/v7/fundamentals/querying/media.md create mode 100644 docs/src/content/docs/v7/fundamentals/querying/members.md create mode 100644 docs/src/content/docs/v7/fundamentals/querying/properties.md create mode 100644 docs/src/content/docs/v7/fundamentals/security.md create mode 100644 docs/src/content/docs/v7/reference/content.md create mode 100644 docs/src/content/docs/v7/reference/endpoint-options.md create mode 100644 docs/src/content/docs/v7/reference/media.md create mode 100644 docs/src/content/docs/v7/reference/member.md create mode 100644 docs/src/content/docs/v7/reference/options.md create mode 100644 docs/src/content/docs/v7/reference/properties.md create mode 100644 docs/src/content/docs/v7/start.md diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 64162d17..c0ba0064 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -23,22 +23,22 @@ export default defineConfig({ label: 'Welcome', items: [ { label: 'Overview', link: '/overview/' }, - { label: 'Version 6', link: '/v6/start/' }, + { label: 'Version 7', link: '/v7/start/' }, ], }, { label: 'Fundamentals', items: [ - { label: 'Getting started', link: 'v6/fundamentals/getting-started/' }, - { label: 'Security', link: 'v6/fundamentals/security/' }, + { label: 'Getting started', link: 'v7/fundamentals/getting-started/' }, + { label: 'Security', link: 'v7/fundamentals/security/' }, { label: 'Querying', collapsed: true, items: [ - { label: 'Content', link: 'v6/fundamentals/querying/content/' }, - { label: 'Media', link: 'v6/fundamentals/querying/media/' }, - { label: 'Members', link: 'v6/fundamentals/querying/members/' }, - { label: 'Properties', link: 'v6/fundamentals/querying/properties/' } + { label: 'Content', link: 'v7/fundamentals/querying/content/' }, + { label: 'Media', link: 'v7/fundamentals/querying/media/' }, + { label: 'Members', link: 'v7/fundamentals/querying/members/' }, + { label: 'Properties', link: 'v7/fundamentals/querying/properties/' } ] }, ] @@ -46,18 +46,18 @@ export default defineConfig({ { label: 'Extending', items: [ - { label: 'Content', link: 'v6/extending/content/' }, - { label: 'Media', link: 'v6/extending/media/' }, - { label: 'Member', link: 'v6/extending/member/' }, + { label: 'Content', link: 'v7/extending/content/' }, + { label: 'Media', link: 'v7/extending/media/' }, + { label: 'Member', link: 'v7/extending/member/' }, { label: 'Properties', collapsed: true, items: [ - { label: 'Overview', link: 'v6/extending/properties/overview/' }, - { label: 'Rich text', link: 'v6/extending/properties/rich-text/' }, - { label: 'Media picker', link: 'v6/extending/properties/media-picker/' }, - { label: 'Block list', link: 'v6/extending/properties/block-list/' }, - { label: 'Custom editor', link: 'v6/extending/properties/custom-editor/' }, + { label: 'Overview', link: 'v7/extending/properties/overview/' }, + { label: 'Rich text', link: 'v7/extending/properties/rich-text/' }, + { label: 'Media picker', link: 'v7/extending/properties/media-picker/' }, + { label: 'Block list', link: 'v7/extending/properties/block-list/' }, + { label: 'Custom editor', link: 'v7/extending/properties/custom-editor/' }, ] }, ] @@ -65,22 +65,77 @@ export default defineConfig({ { label: 'Reference', items: [ - { label: 'Options', link: 'v6/reference/options/' }, - { label: 'Endpoint options', link: 'v6/reference/endpoint-options/' }, - { label: 'Content', link: 'v6/reference/content/' }, - { label: 'Media', link: 'v6/reference/media/' }, - { label: 'Member', link: 'v6/reference/member/' }, - { label: 'Member', link: 'v6/reference/properties/' }, + { label: 'Options', link: 'v7/reference/options/' }, + { label: 'Endpoint options', link: 'v7/reference/endpoint-options/' }, + { label: 'Content', link: 'v7/reference/content/' }, + { label: 'Media', link: 'v7/reference/media/' }, + { label: 'Member', link: 'v7/reference/member/' }, + { label: 'Member', link: 'v7/reference/properties/' }, ] }, { label: 'Older versions', collapsed: true, items: [ + { + label: 'Version 6', + collapsed: true, + items: [ + { label: 'Overview', link: '/v6/start/' }, + { + label: 'Fundamentals', + items: [ + { label: 'Getting started', link: 'v6/fundamentals/getting-started/' }, + { label: 'Security', link: 'v6/fundamentals/security/' }, + { + label: 'Querying', + collapsed: true, + items: [ + { label: 'Content', link: 'v6/fundamentals/querying/content/' }, + { label: 'Media', link: 'v6/fundamentals/querying/media/' }, + { label: 'Members', link: 'v6/fundamentals/querying/members/' }, + { label: 'Properties', link: 'v6/fundamentals/querying/properties/' } + ] + }, + ] + }, + { + label: 'Extending', + items: [ + { label: 'Content', link: 'v6/extending/content/' }, + { label: 'Media', link: 'v6/extending/media/' }, + { label: 'Member', link: 'v6/extending/member/' }, + { + label: 'Properties', + collapsed: true, + items: [ + { label: 'Overview', link: 'v6/extending/properties/overview/' }, + { label: 'Rich text', link: 'v6/extending/properties/rich-text/' }, + { label: 'Media picker', link: 'v6/extending/properties/media-picker/' }, + { label: 'Block list', link: 'v6/extending/properties/block-list/' }, + { label: 'Custom editor', link: 'v6/extending/properties/custom-editor/' }, + ] + }, + ] + }, + { + label: 'Reference', + items: [ + { label: 'Options', link: 'v6/reference/options/' }, + { label: 'Endpoint options', link: 'v6/reference/endpoint-options/' }, + { label: 'Content', link: 'v6/reference/content/' }, + { label: 'Media', link: 'v6/reference/media/' }, + { label: 'Member', link: 'v6/reference/member/' }, + { label: 'Member', link: 'v6/reference/properties/' }, + ] + } + ] + }, { label: 'Version 5', collapsed: true, items: [ + { label: 'Overview', link: '/v5/start/' }, { label: 'Fundamentals', items: [ diff --git a/docs/package.json b/docs/package.json index 67f38d95..f760380b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -10,9 +10,9 @@ "astro": "astro" }, "dependencies": { - "@astrojs/starlight": "^0.29.2", - "astro": "^4.16.18", + "@astrojs/starlight": "^0.30.3", + "astro": "^5.1.1", "sharp": "^0.33.5", - "starlight-links-validator": "^0.13.2" + "starlight-links-validator": "^0.14.1" } } \ No newline at end of file diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index 3099db13..f8568776 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -9,95 +9,50 @@ importers: .: dependencies: '@astrojs/starlight': - specifier: ^0.29.2 - version: 0.29.2(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)) + specifier: ^0.30.3 + version: 0.30.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)) astro: - specifier: ^4.16.18 - version: 4.16.18(rollup@4.27.3)(typescript@5.5.4) + specifier: ^5.1.1 + version: 5.1.1(rollup@4.27.3)(typescript@5.5.4) sharp: specifier: ^0.33.5 version: 0.33.5 starlight-links-validator: specifier: ^0.13.2 - version: 0.13.2(@astrojs/starlight@0.29.2(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)))(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)) + version: 0.13.2(@astrojs/starlight@0.30.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)))(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)) packages: - '@ampproject/remapping@2.2.1': - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} - engines: {node: '>=6.0.0'} - '@astrojs/compiler@2.10.3': resolution: {integrity: sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw==} - '@astrojs/internal-helpers@0.4.1': - resolution: {integrity: sha512-bMf9jFihO8YP940uD70SI/RDzIhUHJAolWVcO1v5PUivxGKvfLZTLTVVxEYzGYyPsA3ivdLNqMnL5VgmQySa+g==} - - '@astrojs/markdown-remark@5.2.0': - resolution: {integrity: sha512-vWGM24KZXz11jR3JO+oqYU3T2qpuOi4uGivJ9SQLCAI01+vEkHC60YJMRvHPc+hwd60F7euNs1PeOEixIIiNQw==} + '@astrojs/internal-helpers@0.4.2': + resolution: {integrity: sha512-EdDWkC3JJVcpGpqJAU/5hSk2LKXyG3mNGkzGoAuyK+xoPHbaVdSuIWoN1QTnmK3N/gGfaaAfM8gO2KDCAW7S3w==} - '@astrojs/markdown-remark@5.3.0': - resolution: {integrity: sha512-r0Ikqr0e6ozPb5bvhup1qdWnSPUvQu6tub4ZLYaKyG50BXZ0ej6FhGz3GpChKpH7kglRFPObJd/bDyf2VM9pkg==} + '@astrojs/markdown-remark@6.0.1': + resolution: {integrity: sha512-CTSYijj25NfxgZi15TU3CwPwgyD1/7yA3FcdcNmB9p94nydupiUbrIiq3IqeTp2m5kCVzxbPZeC7fTwEOaNyGw==} - '@astrojs/mdx@3.1.5': - resolution: {integrity: sha512-Fu6oShqcDpi0D1b2/3Pg3ao1I+Q2YqKhFsSsuDzn0YhdGrry5oUyABUyCyGq/OayP2P/34Vwj+GCQ/n9h8FlTQ==} - engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} + '@astrojs/mdx@4.0.3': + resolution: {integrity: sha512-8HcuyNG/KgYUAQWVzKFkboXcTOBCW6aQ0WK0Er/iSmVSF0y3yimg4/3QSt+Twv9dogpwIHL+E8iBJKqieFv4+g==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} peerDependencies: - astro: ^4.8.0 + astro: ^5.0.0 - '@astrojs/prism@3.1.0': - resolution: {integrity: sha512-Z9IYjuXSArkAUx3N6xj6+Bnvx8OdUSHA8YoOgyepp3+zJmtVYJIl/I18GozdJVW1p5u/CNpl3Km7/gwTJK85cw==} - engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} + '@astrojs/prism@3.2.0': + resolution: {integrity: sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} '@astrojs/sitemap@3.1.6': resolution: {integrity: sha512-1Qp2NvAzVImqA6y+LubKi1DVhve/hXXgFvB0szxiipzh7BvtuKe4oJJ9dXSqaubaTkt4nMa6dv6RCCAYeB6xaQ==} - '@astrojs/starlight@0.29.2': - resolution: {integrity: sha512-xv9AhWkP3fxCB6EF6MlT4yEbxzye3aMSbuVbFEGbQh8G/w1MPhdNCnQakIHpmIwwyxwG9cW3mQdAZum4oOO39w==} - peerDependencies: - astro: ^4.14.0 - - '@astrojs/telemetry@3.1.0': - resolution: {integrity: sha512-/ca/+D8MIKEC8/A9cSaPUqQNZm+Es/ZinRv0ZAzvu2ios7POQSsVD+VOj7/hypWNsNM3T7RpfgNq7H2TU1KEHA==} - engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} - - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.26.2': - resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.26.0': - resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.26.2': - resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-annotate-as-pure@7.25.9': - resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.25.9': - resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} + '@astrojs/starlight@0.30.3': + resolution: {integrity: sha512-HbGYYIR2Rnrvvc2jD0dUpp8zUzv3jQYtG5im3aulDgE4Jo21Ahw0yXlb/Y134G3LALLbqhImmlbt/h/nDV3yMA==} peerDependencies: - '@babel/core': ^7.0.0 + astro: ^5.0.0 - '@babel/helper-plugin-utils@7.25.9': - resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} - engines: {node: '>=6.9.0'} + '@astrojs/telemetry@3.2.0': + resolution: {integrity: sha512-wxhSKRfKugLwLlr4OFfcqovk+LIFtKwLyGPqMsv+9/ibqqnW3Gv7tBhtKEb0gAyUAC4G9BTVQeQahqnQAhd6IQ==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} '@babel/helper-string-parser@7.25.9': resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} @@ -107,43 +62,15 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.26.0': - resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} - engines: {node: '>=6.9.0'} - '@babel/parser@7.26.2': resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-jsx@7.25.9': - resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx@7.25.9': - resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/runtime@7.26.0': resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} engines: {node: '>=6.9.0'} - '@babel/template@7.25.9': - resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.25.9': - resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} - engines: {node: '>=6.9.0'} - '@babel/types@7.26.0': resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} engines: {node: '>=6.9.0'} @@ -161,138 +88,288 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@expressive-code/core@0.38.3': resolution: {integrity: sha512-s0/OtdRpBONwcn23O8nVwDNQqpBGKscysejkeBkwlIeHRLZWgiTVrusT5Idrdz1d8cW5wRk9iGsAIQmwDPXgJg==} @@ -410,26 +487,11 @@ packages: cpu: [x64] os: [win32] - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.0': - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - - '@mdx-js/mdx@3.0.1': - resolution: {integrity: sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==} + '@mdx-js/mdx@3.1.0': + resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -591,18 +653,6 @@ packages: '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.6.4': - resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} - - '@types/babel__template@7.4.1': - resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} - - '@types/babel__traverse@7.20.1': - resolution: {integrity: sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==} - '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -618,6 +668,9 @@ packages: '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} @@ -673,6 +726,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -698,9 +755,9 @@ packages: peerDependencies: astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 - astro@4.16.18: - resolution: {integrity: sha512-G7zfwJt9BDHEZwlaLNvjbInIw2hPryyD654314KV/XT34pJU6SfN1S+mWa8RAkALcZNJnJXCJmT3JXLQStD3Lw==} - engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} + astro@5.1.1: + resolution: {integrity: sha512-prpWC2PRs4P3FKQg6gZaU+VNMqbZi5pDvORGB2nrjfRjkrvF6/l4BqhvkJ6YQ0Ohm5rIMVz8ljgaRI77mLHbwg==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} hasBin: true axobject-query@4.1.0: @@ -719,6 +776,10 @@ packages: bcp-47@2.1.0: resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -730,18 +791,10 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - camelcase@8.0.0: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - caniuse-lite@1.0.30001680: - resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==} - ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -761,6 +814,10 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + ci-info@4.1.0: resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} engines: {node: '>=8'} @@ -769,14 +826,6 @@ packages: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} - - cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -804,13 +853,20 @@ packages: common-ancestor-path@1.0.1: resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + consola@3.3.3: + resolution: {integrity: sha512-Qil5KwghMzlqd51UXM0b6fyaGHtOC22scxrwrz4A2882LyUMwQjnvaedN1HAeXzphspQ6CpHkzMAWxBTUruDLg==} + engines: {node: ^14.18.0 || >=16.10.0} + + cookie-es@1.2.2: + resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} cookie@0.7.2: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} + crossws@0.3.1: + resolution: {integrity: sha512-HsZgeVYaG+b5zA+9PbIPGq4+J/CJynJuearykPsXx4V/eMhyQ5EDVg3Ak2FBZtVXCiOLu/U7IiwDHTr9MA+IKw==} + css-selector-parser@3.0.4: resolution: {integrity: sha512-pnmS1dbKsz6KA4EW4BznyPL2xxkNDRg62hcD0v8g6DEw2W7hxOln5M953jsp9hmw5Dg57S6o/A8GOn37mbAgcQ==} @@ -831,10 +887,16 @@ packages: decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -864,9 +926,6 @@ packages: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} engines: {node: '>=4'} - electron-to-chromium@1.5.63: - resolution: {integrity: sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==} - emoji-regex-xs@1.0.0: resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} @@ -883,14 +942,21 @@ packages: es-module-lexer@1.5.4: resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + esast-util-from-estree@2.0.0: + resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} + + esast-util-from-js@2.0.1: + resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} hasBin: true - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} + engines: {node: '>=18'} + hasBin: true escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} @@ -910,6 +976,9 @@ packages: estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + estree-util-scope@1.0.0: + resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + estree-util-to-js@2.0.0: resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} @@ -928,10 +997,6 @@ packages: expressive-code@0.38.3: resolution: {integrity: sha512-COM04AiUotHCKJgWdn7NtW2lqu8OW8owAidMpkXt1qxrZ9Q2iC7+tok/1qIn2ocGnczvr9paIySgGnEwFeEQ8Q==} - extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -966,10 +1031,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - get-east-asian-width@1.2.0: resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} engines: {node: '>=18'} @@ -981,16 +1042,11 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - gray-matter@4.0.3: - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} - engines: {node: '>=6.0'} + h3@1.13.0: + resolution: {integrity: sha512-vFEAu/yf8UMUcB4s43OaDaigcqpQd14yanmOsn+NcRX3/guSKncyE2rOYhq8RIchgJrPSs/QiIddnTTR1ddiAg==} hast-util-embedded@3.0.0: resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} @@ -1028,9 +1084,6 @@ packages: hast-util-to-estree@3.1.0: resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==} - hast-util-to-html@9.0.2: - resolution: {integrity: sha512-RP5wNpj5nm1Z8cloDv4Sl4RS8jH5HYa0v93YB6Wb4poEzgMo/dAAL0KcT4974dCjcNG5pkLqTImeFHHCwwfY3g==} - hast-util-to-html@9.0.3: resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} @@ -1079,6 +1132,9 @@ packages: inline-style-parser@0.2.2: resolution: {integrity: sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==} + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + is-absolute-url@4.0.1: resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1092,6 +1148,10 @@ packages: is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -1100,10 +1160,6 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true - is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1124,10 +1180,6 @@ packages: engines: {node: '>=14.16'} hasBin: true - is-interactive@2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -1136,24 +1188,10 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} - is-reference@3.0.1: - resolution: {integrity: sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==} - - is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - - is-unicode-supported@2.0.0: - resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} - engines: {node: '>=18'} - is-wsl@3.1.0: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true @@ -1162,20 +1200,6 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -1192,15 +1216,11 @@ packages: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} - log-symbols@6.0.0: - resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} - engines: {node: '>=18'} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} @@ -1385,9 +1405,10 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true mrmime@2.0.0: resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} @@ -1408,8 +1429,12 @@ packages: nlcst-to-string@4.0.0: resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + node-fetch-native@1.6.4: + resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} not@0.1.0: resolution: {integrity: sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==} @@ -1417,17 +1442,15 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} + ofetch@1.4.1: + resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} + + ohash@1.1.4: + resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} oniguruma-to-es@0.4.1: resolution: {integrity: sha512-rNcEohFz095QKGRovP/yqPIKc+nP+Sjs4YTHMv33nMePGKrq/r2eu9Yh4646M5XluGJsUnmwoXuiXE69KDs+fQ==} - ora@8.1.1: - resolution: {integrity: sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==} - engines: {node: '>=18'} - p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -1469,8 +1492,8 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - periscopic@3.1.0: - resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1505,6 +1528,10 @@ packages: resolution: {integrity: sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + preferred-pm@4.0.0: resolution: {integrity: sha512-gYBeFTZLu055D8Vv3cSPox/0iTPtkzxpLroSYYA7WXgRi31WCJ51Uyl8ZiPeUUjyvs2MBzK+S8v9JVUgHU/Sqw==} engines: {node: '>=18.12'} @@ -1523,6 +1550,25 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + recma-build-jsx@1.0.0: + resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + + recma-jsx@1.0.0: + resolution: {integrity: sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==} + + recma-parse@1.0.0: + resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + + recma-stringify@1.0.0: + resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -1550,15 +1596,12 @@ packages: rehype-raw@7.0.0: resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} - rehype-stringify@10.0.0: - resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==} + rehype-recma@1.0.0: + resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} rehype-stringify@10.0.1: resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} - rehype@13.0.1: - resolution: {integrity: sha512-AcSLS2mItY+0fYu9xKxOu1LhUZeBZZBx8//5HKzF+0XP+eP8+6a5MXn2+DW2kfXR6Dtp1FEXMVrjyKAcvcU8vg==} - rehype@13.0.2: resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==} @@ -1584,10 +1627,6 @@ packages: remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} - retext-latin@4.0.0: resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} @@ -1615,14 +1654,6 @@ packages: sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} - section-matter@1.0.0: - resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} - engines: {node: '>=4'} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - semver@7.6.3: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} @@ -1635,10 +1666,6 @@ packages: shiki@1.23.1: resolution: {integrity: sha512-8kxV9TH4pXgdKGxNOkrSMydn1Xf6It8lsle0fiqxf7a1149K1WGtdOu3Zb91T5r1JpvRPxqxU3C2XdZZXQnrig==} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -1654,6 +1681,10 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} @@ -1671,10 +1702,6 @@ packages: '@astrojs/starlight': '>=0.15.0' astro: '>=4.0.0' - stdin-discarder@0.2.2: - resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} - engines: {node: '>=18'} - stream-replace-string@2.0.0: resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} @@ -1697,10 +1724,6 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - strip-bom-string@1.0.0: - resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} - engines: {node: '>=0.10.0'} - strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -1746,6 +1769,18 @@ packages: engines: {node: '>=14.17'} hasBin: true + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + ultrahtml@1.5.3: + resolution: {integrity: sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + unenv@1.10.0: + resolution: {integrity: sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==} + unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -1779,11 +1814,64 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - update-browserslist-db@1.1.1: - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} - hasBin: true + unstorage@1.14.4: + resolution: {integrity: sha512-1SYeamwuYeQJtJ/USE1x4l17LkmQBzg7deBJ+U9qOBoHo15d1cDxG4jM31zKRgF7pG0kirZy4wVMX6WL6Zoscg==} peerDependencies: - browserslist: '>= 4.21.0' + '@azure/app-configuration': ^1.8.0 + '@azure/cosmos': ^4.2.0 + '@azure/data-tables': ^13.3.0 + '@azure/identity': ^4.5.0 + '@azure/keyvault-secrets': ^4.9.0 + '@azure/storage-blob': ^12.26.0 + '@capacitor/preferences': ^6.0.3 + '@deno/kv': '>=0.8.4' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.34.3 + '@vercel/blob': '>=0.27.0' + '@vercel/kv': ^1.0.1 + aws4fetch: ^1.0.20 + db0: '>=0.2.1' + idb-keyval: ^6.2.1 + ioredis: ^5.4.2 + uploadthing: ^7.4.1 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + uploadthing: + optional: true util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1797,22 +1885,27 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite@5.4.11: - resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} - engines: {node: ^18.0.0 || >=20.0.0} + vite@6.0.6: + resolution: {integrity: sha512-NSjmUuckPmDU18bHz7QZ+bTYhRR0iA72cs2QAxCqDpafJ0S6qetco0LB3WW2OxlMHS0JmAv+yZ/R3uPmMyGTjQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' less: '*' lightningcss: ^1.21.0 sass: '*' sass-embedded: '*' stylus: '*' sugarss: '*' - terser: ^5.4.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: '@types/node': optional: true + jiti: + optional: true less: optional: true lightningcss: @@ -1827,6 +1920,10 @@ packages: optional: true terser: optional: true + tsx: + optional: true + yaml: + optional: true vitefu@1.0.4: resolution: {integrity: sha512-y6zEE3PQf6uu/Mt6DTJ9ih+kyJLr4XcSgHR2zUkM8SWDhuixEJxfJ6CZGMHh1Ec3vPLoEA0IHU5oWzVqw8ulow==} @@ -1858,9 +1955,6 @@ packages: xxhash-wasm@1.1.0: resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -1869,6 +1963,14 @@ packages: resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} engines: {node: '>=12.20'} + yocto-spinner@0.1.2: + resolution: {integrity: sha512-VfmLIh/ZSZOJnVRQZc/dvpPP90lWL4G0bmxQMP0+U/2vKBA8GSpcBuWv17y7F+CZItRuO97HN1wdbb4p10uhOg==} + engines: {node: '>=18.19'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + zod-to-json-schema@3.23.5: resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==} peerDependencies: @@ -1888,45 +1990,18 @@ packages: snapshots: - '@ampproject/remapping@2.2.1': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - '@astrojs/compiler@2.10.3': {} - '@astrojs/internal-helpers@0.4.1': {} + '@astrojs/internal-helpers@0.4.2': {} - '@astrojs/markdown-remark@5.2.0': + '@astrojs/markdown-remark@6.0.1': dependencies: - '@astrojs/prism': 3.1.0 - github-slugger: 2.0.0 - hast-util-from-html: 2.0.3 - hast-util-to-text: 4.0.2 - import-meta-resolve: 4.1.0 - mdast-util-definitions: 6.0.0 - rehype-raw: 7.0.0 - rehype-stringify: 10.0.1 - remark-gfm: 4.0.0 - remark-parse: 11.0.0 - remark-rehype: 11.1.1 - remark-smartypants: 3.0.2 - shiki: 1.23.1 - unified: 11.0.5 - unist-util-remove-position: 5.0.0 - unist-util-visit: 5.0.0 - unist-util-visit-parents: 6.0.1 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@astrojs/markdown-remark@5.3.0': - dependencies: - '@astrojs/prism': 3.1.0 + '@astrojs/prism': 3.2.0 github-slugger: 2.0.0 hast-util-from-html: 2.0.3 hast-util-to-text: 4.0.2 import-meta-resolve: 4.1.0 + js-yaml: 4.1.0 mdast-util-definitions: 6.0.0 rehype-raw: 7.0.0 rehype-stringify: 10.0.1 @@ -1943,16 +2018,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@3.1.5(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4))': + '@astrojs/mdx@4.0.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4))': dependencies: - '@astrojs/markdown-remark': 5.2.0 - '@mdx-js/mdx': 3.0.1 + '@astrojs/markdown-remark': 6.0.1 + '@mdx-js/mdx': 3.1.0(acorn@8.14.0) acorn: 8.14.0 - astro: 4.16.18(rollup@4.27.3)(typescript@5.5.4) + astro: 5.1.1(rollup@4.27.3)(typescript@5.5.4) es-module-lexer: 1.5.4 estree-util-visit: 2.0.0 - gray-matter: 4.0.3 - hast-util-to-html: 9.0.2 + hast-util-to-html: 9.0.3 kleur: 4.1.5 rehype-raw: 7.0.0 remark-gfm: 4.0.0 @@ -1963,7 +2037,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/prism@3.1.0': + '@astrojs/prism@3.2.0': dependencies: prismjs: 1.29.0 @@ -1973,17 +2047,18 @@ snapshots: stream-replace-string: 2.0.0 zod: 3.23.8 - '@astrojs/starlight@0.29.2(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4))': + '@astrojs/starlight@0.30.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4))': dependencies: - '@astrojs/mdx': 3.1.5(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)) + '@astrojs/mdx': 4.0.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)) '@astrojs/sitemap': 3.1.6 '@pagefind/default-ui': 1.2.0 '@types/hast': 3.0.4 + '@types/js-yaml': 4.0.9 '@types/mdast': 4.0.4 - astro: 4.16.18(rollup@4.27.3)(typescript@5.5.4) - astro-expressive-code: 0.38.3(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)) + astro: 5.1.1(rollup@4.27.3)(typescript@5.5.4) + astro-expressive-code: 0.38.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)) bcp-47: 2.1.0 - hast-util-from-html: 2.0.1 + hast-util-from-html: 2.0.3 hast-util-select: 6.0.2 hast-util-to-string: 3.0.0 hastscript: 9.0.0 @@ -1993,146 +2068,39 @@ snapshots: mdast-util-to-markdown: 2.1.0 mdast-util-to-string: 4.0.0 pagefind: 1.2.0 - rehype: 13.0.1 + rehype: 13.0.2 rehype-format: 5.0.0 remark-directive: 3.0.0 unified: 11.0.5 - unist-util-visit: 5.0.0 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - - '@astrojs/telemetry@3.1.0': - dependencies: - ci-info: 4.1.0 - debug: 4.3.7 - dlv: 1.1.3 - dset: 3.1.4 - is-docker: 3.0.0 - is-wsl: 3.1.0 - which-pm-runs: 1.1.0 - transitivePeerDependencies: - - supports-color - - '@babel/code-frame@7.26.2': - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.26.2': {} - - '@babel/core@7.26.0': - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.2 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.2 - '@babel/template': 7.25.9 - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 - convert-source-map: 2.0.0 - debug: 4.3.7 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.26.2': - dependencies: - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.0.2 - - '@babel/helper-annotate-as-pure@7.25.9': - dependencies: - '@babel/types': 7.26.0 - - '@babel/helper-compilation-targets@7.25.9': - dependencies: - '@babel/compat-data': 7.26.2 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-module-imports@7.25.9': - dependencies: - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': + '@astrojs/telemetry@3.2.0': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.25.9 + ci-info: 4.1.0 + debug: 4.3.7 + dlv: 1.1.3 + dset: 3.1.4 + is-docker: 3.0.0 + is-wsl: 3.1.0 + which-pm-runs: 1.1.0 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.25.9': {} - '@babel/helper-string-parser@7.25.9': {} '@babel/helper-validator-identifier@7.25.9': {} - '@babel/helper-validator-option@7.25.9': {} - - '@babel/helpers@7.26.0': - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 - '@babel/parser@7.26.2': dependencies: '@babel/types': 7.26.0 - '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/types': 7.26.0 - transitivePeerDependencies: - - supports-color - '@babel/runtime@7.26.0': dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.25.9': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - - '@babel/traverse@7.25.9': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 - debug: 4.3.7 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - '@babel/types@7.26.0': dependencies: '@babel/helper-string-parser': 7.25.9 @@ -2148,72 +2116,147 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true + '@esbuild/aix-ppc64@0.24.2': + optional: true + '@esbuild/android-arm64@0.21.5': optional: true + '@esbuild/android-arm64@0.24.2': + optional: true + '@esbuild/android-arm@0.21.5': optional: true + '@esbuild/android-arm@0.24.2': + optional: true + '@esbuild/android-x64@0.21.5': optional: true + '@esbuild/android-x64@0.24.2': + optional: true + '@esbuild/darwin-arm64@0.21.5': optional: true + '@esbuild/darwin-arm64@0.24.2': + optional: true + '@esbuild/darwin-x64@0.21.5': optional: true + '@esbuild/darwin-x64@0.24.2': + optional: true + '@esbuild/freebsd-arm64@0.21.5': optional: true + '@esbuild/freebsd-arm64@0.24.2': + optional: true + '@esbuild/freebsd-x64@0.21.5': optional: true + '@esbuild/freebsd-x64@0.24.2': + optional: true + '@esbuild/linux-arm64@0.21.5': optional: true + '@esbuild/linux-arm64@0.24.2': + optional: true + '@esbuild/linux-arm@0.21.5': optional: true + '@esbuild/linux-arm@0.24.2': + optional: true + '@esbuild/linux-ia32@0.21.5': optional: true + '@esbuild/linux-ia32@0.24.2': + optional: true + '@esbuild/linux-loong64@0.21.5': optional: true + '@esbuild/linux-loong64@0.24.2': + optional: true + '@esbuild/linux-mips64el@0.21.5': optional: true + '@esbuild/linux-mips64el@0.24.2': + optional: true + '@esbuild/linux-ppc64@0.21.5': optional: true + '@esbuild/linux-ppc64@0.24.2': + optional: true + '@esbuild/linux-riscv64@0.21.5': optional: true + '@esbuild/linux-riscv64@0.24.2': + optional: true + '@esbuild/linux-s390x@0.21.5': optional: true + '@esbuild/linux-s390x@0.24.2': + optional: true + '@esbuild/linux-x64@0.21.5': optional: true + '@esbuild/linux-x64@0.24.2': + optional: true + + '@esbuild/netbsd-arm64@0.24.2': + optional: true + '@esbuild/netbsd-x64@0.21.5': optional: true + '@esbuild/netbsd-x64@0.24.2': + optional: true + + '@esbuild/openbsd-arm64@0.24.2': + optional: true + '@esbuild/openbsd-x64@0.21.5': optional: true + '@esbuild/openbsd-x64@0.24.2': + optional: true + '@esbuild/sunos-x64@0.21.5': optional: true + '@esbuild/sunos-x64@0.24.2': + optional: true + '@esbuild/win32-arm64@0.21.5': optional: true + '@esbuild/win32-arm64@0.24.2': + optional: true + '@esbuild/win32-ia32@0.21.5': optional: true + '@esbuild/win32-ia32@0.24.2': + optional: true + '@esbuild/win32-x64@0.21.5': optional: true + '@esbuild/win32-x64@0.24.2': + optional: true + '@expressive-code/core@0.38.3': dependencies: '@ctrl/tinycolor': 4.1.0 @@ -2314,24 +2357,9 @@ snapshots: '@img/sharp-win32-x64@0.33.5': optional: true - '@jridgewell/gen-mapping@0.3.5': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.0': {} - - '@jridgewell/set-array@1.2.1': {} - '@jridgewell/sourcemap-codec@1.5.0': {} - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@mdx-js/mdx@3.0.1': + '@mdx-js/mdx@3.1.0(acorn@8.14.0)': dependencies: '@types/estree': 1.0.6 '@types/estree-jsx': 1.0.0 @@ -2339,14 +2367,15 @@ snapshots: '@types/mdx': 2.0.5 collapse-white-space: 2.1.0 devlop: 1.1.0 - estree-util-build-jsx: 3.0.1 estree-util-is-identifier-name: 3.0.0 - estree-util-to-js: 2.0.0 + estree-util-scope: 1.0.0 estree-walker: 3.0.3 - hast-util-to-estree: 3.1.0 hast-util-to-jsx-runtime: 2.3.0 markdown-extensions: 2.0.0 - periscopic: 3.1.0 + recma-build-jsx: 1.0.0 + recma-jsx: 1.0.0(acorn@8.14.0) + recma-stringify: 1.0.0 + rehype-recma: 1.0.0 remark-mdx: 3.0.1 remark-parse: 11.0.0 remark-rehype: 11.1.1 @@ -2357,6 +2386,7 @@ snapshots: unist-util-visit: 5.0.0 vfile: 6.0.3 transitivePeerDependencies: + - acorn - supports-color '@nodelib/fs.scandir@2.1.5': @@ -2483,27 +2513,6 @@ snapshots: dependencies: '@types/estree': 1.0.6 - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - '@types/babel__generator': 7.6.4 - '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.20.1 - - '@types/babel__generator@7.6.4': - dependencies: - '@babel/types': 7.26.0 - - '@types/babel__template@7.4.1': - dependencies: - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - - '@types/babel__traverse@7.20.1': - dependencies: - '@babel/types': 7.26.0 - '@types/cookie@0.6.0': {} '@types/debug@4.1.8': @@ -2520,6 +2529,8 @@ snapshots: dependencies: '@types/unist': 3.0.2 + '@types/js-yaml@4.0.9': {} + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.2 @@ -2562,6 +2573,11 @@ snapshots: ansi-styles@6.2.1: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + arg@5.0.2: {} argparse@1.0.10: @@ -2576,23 +2592,19 @@ snapshots: astring@1.8.6: {} - astro-expressive-code@0.38.3(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)): + astro-expressive-code@0.38.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)): dependencies: - astro: 4.16.18(rollup@4.27.3)(typescript@5.5.4) + astro: 5.1.1(rollup@4.27.3)(typescript@5.5.4) rehype-expressive-code: 0.38.3 - astro@4.16.18(rollup@4.27.3)(typescript@5.5.4): + astro@5.1.1(rollup@4.27.3)(typescript@5.5.4): dependencies: '@astrojs/compiler': 2.10.3 - '@astrojs/internal-helpers': 0.4.1 - '@astrojs/markdown-remark': 5.3.0 - '@astrojs/telemetry': 3.1.0 - '@babel/core': 7.26.0 - '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/types': 7.26.0 + '@astrojs/internal-helpers': 0.4.2 + '@astrojs/markdown-remark': 6.0.1 + '@astrojs/telemetry': 3.2.0 '@oslojs/encoding': 1.1.0 '@rollup/pluginutils': 5.1.3(rollup@4.27.3) - '@types/babel__core': 7.20.5 '@types/cookie': 0.6.0 acorn: 8.14.0 aria-query: 5.3.2 @@ -2615,7 +2627,6 @@ snapshots: fast-glob: 3.3.2 flattie: 1.1.1 github-slugger: 2.0.0 - gray-matter: 4.0.3 html-escaper: 3.0.3 http-cache-semantics: 4.1.1 js-yaml: 4.1.0 @@ -2625,7 +2636,6 @@ snapshots: micromatch: 4.0.8 mrmime: 2.0.0 neotraverse: 0.6.18 - ora: 8.1.1 p-limit: 6.1.0 p-queue: 8.0.1 preferred-pm: 4.0.0 @@ -2635,20 +2645,41 @@ snapshots: shiki: 1.23.1 tinyexec: 0.3.1 tsconfck: 3.1.4(typescript@5.5.4) + ultrahtml: 1.5.3 unist-util-visit: 5.0.0 + unstorage: 1.14.4 vfile: 6.0.3 - vite: 5.4.11 - vitefu: 1.0.4(vite@5.4.11) + vite: 6.0.6 + vitefu: 1.0.4(vite@6.0.6) which-pm: 3.0.0 xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 + yocto-spinner: 0.1.2 zod: 3.23.8 zod-to-json-schema: 3.23.5(zod@3.23.8) zod-to-ts: 1.2.0(typescript@5.5.4)(zod@3.23.8) optionalDependencies: sharp: 0.33.5 transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' - '@types/node' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - jiti - less - lightningcss - rollup @@ -2658,7 +2689,10 @@ snapshots: - sugarss - supports-color - terser + - tsx - typescript + - uploadthing + - yaml axobject-query@4.1.0: {} @@ -2674,6 +2708,8 @@ snapshots: is-alphanumerical: 2.0.1 is-decimal: 2.0.1 + binary-extensions@2.3.0: {} + boolbase@1.0.0: {} boxen@8.0.1: @@ -2691,17 +2727,8 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.24.2: - dependencies: - caniuse-lite: 1.0.30001680 - electron-to-chromium: 1.5.63 - node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.2) - camelcase@8.0.0: {} - caniuse-lite@1.0.30001680: {} - ccount@2.0.1: {} chalk@5.3.0: {} @@ -2714,16 +2741,22 @@ snapshots: character-reference-invalid@2.0.1: {} + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + 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.3 + ci-info@4.1.0: {} cli-boxes@3.0.0: {} - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-spinners@2.9.2: {} - clsx@2.1.1: {} collapse-white-space@2.1.0: {} @@ -2748,10 +2781,16 @@ snapshots: common-ancestor-path@1.0.1: {} - convert-source-map@2.0.0: {} + consola@3.3.3: {} + + cookie-es@1.2.2: {} cookie@0.7.2: {} + crossws@0.3.1: + dependencies: + uncrypto: 0.1.3 + css-selector-parser@3.0.4: {} cssesc@3.0.0: {} @@ -2764,8 +2803,12 @@ snapshots: dependencies: character-entities: 2.0.2 + defu@6.1.4: {} + dequal@2.0.3: {} + destr@2.0.3: {} + detect-libc@2.0.3: {} deterministic-object-hash@2.0.2: @@ -2786,8 +2829,6 @@ snapshots: dset@3.1.4: {} - electron-to-chromium@1.5.63: {} - emoji-regex-xs@1.0.0: {} emoji-regex@10.3.0: {} @@ -2798,6 +2839,20 @@ snapshots: es-module-lexer@1.5.4: {} + esast-util-from-estree@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.0 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + unist-util-position-from-estree: 2.0.0 + + esast-util-from-js@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.0 + acorn: 8.14.0 + esast-util-from-estree: 2.0.0 + vfile-message: 4.0.2 + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -2824,7 +2879,33 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - escalade@3.2.0: {} + esbuild@0.24.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 escape-string-regexp@5.0.0: {} @@ -2843,6 +2924,11 @@ snapshots: estree-util-is-identifier-name@3.0.0: {} + estree-util-scope@1.0.0: + dependencies: + '@types/estree': 1.0.6 + devlop: 1.1.0 + estree-util-to-js@2.0.0: dependencies: '@types/estree-jsx': 1.0.0 @@ -2869,10 +2955,6 @@ snapshots: '@expressive-code/plugin-shiki': 0.38.3 '@expressive-code/plugin-text-markers': 0.38.3 - extend-shallow@2.0.1: - dependencies: - is-extendable: 0.1.1 - extend@3.0.2: {} fast-glob@3.3.2: @@ -2908,8 +2990,6 @@ snapshots: fsevents@2.3.3: optional: true - gensync@1.0.0-beta.2: {} - get-east-asian-width@1.2.0: {} github-slugger@2.0.0: {} @@ -2918,16 +2998,20 @@ snapshots: dependencies: is-glob: 4.0.3 - globals@11.12.0: {} - graceful-fs@4.2.11: {} - gray-matter@4.0.3: + h3@1.13.0: dependencies: - js-yaml: 3.14.1 - kind-of: 6.0.3 - section-matter: 1.0.0 - strip-bom-string: 1.0.0 + cookie-es: 1.2.2 + crossws: 0.3.1 + defu: 6.1.4 + destr: 2.0.3 + iron-webcrypto: 1.2.1 + ohash: 1.1.4 + radix3: 1.1.2 + ufo: 1.5.4 + uncrypto: 0.1.3 + unenv: 1.10.0 hast-util-embedded@3.0.0: dependencies: @@ -3043,20 +3127,6 @@ snapshots: transitivePeerDependencies: - supports-color - hast-util-to-html@9.0.2: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.2 - ccount: 2.0.1 - comma-separated-tokens: 2.0.3 - hast-util-whitespace: 3.0.0 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.1.0 - property-information: 6.2.0 - space-separated-tokens: 2.0.2 - stringify-entities: 4.0.3 - zwitch: 2.0.4 - hast-util-to-html@9.0.3: dependencies: '@types/hast': 3.0.4 @@ -3150,6 +3220,8 @@ snapshots: inline-style-parser@0.2.2: {} + iron-webcrypto@1.2.1: {} + is-absolute-url@4.0.1: {} is-alphabetical@2.0.1: {} @@ -3161,12 +3233,14 @@ snapshots: is-arrayish@0.3.2: {} + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + is-decimal@2.0.1: {} is-docker@3.0.0: {} - is-extendable@0.1.1: {} - is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} @@ -3181,26 +3255,14 @@ snapshots: dependencies: is-docker: 3.0.0 - is-interactive@2.0.0: {} - is-number@7.0.0: {} is-plain-obj@4.1.0: {} - is-reference@3.0.1: - dependencies: - '@types/estree': 1.0.6 - - is-unicode-supported@1.3.0: {} - - is-unicode-supported@2.0.0: {} - is-wsl@3.1.0: dependencies: is-inside-container: 1.0.0 - js-tokens@4.0.0: {} - js-yaml@3.14.1: dependencies: argparse: 1.0.10 @@ -3210,12 +3272,6 @@ snapshots: dependencies: argparse: 2.0.1 - jsesc@3.0.2: {} - - json5@2.2.3: {} - - kind-of@6.0.3: {} - kleur@3.0.3: {} kleur@4.1.5: {} @@ -3231,16 +3287,9 @@ snapshots: dependencies: p-locate: 4.1.0 - log-symbols@6.0.0: - dependencies: - chalk: 5.3.0 - is-unicode-supported: 1.3.0 - longest-streak@3.1.0: {} - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 + lru-cache@10.4.3: {} magic-string@0.30.17: dependencies: @@ -3719,7 +3768,7 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mimic-function@5.0.1: {} + mime@3.0.0: {} mrmime@2.0.0: {} @@ -3733,7 +3782,9 @@ snapshots: dependencies: '@types/nlcst': 2.0.3 - node-releases@2.0.18: {} + node-fetch-native@1.6.4: {} + + normalize-path@3.0.0: {} not@0.1.0: {} @@ -3741,9 +3792,13 @@ snapshots: dependencies: boolbase: 1.0.0 - onetime@7.0.0: + ofetch@1.4.1: dependencies: - mimic-function: 5.0.1 + destr: 2.0.3 + node-fetch-native: 1.6.4 + ufo: 1.5.4 + + ohash@1.1.4: {} oniguruma-to-es@0.4.1: dependencies: @@ -3751,18 +3806,6 @@ snapshots: regex: 5.0.2 regex-recursion: 4.2.1 - ora@8.1.1: - dependencies: - chalk: 5.3.0 - cli-cursor: 5.0.0 - cli-spinners: 2.9.2 - is-interactive: 2.0.0 - is-unicode-supported: 2.0.0 - log-symbols: 6.0.0 - stdin-discarder: 0.2.2 - string-width: 7.2.0 - strip-ansi: 7.1.0 - p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -3818,11 +3861,7 @@ snapshots: path-exists@4.0.0: {} - periscopic@3.1.0: - dependencies: - '@types/estree': 1.0.6 - estree-walker: 3.0.3 - is-reference: 3.0.1 + pathe@1.1.2: {} picocolors@1.1.1: {} @@ -3852,6 +3891,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.0 + postcss@8.4.49: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + preferred-pm@4.0.0: dependencies: find-up-simple: 1.0.0 @@ -3869,6 +3914,42 @@ snapshots: queue-microtask@1.2.3: {} + radix3@1.1.2: {} + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + recma-build-jsx@1.0.0: + dependencies: + '@types/estree': 1.0.6 + estree-util-build-jsx: 3.0.1 + vfile: 6.0.3 + + recma-jsx@1.0.0(acorn@8.14.0): + dependencies: + acorn-jsx: 5.3.2(acorn@8.14.0) + estree-util-to-js: 2.0.0 + recma-parse: 1.0.0 + recma-stringify: 1.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - acorn + + recma-parse@1.0.0: + dependencies: + '@types/estree': 1.0.6 + esast-util-from-js: 2.0.1 + unified: 11.0.5 + vfile: 6.0.3 + + recma-stringify@1.0.0: + dependencies: + '@types/estree': 1.0.6 + estree-util-to-js: 2.0.0 + unified: 11.0.5 + vfile: 6.0.3 + regenerator-runtime@0.14.1: {} regex-recursion@4.2.1: @@ -3916,11 +3997,13 @@ snapshots: hast-util-raw: 9.0.2 vfile: 6.0.3 - rehype-stringify@10.0.0: + rehype-recma@1.0.0: dependencies: + '@types/estree': 1.0.6 '@types/hast': 3.0.4 - hast-util-to-html: 9.0.2 - unified: 11.0.5 + hast-util-to-estree: 3.1.0 + transitivePeerDependencies: + - supports-color rehype-stringify@10.0.1: dependencies: @@ -3928,13 +4011,6 @@ snapshots: hast-util-to-html: 9.0.3 unified: 11.0.5 - rehype@13.0.1: - dependencies: - '@types/hast': 3.0.4 - rehype-parse: 9.0.0 - rehype-stringify: 10.0.0 - unified: 11.0.5 - rehype@13.0.2: dependencies: '@types/hast': 3.0.4 @@ -3999,11 +4075,6 @@ snapshots: mdast-util-to-markdown: 2.1.0 unified: 11.0.5 - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - retext-latin@4.0.0: dependencies: '@types/nlcst': 2.0.3 @@ -4061,13 +4132,6 @@ snapshots: sax@1.2.4: {} - section-matter@1.0.0: - dependencies: - extend-shallow: 2.0.1 - kind-of: 6.0.3 - - semver@6.3.1: {} - semver@7.6.3: {} sharp@0.33.5: @@ -4105,8 +4169,6 @@ snapshots: '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 - signal-exit@4.1.0: {} - simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 @@ -4122,17 +4184,19 @@ snapshots: source-map-js@1.2.0: {} + source-map-js@1.2.1: {} + source-map@0.7.4: {} space-separated-tokens@2.0.2: {} sprintf-js@1.0.3: {} - starlight-links-validator@0.13.2(@astrojs/starlight@0.29.2(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)))(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)): + starlight-links-validator@0.13.2(@astrojs/starlight@0.30.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)))(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)): dependencies: - '@astrojs/starlight': 0.29.2(astro@4.16.18(rollup@4.27.3)(typescript@5.5.4)) + '@astrojs/starlight': 0.30.3(astro@5.1.1(rollup@4.27.3)(typescript@5.5.4)) '@types/picomatch': 2.3.3 - astro: 4.16.18(rollup@4.27.3)(typescript@5.5.4) + astro: 5.1.1(rollup@4.27.3)(typescript@5.5.4) github-slugger: 2.0.0 hast-util-from-html: 2.0.1 hast-util-has-property: 3.0.0 @@ -4142,8 +4206,6 @@ snapshots: picomatch: 4.0.2 unist-util-visit: 5.0.0 - stdin-discarder@0.2.2: {} - stream-replace-string@2.0.0: {} string-width@4.2.3: @@ -4171,8 +4233,6 @@ snapshots: dependencies: ansi-regex: 6.0.1 - strip-bom-string@1.0.0: {} - strip-bom@3.0.0: {} style-to-object@0.4.1: @@ -4204,6 +4264,20 @@ snapshots: typescript@5.5.4: {} + ufo@1.5.4: {} + + ultrahtml@1.5.3: {} + + uncrypto@0.1.3: {} + + unenv@1.10.0: + dependencies: + consola: 3.3.3 + defu: 6.1.4 + mime: 3.0.0 + node-fetch-native: 1.6.4 + pathe: 1.1.2 + unified@11.0.5: dependencies: '@types/unist': 3.0.2 @@ -4260,11 +4334,16 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - update-browserslist-db@1.1.1(browserslist@4.24.2): + unstorage@1.14.4: dependencies: - browserslist: 4.24.2 - escalade: 3.2.0 - picocolors: 1.1.1 + anymatch: 3.1.3 + chokidar: 3.6.0 + destr: 2.0.3 + h3: 1.13.0 + lru-cache: 10.4.3 + node-fetch-native: 1.6.4 + ofetch: 1.4.1 + ufo: 1.5.4 util-deprecate@1.0.2: {} @@ -4283,17 +4362,17 @@ snapshots: '@types/unist': 3.0.2 vfile-message: 4.0.2 - vite@5.4.11: + vite@6.0.6: dependencies: - esbuild: 0.21.5 - postcss: 8.4.44 + esbuild: 0.24.2 + postcss: 8.4.49 rollup: 4.27.3 optionalDependencies: fsevents: 2.3.3 - vitefu@1.0.4(vite@5.4.11): + vitefu@1.0.4(vite@6.0.6): optionalDependencies: - vite: 5.4.11 + vite: 6.0.6 web-namespaces@2.0.1: {} @@ -4315,12 +4394,16 @@ snapshots: xxhash-wasm@1.1.0: {} - yallist@3.1.1: {} - yargs-parser@21.1.1: {} yocto-queue@1.1.1: {} + yocto-spinner@0.1.2: + dependencies: + yoctocolors: 2.1.1 + + yoctocolors@2.1.1: {} + zod-to-json-schema@3.23.5(zod@3.23.8): dependencies: zod: 3.23.8 diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts index 02ea2ac0..212277b2 100644 --- a/docs/src/content/config.ts +++ b/docs/src/content/config.ts @@ -1,7 +1,8 @@ import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from "@astrojs/starlight/loaders"; import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), }; diff --git a/docs/src/content/docs/overview.md b/docs/src/content/docs/overview.md index 7d9664c0..49f5c806 100644 --- a/docs/src/content/docs/overview.md +++ b/docs/src/content/docs/overview.md @@ -11,6 +11,7 @@ Welcome to the documentation for Nikcio.UHeadless! Here you will find resources - [Version 4.0.0+](../v4/start/): Documentation for version 4.0.0 and above. - [Version 5.0.0+](../v5/start/): Documentation for version 5.0.0 and above. - [Version 6.0.0+](../v6/start/): Documentation for version 6.0.0 and above. +- [Version 7.0.0+](../v7/start/): Documentation for version 7.0.0 and above. Choose the appropriate version and explore the documentation tailored to your needs. diff --git a/docs/src/content/docs/v7/extending/content.md b/docs/src/content/docs/v7/extending/content.md new file mode 100644 index 00000000..3085da7c --- /dev/null +++ b/docs/src/content/docs/v7/extending/content.md @@ -0,0 +1,291 @@ +--- +title: Extending Content Data Structures in Nikcio.UHeadless +description: Learn how to extend the content model in Nikcio.UHeadless. +--- + +Nikcio.UHeadless provides flexibility to extend and replace content data structures to accommodate your specific needs. This documentation outlines some examples of how you can extend the content data structures. + +## Example custom content model extending the existing content model: + +1. Create your content model by inheriting from `Nikcio.UHeadless.Defaults.ContentItems.ContentItem`: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; + +/// +/// This example demonstrates how to create a custom content item with custom properties and methods. +/// +/// +/// The can be used to resolve services from the DI container like you normally would with dependency injection. +/// It's important to contain any logic to the specific property or method within the property or method itself if possiable. +/// As GraphQL will only call the properties or methods that are requestedm and may not call all of them. +/// +[GraphQLName("CustomContentItemExampleContentItem")] +public class ContentItem : Nikcio.UHeadless.Defaults.ContentItems.ContentItem +{ + public ContentItem(CreateCommand command) : base(command) + { + } + + public string? CustomProperty => "Custom value"; + + public string? CustomMethod() + { + return "Custom method"; + } + + public string? CustomMethodWithParameter(string? parameter) + { + return $"Custom method with parameter: {parameter}"; + } + + public string? CustomMethodWithResolverContext(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; + } +} +``` + +When making your model you can use properties and methods to expose data. When using methods you can add parameters to the method to make it more dynamic. You can also use the `IResolverContext` to resolve services from the DI container. Every parameter except the `IResolverContext` will be a part of the GraphQL schema and will be a paramter you pass to the query. + +2. Extend the query where you want the model to be present. In this example, we extend the `ContentByIdQuery` query: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; +using HotChocolate.Types; +using Nikcio.UHeadless; +using Nikcio.UHeadless.ContentItems; +using Nikcio.UHeadless.Defaults.ContentItems; +using Umbraco.Cms.Core.Models.PublishedContent; + +[ExtendObjectType(typeof(HotChocolateQueryObject))] +public class CustomContentItemExampleQuery : ContentByIdQuery +{ + [GraphQLName("CustomContentItemExampleQuery")] + public override ContentItem? ContentById( + IResolverContext resolverContext, + [GraphQLDescription("The id to fetch.")] int id, + [GraphQLDescription("The context of the request.")] QueryContext? inContext = null) + { + return base.ContentById(resolverContext, id, inContext); + } + + protected override ContentItem? CreateContentItem(IPublishedContent? publishedContent, IContentItemRepository contentItemRepository, IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(contentItemRepository); + + return contentItemRepository.GetContentItem(new Nikcio.UHeadless.Defaults.ContentItems.ContentItem.CreateCommand() + { + PublishedContent = publishedContent, + ResolverContext = resolverContext, + StatusCode = publishedContent == null ? StatusCodes.Status404NotFound : StatusCodes.Status200OK, + Redirect = null + }); + } +} + +``` + +If you don't already have the `ContentByIdQuery` you don't need to override the `ContentById` method as you don't need to alter the `GraphQLName` which is the name of the query in the schema. This defaults to the query names you would normally use when using the query. (In this example `contentById`) + +3. Register the query in Nikcio.UHeadless: + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +4. Open `/graphql` and observe your new model for the `CustomContentItemExampleQuery` query. + +## Example extended the content model with public access settings: + +1. Create your access rule model: + +```csharp +using HotChocolate; + +[GraphQLDescription("Represents an access rule for the restrict public access settings.")] +public class AccessRuleModel +{ + public AccessRuleModel(string? ruleType, string? ruleValue) + { + RuleType = ruleType ?? string.Empty; + RuleValue = ruleValue ?? string.Empty; + } + + [GraphQLDescription("Gets the type of protection to grant access to the content item.")] + public string RuleType { get; set; } + + [GraphQLDescription("Gets the name of who has access to the content item.")] + public string RuleValue { get; set; } +} + +``` + +2. Create your Permissions model: + +```csharp +using HotChocolate; + +[GraphQLDescription("Represents a restrict public access settings of a content item.")] +public class PermissionsModel +{ + public PermissionsModel() + { + AccessRules = []; + } + + [GraphQLDescription("Gets the url to the login page.")] + public string? UrlLogin { get; set; } + + [GraphQLDescription("Gets the url to the error page.")] + public string? UrlNoAccess { get; set; } + + [GraphQLDescription("Gets the access rules for the restrict public access settings.")] + public List AccessRules { get; set; } +} +``` + +3. Create your content model: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; +using Nikcio.UHeadless; +using Nikcio.UHeadless.ContentItems; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.PublishedCache; +using Umbraco.Cms.Core.Routing; +using Umbraco.Cms.Core.Services; + +/// +/// This example demonstrates how to create a custom content item that includes the public access settings from Umbraco. +/// with this information you can block access to content based on the user using the site. +/// +/// +/// This example uses the default class from UHeadless +/// but could also be implemented using the class. +/// +[GraphQLName("PublishAccessExampleContentItem")] +public class ContentItem : Nikcio.UHeadless.Defaults.ContentItems.ContentItem +{ + public ContentItem(CreateCommand command) : base(command) + { + } + + [GraphQLDescription("Gets the restrict public access settings of the content item.")] + public PermissionsModel? Permissions(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + ILogger logger = resolverContext.Service>(); + IContentService contentService = resolverContext.Service(); + IPublicAccessService publicAccessService = resolverContext.Service(); + IContentItemRepository contentItemRepository = resolverContext.Service>(); + + if (PublishedContent == null) + { + logger.LogWarning("Content is null"); + return null; + } + + IContent? content = contentService.GetById(PublishedContent.Id); + + if (content == null) + { + logger.LogWarning("Content from content service is null. Id: {ContentId}", PublishedContent.Id); + return null; + } + + PublicAccessEntry? entry = publicAccessService.GetEntryForContent(content); + + if (entry == null) + { + logger.LogWarning("Public access entry is null. ContentId: {ContentId}", PublishedContent.Id); + return null; + } + + IPublishedContentCache? contentCache = contentItemRepository.GetCache(); + + if (contentCache == null) + { + throw new InvalidOperationException("The content cache is not available"); + } + + IPublishedContent? loginContent = contentCache.GetById(entry.LoginNodeId); + IPublishedContent? noAccessContent = contentCache.GetById(entry.NoAccessNodeId); + + var permissions = new PermissionsModel + { + UrlLogin = loginContent?.Url(resolverContext.Service(), resolverContext.Culture(), UrlMode.Absolute), + UrlNoAccess = noAccessContent?.Url(resolverContext.Service(), resolverContext.Culture(), UrlMode.Absolute) + }; + + foreach (PublicAccessRule rule in entry.Rules) + { + permissions.AccessRules.Add(new AccessRuleModel(rule.RuleType, rule.RuleValue)); + } + + return permissions; + } +} +``` + +4. Extend the query where you want the model to be present. In this example, we extend the `ContentByIdQuery` query: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; +using HotChocolate.Types; +using Nikcio.UHeadless; +using Nikcio.UHeadless.ContentItems; +using Nikcio.UHeadless.Defaults.ContentItems; +using Umbraco.Cms.Core.Models.PublishedContent; + +[ExtendObjectType(typeof(HotChocolateQueryObject))] +public class PublishAccessExampleQuery : ContentByIdQuery +{ + [GraphQLName("publishAccessExampleQuery")] + public override ContentItem? ContentById( + IResolverContext resolverContext, + [GraphQLDescription("The id to fetch.")] int id, + [GraphQLDescription("The context of the request.")] QueryContext? inContext = null) + { + return base.ContentById(resolverContext, id, inContext); + } + + protected override ContentItem? CreateContentItem(IPublishedContent? publishedContent, IContentItemRepository contentItemRepository, IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(contentItemRepository); + + return contentItemRepository.GetContentItem(new Nikcio.UHeadless.Defaults.ContentItems.ContentItem.CreateCommand() + { + PublishedContent = publishedContent, + ResolverContext = resolverContext, + StatusCode = publishedContent == null ? StatusCodes.Status404NotFound : StatusCodes.Status200OK, + Redirect = null + }); + } +} + +``` + +3. Register the query in Nikcio.UHeadless: + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +4. Open `/graphql` and observe your new model for the `publishAccessExampleQuery` query. diff --git a/docs/src/content/docs/v7/extending/media.md b/docs/src/content/docs/v7/extending/media.md new file mode 100644 index 00000000..604dc668 --- /dev/null +++ b/docs/src/content/docs/v7/extending/media.md @@ -0,0 +1,102 @@ +--- +title: Extending Media Data Structures in Nikcio.UHeadless +description: Learn how to extend the media model in Nikcio.UHeadless. +--- + +Nikcio.UHeadless provides flexibility to extend and replace media data structures to accommodate your specific needs. This documentation outlines three examples of how you can extend the media data structures. + +## Example custom media model extending the existing media model: + +1. Create your own media model by inheriting from `Nikcio.UHeadless.Defaults.MediaItems.MediaItem`: + +```csharp +using HotChocolate.Resolvers; +using HotChocolate; + +/// +/// This example demonstrates how to create a custom media item with custom properties and methods. +/// +/// +/// The can be used to resolve services from the DI container like you normally would with dependency injection. +/// It's important to contain any logic to the specific property or method within the property or method itself if possiable. +/// As GraphQL will only call the properties or methods that are requestedm and may not call all of them. +/// +[GraphQLName("CustomMediaItemExampleMediaItem")] +public class MediaItem : Nikcio.UHeadless.Defaults.MediaItems.MediaItem +{ + public MediaItem(CreateCommand command) : base(command) + { + } + + public string? CustomProperty => "Custom value"; + + public string? CustomMethod() + { + return "Custom method"; + } + + public string? CustomMethodWithParameter(string? parameter) + { + return $"Custom method with parameter: {parameter}"; + } + + public string? CustomMethodWithResolverContext(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; + } +} +``` + +When making your model you can use properties and methods to expose data. When using methods you can add parameters to the method to make it more dynamic. You can also use the `IResolverContext` to resolve services from the DI container. Every parameter except the `IResolverContext` will be a part of the GraphQL schema and will be a paramter you pass to the query. + +2. Extend the query where you want the model to be present. In this example, we extend the `MediaByIdQuery` query: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; +using HotChocolate.Types; +using Nikcio.UHeadless; +using Nikcio.UHeadless.Defaults.MediaItems; +using Nikcio.UHeadless.MediaItems; +using Umbraco.Cms.Core.Models.PublishedContent; + +[ExtendObjectType(typeof(HotChocolateQueryObject))] +public class CustomMediaItemExampleQuery : MediaByIdQuery +{ + [GraphQLName("CustomMediaItemExampleQuery")] + public override MediaItem? MediaById( + IResolverContext resolverContext, + [GraphQLDescription("The id to fetch.")] int id) + { + return base.MediaById(resolverContext, id); + } + + protected override MediaItem? CreateMediaItem(IPublishedContent? media, IMediaItemRepository mediaItemRepository, IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(mediaItemRepository); + + return mediaItemRepository.GetMediaItem(new Nikcio.UHeadless.Media.MediaItemBase.CreateCommand() + { + PublishedContent = media, + ResolverContext = resolverContext, + }); + } +} +``` + +If you don't already have the `MediaByIdQuery` you don't need to override the `MediaById` method as you don't need to alter the `GraphQLName` which is the name of the query in the schema. This defaults to the query names you would normally use when using the query. (In this example `MediaById`) + +3. Register the query in Nikcio.UHeadless: + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +4. Open `/graphql` and observe your new model for the `CustomMediaItemExampleQuery` query. diff --git a/docs/src/content/docs/v7/extending/member.md b/docs/src/content/docs/v7/extending/member.md new file mode 100644 index 00000000..049ac5d6 --- /dev/null +++ b/docs/src/content/docs/v7/extending/member.md @@ -0,0 +1,103 @@ +--- +title: Extending Member Data Structures in Nikcio.UHeadless +description: Learn how to extend the member model in Nikcio.UHeadless. +--- + +Nikcio.UHeadless provides flexibility to extend and replace member data structures to accommodate your specific needs. This documentation outlines three examples of how you can extend the member data structures. + +## Example custom member model extending the existing member model: + +1. Create your own member model by inheriting from `Nikcio.UHeadless.Defaults.Members.MemberItem`: + +```csharp +using HotChocolate.Resolvers; +using HotChocolate; + +/// +/// This example demonstrates how to create a custom member item with custom properties and methods. +/// +/// +/// The can be used to resolve services from the DI container like you normally would with dependency injection. +/// It's important to contain any logic to the specific property or method within the property or method itself if possiable. +/// As GraphQL will only call the properties or methods that are requestedm and may not call all of them. +/// +[GraphQLName("CustomMemberItemExampleMemberItem")] +public class MemberItem : Nikcio.UHeadless.Defaults.Members.MemberItem +{ + public MemberItem(CreateCommand command) : base(command) + { + } + + public string? CustomProperty => "Custom value"; + + public string? CustomMethod() + { + return "Custom method"; + } + + public string? CustomMethodWithParameter(string? parameter) + { + return $"Custom method with parameter: {parameter}"; + } + + public string? CustomMethodWithResolverContext(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; + } +} +``` + +When making your model you can use properties and methods to expose data. When using methods you can add parameters to the method to make it more dynamic. You can also use the `IResolverContext` to resolve services from the DI container. Every parameter except the `IResolverContext` will be a part of the GraphQL schema and will be a paramter you pass to the query. + +2. Extend the query where you want the model to be present. In this example, we extend the `MemberByIdQuery` query: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; +using HotChocolate.Types; +using Nikcio.UHeadless; +using Nikcio.UHeadless.Defaults.Members; +using Nikcio.UHeadless.MemberItems; +using Umbraco.Cms.Core.Models.PublishedContent; + +[ExtendObjectType(typeof(HotChocolateQueryObject))] +public class CustomMemberItemExampleQuery : MemberByIdQuery +{ + [GraphQLName("CustomMemberItemExampleQuery")] + public override MemberItem? MemberById( + IResolverContext resolverContext, + [GraphQLDescription("The id to fetch.")] int id) + { + return base.MemberById(resolverContext, id); + } + + protected override MemberItem? CreateMemberItem(IPublishedContent? member, IMemberItemRepository memberItemRepository, IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(memberItemRepository); + + return memberItemRepository.GetMemberItem(new Nikcio.UHeadless.Members.MemberItemBase.CreateCommand() + { + PublishedContent = member, + ResolverContext = resolverContext, + }); + } +} + +``` + +If you don't already have the `MemberByIdQuery` you don't need to override the `MemberById` method as you don't need to alter the `GraphQLName` which is the name of the query in the schema. This defaults to the query names you would normally use when using the query. (In this example `MemberById`) + +3. Register the query in Nikcio.UHeadless: + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +4. Open `/graphql` and observe your new model for the `CustomMemberItemExampleQuery` query. diff --git a/docs/src/content/docs/v7/extending/properties/block-list.md b/docs/src/content/docs/v7/extending/properties/block-list.md new file mode 100644 index 00000000..0a6eee1f --- /dev/null +++ b/docs/src/content/docs/v7/extending/properties/block-list.md @@ -0,0 +1,109 @@ +--- +title: Extending the Block list model in Nikcio.UHeadless +description: Learn how to extend the block list model in Nikcio.UHeadless. +--- + +Nikcio.UHeadless provides flexibility to extend and replace the block list model to accommodate your specific needs. + +## Example + +1. Create your block list model: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; + +namespace Code.Examples.Headless.CustomBlockListExample; + +[GraphQLName("CustomBlockList")] +public class BlockList : Nikcio.UHeadless.Defaults.Properties.BlockList +{ + public BlockList(CreateCommand command) : base(command) + { + } + + protected override BlockListItem CreateBlock(Umbraco.Cms.Core.Models.Blocks.BlockListItem blockListItem, IResolverContext resolverContext) + { + return new BlockListItem(blockListItem, resolverContext); + } + + public string? CustomProperty => "Custom value"; + + public string? CustomMethod() + { + return "Custom method"; + } + + public string? CustomMethodWithParameter(string? parameter) + { + return $"Custom method with parameter: {parameter}"; + } + + public string? CustomMethodWithResolverContext(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; + } +} + +public class BlockListItem : Nikcio.UHeadless.Defaults.Properties.BlockListItem +{ + public BlockListItem(Umbraco.Cms.Core.Models.Blocks.BlockListItem blockListItem, IResolverContext resolverContext) : base(blockListItem, resolverContext) + { + } + + public string? CustomProperty => "Custom value"; + + public string? CustomMethod() + { + return "Custom method"; + } + + public string? CustomMethodWithParameter(string? parameter) + { + return $"Custom method with parameter: {parameter}"; + } + + public string? CustomMethodWithResolverContext(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; + } +} + +``` + +2. Register the model in the UHeadless options: + +```csharp +.AddUHeadless(options => +{ + options.AddEditorMapping(Constants.PropertyEditors.Aliases.BlockList); +}) +``` + +There are two methods available to register the model in the UHeadless options: + +| Method Name | Description | +|-------------------|--------------------------------------------------------------------------------| +| AddAliasMapping | Adds a mapping of a type to a content type alias and property type alias. | +| AddEditorMapping | Adds a mapping of a type to an editor alias. | + + +## Resolver context extensions + +The `IResolverContext` contains the following extensions that can be used to get information about the current query: + +| Extension Name | Description | +|----------------------|----------------------------------------------------------------------------------------------------------------------------------| +| IncludePreview() | Gets whether to include preview content in the query. | +| Culture() | Gets the culture of the query. | +| Segment() | Gets the segment of the query. | +| Fallback() | Gets the fallback of the query to be used for property values. | +| PublishedContent() |Gets the published content from the scoped data. This can be different depending on where in the query resolution the code runs. | diff --git a/docs/src/content/docs/v7/extending/properties/custom-editor.md b/docs/src/content/docs/v7/extending/properties/custom-editor.md new file mode 100644 index 00000000..4df99144 --- /dev/null +++ b/docs/src/content/docs/v7/extending/properties/custom-editor.md @@ -0,0 +1,58 @@ +--- +title: Adding your custom editor model in Nikcio.UHeadless +description: Learn how to add your custom editor model in Nikcio.UHeadless. +--- + +Nikcio.UHeadless provides flexibility to add your models for custom property editors. + +## Example + +1. Create your custom editor model: + +```csharp +using HotChocolate.Resolvers; +using Nikcio.UHeadless; +using Nikcio.UHeadless.Common.Properties; + +public class CustomEditor : PropertyValue +{ + public CustomEditor(CreateCommand command) : base(command) + { + ArgumentNullException.ThrowIfNull(command); + + IResolverContext resolverContext = command.ResolverContext; + Value = PublishedProperty.Value(PublishedValueFallback, resolverContext.Culture(), resolverContext.Segment(), resolverContext.Fallback()); + } + + public string? Value { get; } +} +``` + +2. Register the model in the UHeadless options: + +```csharp +.AddUHeadless(options => +{ + options.AddEditorMapping("customEditorAlias"); +}) +``` + +There are two methods available to register the model in the UHeadless options: + +| Method Name | Description | +|-------------------|--------------------------------------------------------------------------------| +| AddAliasMapping | Adds a mapping of a type to a content type alias and property type alias. | +| AddEditorMapping | Adds a mapping of a type to an editor alias. | + + +## Resolver context extensions + +The `IResolverContext` contains the following extensions that can be used to get information about the current query: + +| Extension Name | Description | +|----------------------|----------------------------------------------------------------------------------------------------------------------------------| +| IncludePreview() | Gets whether to include preview content in the query. | +| Culture() | Gets the culture of the query. | +| Segment() | Gets the segment of the query. | +| Fallback() | Gets the fallback of the query to be used for property values. | +| PublishedContent() |Gets the published content from the scoped data. This can be different depending on where in the query resolution the code runs. | diff --git a/docs/src/content/docs/v7/extending/properties/media-picker.md b/docs/src/content/docs/v7/extending/properties/media-picker.md new file mode 100644 index 00000000..97a8af84 --- /dev/null +++ b/docs/src/content/docs/v7/extending/properties/media-picker.md @@ -0,0 +1,105 @@ +--- +title: Extending the Media Picker model in Nikcio.UHeadless +description: Learn how to extend the media picker model in Nikcio.UHeadless. +--- + +Nikcio.UHeadless provides flexibility to extend and replace the media picker model to accommodate your specific needs. + +## Example 1 + +1. Create your own media picker model: + +```csharp +using HotChocolate.Resolvers; +using Umbraco.Cms.Core.Models.PublishedContent; + +namespace Code.Examples.Headless.CustomMediaPickerExample; + +public class MediaPicker : Nikcio.UHeadless.Defaults.Properties.MediaPicker +{ + public MediaPicker(CreateCommand command) : base(command) + { + } + + protected override MediaPickerItem CreateMediaPickerItem(IPublishedContent publishedContent, IResolverContext resolverContext) + { + return new MediaPickerItem(publishedContent, resolverContext); + } + public string? CustomProperty => "Custom value"; + + public string? CustomMethod() + { + return "Custom method"; + } + + public string? CustomMethodWithParameter(string? parameter) + { + return $"Custom method with parameter: {parameter}"; + } + + public string? CustomMethodWithResolverContext(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; + } +} + +public class MediaPickerItem : Nikcio.UHeadless.Defaults.Properties.MediaPickerItem +{ + public MediaPickerItem(IPublishedContent publishedContent, IResolverContext resolverContext) : base(publishedContent, resolverContext) + { + } + public string? CustomProperty => "Custom value"; + + public string? CustomMethod() + { + return "Custom method"; + } + + public string? CustomMethodWithParameter(string? parameter) + { + return $"Custom method with parameter: {parameter}"; + } + + public string? CustomMethodWithResolverContext(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; + } +} +``` + +2. Register the model in the UHeadless options: + +```csharp +.AddUHeadless(options => +{ + options.AddEditorMapping(Constants.PropertyEditors.Aliases.MediaPicker); +}) +``` + +There are two methods available to register the model in the UHeadless options: + +| Method Name | Description | +|-------------------|--------------------------------------------------------------------------------| +| AddAliasMapping | Adds a mapping of a type to a content type alias and property type alias. | +| AddEditorMapping | Adds a mapping of a type to an editor alias. | + + +## Resolver context extensions + +The `IResolverContext` contains the following extensions that can be used to get information about the current query: + +| Extension Name | Description | +|----------------------|----------------------------------------------------------------------------------------------------------------------------------| +| IncludePreview() | Gets whether to include preview content in the query. | +| Culture() | Gets the culture of the query. | +| Segment() | Gets the segment of the query. | +| Fallback() | Gets the fallback of the query to be used for property values. | +| PublishedContent() |Gets the published content from the scoped data. This can be different depending on where in the query resolution the code runs. | diff --git a/docs/src/content/docs/v7/extending/properties/overview.md b/docs/src/content/docs/v7/extending/properties/overview.md new file mode 100644 index 00000000..c6b96a76 --- /dev/null +++ b/docs/src/content/docs/v7/extending/properties/overview.md @@ -0,0 +1,49 @@ +--- +title: Nikcio.UHeadless Extension Documentation +description: Get an overview of the Nikcio.UHeadless extension documentation. +--- + +Welcome to the Nikcio.UHeadless Extension Documentation! Here, you'll find resources to help you extend and customize various features of Nikcio.UHeadless. Please select the topic you want to explore: + +- [Block List](./block-list): Learn how to extend and replace the block list property with your custom implementation. +- [Custom Editor](./custom-editor): Discover how to create and integrate your custom editor for property values. +- [Media Picker](./media-picker): Find out how to extend and customize the media picker data. +- [Rich Text](./rich-text): Learn how to extend and replace the rich text editor with your custom implementation. + +## Dependency Injection + +Dependency injection is supported via the `IResolverContext` which is available on the command in the contructor of the property model. This allows you to resolve services and other dependencies needed for your custom implementation. + +You can also inject the `IResolverContext` into methods on the property model to resolve services and other dependencies needed for your custom implementation. + +### Examples + +```csharp +public CustomEditor(CreateCommand command) : base(command) +{ + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); +} +``` + +```csharp +public string? CustomMethodWithResolverContext(IResolverContext resolverContext) +{ + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; +} +``` + +## Resolver context extensions + +The `IResolverContext` contains the following extensions that can be used to get information about the current query: + +| Extension Name | Description | +|----------------------|----------------------------------------------------------------------------------------------------------------------------------| +| IncludePreview() | Gets whether to include preview content in the query. | +| Culture() | Gets the culture of the query. | +| Segment() | Gets the segment of the query. | +| Fallback() | Gets the fallback of the query to be used for property values. | +| PublishedContent() |Gets the published content from the scoped data. This can be different depending on where in the query resolution the code runs. | diff --git a/docs/src/content/docs/v7/extending/properties/rich-text.md b/docs/src/content/docs/v7/extending/properties/rich-text.md new file mode 100644 index 00000000..a8a38cc2 --- /dev/null +++ b/docs/src/content/docs/v7/extending/properties/rich-text.md @@ -0,0 +1,74 @@ +--- +title: Extending the Rich text model in Nikcio.UHeadless +description: Learn how to extend the rich text model in Nikcio.UHeadless. +--- + +Nikcio.UHeadless provides flexibility to extend and replace the rich text model to accommodate your specific needs. + +## Example + +1. Create your rich text model: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; + +namespace Code.Examples.Headless.CustomRichTextExample; + +[GraphQLName("CustomRichText")] +public class RichText : Nikcio.UHeadless.Defaults.Properties.RichText +{ + public RichText(CreateCommand command) : base(command) + { + } + public string? CustomProperty => "Custom value"; + + public string? CustomMethod() + { + return "Custom method"; + } + + public string? CustomMethodWithParameter(string? parameter) + { + return $"Custom method with parameter: {parameter}"; + } + + public string? CustomMethodWithResolverContext(IResolverContext resolverContext) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + IHttpContextAccessor httpContextAccessor = resolverContext.Service(); + + return $"Custom method with resolver context so you can resolve the services needed: {httpContextAccessor.HttpContext?.Request.Path}"; + } +} +``` + +2. Register the model in the UHeadless options: + +```csharp +.AddUHeadless(options => +{ + options.AddEditorMapping(Constants.PropertyEditors.Aliases.TinyMce); +}) +``` + +There are two methods available to register the model in the UHeadless options: + +| Method Name | Description | +|-------------------|--------------------------------------------------------------------------------| +| AddAliasMapping | Adds a mapping of a type to a content type alias and property type alias. | +| AddEditorMapping | Adds a mapping of a type to an editor alias. | + + +## Resolver context extensions + +The `IResolverContext` contains the following extensions that can be used to get information about the current query: + +| Extension Name | Description | +|----------------------|----------------------------------------------------------------------------------------------------------------------------------| +| IncludePreview() | Gets whether to include preview content in the query. | +| Culture() | Gets the culture of the query. | +| Segment() | Gets the segment of the query. | +| Fallback() | Gets the fallback of the query to be used for property values. | +| PublishedContent() |Gets the published content from the scoped data. This can be different depending on where in the query resolution the code runs. | diff --git a/docs/src/content/docs/v7/extending/skybrud-redirects.md b/docs/src/content/docs/v7/extending/skybrud-redirects.md new file mode 100644 index 00000000..13dd612f --- /dev/null +++ b/docs/src/content/docs/v7/extending/skybrud-redirects.md @@ -0,0 +1,112 @@ +--- +title: Integrating Skybrud.Umbraco.Redirects in Nikcio.UHeadless +description: Learn how to integrate Skybrud.Umbraco.Redirects in Nikcio.UHeadless. +--- + +The Nikcio.UHeadless package provides a way to integrate the Skybrud.Umbraco.Redirects package in your Umbraco Headless project. This allows you to query for content like you would usually do but with the added benefit of getting redirect information from SKybrud.Umbraco.Redirects. + +## Example + +:::note +This example is based on `Skybrud.Umbraco.Redirects` version `13.0.4` +::: + +### Step 1: Install the Skybrud.Umbraco.Redirects package + +First, you need to install the `Skybrud.Umbraco.Redirects` package. You can do this by running the following command in the Package Manager Console: + +```bash +Install-Package Skybrud.Umbraco.Redirects +``` + +### Step 2: Create a query class + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; +using HotChocolate.Types; +using Nikcio.UHeadless; +using Nikcio.UHeadless.ContentItems; +using Nikcio.UHeadless.Defaults.ContentItems; +using Skybrud.Umbraco.Redirects.Models; +using Skybrud.Umbraco.Redirects.Services; + +[ExtendObjectType(typeof(HotChocolateQueryObject))] +public class SkybrudRedirectsExampleQuery : ContentByRouteQuery +{ + [GraphQLName("skybrudRedirectsExampleQuery")] + public override Task ContentByRouteAsync( + IResolverContext resolverContext, + [GraphQLDescription("The route to fetch. Example '/da/frontpage/'.")] string route, + [GraphQLDescription("The base url for the request. Example: 'https://localhost:4000'. Default is the current domain")] string baseUrl = "", + [GraphQLDescription("The context of the request.")] QueryContext? inContext = null) + { + return base.ContentByRouteAsync(resolverContext, route, baseUrl, inContext); + } + + protected override async Task CreateContentItemFromRouteAsync(IResolverContext resolverContext, string route, string baseUrl) + { + ArgumentNullException.ThrowIfNull(resolverContext); + ArgumentNullException.ThrowIfNull(baseUrl); + + IRedirectsService redirectService = resolverContext.Service(); + + var uri = new Uri($"{baseUrl.TrimEnd('/')}{route}"); + IRedirect? redirect = redirectService.GetRedirectByUri(uri); + + if (redirect != null) + { + IContentItemRepository contentItemRepository = resolverContext.Service>(); + + string redirectUrl = redirect.Destination.FullUrl; + + if (redirect.ForwardQueryString) + { + redirectUrl = redirectUrl.TrimEnd('/') + uri.Query; + } + + return contentItemRepository.GetContentItem(new ContentItem.CreateCommand() + { + PublishedContent = null, + ResolverContext = resolverContext, + Redirect = new() + { + IsPermanent = redirect.IsPermanent, + RedirectUrl = redirectUrl, + }, + StatusCode = redirect.IsPermanent ? StatusCodes.Status301MovedPermanently : StatusCodes.Status307TemporaryRedirect, + }); + } + + return await base.CreateContentItemFromRouteAsync(resolverContext, route, baseUrl).ConfigureAwait(false); + } +} +``` + +This query class extends the `ContentByRouteQuery` query and overrides the `CreateContentItemFromRouteAsync` method. This method is called when a content item is fetched by route. In this method, we get the `IRedirectsService` from the `IResolverContext` and fetch the redirect for the route. If a redirect is found, we create a new `ContentItem` with the redirect information. + +### Step 3: Add the query to the UHeadless configuration + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +### Step 4: Query the content + +Now you can query the content by route and get the redirect information: + +```graphql +query { + skybrudRedirectsExampleQuery(baseUrl: "", route: "/") { + redirect { + isPermanent + redirectUrl + } + } +} +``` + +This will return the redirect information if a redirect is found for the route. If no redirect is found, the content item will be fetched as usual. \ No newline at end of file diff --git a/docs/src/content/docs/v7/extending/url-tracker.md b/docs/src/content/docs/v7/extending/url-tracker.md new file mode 100644 index 00000000..b61c80b8 --- /dev/null +++ b/docs/src/content/docs/v7/extending/url-tracker.md @@ -0,0 +1,288 @@ +--- +title: Integrating UrlTracker in Nikcio.UHeadless +description: Learn how to integrate UrlTracker in Nikcio.UHeadless. +--- + +The Nikcio.UHeadless package provides a way to integrate the UrlTracker package into your UHeadless project. This allows you to use the UrlTracker package for redirects in your UHeadless project. + +## Example + +:::note +This example is based on `UrlTracker` version `13.2.0-alpha0003` +::: + +### Step 1: Install the UrlTracker package + +First, you need to install the `UrlTracker` package. You can do this by running the following command in the Package Manager Console: + +```bash +Install-Package UrlTracker +``` + +### Step 2: Create a query class + +```csharp +using System.Text.RegularExpressions; +using HotChocolate; +using HotChocolate.Resolvers; +using HotChocolate.Types; +using Microsoft.Extensions.Options; +using Nikcio.UHeadless; +using Nikcio.UHeadless.ContentItems; +using Nikcio.UHeadless.Defaults.ContentItems; +using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Routing; +using UrlTracker.Core; +using UrlTracker.Core.Intercepting.Models; +using UrlTracker.Core.Models; +using UrlTracker.Web.Processing; + +namespace Code.Examples.Headless.UrlTrackerExample; + +[ExtendObjectType(typeof(HotChocolateQueryObject))] +public class UrlTrackerExampleQuery : ContentByRouteQuery +{ + [GraphQLName("urlTrackerExampleQuery")] + public override Task ContentByRouteAsync( + IResolverContext resolverContext, + [GraphQLDescription("The route to fetch. Example '/da/frontpage/'.")] string route, + [GraphQLDescription("The base url for the request. Example: 'https://localhost:4000'. Default is the current domain")] string baseUrl = "", + [GraphQLDescription("The context of the request.")] QueryContext? inContext = null) + { + return base.ContentByRouteAsync(resolverContext, route, baseUrl, inContext); + } + + protected override async Task CreateContentItemFromRouteAsync(IResolverContext resolverContext, string route, string baseUrl) + { + ArgumentNullException.ThrowIfNull(resolverContext); + ArgumentNullException.ThrowIfNull(baseUrl); + + IRequestInterceptFilterCollection requestInterceptFilters = resolverContext.Service(); + + var requestedUrl = Url.Parse($"{baseUrl.TrimEnd('/')}{route}"); + + if (!await requestInterceptFilters.EvaluateCandidateAsync(requestedUrl).ConfigureAwait(false)) + { + return await base.CreateContentItemFromRouteAsync(resolverContext, route, baseUrl).ConfigureAwait(false); + } + + IInterceptService interceptService = resolverContext.Service(); + + IIntercept intercept = await interceptService.GetAsync(requestedUrl).ConfigureAwait(false); + + if (intercept.Info is not Redirect redirect) + { + return await base.CreateContentItemFromRouteAsync(resolverContext, route, baseUrl).ConfigureAwait(false); + } + + IContentItemRepository contentItemRepository = resolverContext.Service>(); + + string? redirectUrl = redirect.Target switch + { + + UrlTargetStrategy target => GetUrl(resolverContext, redirect, target, requestedUrl), + ContentPageTargetStrategy target => GetUrl(resolverContext, redirect, target, requestedUrl), + _ => throw new NotImplementedException(), + }; + + return contentItemRepository.GetContentItem(new ContentItem.CreateCommand() + { + PublishedContent = null, + ResolverContext = resolverContext, + Redirect = new() + { + IsPermanent = redirect.Permanent, + RedirectUrl = redirectUrl, + }, + StatusCode = redirectUrl == null ? StatusCodes.Status410Gone : GetStatusCode(redirect), + }); + } + + private static int GetStatusCode(Redirect redirect) + { + return redirect.Permanent ? StatusCodes.Status301MovedPermanently : StatusCodes.Status307TemporaryRedirect; + } + + private static string? GetUrl(IResolverContext resolverContext, Redirect redirect, UrlTargetStrategy target, Url requestedUrl) + { + string urlString = target.Url; + + if (redirect.Source is RegexSourceStrategy regexsource) + { + urlString = Regex.Replace((requestedUrl.Path + requestedUrl.Query).TrimStart('/'), regexsource.Value, urlString, RegexOptions.None, TimeSpan.FromMilliseconds(100)); + } + + var url = Url.Parse(urlString); + + if (redirect.RetainQuery) + { + url.Query = requestedUrl.Query; + } + + if (url.AvailableUrlTypes.Contains(UrlTracker.Core.Models.UrlType.Absolute)) + { + RequestHandlerSettings requestHandlerSettingsValue = resolverContext.Service>().Value; + return url.ToString(UrlTracker.Core.Models.UrlType.Absolute, requestHandlerSettingsValue.AddTrailingSlash); + } + else + { + return url.ToString(); + } + } + + private static string? GetUrl(IResolverContext resolverContext, Redirect redirect, ContentPageTargetStrategy target, Url requestedUrl) + { + if (target.Content is null) + { + return null; + } + + IPublishedUrlProvider publishedUrlProvider = resolverContext.Service(); + var url = Url.Parse(target.Content.Url(publishedUrlProvider, target.Culture.DefaultIfNullOrWhiteSpace(null), UrlMode.Absolute)); + + if (redirect.RetainQuery) + { + url.Query = requestedUrl.Query; + } + + if (url.AvailableUrlTypes.Contains(UrlTracker.Core.Models.UrlType.Absolute)) + { + RequestHandlerSettings requestHandlerSettingsValue = resolverContext.Service>().Value; + return url.ToString(UrlTracker.Core.Models.UrlType.Absolute, requestHandlerSettingsValue.AddTrailingSlash); + } + else + { + return url.ToString(); + } + } +} +``` + +This query class extends the `ContentByRouteQuery` query and overrides the `CreateContentItemFromRouteAsync` method. This method is called when a content item is fetched by route. In this method, we get the `IInterceptService` from the `IResolverContext` and fetch the redirect for the route. If a redirect is found, we create a new `ContentItem` with the redirect information. + +### Step 3: Register the query class + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +### Step 4: Query the content + +Now you can query the content by route and get the redirect information: + +```graphql +query { + urlTrackerExampleQuery(baseUrl: "", route: "/") { + redirect { + isPermanent + redirectUrl + } + } +} +``` + +## Track error status codes + +The UrlTracker package also allows you to track error status codes to get recommendations about missing redirects. You can create a mutation to track these error status codes from your frontend like this: + +```csharp +using HotChocolate; +using HotChocolate.Resolvers; +using HotChocolate.Types; +using Nikcio.UHeadless; +using Nikcio.UHeadless.Defaults.Authorization; +using UrlTracker.Middleware.Background; + +namespace Code.Examples.Headless.UrlTrackerExample; + +[ExtendObjectType(typeof(HotChocolateMutationObject))] +public class TrackErrorStatusCodeMutation : IGraphQLMutation +{ + public const string PolicyName = "TrackErrorStatusCode"; + + public const string ClaimValue = "track.error.statuscode.mutation"; + + [GraphQLIgnore] + public virtual void ApplyConfiguration(UHeadlessOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + options.UmbracoBuilder.Services.AddAuthorizationBuilder().AddPolicy(PolicyName, policy => + { + if (options.DisableAuthorization) + { + policy.AddRequirements(new AlwaysAllowAuthoriaztionRequirement()); + return; + } + + policy.AddAuthenticationSchemes(DefaultAuthenticationSchemes.UHeadless); + + policy.RequireAuthenticatedUser(); + + policy.RequireClaim(DefaultClaims.UHeadlessScope, ClaimValue); + }); + } + + public async Task TrackErrorStatusCodeAsync( + IResolverContext resolverContext, + [GraphQLDescription("Status code of the client error.")] int statusCode, + [GraphQLDescription("The URL that generated the client error.")] string url, + [GraphQLDescription("The time and date at which the client error was generated")] DateTime timestamp, + [GraphQLDescription("The URL from which the current URL is requested")] string? referrer) + { + ArgumentNullException.ThrowIfNull(resolverContext); + + ILogger logger = resolverContext.Service>(); + switch (statusCode) + { + case StatusCodes.Status404NotFound: + IClientErrorProcessorQueue clientErrorProcessorQueue = resolverContext.Service(); + await clientErrorProcessorQueue.WriteAsync(new ClientErrorProcessorItem(url, timestamp, referrer)).ConfigureAwait(false); + break; + case StatusCodes.Status500InternalServerError: + logger.LogError("Internal server error occurred at {Timestamp} for URL {Url} with referrer {Referrer}", timestamp, url, referrer); + break; + default: + logger.LogWarning("Client error occurred at {Timestamp} for URL {Url} with referrer {Referrer} and status code {StatusCode}", timestamp, url, referrer, statusCode); + break; + } + + return new TrackErrorStatusCodeResponse + { + Success = true + }; + } +} + +public sealed class TrackErrorStatusCodeResponse +{ + public required bool Success { get; init; } +} +``` + +This mutation class allows you to track error status codes from your frontend. You can use this mutation to track client errors like `404` and `500` errors. You can also track the time and date at which the client error was generated and the URL from which the current URL is requested. + +### Register the mutation class + +```csharp +.AddUHeadless(options => +{ + options.AddMutation(); +}) +``` + +### Query the mutation + +Now you can query the mutation to track the error status codes: + +```graphql +mutation { + trackErrorStatusCode(statusCode: 404, url: "https://my-website.com/page-not-found", timestamp: "2022-01-01T00:00:00Z", referrer: "https://my-website.com") { + success + } +} +``` diff --git a/docs/src/content/docs/v7/fundamentals/getting-started.md b/docs/src/content/docs/v7/fundamentals/getting-started.md new file mode 100644 index 00000000..7e5aba4c --- /dev/null +++ b/docs/src/content/docs/v7/fundamentals/getting-started.md @@ -0,0 +1,146 @@ +--- +title: Getting Started with Nikcio.UHeadless +description: Learn how to get started with Nikcio.UHeadless. +--- + +This guide will walk you through the process of integrating Nikcio.UHeadless into your Umbraco solution. By following these steps, you'll be able to create a headless GraphQL interface for your Umbraco CMS. + +## Installation + +To get started, follow the steps below: + +### Step 1: Install the package + +Install the Nikcio.UHeadless package using the following command: + +```shell +dotnet add Nikcio.UHeadless +``` + +### Step 2: Add the extensions to the `Program.cs` file + +In your `Program.cs` file, add the necessary extensions by following the code snippet below: + +Namespaces: + +```csharp +using Nikcio.UHeadless; +using Nikcio.UHeadless.Defaults.ContentItems; +``` + +On the `UmbracoBuilder`, add the following code: + +```csharp +builder.CreateUmbracoBuilder() + // Default Umbraco configuration + .AddUHeadless(options => + { + options.DisableAuthorization = true; // Change this later when adding authentication - See documentation + + options.AddDefaults(); + + options.AddQuery(); + options.AddQuery(); + }) + .Build(); +``` + +Then after the `app.BootUmbracoAsync()` method, add the following code: + +```csharp +await app.BootUmbracoAsync(); + +app.UseAuthentication(); +app.UseAuthorization(); + +GraphQLEndpointConventionBuilder graphQLEndpointBuilder = app.MapUHeadless(); + +// Only enable the GraphQL IDE in development +if (!builder.Environment.IsDevelopment()) +{ + graphQLEndpointBuilder.WithOptions(new GraphQLServerOptions() + { + Tool = + { + Enable = false, + } + }); +} + +app.UseUmbraco() + // Default Umbraco configuration +``` + +The `.AddUHeadless()` method adds the services needed for Nikcio.UHeadless to run, while `app.MapUHeadless()` adds the endpoint from where you interact with the GraphQL interface. These extensions provide a range of options that can be customized. To learn more about available options, refer to the [UHeadless options](../reference/options) and [UHeadless endpoint options](../reference/endpoint-options) documentation. + +### Step 3: Find the GraphQL endpoint + +By default, the GraphQL endpoint can be accessed at `/graphql` in your application. + +### Step 4: Make your first query + +To get started, try querying your content using their GUIDs or routes. For example with the query below: + +__Tip: GUIDs can be found in the info tab when viewing content in the backoffice__ + +```graphql +query { + contentByGuid(id: "dcf18a51-6919-4cf8-89d1-36b94ce4d963") { + id + key + name + statusCode + templateId + updateDate + url(urlMode: ABSOLUTE) + urlSegment + } +} +``` + +This query fetches a content item with the given GUID. + +Congratulations! You have successfully integrated Nikcio.UHeadless into your Umbraco solution. + +## Adding a more queries + +To add a more queries to Nikcio.UHeadless, you can include the following code in your `Program.cs` file: + +```csharp +.AddUHeadless(options => +{ + // Existing configuration + + options.AddQuery(); +}) +``` + +This example demonstrates how to add the `ContentByIdQuery` query to Nikcio.UHeadless. By including this code, you will enable the ability to query a content item by the numeric ID instead of the GUID: + +```graphql +query { + contentById(id: 1050) { + id + key + name + statusCode + templateId + updateDate + url(urlMode: ABSOLUTE) + urlSegment + } +} +``` + +To explore the available queries and how to use them, refer to the following documentation: + +- [Learn how to query properties](../querying/properties) +- [Querying Content](../querying/content) +- [Querying Media](../querying/media) +- [Querying Members](../querying/members) + +## Next steps + +- [Security Considerations](../security) + +If you have any questions or need further assistance, don't hesitate to reach out to us. Happy coding with Nikcio.UHeadless \ No newline at end of file diff --git a/docs/src/content/docs/v7/fundamentals/querying/content.md b/docs/src/content/docs/v7/fundamentals/querying/content.md new file mode 100644 index 00000000..5e8db349 --- /dev/null +++ b/docs/src/content/docs/v7/fundamentals/querying/content.md @@ -0,0 +1,38 @@ +--- +title: Content Queries +description: Learn how to query content in Nikcio.UHeadless. +--- + +The Nikcio.UHeadless package provides various content queries that allow you to retrieve content items in different ways from Umbraco CMS. + +## Queries + +You can add any query to the UHeadless options as seen here: + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +The following content queries are available: + +| Query class Name | Description | Needed claim values | +|------------------------------|---------------------------------------------|-----------------------------------------------------| +| ContentAtRootQuery | Gets all the content items at root level. | content.at.root.query or global.content.read | +| ContentByContentTypeQuery | Gets all the content items by content type. | content.by.contentType.query or global.content.read | +| ContentByGuidQuery | Gets a content item by Guid. | content.by.guid.query or global.content.read | +| ContentByIdQuery | Gets a content item by id. | content.by.id.query or global.content.read | +| ContentByRouteQuery | Gets a content item by a route. | content.by.route.query or global.content.read | +| ContentByTagQuery | Gets content items by tag. | content.by.tag.query or global.content.read | + +You can explore these queries and their parameters in the UI provided at `/graphql` when you have added them to the UHeadless options as seen above. + +The claim values are needed when having authorization enabled. You can read more about authorization and how to create tokens in the [Security Considerations](../security) section. + +A special case for claim values are for the member picker editor. To access the data of the member picker you will need one of the following claim values: `property.values.member.picker` or `global.member.read`. + +## Next steps + +- [Building your property query](./properties) \ No newline at end of file diff --git a/docs/src/content/docs/v7/fundamentals/querying/media.md b/docs/src/content/docs/v7/fundamentals/querying/media.md new file mode 100644 index 00000000..a1f8e9a8 --- /dev/null +++ b/docs/src/content/docs/v7/fundamentals/querying/media.md @@ -0,0 +1,36 @@ +--- +title: Media Queries +description: Learn how to query media in Nikcio.UHeadless. +--- + +The Nikcio.UHeadless package provides various media queries that allow you to retrieve media items in different ways from Umbraco CMS. + +## Queries + +You can add any query to the UHeadless options as seen here: + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +The following content queries are available: + +| Query class Name | Description | Needed claim values | +|------------------------------|---------------------------------------------|-----------------------------------------------------| +| MediaAtRootQuery | Gets all the media items at root level. | media.at.root.query or global.media.read | +| MediaByContentTypeQuery | Gets all the media items by content type. | media.by.contentType.query or global.media.read | +| MediaByGuidQuery | Gets a Media item by Guid. | media.by.guid.query or global.media.read | +| MediaByIdQuery | Gets a Media item by id. | media.by.id.query or global.media.read | + +You can explore these queries and their parameters in the UI provided at `/graphql` when you have added them to the UHeadless options as seen above. + +The claim values are needed when having authorization enabled. You can read more about authorization and how to create tokens in the [Security Considerations](../security) section. + +A special case for claim values are for the member picker editor. To access the data of the member picker you will need one of the following claim values: `property.values.member.picker` or `global.member.read`. + +## Next steps + +- [Building your property query](./properties) \ No newline at end of file diff --git a/docs/src/content/docs/v7/fundamentals/querying/members.md b/docs/src/content/docs/v7/fundamentals/querying/members.md new file mode 100644 index 00000000..58c12b5b --- /dev/null +++ b/docs/src/content/docs/v7/fundamentals/querying/members.md @@ -0,0 +1,41 @@ +--- +title: Member Queries +description: Learn how to query members in Nikcio.UHeadless. +--- + +The Nikcio.UHeadless package provides various member queries that allow you to retrieve member data from Umbraco CMS. +The Nikcio.UHeadless package provides various media queries that allow you to retrieve media items in different ways from Umbraco CMS. + +## Queries + +You can add any query to the UHeadless options as seen here: + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +The following content queries are available: + +| Query class Name | Description | Needed claim values | +|-------------------------------|---------------------------------------------|-------------------------------------------------------------| +| FindMembersByDisplayNameQuery | Finds members by display name. | find.members.by.display.name.query or global.member.read | +| FindMembersByEmailQuery | Finds members by email. | find.members.by.email.query or global.member.read | +| FindMembersByRoleQuery | Finds members by role. | find.members.by.role.query or global.member.read | +| FindMembersByUsernameQuery | Finds members by username. | find.members.by.username.query or global.member.read | +| MemberByEmailQuery | Gets a member by email. | member.by.email.query or global.member.read | +| MemberByGuidQuery | Gets a member by Guid. | member.by.guid.query or global.member.read | +| MemberByIdQuery | Gets a member by id. | member.by.id.query or global.member.read | +| MemberByUsernameQuery | Gets a member by username. | member.by.username.query or global.member.read | + +You can explore these queries and their parameters in the UI provided at `/graphql` when you have added them to the UHeadless options as seen above. + +The claim values are needed when having authorization enabled. You can read more about authorization and how to create tokens in the [Security Considerations](../security) section. + +A special case for claim values are for the member picker editor. To access the data of the member picker you will need one of the following claim values: `property.values.member.picker` or `global.member.read`. + +## Next steps + +- [Building your property query](./properties) \ No newline at end of file diff --git a/docs/src/content/docs/v7/fundamentals/querying/properties.md b/docs/src/content/docs/v7/fundamentals/querying/properties.md new file mode 100644 index 00000000..483faa8d --- /dev/null +++ b/docs/src/content/docs/v7/fundamentals/querying/properties.md @@ -0,0 +1,74 @@ +--- +title: Building Your Property Query +description: Learn how to build your property query in Nikcio.UHeadless. +--- + +In GraphQL, queries are used to request specific data from a server. When building a property query in GraphQL, you can use fragments to organize and reuse common selections of fields. Fragments allow you to define a set of fields that can be included in multiple queries, reducing duplication and making queries more modular. + +## Quering properties + +To query properties you use a list of property aliases that you want to fetch. This is possible on content, media and member models. To query properties you use the content, content compositions, media or member types created in Umbraco. Example: + +```graphql +query { + contentByRoute(baseUrl: "", route: "/") { + properties { + ... on IArticle { + title { + value + } + articleDate { + value + } + author { + items { + name + } + } + } + __typename + } + } +} +``` + +This works by the properties getting the type of content your fetching and then fetching the properties based on that type. In this example we have created a content type called `Article` in Umbraco and if the content item we find with our query matches the `Article` type we fetch the properties `title`, `articleDate` and `author`. + +The `__typename` field is used to get the type of the content item we fetch. This can help you figure out what properties are available on the content item you fetch. In this example if the `__typename` field returns `Article` we know that the properties `title`, `articleDate` and `author` are available on the content item. + +This is because all types of content, media and member types which have properties have a matching type and interface in the GraphQL schema. + +For this example we will see the following in the GraphQL schema: + +```graphql +type Article implements IArticleControls & IContentControls & IHeaderControls & IMainImageControls & ISEOControls & IVisibilityControls & IArticle { + +# ... the fields of the type ... + +} +``` + +Here we can see that the `Article` type implements the `IArticle` interface. This means that we can fetch the properties of the `IArticle` interface on the `Article` type. This is why we can fetch the properties `title`, `articleDate` and `author` on the `Article` type. + +Other than is we can see multiple other interfaces that the `Article` type implements. This means that we can fetch the properties of those interfaces on the `Article` type as well. This is useful when you have compositions in Umbraco that you want to fetch properties from. + +For example we can see that the `IArticleControls` interface has the following properties: + +```graphql +type ArticleControls implements IArticleControls { + """ + Enter the date for the article + """ + articleDate: DateTimePicker + + author: ContentPicker + + categories: ContentPicker +} +``` + +This means that we can use a fragment selection on the `IArticleControls` interface to fetch the properties `articleDate`, `author` and `categories` on the any type that has this compostion in Umbraco. + +:::note +When fetching properties you need to use the interfaces (They are prefixed with `I` on the type name) instead of the concrete types as the concrete types don't always return the expected values due to the matching rules in GraphQL. +::: \ No newline at end of file diff --git a/docs/src/content/docs/v7/fundamentals/security.md b/docs/src/content/docs/v7/fundamentals/security.md new file mode 100644 index 00000000..047cfc2c --- /dev/null +++ b/docs/src/content/docs/v7/fundamentals/security.md @@ -0,0 +1,313 @@ +--- +title: Security Considerations +description: Learn about what areas to consider when securing your Nikcio.UHeadless application. +--- + +When using Nikcio.UHeadless, it is important to consider security measures to protect your GraphQL data and ensure that access to sensitive information is properly controlled. This section highlights some key security considerations and provides guidance on implementing security measures. + +## Using Authentication and Authorization in Nikcio.UHeadless + +To enable authentication and authorization in Nikcio.UHeadless follow the code example below: + +### Step 1: Configure the Services in the `Program.cs` file + +In the `AddUHeadless` options add the following code snippet: + +:::note +The `.AddAuth()` call must be the first thing in the options +::: + +```csharp +.AddUHeadless(options => +{ + options.AddAuth(new() + { + ApiKey = builder.Configuration.GetValue("UHeadless:ApiKey") ?? throw new InvalidOperationException("No value for UHeadless:ApiKey was found"), + Secret = builder.Configuration.GetValue("UHeadless:Secret") ?? throw new InvalidOperationException("No value for UHeadless:Secret was found"), + }); + + // Other configuration +}) +``` + +The `ApiKey` can be any value over 32 characters long. This value is used in the `X-UHeadless-Api-Key` header when creating tokens used for quering the GraphQL endpoint. + +The `Secret` can be any value over 64 characters long. This value is used as the signing key when creating the JWT tokens used for quering the GraphQL endpoint. + +:::note +You can provide the `ApiKey` and `Secret` from anywhere this example shows loading them from the `appsettings.json` file. +::: + +Also make sure to add the following code snippet to the request pipeline after the `app.BootUmbracoAsync()` method: + +```csharp +app.UseAuthentication(); +app.UseAuthorization(); +``` + +### Step 2: Create a token for queries to the GraphQL endpoint + +Once the configuration above have been added all the default queries in the package will automatically be protected and require a token to be queried. To create a token run the application, go to `/graphql` and run the following query: + +```graphql +mutation { + createToken(claims: [ + { + name: "headless-scope", + value: "global.content.read" + } + ]) { + expires + header + prefix + token + } +} +``` + +Make sure to include the `X-UHeadless-Api-Key` header with the value of the `ApiKey` you provided in the configuration. This will create a token that can query all content queries. + +![Create token example image](../../../../assets/v5/create-token-example-image.png) + +### Step 3: Use the token to query the GraphQL endpoint + +The `createToken` mutation will return a token in the following format: + +```json +{ + "data": { + "createToken": { + "expires": 1717883090, + "header": "X-UHeadless-Token", + "prefix": "Bearer ", + "token": "" + } + } +} +``` + +To query a query use the token provided along with the prefix in the header `X-UHeadless-Token` like so: + +```graphql +query { + contentByRoute(baseUrl: "", route: "/") { + id + key + name + statusCode + templateId + updateDate + url(urlMode: ABSOLUTE) + urlSegment + } +} +``` + +```text +X-UHeadless-Token: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJoZWFkbGVzcy1zY29wZSI6Imdsb2JhbC5jb250ZW50LnJlYWQiLCJleHAiOjE3MTc3OTIyMTYsImlzcyI6Ik5pa2Npby5VSGVhZGxlc3MiLCJhdWQiOiJOaWtjaW8uVUhlYWRsZXNzIn0.Iwis2EPUjk4uY9_ZyDLYg3NRs2lTh8S-7KEaVCQTFv6nKywMmZRiPMN4Fe2uanq44WqmzWeHRqOWhp5tCGHfKA +``` + +![Use token example image](../../../../assets/v5/use-token-example-image.png) + +Now you have successfully added authentication and authorization to your Nikcio.UHeadless application. + +## Different claims for different queries + +To create a token with different claims for different queries you can use the `createToken` mutation like so: + +```graphql +mutation { + createToken(claims: [ + { + name: "headless-scope", + value: ["global.content.read", "global.media.read"] + } + ]) { + expires + header + prefix + token + } +} +``` + +or + +```graphql +mutation { + createToken(claims: [ + { + name: "headless-scope", + value: "global.content.read" + }, + { + name: "headless-scope", + value: "global.media.read" + } + ]) { + expires + header + prefix + token + } +} +``` + +There exists a few different claims in the default queries for UHeadless. What claims are required for each query can be found in the documentation for the query. + +See [content queries](../querying/content), [media queries](../querying/media) or [member queries](../querying/members) for more information. + +A special case for claim values are for the member picker editor. To access the data of the member picker you will need one of the following claim values: `property.values.member.picker` or `global.member.read`. + +## Adding security to your own queries + +If you have created your own queries you can add security to them by adding the policy configuration in the `ApplyConfiguration` method and adding the `[Authorize]` attribute from `HotChocolate.Authorization` to the query method like so: + +:::caution +It's important to use the `[Authorize]` from `HotChocolate.Authorization` and not the one from `Microsoft.AspNetCore.Authorization` as the one from `HotChocolate.Authorization` is the one that works with HotChocolate and adding the other one will have no effect. +::: + +```csharp +using HotChocolate.Authorization; +using Nikcio.UHeadless; +using Nikcio.UHeadless.Defaults.Authorization; + +public class MyCustomQuery : IGraphQLQuery +{ + public const string PolicyName = "MyCustomQuery"; + + public const string ClaimValue = "my.custom.query"; + + [GraphQLIgnore] + public virtual void ApplyConfiguration(UHeadlessOptions options) + { + ArgumentNullException.ThrowIfNull(options); + + options.UmbracoBuilder.Services.AddAuthorizationBuilder().AddPolicy(PolicyName, policy => + { + policy.AddAuthenticationSchemes(DefaultAuthenticationSchemes.UHeadless); + + policy.RequireAuthenticatedUser(); + + policy.RequireClaim(DefaultClaims.UHeadlessScope, ClaimValue); + }); + } + + [Authorize(Policy = PolicyName)] + [GraphQLDescription("My custom query.")] + public virtual List MyQuery() + { + return ["Hello", "World"]; + } +} +``` + +## Utillty queries + +There is one utility query that can be used to find all default claims are used by the queries you have added to your application. This query is called `utility_GetClaimGroups` and can be used like so: + +:::note +The `utility_GetClaimGroups` query is publicly accessible and should only be used for development purposes. +::: + +```csharp +.AddUHeadless(options => +{ + options.AddQuery(); +}) +``` + +Query: + +```graphql +query { + utility_GetClaimGroups { + groupName + claimValues { + name + values + } + } +} +``` + +Response example: + +```json +{ + "data": { + "utility_GetClaimGroups": [ + { + "groupName": "Members", + "claimValues": [ + { + "name": "headless-scope", + "values": [ + "property.values.member.picker", + "global.member.read", + "find.members.by.display.name.query", + "find.members.by.email.query", + "find.members.by.role.query", + "find.members.by.username.query", + "member.by.email.query", + "member.by.guid.query", + "member.by.id.query", + "member.by.username.query" + ] + } + ] + }, + { + "groupName": "Content", + "claimValues": [ + { + "name": "headless-scope", + "values": [ + "content.by.route.query", + "global.content.read", + "content.by.contentType.query", + "content.at.root.query", + "content.by.id.query", + "content.by.guid.query", + "content.by.tag.query" + ] + } + ] + }, + { + "groupName": "Media", + "claimValues": [ + { + "name": "headless-scope", + "values": [ + "media.by.contentType.query", + "global.media.read", + "media.at.root.query", + "media.by.id.query", + "media.by.guid.query" + ] + } + ] + } + ] + } +} +``` + +## HotChocolate Documentation + +Nikcio.UHeadless leverages the [HotChocolate](https://chillicream.com/docs/hotchocolate) NuGet package, which is a powerful GraphQL server implementation for .NET. HotChocolate provides documentation on various security topics, including how to add authentication and authorization to your GraphQL queries and data. + +For detailed insights into how the implementation works with HotChocolate, refer to the official HotChocolate documentation on security at: + +[HotChocolate Security Documentation](https://chillicream.com/docs/hotchocolate/v13/security) + +This documentation covers different authentication and authorization mechanisms supported by HotChocolate and provides guidelines on securing your GraphQL API effectively. + +## Additional or Alternative Security Measures + +In addition to leveraging built-in security features and following best practices for authentication and authorization, you can implement additional security measures to protect your Nikcio.UHeadless GraphQL data. Here are some suggestions: + +One suggestion is to use a reverse proxy or similar technology to route all traffic to and from the `/graphql` endpoint internally. By configuring the reverse proxy to allow access only from trusted sources, you can ensure that your GraphQL data remains inaccessible to the public. + +Another suggestion is to only route GraphQL traffic server side to your FE application as this will prevent leaking access tokens to the client. \ No newline at end of file diff --git a/docs/src/content/docs/v7/reference/content.md b/docs/src/content/docs/v7/reference/content.md new file mode 100644 index 00000000..a618a44d --- /dev/null +++ b/docs/src/content/docs/v7/reference/content.md @@ -0,0 +1,11 @@ +--- +title: Content bases reference +description: Overview of content bases in Nikcio.UHeadless. +--- + +In Nikcio.UHeadless, content bases provide a way to create custom models that can be used in place of existing models. These bases allow you to define your own content data structure or extend the existing data structure. + +| Class Name | Description | +|-------------------|--------------------------------------------------------------------------------| +| ContentItemBase | The lowest level for a content item. Contains no public properties | +| ContentItem | The default model used for queries. This includes the most common properties | diff --git a/docs/src/content/docs/v7/reference/endpoint-options.md b/docs/src/content/docs/v7/reference/endpoint-options.md new file mode 100644 index 00000000..db37942c --- /dev/null +++ b/docs/src/content/docs/v7/reference/endpoint-options.md @@ -0,0 +1,38 @@ +--- +title: Endpoint Options +description: Overview of the endpoint options in Nikcio.UHeadless. +--- + +The UHeadless endpoint can be customized using the builder returned from the `.MapUHeadless()` method. The builder provides a number of options to configure the endpoint. + +## Disabling the GraphQL IDE in production + +```csharp +GraphQLEndpointConventionBuilder graphQLEndpointBuilder = app.MapUHeadless(); + +// Only enable the GraphQL IDE in development +if (!builder.Environment.IsDevelopment()) +{ + graphQLEndpointBuilder.WithOptions(new GraphQLServerOptions() + { + Tool = + { + Enable = false, + } + }); +} +``` + +## GraphQLServerOptions Properties + +| Property | Description | +|-----------------------------------------|----------------------------------------------------------------------------------------------------| +| Tool | The options for configuring the GraphQL tool (e.g., Banana Cake Pop). | +| Sockets | The options for configuring GraphQL sockets. | +| AllowedGetOperations | Specifies which GraphQL options are allowed on GET requests. | +| EnableGetRequests | Specifies whether GraphQL HTTP GET requests are allowed. | +| EnforceGetRequestsPreflightHeader | Specifies whether to enforce the preflight header for GraphQL HTTP GET requests. | +| EnableMultipartRequests | Specifies whether GraphQL HTTP multipart requests are allowed. | +| EnforceMultipartRequestsPreflightHeader | Specifies whether to enforce the preflight header for GraphQL HTTP multipart requests. | +| EnableSchemaRequests | Specifies whether the GraphQL schema SDL can be downloaded. | +| EnableBatching | Specifies whether request batching is enabled. | \ No newline at end of file diff --git a/docs/src/content/docs/v7/reference/media.md b/docs/src/content/docs/v7/reference/media.md new file mode 100644 index 00000000..c47edd7f --- /dev/null +++ b/docs/src/content/docs/v7/reference/media.md @@ -0,0 +1,11 @@ +--- +title: Media Bases reference +description: Overview of media bases in Nikcio.UHeadless. +--- + +In Nikcio.UHeadless, media bases provide a way to create custom models that can be used in place of existing models. These bases allow you to define your own media data structure or extend the existing data structure. + +| Class Name | Description | +|-------------------|--------------------------------------------------------------------------------| +| MediaItemBase | The lowest level for a media item. Contains no public properties | +| MediaItem | The default model used for queries. This includes the most common properties | diff --git a/docs/src/content/docs/v7/reference/member.md b/docs/src/content/docs/v7/reference/member.md new file mode 100644 index 00000000..6286ae72 --- /dev/null +++ b/docs/src/content/docs/v7/reference/member.md @@ -0,0 +1,11 @@ +--- +title: Member Bases reference +description: Overview of member bases in Nikcio.UHeadless. +--- + +In Nikcio.UHeadless, member bases provide a way to create custom models that can be used in place of existing models. These bases allow you to define your own member data structure or extend the existing data structure. + +| Class Name | Description | +|-------------------|--------------------------------------------------------------------------------| +| MemberBase | The lowest level for a member item. Contains no public properties | +| MemberItem | The default model used for queries. This includes the most common properties | \ No newline at end of file diff --git a/docs/src/content/docs/v7/reference/options.md b/docs/src/content/docs/v7/reference/options.md new file mode 100644 index 00000000..c3da497f --- /dev/null +++ b/docs/src/content/docs/v7/reference/options.md @@ -0,0 +1,27 @@ +--- +title: UHeadless Options +description: Overview of the options in Nikcio.UHeadless. +--- + +The `UHeadlessOptions` class provides configuration options for the UHeadless package. These options can be used to customize various aspects of UHeadless behavior. + +## UHeadlessOptions Properties + +| Property | Description | +|---------------------------|-----------------------------------------------------------------------------------------| +| PropertyMap | Used to register custom models to specific property values. | +| DisableAuthorization | Disables authorization for the GraphQL server. | +| RequestExecutorBuilder | Used to customize the GraphQL server. | + +## Extensions + +| Property | Description | +|------------------------|--------------------------------------------------------------------------------------------| +| AddDefaults | Adds default property mappings and services to be used for the default queries. | +| AddAuth | Adds the authentication services to the UHeadless package. | +| AddQuery | Adds a query to the GraphQL schema | +| AddMutation | Adds a mutation to the GraphQL schema | +| AddEditorMapping | Adds a mapping of a type to a editor alias. | +| AddAliasMapping | Adds a mapping of a type to a content type alias combined with a property type alias. | +| RemoveAliasMapping | Removes a alias mapping | +| RemoveEditorMapping | Removes a editor mapping | \ No newline at end of file diff --git a/docs/src/content/docs/v7/reference/properties.md b/docs/src/content/docs/v7/reference/properties.md new file mode 100644 index 00000000..1943607e --- /dev/null +++ b/docs/src/content/docs/v7/reference/properties.md @@ -0,0 +1,22 @@ +--- +title: Property models reference +description: Overview of property models in Nikcio.UHeadless. +--- + +In Nikcio.UHeadless, property models can be extended and customized adding additional properties and functionality. The default property models provide a solid foundation for building custom property models. By extending these models, you can tailor them to your specific application requirements. + +| Class Name | Description | +|------------------------------------------------|---------------------------------------------------------------------------------------------------| +| PropertyValue | A base for property values. This is the lowest level of any property value. | +| BlockGrid | Represents a block grid property value | +| BlockList | Represents a block list model | +| ContentPicker | Represents a content picker value | +| DateTimePicker | Represents a date time property value | +| DefaultProperty | A catch all property value that simply returns the value of the property. This is all that is needed for simple properties that doesn't need any special handling or formatting. | +| Label | Gets the value of the property | +| MediaPicker | Represents a media picker item | +| MemberPicker | Represents a member picker | +| MultiUrlPicker | Represents a multi url picker | +| NestedContent | Represents nested content | +| RichText | Represents a rich text editor | +| UnsupportedProperty | Represents an unsupported property value | diff --git a/docs/src/content/docs/v7/start.md b/docs/src/content/docs/v7/start.md new file mode 100644 index 00000000..e5ac5129 --- /dev/null +++ b/docs/src/content/docs/v7/start.md @@ -0,0 +1,72 @@ +--- +title: Nikcio.UHeadless Documentation - Version 7.0.0+ +description: Welcome to version 7 of the Nikcio.UHeadless documentation! This documentation aims to provide you with comprehensive resources to help you get started and make the most out of the Nikcio.UHeadless package. +--- + +Welcome to the documentation for Nikcio.UHeadless version 7.0.0! This documentation aims to provide you with comprehensive resources to help you get started and make the most out of the Nikcio.UHeadless package. Whether you're new to the package or looking to extend its functionality, we've got you covered. + +## Fundamentals + +In this section, you will find essential information about Nikcio.UHeadless and its core concepts. It covers topics such as extending Nikcio.UHeadless and important security considerations. + +### Getting Started +- [Getting started](../fundamentals/getting-started): Find step-by-step instructions on how to install Nikcio.UHeadless and get started with querying content, media, and members. + - [Querying content](../fundamentals/querying/content): Explore the query options for content. + - [Querying media](../fundamentals/querying/media): Explore the query options for media. + - [Querying members](../fundamentals/querying/members): Explore the query options for members. + - [Querying properties](../fundamentals/querying/content): Discover how to query properties on content, media and members. +- [Security Considerations](../fundamentals/security): Explore important security considerations when using Nikcio.UHeadless. + +## Extending Nikcio.UHeadless + +This section focuses on extending Nikcio.UHeadless to tailor it to your project's needs. It covers different areas where you can extend Nikcio.UHeadless, including content, media, members, integrations, and properties. + +### Content + +- [Extending Content](../extending/content): Learn how to extend the existing content model and how build your own in Nikcio.UHeadless. + +### Media + +- [Extending Media](../extending/media): Discover how to extend the existing media model and how build your own in Nikcio.UHeadless. + +### Members + +- [Extending Members](../extending/member): Learn how to extend the existing member model and how build your own in Nikcio.UHeadless. + +### Integrations + +- [Skybrud Redirects](../extending/skybrud-redirects): Explore how to integrate Nikcio.UHeadless with [Skybrud Redirects](https://marketplace.umbraco.com/package/skybrud.umbraco.redirects) for enhanced functionality. +- [Url Tracker](../extending/url-tracker): Learn how to integrate Nikcio.UHeadless with [Url Tracker](https://marketplace.umbraco.com/package/urltracker) for enhanced functionality. + +### Performance + +- Persisted queries: Learn how to use persisted queries to improve performance when querying content, media, and members in Nikcio.UHeadless. + - HotChocolate has a great overview of how to integrate persisted queries in their [documentation](https://chillicream.com/docs/hotchocolate/v13/performance/#persisted-queries). Use add any extension methods to the `IRequestExecutorBuilder` in the `Program.cs` file where you configure UHeadless. + +### Properties + +- [Overview of Properties](../extending/properties/overview): Get an overview of the different property types and their usage in Nikcio.UHeadless. +- [Block List](../extending/properties/block-list): Discover how to extend the block list property model in Nikcio.UHeadless. +- [Custom Editor](../extending/properties/custom-editor): Learn how to use custom property editors in Nikcio.UHeadless. +- [Media Picker](../extending/properties/media-picker): Explore how to extend the media picker property model in Nikcio.UHeadless. +- [Rich Text](../extending/properties/rich-text): Learn how to extend the rich text property model in Nikcio.UHeadless. + +## Reference + +In the reference section, you will find detailed information about various aspects of Nikcio.UHeadless, including options, content, media, members, and properties. + +- [Options](../reference/options): Learn about the options available for configuring Nikcio.UHeadless. +- [Endpoint Options](../reference/endpoint-options): Explore the available options for configuring the Nikcio.UHeadless endpoint. + +- [Content Reference](../reference/content): Find reference documentation for working with content in Nikcio.UHeadless. +- [Media Reference](../reference/media): Find reference documentation for working with media in Nikcio.UHeadless. +- [Members Reference](../reference/members): Find reference documentation for working with members in Nikcio.UHeadless. +- [Properties Reference](../reference/properties): Find reference documentation for working with properties in Nikcio.UHeadless. + +We hope this documentation helps you make the most out of Nikcio.UHeadless. If you have any questions or need further assistance, don't hesitate to reach out to us. + +**Enjoy building a headless GraphQL interface with Nikcio.UHeadless!** + +--- + +For those interested in supporting the development of Nikcio.UHeadless, consider becoming a sponsor on [GitHub Sponsors](https://github.com/sponsors/nikcio/). Your sponsorship helps us continue to improve and maintain this package. Thank you for your support! \ No newline at end of file