diff --git a/packages/core/package.json b/packages/core/package.json index d78424d1..5c27bbfc 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -79,6 +79,11 @@ "import": "./dist/globals-injector-standalone/edge/injector.js", "default": "./dist/globals-injector-standalone/edge/injector.cjs" }, + "./injector-standalone/edge-auto": { + "ts-src": "./src/globals-injector/auto-inject.ts", + "import": "./dist/globals-injector-standalone/edge/auto-inject.js", + "default": "./dist/globals-injector-standalone/edge/auto-inject.cjs" + }, "./tsconfigs/*.json": "./tsconfigs/*", "./tsconfigs/*": "./tsconfigs/*.json" }, diff --git a/packages/core/src/config-engine/authoring-utils.ts b/packages/core/src/config-engine/authoring-utils.ts index 2775342b..9e9f0f28 100644 --- a/packages/core/src/config-engine/authoring-utils.ts +++ b/packages/core/src/config-engine/authoring-utils.ts @@ -7,31 +7,54 @@ import { DmnoDataTypeMetadata } from './configraph-adapter'; // export function pickFromSchemaObject>(schemaObj: S, keys: Array); // export function pickFromSchemaObject>(schemaObj: S, ...keys: Array); -export function pickFromSchemaObject>( +export function pickFromSchemaObject< + S extends Record>, +>( schemaObj: S, - firstKeyOrKeyArray: keyof S | Array, + pickSettings: ( + keyof S | + Array | + Partial>> + ), ...keysRest: Array -) { - const keyArray = _.isArray(firstKeyOrKeyArray) ? firstKeyOrKeyArray : [firstKeyOrKeyArray, ...keysRest]; - return Object.fromEntries(keyArray.map((k) => [k, schemaObj[k]])); +): Partial>> { + if (_.isArray(pickSettings) || _.isString(pickSettings)) { + const keyArray = _.isArray(pickSettings) + ? pickSettings + : [pickSettings, ...keysRest]; + return _.pick(schemaObj, keyArray); + } else if (_.isObject(pickSettings)) { + return _.mapValues(pickSettings, (itemOverrides, key) => { + return { + ...schemaObj[key], + ...itemOverrides, + }; + }); + } else { + throw new Error('Invalid pick from schema'); + } } -export function createVendorSchema( - schema: Record>, +export function createVendorSchema< + S extends Record>, +>( + schema: S, commonTraits?: Partial>, -) { - if (!commonTraits) return schema; +): Record< keyof S, ConfigraphDataTypeDefinition> { return _.mapValues(schema, (item, _itemKey) => { if (item instanceof ConfigraphDataType || _.isString(item) || _.isFunction(item)) { return { extends: item, ...commonTraits, }; + } else { + return { + // TODO: not sure why I need this any :( + ...item as any, + ...commonTraits, + }; } - return { - ...item, - ...commonTraits, - }; + // throw Error('invalid vendor schema'); }); } diff --git a/packages/core/src/config-loader/vite-server.ts b/packages/core/src/config-loader/vite-server.ts index 7c4dd9bd..3e53d7cd 100644 --- a/packages/core/src/config-loader/vite-server.ts +++ b/packages/core/src/config-loader/vite-server.ts @@ -34,6 +34,8 @@ export async function setupViteServer(opts: { }, transform(code, id, options) { + // TODO: need to detect file types more broadly and can do better detection of if we need to inject at all + if (id.endsWith('.json')) return; // fairly naive way of doing this... but for now we are replacing `DMNO_CONFIG.SOME_KEY` with `getResolverCtx().get('SOME_KEY')` // TODO: we probably should limit which files this applies in const fixedCode = new MagicString(code); diff --git a/packages/core/src/globals-injector/auto-inject.ts b/packages/core/src/globals-injector/auto-inject.ts index 90f48114..a0ded22e 100644 --- a/packages/core/src/globals-injector/auto-inject.ts +++ b/packages/core/src/globals-injector/auto-inject.ts @@ -3,7 +3,13 @@ import { injectDmnoGlobals as _injectDmnoGlobals } from './injector'; -_injectDmnoGlobals(); +let defineInjectedConfig; +try { + // @ts-ignore + defineInjectedConfig = __DMNO_INJECTED_CONFIG__; +} catch (err) {} +if (defineInjectedConfig) _injectDmnoGlobals({ injectedConfig: defineInjectedConfig }); +else _injectDmnoGlobals(); export const injectDmnoGlobals = _injectDmnoGlobals; diff --git a/packages/core/tsup.inject-standalone.config.ts b/packages/core/tsup.inject-standalone.config.ts index 92011ca2..c7307348 100644 --- a/packages/core/tsup.inject-standalone.config.ts +++ b/packages/core/tsup.inject-standalone.config.ts @@ -28,6 +28,7 @@ const outDir = `dist/globals-injector-standalone${process.env.DMNO_EDGE_COMPAT ? export default defineConfig({ entry: [ // Entry point(s) 'src/globals-injector/injector.ts', // function used to inject dmno globals + 'src/globals-injector/auto-inject.ts', // exports inject function and automatically calls it once ], esbuildPlugins: [ diff --git a/packages/docs-site/astro.config.ts b/packages/docs-site/astro.config.ts index 87e9a88e..cea40c88 100644 --- a/packages/docs-site/astro.config.ts +++ b/packages/docs-site/astro.config.ts @@ -206,6 +206,10 @@ export default defineConfig({ label: 'Overview', link: '/docs/platforms/overview/', }, + { + label: 'Cloudflare', + link: '/docs/platforms/cloudflare/', + }, { label: 'Netlify', link: '/docs/platforms/netlify/', diff --git a/packages/docs-site/src/content/docs/docs/guides/typescript.mdx b/packages/docs-site/src/content/docs/docs/guides/typescript.mdx index 0a57c9de..2bb228a6 100644 --- a/packages/docs-site/src/content/docs/docs/guides/typescript.mdx +++ b/packages/docs-site/src/content/docs/docs/guides/typescript.mdx @@ -82,12 +82,17 @@ Even if you are not writing TypeScript, these days you are still likely relying // ... "include": [ "**/*.js", -+ ".dmno/.typegen/global.d.ts" ++ ".dmno/.typegen/global.d.ts", + ".dmno/.typegen/global-public.d.ts" ] } ``` +:::note[Invalid keys are not strict] +JavaScript is by default not strict - so while you will get nice autocompletion and IntelliSense on your config, your IDE will not give you the handy red squiggle if you use an _invalid_ key. Depending on your setup you may still get a build/runtime error. +::: + + #### Injecting `DMNO_CONFIG` vs `DMNO_PUBLIC_CONFIG` diff --git a/packages/docs-site/src/content/docs/docs/platforms/cloudflare.mdx b/packages/docs-site/src/content/docs/docs/platforms/cloudflare.mdx new file mode 100644 index 00000000..d39141ed --- /dev/null +++ b/packages/docs-site/src/content/docs/docs/platforms/cloudflare.mdx @@ -0,0 +1,284 @@ +--- +title: Using DMNO with Cloudflare +description: Use DMNO while deploying on Cloudflare Workers and Pages +npmPackage: "@dmno/cloudflare-platform" +--- + +import CloudflareLogo from "~icons/logos/cloudflare"; + +import TabbedCode from '@/components/TabbedCode.astro'; +import BugReportLink from '@/components/BugReportLink.astro'; + +At DMNO we _love_ [Cloudflare](https://cloudflare.com/). This very site is hosted on it! That's why we're very excited to make it easier and safer to use environment variables in all of your Cloudflare projects. + +This platform integration exposes a pre-made config schema and underlying types to interact with the env vars that Cloudflare injects while on their platform. + +It also exposes a Netlify build plugin - which injects your resolved DMNO config into functions and edge functions. You may not need to use this plugin if you already have a build process that injects config values into your functions code before deployment. + +Aside from all the usual benefits of DMNO - validations, type-safety, pull secrets from backends like 1Password, share config across a monorepo, our Cloudflare integration has a few extra tricks up it's sleeve: +- configure `wrangler` using DMNO, injecting +- inject config into Cloudflare Workers - both during local dev and deployment +- handle static and dynamic config properly +- add full type-safety to your config, without needing to run `wrangler types` + + + +## Setup + + + +:::note +If you run into any issues, feel free to report them to us on GitHub and try the manual installation steps below. +::: + + +## Configuring `wrangler` using DMNO +Many facets of the `wrangler` cli, including authentication, can be set using environment variables. By default, if you have a `.env` file in your repo, `wrangler` will automatically use it, but of course this suffers from all the same usual headaches of using a `.env` file. Instead, DMNO provides a platform schema and associated types so you can inject settings into `wrangler` without resorting to a gitignored `.env` file. This means for example we could pull our sensitive Cloudflare API keys from 1password or an encrypted vault, share values across a monorepo, or compose our config however we see fit. + +Because `wrangler` is configured using a mix of `wrangler.toml` and CLI flags and has no concept of plugins, we provide a small wrapper CLI, called `dwrangler`, that handles everything for you. + +For example, if we wanted to pull our Cloudflare credentials from 1password, and set a few more settings, our config might look like this: + +```ts title=".dmno/config.mts" +import { DmnoWranglerEnvSchema } from '@dmno/cloudflare-platform'; +import { + DmnoBaseTypes, defineDmnoService, pickFromSchemaObject, switchBy, +} from 'dmno'; + +const opSecrets = new OnePasswordDmnoPlugin('1pass', { + fallbackToCliBasedAuth: true, +}); + +export default defineDmnoService({ + schema: { + // configure wrangler + ...pickFromSchemaObject(DmnoWranglerEnvSchema, { + CLOUDFLARE_ACCOUNT_ID: { + value: opSecrets.itemByReference('op://Shared/Cloudflare/account id'), + }, + CLOUDFLARE_API_TOKEN: { + value: opSecrets.itemByReference('op://Shared/Cloudflare/workers api token'), + }, + WRANGLER_ENV: {}, // passed as --env + WRANGLER_DEV_PORT: { value: 8881 }, // passed as --port + WRANGLER_DEV_IP: { value: 'custom.host.local' }, // passed as --ip + WRANGLER_DEV_URL: {}, // full constructed dev URL + WRANGLER_LIVE_RELOAD: { value: true }, // passed as `--live-reload` + DWRANGLER_INJECT_MODE: { value: 'define' }, // how to inject secrets, more on that below + }), + + // ... your app config + SOME_VAR: { + value: switchBy('WRANGLER_ENV', { // use an env flag to toggle other config + _default: 'dev value', + production: 'prod value', + }), + }, + }, +}); +``` + +To take advantage of this new config, we swap usage of `wrangler` to `dwrangler`, whether directly or in our `package.json` file. + +```diff lang="json" title="package.json" ins=/(d)wrangler/ +{ + "scripts": { + "dev": "dwrangler dev", + "deploy": "dwrangler deploy" + } +} +``` + +:::note[Don't worry, `dwrangler` is a simple wrapper] +It's mostly a simple wrapper script that puts config into env vars, flags, and handles smart reloading in dev mode. +::: + + +## Cloudflare Workers + +DMNO makes dealing with config and secrets in Cloudflare workers much simpler. Define your dmno config, and we take care of the rest. + + +Dealing with [config in Cloudflare Workers](https://developers.cloudflare.com/workers/configuration/environment-variables/) is a bit different than other Node.js projects. Instead of relying on a global `process.env`, config is passed in as "bindings" to route handlers. These values can be either "vars" (not-sensitive, plaintext) or "secrets" (sensitive, encrypted), and can be set in a variety of ways for local development and for deployments. + +- Wrangler's `--var` cli option - sets vars during local dev, also sets non-sensitive vars during `wrangler deploy` +- `wrangler.toml` in a `[vars]` section - sets non-senstive vars, can also be varied per environment (e.g., `[staging.vars]`) +- `.dev.vars` file - sensitive secrets during local development +- additionally, `wrangler` has commands to set secrets - `wrangler secret`, `wrangler versions secret` + +Additionally, if not relying on a custom build, `wrangler` internally uses esbuild, and you can do build-time replacements, which can also be used for config purposes: + +- `wrangler.toml` in a `[define]` section - static vars, can also be varied per environment (e.g., `[staging.define]`) +- Wrangler's `--define` cli option - does static replacements during the build, both locally and during deploys + + + + +DMNO gives you a unified way to access your configuration, whether you want it to be _static_ vs _dynamic_. You can read more about it in the [dynamic config guide](/docs/guides/dynamic-config/). + +Static config items are always replaced during the build process. That means these items can be accessed anywhere, not just in a request handler. + + +"define" mode +- static config items are replaced at build time +- your entire resolved config in injected at build time via `--define` +- + + +### Injection via "inline" mode + +While it is not very _Cloudflare-y_, our preferred way to inject DMNO config is by inlining the entire resolved config during the build/deploy process. While it may feel a little odd, config changes always trigger a new deployment anyway, and your bundled code is not accessible to anyone. + +Doing it this way has a few important benefits: +- we now have the full validated, coerced config, with additional metadata, and it is directly a part of a specific version of your code +- all config can now be accessed _everywhere_, just like `process.env`, not just within request handlers +- we can enable DMNO's [security features](http://localhost:4321/docs/get-started/security/) to prevent secrets from leaking over http responses, requests to other servers, and redact secrets from logs + + +The one drawback is that existing uses of `env.SOME_SECRET` will no longer work - you must use `DMNO_CONFIG.SOME_SECRET` instead. + +We must import the dmno globals injector. This version is specifically made to be compatible with Cloudflare's edge runtime, and will look for data injected by `dwrangler` at build time. + +```diff lang="js" title="your-worker.js" ++import 'dmno/injector-standalone/edge-auto'; + +console.log(DMNO_CONFIG.SOME_ITEM); // all config is available everywhere! + +export default { + async fetch(request, env, ctx) { + return new Response(`API host: ${DMNO_CONFIG.API_HOST}`); + }, +}; +``` + + +### Injection via "secrets" mode + +If you want to continue to use Cloudflare's built-in secrets functionality, you can instead use the "secrets" injection mode. In this mode, while static config items will still be replaced at build time, dynamic config items will be set as [Cloudflare secrets](https://developers.cloudflare.com/workers/configuration/secrets/#secrets-on-deployed-workers) and you will continue to read them from the `env` binding injected into your route handlers. + +To enable this mode, you must set the `DWRANGLER_INJECT_MODE` in your config to `secrets`: +```diff lang="ts" title=".dmno/config.mts" +export default defineDmnoService({ + schema: { + ...pickFromSchemaObject(DmnoWranglerEnvSchema, { ++ DWRANGLER_INJECT_MODE: { value: 'secrets' }, + }), + }, +}); +``` + +**Pros:** +- secrets are no longer bundled into your code +- existing calls to `env.SOME_KEY` will continue to work + +**Cons:** +- we cannot activate DMNO's security features - sensitive secrets can appear in logs, and easily be leaked +- you (still) cannot access config outside of route handlers + +To make things a bit more convenient, we do replace references to `DMNO_CONFIG.SOME_VAR` to `env.SOME_VAR`, which means you get automatic type-safety and intellisense, and you never have to think about whether a config item is static or dynamic. + +:::caution[You must use the `env` convention] +This replacement means that to use `DMNO_CONFIG` and take advantage of the type safety it provides, you must stick with the convention of naming the bindings argument of your route handlers `env`, and if you pass it around to other functions, you should also stick with the name. + +```js title="my-worker.js" /env/ +export default { + async fetch(request, env, ctx) { + someHelper(env); + return new Response(`API host: ${DMNO_CONFIG.API_HOST}`); + }, +}; + +function someHelper(env) { + return DMNO_CONFIG.ANOTHER_ITEM; +} +``` +::: + + + + +While it should all feel pretty seamless, internally, we hijack `dwrangler deploy` and instead do a 3-part deployment +- build and upload a new versioned deploy, without activating it +- upload resolved config as encrypted secrets, creating another version with secrets attached +- activate the new version + + + +- static config items are replaced at build time +- your entire resolved config in injected at build time via `--define` +- + + + +### Which mode should you use? + +We think for most users the "inline" mode is the better choice, but both options are totally sensible. Here is a comparison table to help: + +| Inline mode | Secrets mode | +|---|---| +| 👍 Static config injected at build time, accessible anywhere | < same | +| ✨ Dynamic config acessible outside route handlers! | 😪 Dynamic config only accessible within route handlers
must use `env` naming convention | +| 🔐 Log redaction, leak detection! | 😢 No DMNO security features | +| 🛠️ Additional installation code | 🛠️ More complex deployment | + + +### Using `dwrangler` with the Workers Builds git integration +Cloudflare's new [Workers Builds (beta)](https://developers.cloudflare.com/workers/ci-cd/builds/) allows you to connect your worker to a git repo, and it will run the CI process within Cloudflare, similar to how it works for Pages. + +While this is great, it's not much different than running your CI anywhere else, and the same issues of dealing with getting config into your running worker are present. + +To use `dmno` within Workers Builds, just swap your deploy command from `wrangler` to `dwrangler`, just like if you were running it anywhere else. There is also a section for setting "Build variables and secrets" where you can populate any additional config needed during the build. If you are using DMNO to fetch sensitive config from somehwere else, this is how you would pass in that _secret-zero_, for example, a service account token for 1password. + +:::caution[No preview deployments] +At this time, Workers Builds has no notion of deploy previews for PRs or branches. Your only option is to create another worker and point the build settings at a specific branch. +::: + + +## Cloudflare Pages + +Cloudflare pages allows you to host static sites and provides a little sugar on top of Cloudflare Workers for attached functions. Unfortunately, Wrangler's Pages functionality does not allow the same level of configuration of the underlying ESBuild process. However it may not matter, because in practice, most users are likely using an existing framework and have their own build process already. In this case, you can rely on our [drop-in integrations](/docs/integrations/overview/) to inject your DMNO config. + +:::tip[Just use workers!] +Workers support hosting [static assets](https://developers.cloudflare.com/workers/static-assets/) too and it seems that the Cloudflare team is working to make workers do everything that Pages can. Our hunch is that Pages will eventually be deprecated, and moving over to Workers will be a smart bet. +::: + +Regardless, you could still use DMNO to resolve your config and upload secrets to Cloudflare, but without a custom build, you would have to rely on `env` rather than `DMNO_CONFIG`, and you would not get all the benefits of DMNO. + +Please reach out if you need help setting things up, or have a use case that is not supported. + + +### Cloudflare Pages env vars + +The Cloudflare Pages environment injects a few [environment variables](https://docs.netlify.com/configure-builds/environment-variables/#read-only-variables) into its _build environment_ that provide information about the current build. This module exposes a pre-made config schema object which you can use in your own schema. You can use the `pickFromSchemaObject` utility to pick only the env var keys that you need from the full list. For example: + +```ts title='.dmno/config.mts' +import { defineDmnoService, switchBy, pickFromSchemaObject } from 'dmno'; +import { CloudflarePagesEnvSchema } from '@dmno/cloudflare-platform'; + +export default defineDmnoService({ + schema: { + ...pickFromSchemaObject(CloudflarePagesEnvSchema, 'CONTEXT', 'BUILD_ID'), + APP_ENV: { + value: switchBy('CONTEXT', { + _default: 'local', + 'deploy-preview': 'staging', + 'branch-deploy': 'staging', + production: 'production', + }), + }, + }, +}); +``` + + +## Other workflows +If you have a totally custom setup, that does not fit with the above workflows, you can still use `dwrangler` to manage Cloudflare auth, and push resolved config to Cloudflare however you want. + +Note that `wrangler` has several bulk secret related methods, and they all take JSON from stdin. + +- [`wrangler secret:bulk`](https://developers.cloudflare.com/workers/wrangler/commands/#secretbulk) +- [`wrangler versions secret bulk`](https://developers.cloudflare.com/workers/wrangler/commands/#secret-bulk-1) +- [`wrangler pages secret bulk`](https://developers.cloudflare.com/workers/wrangler/commands/#secret-bulk) + +For example: `dwrangler secrets:bulk < dmno resolve --format json --keys="KEY1,KEY2,KEY3"` + diff --git a/packages/docs-site/src/content/docs/docs/platforms/overview.mdx b/packages/docs-site/src/content/docs/docs/platforms/overview.mdx index acffa5a0..00a7c5df 100644 --- a/packages/docs-site/src/content/docs/docs/platforms/overview.mdx +++ b/packages/docs-site/src/content/docs/docs/platforms/overview.mdx @@ -10,6 +10,16 @@ In many cases, you may not need to do anything special, but our platform-specifi ![Platform config schema example](../../../../assets/docs-images/platform-intellisense-example.png) +### [Cloudflare](/docs/platforms/cloudflare/) + +Package: `@dmno/cloudflare-platform` + +Includes: +- Cloudflare-specific data types +- Config schema of env vars injected by the Cloudflare platform +- `dwrangler` cli - wrapper around `wrangler` to inject DMNO config + + ### [Netlify](/docs/platforms/netlify/) Package: `@dmno/netlify-platform` @@ -27,13 +37,11 @@ Includes: - Config schema of env vars injected by the Vercel platform - Vercel-specific data types - ### Next up We're already working on more platform integrations, but we'd love to hear from you which platforms to tackle next! On the roadmap: -- Cloudflare - Fly.io - Heroku - Render.com diff --git a/packages/integrations/astro/src/index.ts b/packages/integrations/astro/src/index.ts index 2c71e568..ba9c3768 100644 --- a/packages/integrations/astro/src/index.ts +++ b/packages/integrations/astro/src/index.ts @@ -270,6 +270,7 @@ function dmnoAstroIntegration(dmnoIntegrationOpts?: DmnoAstroIntegrationOptions) ssrInjectConfigAtBuildTime = [ '@astrojs/netlify', '@astrojs/vercel/serverless', + '@astrojs/cloudflare', ].includes(opts.config.adapter?.name || ''); }, diff --git a/packages/integrations/nextjs/src/index.ts b/packages/integrations/nextjs/src/index.ts index 54530d8f..1516d299 100644 --- a/packages/integrations/nextjs/src/index.ts +++ b/packages/integrations/nextjs/src/index.ts @@ -63,7 +63,9 @@ export function dmnoNextConfigPlugin(dmnoOptions?: DmnoPluginOptions) { (process.env.__VERCEL_BUILD_RUNNING || process.env.VERCEL) // build running via `vercel` cli or on vercel || process.env.NETLIFY // build running remotely on netlify || (process.env.NETLIFY_LOCAL && !process.env.NETLIFY_DEV) // build running locally via `netlify` cli + || process.env.CF_PAGES // maybe add additional check for /functions folder? || dmnoOptions?.injectResolvedConfigAtBuildTime // explicit opt-in + ); // nextjs doesnt have a proper plugin system, so we write a function which takes in a config object and returns an augmented one diff --git a/packages/integrations/remix/src/index.ts b/packages/integrations/remix/src/index.ts index 32c5ace4..11b71a54 100644 --- a/packages/integrations/remix/src/index.ts +++ b/packages/integrations/remix/src/index.ts @@ -63,7 +63,9 @@ export function dmnoRemixVitePlugin(dmnoOptions?: DmnoPluginOptions) { process.env.__VERCEL_BUILD_RUNNING // build running via `vercel` cli || process.env.NETLIFY // build running remotely on netlify || (process.env.NETLIFY_LOCAL && !process.env.NETLIFY_DEV) // build running locally via `netlify` cli + || process.env.CF_PAGES // maybe add additional check for /functions folder? || dmnoOptions?.injectResolvedConfigAtBuildTime // explicit opt-in + ); return { diff --git a/packages/platforms/cloudflare/.eslintrc.cjs b/packages/platforms/cloudflare/.eslintrc.cjs new file mode 100644 index 00000000..8f2a36a2 --- /dev/null +++ b/packages/platforms/cloudflare/.eslintrc.cjs @@ -0,0 +1,6 @@ +module.exports = { + extends: ["@dmno/eslint-config/base"], + ignorePatterns: ["tsup.config.ts"], + rules: { + }, +}; diff --git a/packages/platforms/cloudflare/README.md b/packages/platforms/cloudflare/README.md new file mode 100644 index 00000000..6a12fd59 --- /dev/null +++ b/packages/platforms/cloudflare/README.md @@ -0,0 +1,9 @@ +Check out the [docs](https://dmno.dev/docs/platforms/cloudflare/) for more information on how to use [DMNO](https://dmno.dev) with [Cloudflare](https://cloudflare.com/). + +*** THIS IS PREVIEW SOFTWARE AND SUBJECT TO RAPID CHANGE *** + +If you have any questions, please reach out to us on [Discord](https://chat.dmno.dev). + +---- + +# @dmno/cloudflare-platform [![npm](https://img.shields.io/npm/v/@dmno/cloudflare-platform)](https://www.npmjs.com/package/@dmno/cloudflare-platform) diff --git a/packages/platforms/cloudflare/package.json b/packages/platforms/cloudflare/package.json new file mode 100644 index 00000000..1e13bae0 --- /dev/null +++ b/packages/platforms/cloudflare/package.json @@ -0,0 +1,70 @@ +{ + "name": "@dmno/cloudflare-platform", + "version": "0.0.0", + "description": "tools and types to use dmno with cloudflare", + "author": "dmno-dev", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/dmno-dev/dmno.git", + "directory": "packages/platforms/cloudflare" + }, + "bugs": "https://github.com/dmno-dev/dmno/issues", + "homepage": "https://dmno.dev/docs/platforms/cloudflare", + "keywords": [ + "dmno", + "cloudflare", + "config", + "env vars", + "environment variables", + "secrets", + "dmno-plugin" + ], + "type": "module", + "exports": { + ".": { + "ts-src": "./src/index.js", + "default": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "bin": { + "dwrangler": "./dist/dwrangler.js" + }, + "files": [ + "/dist" + ], + "scripts": { + "build": "tsup", + "build:ifnodist": "[ -d \"./dist\" ] && echo 'dist exists' || pnpm build", + "build:tarball": "turbo build && pnpm pack --pack-destination \"../../../../tmp-package-registry\"", + "dev": "pnpm run build --watch", + "lint": "eslint src --ext .ts,.cjs,.mjs", + "lint:fix": "pnpm run lint --fix" + }, + "devDependencies": { + "@dmno/eslint-config": "workspace:*", + "@dmno/tsconfig": "workspace:*", + "@types/debug": "catalog:", + "@types/lodash-es": "catalog:", + "@types/node": "catalog:", + "dmno": "workspace:*", + "tsup": "catalog:", + "typescript": "catalog:" + }, + "dependencies": { + "debug": "catalog:", + "execa": "^9.5.1", + "lodash-es": "catalog:", + "nano-spawn": "^0.2.0" + }, + "peerDependencies": { + "dmno": "^0", + "wrangler": "^3" + }, + "peerDependenciesMeta": { + "wrangler": { + "optional": true + } + } +} diff --git a/packages/platforms/cloudflare/src/data-types.ts b/packages/platforms/cloudflare/src/data-types.ts new file mode 100644 index 00000000..44142a28 --- /dev/null +++ b/packages/platforms/cloudflare/src/data-types.ts @@ -0,0 +1,180 @@ +import { DmnoBaseTypes, createDmnoDataType, createVendorSchema } from 'dmno'; +import { GitDataTypes } from 'dmno/vendor-types'; + +function getCommonPagesTypeInfo(skipIcon = false) { + return { + externalDocs: { + url: 'https://developers.cloudflare.com/pages/configuration/build-configuration/#environment-variables', + description: 'Cloudflare Pages docs - env vars', + }, + ...!skipIcon && { + ui: { + icon: 'simple-icons:cloudflarepages', + color: 'F38020', // cloudflare brand + }, + }, + }; +} + +export const CloudflarePagesEnvSchema = createVendorSchema({ + CF_PAGES: { + extends: DmnoBaseTypes.boolean(), + typeDescription: 'Flag to detect the build is running on Cloudflare Pages rather than locally', + ...getCommonPagesTypeInfo(), + }, + CF_PAGES_BRANCH: { + extends: GitDataTypes.BranchName, + description: 'unique ID for the Cloudflare Pages commit', + ...getCommonPagesTypeInfo(), + }, + CF_PAGES_COMMIT_SHA: { + extends: GitDataTypes.CommitSha, + description: 'sha hash of the current Cloudflare Pages commit', + ...getCommonPagesTypeInfo(), + }, + CF_PAGES_URL: { + extends: 'url', + description: 'URL of the current Cloudflare Pages site', + ...getCommonPagesTypeInfo(), + }, +}, { fromVendor: 'cloudflare-pages' }); + +function getCommonWranglerTypeInfo(skipIcon = false) { + return { + externalDocs: { + url: 'https://developers.cloudflare.com/workers/wrangler/system-environment-variables/', + description: 'Cloudflare Wrangler env var docs', + }, + ...!skipIcon && { + ui: { + icon: 'simple-icons:cloudflare', + color: 'F38020', // cloudflare brand + }, + }, + }; +} + +export const CloudflareWranglerDataTypes = { + AccountId: createDmnoDataType({ + extends: DmnoBaseTypes.string(), + typeLabel: 'cloudflare-wrangler/account-id', + typeDescription: 'The account ID for the Workers related account.', + ...getCommonWranglerTypeInfo(), + }), + ApiToken: createDmnoDataType({ + extends: DmnoBaseTypes.string(), + typeLabel: 'cloudflare-wrangler/api-token', + typeDescription: 'The API token for your Cloudflare account, can be used for authentication for situations like CI/CD, and other automation.', + sensitive: true, + ...getCommonWranglerTypeInfo(), + }), + ApiKey: createDmnoDataType({ + extends: DmnoBaseTypes.string(), + typeLabel: 'cloudflare-wrangler/api-key', + typeDescription: 'The API key for your Cloudflare account, usually used for older authentication method with `CLOUDFLARE_EMAIL`.', + sensitive: true, + ...getCommonWranglerTypeInfo(), + }), + HyperDriveLocalConnectionString: createDmnoDataType({ + extends: DmnoBaseTypes.string(), + typeLabel: 'cloudflare-wrangler/hyperdrive-local-connection-string', + typeDescription: 'The local connection string for your database to use in local development with Hyperdrive. For example, if the binding for your Hyperdrive is named PROD_DB, this would be WRANGLER_HYPERDRIVE_LOCAL_CONNECTION_STRING_PROD_DB="postgres://user:password@127.0.0.1:5432/testdb". Each Hyperdrive is uniquely distinguished by the binding name.', + exampleValue: 'postgres://user:password@127.0.0.1:5432/testdb', + sensitive: true, + ...getCommonWranglerTypeInfo(), + }), +}; + +export const CloudflareWranglerEnvSchema = createVendorSchema({ + CLOUDFLARE_ACCOUNT_ID: CloudflareWranglerDataTypes.AccountId, + CLOUDFLARE_API_TOKEN: CloudflareWranglerDataTypes.ApiToken, + CLOUDFLARE_API_KEY: CloudflareWranglerDataTypes.ApiKey, + CLOUDFLARE_EMAIL: { + extends: DmnoBaseTypes.email(), + description: 'The email address associated with your Cloudflare account, usually used for older authentication method with `CLOUDFLARE_API_KEY`.', + ...getCommonWranglerTypeInfo(), + }, + CLOUDFLARE_SEND_METRICS: { + // CF says this is a string, but it's actually a boolean + extends: DmnoBaseTypes.boolean(), + description: 'Whether to send anonymous usage metrics to Cloudflare.', + ...getCommonWranglerTypeInfo(), + }, + CLOUDFLARE_API_BASE_URL: { + extends: DmnoBaseTypes.url(), + description: 'The base URL for the Cloudflare API.', + exampleValue: 'https://api.cloudflare.com/client/v4', + ...getCommonWranglerTypeInfo(), + }, + WRANGLER_LOG: { + // TODO: this should be a reusable type! + extends: DmnoBaseTypes.enum(['none', 'error', 'warn', 'info', 'log', 'debug']), + coerce: (val) => val.toString().toLowerCase(), + typeDescription: 'controls what level of logs should be shown', + description: 'If an invalid level is specified, Wrangler will fallback to the default (log)', + ...getCommonWranglerTypeInfo(), + }, + FORCE_COLOR: { + extends: DmnoBaseTypes.enum([0, 1]), + description: 'By setting this to 0, you can disable Wrangler\'s colorised output, which makes it easier to read with some terminal setups', + ...getCommonWranglerTypeInfo(), + }, +}, { fromVendor: 'cloudflare-wrangler' }); + + +/** + * These settings are related to `dwrangler`, the DMNO wrangler wrapper + */ +export const DmnoWranglerEnvSchema = createVendorSchema({ + WRANGLER_ENV: { + description: 'sets value of wrangler --env flag', + // can do something special here, where dwrangler will populate it for us + }, + WRANGLER_DEV_IP: { + description: 'IP/host for wrangler dev to listen on (defaults to localhost)', + extends: 'string', // TODO: add a proper host type + value: 'localhost', + }, + WRANGLER_DEV_PORT: { + description: 'Port for wrangler dev to listen on (defaults to 8787)', + extends: DmnoBaseTypes.port(), + value: 8787, + }, + WRANGLER_DEV_PROTOCOL: { + description: 'Protocol to listen to requests on (defaults to http)', + extends: DmnoBaseTypes.enum(['http', 'https']), + value: 'http', + }, + WRANGLER_DEV_URL: { + description: 'Full url of local wrangler dev server', + extends: 'url', + // TODO: this would be a good one to mark as NOT overrideable? (flag does not exist yet) + // override: false, + value: (ctx) => { + return [ + ctx.get('WRANGLER_DEV_PROTOCOL', { allowMissing: true }) || 'http', + '://', + ctx.get('WRANGLER_DEV_IP', { allowMissing: true }) || 'localhost', + ':', + ctx.get('WRANGLER_DEV_PORT', { allowMissing: true }) || 8787, + ].join(''); + }, + }, + WRANGLER_LIVE_RELOAD: { + extends: DmnoBaseTypes.boolean, + description: 'enable wrangler live-reload without needing to pass in a --live-reload flag', + }, + + DWRANGLER_INJECT_MODE: { + extends: DmnoBaseTypes.enum({ + define: { description: 'inlines entire resolved config into built files' }, + vars: { description: 'sets config as secrets on Cloudflare' }, + }), + value: 'define', + description: 'Controls how _dynamic_ config values are injected into your cloudflare workers', + externalDocs: { + description: 'DMNO docs - Wrangler platform plugin', + url: 'https://dmno.dev/docs/platforms/cloudflare/', // TODO: add link to specific section? + }, + }, +}); diff --git a/packages/platforms/cloudflare/src/dwrangler.ts b/packages/platforms/cloudflare/src/dwrangler.ts new file mode 100644 index 00000000..833bbd8a --- /dev/null +++ b/packages/platforms/cloudflare/src/dwrangler.ts @@ -0,0 +1,332 @@ +/** + * small wrapper around the wrangler cli to help inject DMNO config + * ideally we could inject using other methods, + * - we dont want to write resolved config to local temp files + * - using xargs in complex scenarios proved very awkward + * - making users change their scripts to long complicated things isn't great + */ + +import { + ChildProcess, spawn, +} from 'node:child_process'; +import { execa } from 'execa'; +import { checkServiceIsValid, DmnoServer, InjectedDmnoEnv } from 'dmno'; +import Debug from 'debug'; +import { CloudflareWranglerEnvSchema, DmnoWranglerEnvSchema } from './data-types'; + +const debug = Debug('dmno:dwrangler'); + +const args = process.argv.slice(2); +let wranglerCommand = args[0]; +if (['versions', 'pages'].includes(wranglerCommand)) wranglerCommand += ` ${args[1]}`; + +// TODO: more bulletproof way of finding this +const wranglerBinPath = './node_modules/.bin/wrangler'; + +const isDevMode = wranglerCommand === 'dev' || wranglerCommand === 'pages dev'; +let injectedDmnoEnv: InjectedDmnoEnv; +let injectedValues = {} as Record; +let injectedDynamicValues = {} as Record; +let dmnoHasTriggeredReload = false; +let dmnoConfigValid = true; +let wranglerSystemEnv: Record = {}; +let dmnoWranglerSettings: Record = {}; +const staticReplacements = { + dmnoConfig: {} as Record, + dmnoPublicConfig: {} as Record, +}; + +const wranglerSystemEnvKeys = Object.keys(CloudflareWranglerEnvSchema); +const dmnoWranglerEnvKeys = Object.keys(DmnoWranglerEnvSchema); + +const dmnoServer = new DmnoServer({ watch: isDevMode }); + +async function reloadDmnoConfig() { + const resolvedService = await dmnoServer.getCurrentPackageConfig(); + injectedDmnoEnv = resolvedService.injectedEnv; + dmnoConfigValid = resolvedService.serviceDetails.isValid; + + // shows nicely formatted errors in the terminal + checkServiceIsValid(resolvedService.serviceDetails); + + staticReplacements.dmnoConfig = {}; + staticReplacements.dmnoPublicConfig = {}; + + wranglerSystemEnv = {}; + dmnoWranglerSettings = {}; + injectedValues = {}; + injectedDynamicValues = {}; + + for (const itemKey in injectedDmnoEnv) { + if (itemKey.startsWith('$')) continue; + + const injectedItem = injectedDmnoEnv[itemKey]; + const val = injectedItem.value; + + // some config is to affect wrangler itself + if ( + wranglerSystemEnvKeys.includes(itemKey) + // users can pass in multiple bindings that will have different keys + || itemKey.startsWith('WRANGLER_HYPERDRIVE_LOCAL_CONNECTION_STRING_') + ) { + wranglerSystemEnv[itemKey] = val; + continue; + } + if (dmnoWranglerEnvKeys.includes(itemKey)) { + dmnoWranglerSettings[itemKey] = val; + continue; + } + + // set up static build-time replacements + if (!injectedItem.dynamic) { + if (!injectedItem.sensitive) { + staticReplacements.dmnoPublicConfig[`DMNO_PUBLIC_CONFIG.${itemKey}`] = JSON.stringify(injectedItem.value); + } + staticReplacements.dmnoConfig[`DMNO_CONFIG.${itemKey}`] = JSON.stringify(injectedItem.value); + } + + injectedValues[itemKey] = val; + } +} + +let wranglerProcess: ChildProcess | undefined; + +if (isDevMode) { + dmnoServer.enableWatchMode(async () => { + console.log('reload!!!'); + dmnoHasTriggeredReload = true; + if (wranglerProcess) { + // wranglerProcess.kill(15); + wranglerProcess.kill(2); + } + await restartWrangler(); + }); +} + + +let exitCode; +async function restartWrangler() { + await reloadDmnoConfig(); + if (!dmnoConfigValid) { + if (isDevMode) { + console.log('watching for config changes...'); + return; + } else { + process.exit(1); + } + } + + + const injectMode = dmnoWranglerSettings.DWRANGLER_INJECT_MODE || 'define'; + + const wranglerBuildArgs = []; + const wranglerDevArgs = []; + + // some commands trigger a build, and we need to inject config + // this would be easier if wrangler had a .js config option and allowed plugins... + if (['dev', 'deploy', 'versions upload'].includes(wranglerCommand)) { + // all "static" config will be replaced at build time (using --define) + + // for "dynamic" config, we have 2 methods of injecting - vars or define + + // users can toggle between these modes by setting DWRANGLER_INJECT_MODE in their config.mts + + // in "define" mode, we inline the entire resolved config with additional metadata into the build code + // this is necessary for our global patching stuff to work, and it also enables users to use config + // outside of request handlers. Generally it's a lot simpler, but the idea of injecting at build time + // and using globals may be offputting to some - although it is safe! + if (injectMode === 'define') { + debug('injecting dynamic config using define'); + wranglerBuildArgs.push('--define', `__DMNO_INJECTED_CONFIG__:${JSON.stringify(injectedDmnoEnv)}`); + + + // in "vars" mode, we do things the cloudflare way, and inject config as cloudflare "secrets" + // during local dev, we use --var to inject, and to deploy we must do a multi-step versioned deploy + // we also replace `DMNO_CONFIG.X` with `env.X` for convenience and type safety + // this does require that users use the conventional `env` name for their handler + // TODO: they will actually all be strings, so we need to figure out what to do about that + // the upside is we are doing things the cloudflare way, the downsides are + // - no security features (log redaction, leak detection) + // - everythign is a string + // - only able to use config within request handlers + // - more complicated deployment workflow + } else if (injectMode === 'vars') { + debug('injecting dynamic config as secrets'); + for (const key in injectedValues) { + // we don't need to inject any static items, as they will be replaced + if (injectedDmnoEnv[key].dynamic) { + injectedDynamicValues[key] = injectedValues[key]; + // during local dev, we use --var to inject the dynamic env vars + // but if we do that during deploy, it will treat them as "text" instead of "secret" + if (wranglerCommand === 'dev') { + wranglerBuildArgs.push('--var', `${key}:${injectedValues[key]}`); + } + wranglerBuildArgs.push('--define', `DMNO_CONFIG.${key}:env.${key}`); + } + } + } + // always inject static items using --define + const allReplacements = { ...staticReplacements.dmnoConfig, ...staticReplacements.dmnoPublicConfig }; + for (const k in allReplacements) { + wranglerBuildArgs.push('--define', `${k}:${allReplacements[k]}`); + } + } + + // apply some config items as args for wrangler dev + // this is useful because we can manage it in our config, and we can reuse that data in our config + if (isDevMode) { + if (dmnoWranglerSettings.WRANGLER_DEV_PORT) { + wranglerDevArgs.push('--port', dmnoWranglerSettings.WRANGLER_DEV_PORT); + } + if (dmnoWranglerSettings.WRANGLER_DEV_IP) { + wranglerDevArgs.push('--ip', dmnoWranglerSettings.WRANGLER_DEV_IP); + } + if (dmnoWranglerSettings.WRANGLER_LIVE_RELOAD) { + wranglerDevArgs.push('--live-reload'); + } + if (dmnoWranglerSettings.WRANGLER_ENV) { + wranglerDevArgs.push('--env', dmnoWranglerSettings.WRANGLER_ENV); + } + } + + // if we are deploying and using vars, we need to actually do a multi-step deployment: + // - create new version + // - set bulk secrets for that new version + // - deploy the version + if (wranglerCommand === 'deploy' && injectMode === 'vars' && !args.includes('--dry-run')) { + console.log('dwrangler will run a multi-step deployment for you'); + + console.log('1 - CREATING NEW VERSION'); + + + const multiStepDeployEnv = { + FORCE_COLOR: 'true', + ...process.env, + ...wranglerSystemEnv, + }; + + try { + console.log('> STEP 1: BUILD AND CREATE NEW PENDING VERSION'); + const { stdout: versionsUploadOutput } = await execa( + 'wrangler', + [ + 'versions', 'upload', + '--message', 'dmno dwrangler create deployment (secrets not yet set)', + ...wranglerBuildArgs, + ], + { + stdout: ['pipe', 'inherit'], + env: multiStepDeployEnv, + }, + ); + + const versionId = versionsUploadOutput.match(/Worker Version ID: ([^\s]+)\n/)?.[1]; + // const previewUrl = versionsUploadOutput.match(/Version Preview URL: ([^\s]+)\n/)?.[1]; + if (!versionId) throw new Error('Did not create new version successfully'); + + console.log('> STEP 2: ATTACH SECRETS TO PENDING VERSION'); + const { stdout: secretsOutput } = await execa( + 'wrangler', + [ + 'versions', 'secret', 'bulk', + '--message', 'dmno dwrangler set bulk secrets', + ], + { + stdout: ['pipe', 'inherit'], + env: multiStepDeployEnv, + input: JSON.stringify(injectedDynamicValues), + }, + ); + + const versionIdWithSecrets = secretsOutput.match(/Created version ([^\s]+)\s/)?.[1]; + if (!versionId) throw new Error('Did not deploy version with secrets successfully'); + + console.log('> STEP 3: ACTIVATE NEW VERSION'); + const { stdout: deployOutput } = await execa( + 'wrangler', + [ + 'versions', 'deploy', + `${versionIdWithSecrets}@100%`, + '--yes', + ], + { + stdout: ['pipe', 'inherit'], + env: multiStepDeployEnv, + }, + ); + } catch (err) { + console.log(err); + } + } else { + wranglerProcess = spawn( + // TODO: how do we want to find the path to wrangler? + wranglerBinPath, + [...args, ...wranglerBuildArgs, ...wranglerDevArgs], + { + stdio: 'inherit', + env: { + ...process.env, + ...wranglerSystemEnv, + }, + }, + ); + + + // wranglerProcess?.stdout?.on('data', (data) => { + // console.log('stdoutt!', data); + // }); + // wranglerProcess?.stderr?.on('data', (data) => { + // console.log('stderr!', data); + // }); + // wranglerProcess?.stderr?.on('error', (data) => { + // console.log('error!', data); + // }); + wranglerProcess.on('exit', (code, signal) => { + console.log('wranglerProcess exit', { code, signal }); + // we are seeing wrangler exit code 0 and no signal both when + // the user hits CTRL+C and when we restart the process + // so we have to track whether we restarted it and ignore the close signal we get right after + exitCode = code ?? 0; + if (exitCode === 0) { + if (dmnoHasTriggeredReload) { + dmnoHasTriggeredReload = false; + } else { + process.exit(0); + } + } else { + process.exit(exitCode); + } + }); + // wranglerProcess.on('close', () => { + // console.log('wrangler process - close'); + // }); + // wranglerProcess.on('disconnect', () => { + // console.log('wrangler process - disconnect'); + // }); + // wranglerProcess.on('error', () => { + // console.log('wrangler process - error'); + // }); + // wranglerProcess.on('message', () => { + // console.log('wrangler process - message'); + // }); + } +} + +// if first run, we need to attach some extra exit handling + +// try to make sure we shut down cleanly and kill the child process +process.on('exit', (code: any, signal: any) => { + debug('dwrangler exit!'); + wranglerProcess?.kill(9); +}); + +['SIGTERM', 'SIGINT'].forEach((signal) => { + process.on(signal, () => { + debug('dwrangler received signal', signal); + wranglerProcess?.kill(9); + process.exit(1); + }); +}); +// TODO: handle other signals? + +await restartWrangler(); diff --git a/packages/platforms/cloudflare/src/index.ts b/packages/platforms/cloudflare/src/index.ts new file mode 100644 index 00000000..ea98209e --- /dev/null +++ b/packages/platforms/cloudflare/src/index.ts @@ -0,0 +1 @@ +export * from './data-types'; diff --git a/packages/platforms/cloudflare/tsconfig.json b/packages/platforms/cloudflare/tsconfig.json new file mode 100644 index 00000000..8572ecc4 --- /dev/null +++ b/packages/platforms/cloudflare/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@dmno/tsconfig/tsconfig.node.json", + "compilerOptions": { + "rootDir": ".", + "module": "ESNext", + "outDir": "dist", + "lib": [ + "ESNext" + ], + }, + "include": [ + "src/**/*.ts", + "src/**/*.d.ts", + ] +} diff --git a/packages/platforms/cloudflare/tsup.config.ts b/packages/platforms/cloudflare/tsup.config.ts new file mode 100644 index 00000000..3b17a6a8 --- /dev/null +++ b/packages/platforms/cloudflare/tsup.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: [ // Entry point(s) + 'src/index.ts', // preset + data types + 'src/dwrangler.ts', + ], + + dts: true, // Generate .d.ts files + // minify: true, // Minify output + sourcemap: true, // Generate sourcemaps + treeshake: true, // Remove unused code + + clean: true, // Clean output directory before building + outDir: "dist", // Output directory + + format: ['esm'], // Output format(s) + + splitting: true, // split output into chunks - MUST BE ON! or we get issues with multiple copies of classes and instanceof + keepNames: true, // stops build from prefixing our class names with `_` in some cases +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ebb4e15..41e73414 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -233,7 +233,7 @@ importers: version: 5.5.4 uWebSockets.js: specifier: github:uNetworking/uWebSockets.js#semver:^20.49.0 - version: https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/442087c0a01bf146acb7386910739ec81df06700 + version: https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/6609a88ffa9a16ac5158046761356ce03250a0df validate-npm-package-name: specifier: ^5.0.0 version: 5.0.0 @@ -409,7 +409,7 @@ importers: version: 0.25.5(astro@4.15.9(@types/node@20.14.12)(less@4.2.0)(rollup@4.21.3)(typescript@5.5.4)) '@astrojs/vue': specifier: ^4.5.0 - version: 4.5.0(astro@4.15.9(@types/node@20.14.12)(less@4.2.0)(rollup@4.21.3)(typescript@5.5.4))(rollup@4.21.3)(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) + version: 4.5.0(astro@4.15.9(@types/node@20.14.12)(less@4.2.0)(rollup@4.21.3)(typescript@5.5.4))(rollup@4.21.3)(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) '@dmno/astro-integration': specifier: workspace:* version: link:../integrations/astro @@ -676,7 +676,7 @@ importers: version: link:../../tsconfig '@remix-run/dev': specifier: ^2.10.3 - version: 2.10.3(@remix-run/react@2.10.3(react-dom@18.3.0(react@18.3.0))(react@18.3.0)(typescript@5.5.4))(@types/node@20.14.12)(less@4.2.0)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4))(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.12)(less@4.2.0)) + version: 2.10.3(@remix-run/react@2.10.3(react-dom@18.3.0(react@18.3.0))(react@18.3.0)(typescript@5.5.4))(@types/node@20.14.12)(less@4.2.0)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4))(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.12)(less@4.2.0))(wrangler@3.95.0) '@remix-run/react': specifier: ^2.10.3 version: 2.10.3(react-dom@18.3.0(react@18.3.0))(react@18.3.0)(typescript@5.5.4) @@ -745,6 +745,49 @@ importers: specifier: ^5.4.10 version: 5.4.11(@types/node@20.14.12)(less@4.2.0) + packages/platforms/cloudflare: + dependencies: + debug: + specifier: 'catalog:' + version: 4.3.7(supports-color@9.4.0) + execa: + specifier: ^9.5.1 + version: 9.5.2 + lodash-es: + specifier: 'catalog:' + version: 4.17.21 + nano-spawn: + specifier: ^0.2.0 + version: 0.2.0 + wrangler: + specifier: ^3 + version: 3.95.0 + devDependencies: + '@dmno/eslint-config': + specifier: workspace:* + version: link:../../eslint-config + '@dmno/tsconfig': + specifier: workspace:* + version: link:../../tsconfig + '@types/debug': + specifier: 'catalog:' + version: 4.1.12 + '@types/lodash-es': + specifier: 'catalog:' + version: 4.17.12 + '@types/node': + specifier: 'catalog:' + version: 20.14.12 + dmno: + specifier: workspace:* + version: link:../../core + tsup: + specifier: 'catalog:' + version: 8.2.4(jiti@1.21.0)(postcss@8.4.47)(tsx@4.19.2)(typescript@5.5.4)(yaml@2.5.1) + typescript: + specifier: 'catalog:' + version: 5.5.4 + packages/platforms/netlify: dependencies: '@netlify/blobs': @@ -1535,6 +1578,44 @@ packages: '@changesets/write@0.3.0': resolution: {integrity: sha512-slGLb21fxZVUYbyea+94uFiD6ntQW0M2hIKNznFizDhZPDgn2c/fv1UzzlW43RVzh1BEDuIqW6hzlJ1OflNmcw==} + '@cloudflare/kv-asset-handler@0.3.4': + resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} + engines: {node: '>=16.13'} + + '@cloudflare/workerd-darwin-64@1.20241205.0': + resolution: {integrity: sha512-TArEZkSZkHJyEwnlWWkSpCI99cF6lJ14OVeEoI9Um/+cD9CKZLM9vCmsLeKglKheJ0KcdCnkA+DbeD15t3VaWg==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20241205.0': + resolution: {integrity: sha512-u5eqKa9QRdA8MugfgCoD+ADDjY6EpKbv3hSYJETmmUh17l7WXjWBzv4pUvOKIX67C0UzMUy4jZYwC53MymhX3w==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20241205.0': + resolution: {integrity: sha512-OYA7S5zpumMamWEW+IhhBU6YojIEocyE5X/YFPiTOCrDE3dsfr9t6oqNE7hxGm1VAAu+Irtl+a/5LwmBOU681w==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20241205.0': + resolution: {integrity: sha512-qAzecONjFJGIAVJZKExQ5dlbic0f3d4A+GdKa+H6SoUJtPaWiE3K6WuePo4JOT7W3/Zfh25McmX+MmpMUUcM5Q==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20241205.0': + resolution: {integrity: sha512-BEab+HiUgCdl6GXAT7EI2yaRtDPiRJlB94XLvRvXi1ZcmQqsrq6awGo6apctFo4WUL29V7c09LxmN4HQ3X2Tvg==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + + '@cloudflare/workers-shared@0.11.0': + resolution: {integrity: sha512-A+lQ8xp7992qSeMmuQ0ssL6CPmm+ZmAv6Ddikan0n1jjpMAic+97l7xtVIsswSn9iLMFPYQ9uNN/8Fl0AgARIQ==} + engines: {node: '>=16.7.0'} + '@cloudflare/workers-types@4.20241112.0': resolution: {integrity: sha512-Q4p9bAWZrX14bSCKY9to19xl0KMU7nsO5sJ2cTVspHoypsjPUMeQCsjHjmsO2C4Myo8/LPeDvmqFmkyNAPPYZw==} @@ -1634,6 +1715,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/android-arm64@0.17.19': + resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.17.6': resolution: {integrity: sha512-YnYSCceN/dUzUr5kdtUzB+wZprCafuD89Hs0Aqv9QSdwhYQybhXTaSTcrl6X/aWThn1a/j0eEpUBGOE7269REg==} engines: {node: '>=12'} @@ -1676,6 +1763,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm@0.17.19': + resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.17.6': resolution: {integrity: sha512-bSC9YVUjADDy1gae8RrioINU6e1lCkg3VGVwm0QQ2E1CWcC4gnMce9+B6RpxuSsrsXsk1yojn7sp1fnG8erE2g==} engines: {node: '>=12'} @@ -1718,6 +1811,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-x64@0.17.19': + resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.17.6': resolution: {integrity: sha512-MVcYcgSO7pfu/x34uX9u2QIZHmXAB7dEiLQC5bBl5Ryqtpj9lT2sg3gNDEsrPEmimSJW2FXIaxqSQ501YLDsZQ==} engines: {node: '>=12'} @@ -1760,6 +1859,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/darwin-arm64@0.17.19': + resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.17.6': resolution: {integrity: sha512-bsDRvlbKMQMt6Wl08nHtFz++yoZHsyTOxnjfB2Q95gato+Yi4WnRl13oC2/PJJA9yLCoRv9gqT/EYX0/zDsyMA==} engines: {node: '>=12'} @@ -1802,6 +1907,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-x64@0.17.19': + resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.17.6': resolution: {integrity: sha512-xh2A5oPrYRfMFz74QXIQTQo8uA+hYzGWJFoeTE8EvoZGHb+idyV4ATaukaUvnnxJiauhs/fPx3vYhU4wiGfosg==} engines: {node: '>=12'} @@ -1844,6 +1955,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.17.19': + resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.17.6': resolution: {integrity: sha512-EnUwjRc1inT4ccZh4pB3v1cIhohE2S4YXlt1OvI7sw/+pD+dIE4smwekZlEPIwY6PhU6oDWwITrQQm5S2/iZgg==} engines: {node: '>=12'} @@ -1886,6 +2003,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-x64@0.17.19': + resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.17.6': resolution: {integrity: sha512-Uh3HLWGzH6FwpviUcLMKPCbZUAFzv67Wj5MTwK6jn89b576SR2IbEp+tqUHTr8DIl0iDmBAf51MVaP7pw6PY5Q==} engines: {node: '>=12'} @@ -1928,6 +2051,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.17.19': + resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.17.6': resolution: {integrity: sha512-bUR58IFOMJX523aDVozswnlp5yry7+0cRLCXDsxnUeQYJik1DukMY+apBsLOZJblpH+K7ox7YrKrHmJoWqVR9w==} engines: {node: '>=12'} @@ -1970,6 +2099,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.17.19': + resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.17.6': resolution: {integrity: sha512-7YdGiurNt7lqO0Bf/U9/arrPWPqdPqcV6JCZda4LZgEn+PTQ5SMEI4MGR52Bfn3+d6bNEGcWFzlIxiQdS48YUw==} engines: {node: '>=12'} @@ -2012,6 +2147,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-ia32@0.17.19': + resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.17.6': resolution: {integrity: sha512-ujp8uoQCM9FRcbDfkqECoARsLnLfCUhKARTP56TFPog8ie9JG83D5GVKjQ6yVrEVdMie1djH86fm98eY3quQkQ==} engines: {node: '>=12'} @@ -2054,6 +2195,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.17.19': + resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.17.6': resolution: {integrity: sha512-y2NX1+X/Nt+izj9bLoiaYB9YXT/LoaQFYvCkVD77G/4F+/yuVXYCWz4SE9yr5CBMbOxOfBcy/xFL4LlOeNlzYQ==} engines: {node: '>=12'} @@ -2096,6 +2243,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-mips64el@0.17.19': + resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.17.6': resolution: {integrity: sha512-09AXKB1HDOzXD+j3FdXCiL/MWmZP0Ex9eR8DLMBVcHorrWJxWmY8Nms2Nm41iRM64WVx7bA/JVHMv081iP2kUA==} engines: {node: '>=12'} @@ -2138,6 +2291,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-ppc64@0.17.19': + resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.17.6': resolution: {integrity: sha512-AmLhMzkM8JuqTIOhxnX4ubh0XWJIznEynRnZAVdA2mMKE6FAfwT2TWKTwdqMG+qEaeyDPtfNoZRpJbD4ZBv0Tg==} engines: {node: '>=12'} @@ -2180,6 +2339,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-riscv64@0.17.19': + resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.17.6': resolution: {integrity: sha512-Y4Ri62PfavhLQhFbqucysHOmRamlTVK10zPWlqjNbj2XMea+BOs4w6ASKwQwAiqf9ZqcY9Ab7NOU4wIgpxwoSQ==} engines: {node: '>=12'} @@ -2222,6 +2387,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-s390x@0.17.19': + resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.17.6': resolution: {integrity: sha512-SPUiz4fDbnNEm3JSdUW8pBJ/vkop3M1YwZAVwvdwlFLoJwKEZ9L98l3tzeyMzq27CyepDQ3Qgoba44StgbiN5Q==} engines: {node: '>=12'} @@ -2264,6 +2435,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-x64@0.17.19': + resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.17.6': resolution: {integrity: sha512-a3yHLmOodHrzuNgdpB7peFGPx1iJ2x6m+uDvhP2CKdr2CwOaqEFMeSqYAHU7hG+RjCq8r2NFujcd/YsEsFgTGw==} engines: {node: '>=12'} @@ -2306,6 +2483,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/netbsd-x64@0.17.19': + resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.17.6': resolution: {integrity: sha512-EanJqcU/4uZIBreTrnbnre2DXgXSa+Gjap7ifRfllpmyAU7YMvaXmljdArptTHmjrkkKm9BK6GH5D5Yo+p6y5A==} engines: {node: '>=12'} @@ -2354,6 +2537,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.17.19': + resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.17.6': resolution: {integrity: sha512-xaxeSunhQRsTNGFanoOkkLtnmMn5QbA0qBhNet/XLVsc+OVkpIWPHcr3zTW2gxVU5YOHFbIHR9ODuaUdNza2Vw==} engines: {node: '>=12'} @@ -2396,6 +2585,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/sunos-x64@0.17.19': + resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.17.6': resolution: {integrity: sha512-gnMnMPg5pfMkZvhHee21KbKdc6W3GR8/JuE0Da1kjwpK6oiFU3nqfHuVPgUX2rsOx9N2SadSQTIYV1CIjYG+xw==} engines: {node: '>=12'} @@ -2438,6 +2633,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.17.19': + resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.17.6': resolution: {integrity: sha512-G95n7vP1UnGJPsVdKXllAJPtqjMvFYbN20e8RK8LVLhlTiSOH1sd7+Gt7rm70xiG+I5tM58nYgwWrLs6I1jHqg==} engines: {node: '>=12'} @@ -2480,6 +2681,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-ia32@0.17.19': + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.17.6': resolution: {integrity: sha512-96yEFzLhq5bv9jJo5JhTs1gI+1cKQ83cUpyxHuGqXVwQtY5Eq54ZEsKs8veKtiKwlrNimtckHEkj4mRh4pPjsg==} engines: {node: '>=12'} @@ -2522,6 +2729,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.17.19': + resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.17.6': resolution: {integrity: sha512-n6d8MOyUrNp6G4VSpRcgjs5xj4A91svJSaiwLIDWVWEsZtpN5FA9NlBbZHDmAJc2e8e6SF4tkBD3HAvPF+7igA==} engines: {node: '>=12'} @@ -2604,6 +2817,10 @@ packages: '@fastify/ajv-compiler@4.0.1': resolution: {integrity: sha512-DxrBdgsjNLP0YM6W5Hd6/Fmj43S8zMKiFJYgi+Ri3htTGAowPVG/tG1wpnWLMjufEnehRivUCKZ1pLDIoZdTuw==} + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + '@fastify/error@3.4.1': resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} @@ -3715,6 +3932,9 @@ packages: cpu: [x64] os: [win32] + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + '@shikijs/core@1.18.0': resolution: {integrity: sha512-VK4BNVCd2leY62Nm2JjyxtRLkyrZT/tv104O81eyaCjHq4Adceq2uJVFJJAIof6lT1mBwZrEo2qT/T+grv3MQQ==} @@ -3741,6 +3961,10 @@ packages: resolution: {integrity: sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==} engines: {node: '>=18'} + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + '@sindresorhus/slugify@2.2.1': resolution: {integrity: sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==} engines: {node: '>=12'} @@ -4681,6 +4905,9 @@ packages: resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} engines: {node: '>=12'} + as-table@1.0.55: + resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} + asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} @@ -4879,6 +5106,9 @@ packages: bl@5.1.0: resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + blake3-wasm@2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + blueimp-md5@2.19.0: resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} @@ -5035,6 +5265,9 @@ packages: caniuse-lite@1.0.30001663: resolution: {integrity: sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==} + capnp-ts@0.7.0: + resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -5104,6 +5337,10 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} + engines: {node: '>= 14.16.0'} + chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -5376,6 +5613,10 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + cookie@1.0.2: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} @@ -5508,6 +5749,9 @@ packages: cyclist@1.0.2: resolution: {integrity: sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==} + data-uri-to-buffer@2.0.2: + resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} + data-uri-to-buffer@3.0.1: resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==} engines: {node: '>= 6'} @@ -5531,6 +5775,9 @@ packages: dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + date-time@3.1.0: resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} engines: {node: '>=6'} @@ -5969,6 +6216,11 @@ packages: peerDependencies: esbuild: ^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 + esbuild@0.17.19: + resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} + engines: {node: '>=12'} + hasBin: true + esbuild@0.17.6: resolution: {integrity: sha512-TKFRp9TxrJDdRWfSsSERKEovm6v30iHnrjlcGhLBOtReE28Yp1VSBRfO3GTaOFMoxsNerx4TjrhzSuma9ha83Q==} engines: {node: '>=12'} @@ -6288,6 +6540,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + execa@9.5.2: + resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==} + engines: {node: ^18.19.0 || >=20.5.0} + exit-hook@2.2.1: resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} engines: {node: '>=6'} @@ -6463,6 +6719,10 @@ packages: resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} engines: {node: '>=14'} + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -6727,6 +6987,9 @@ packages: resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} engines: {node: '>=16'} + get-source@2.0.12: + resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} + get-stream@5.2.0: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} @@ -6739,6 +7002,10 @@ packages: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} @@ -6778,6 +7045,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.3.12: resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} engines: {node: '>=16 || 14 >=14.17'} @@ -7114,6 +7384,10 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} + human-signals@8.0.0: + resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==} + engines: {node: '>=18.18.0'} + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -7484,6 +7758,10 @@ packages: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -7576,6 +7854,9 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} + itty-time@1.0.6: + resolution: {integrity: sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==} + jackspeak@2.3.6: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} @@ -7949,6 +8230,9 @@ packages: resolution: {integrity: sha512-fSErXALFNsnowREYZ49XCdOHF8wOPWuFOGQrAhP7x5J/BqQv+B02cNsTykGpDgRVx43EKg++6ANmTaGTtW+hUA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} @@ -8436,6 +8720,11 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} + miniflare@3.20241205.0: + resolution: {integrity: sha512-Z0cTtIf6ZrcAJ3SrOI9EUM3s4dkGhNeU6Ubl8sroYhsPVD+rtz3m5+p6McHFWCkcMff1o60X5XEKVTmkz0gbpA==} + engines: {node: '>=16.13'} + hasBin: true + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -8565,6 +8854,10 @@ packages: resolution: {integrity: sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==} engines: {node: '>= 0.10'} + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + mute-stream@0.0.7: resolution: {integrity: sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==} @@ -8578,6 +8871,10 @@ packages: nan@2.19.0: resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==} + nano-spawn@0.2.0: + resolution: {integrity: sha512-IjZBIOLxSlxu+m/kacg9JuP93oUpRemeV0mEuCy64nzBKKIL9m0aLJHtVPcVuzJDHFhElzjpwbW4a3tMzgKoZQ==} + engines: {node: '>=18.19'} + nanoassert@2.0.0: resolution: {integrity: sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==} @@ -8872,6 +9169,9 @@ packages: ohash@1.1.3: resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} + ohash@1.1.4: + resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} + omit.js@2.0.2: resolution: {integrity: sha512-hJmu9D+bNB40YpL9jYebQl4lsTW6yEHRTroJzNLqQJYHm7c+NQnJGfZmIWh8S3q3KoaxV1aLhV6B3+0N0/kyJg==} @@ -9182,6 +9482,9 @@ packages: path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -9443,10 +9746,17 @@ packages: resolution: {integrity: sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==} engines: {node: '>=14.16'} + pretty-ms@9.2.0: + resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} + engines: {node: '>=18'} + prettyjson@1.2.5: resolution: {integrity: sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw==} hasBin: true + printable-characters@1.0.42: + resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} @@ -9728,6 +10038,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + real-require@0.2.0: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} @@ -9959,6 +10273,16 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + rollup-plugin-inject@3.0.2: + resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==} + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. + + rollup-plugin-node-polyfills@0.2.1: + resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==} + + rollup-pluginutils@2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + rollup@4.19.0: resolution: {integrity: sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -10044,6 +10368,10 @@ packages: resolution: {integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==} hasBin: true + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + semver-diff@4.0.0: resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} engines: {node: '>=12'} @@ -10277,6 +10605,10 @@ packages: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -10329,6 +10661,9 @@ packages: stackframe@1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + stacktracey@2.1.8: + resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + starlight-blog@0.11.1: resolution: {integrity: sha512-2nMcYzCOrWZ8/34G7SouSX1jVzwKPARFwyszTF2497FN6ZUdrTsnhLB6Q7/l6fEKdcQkh9UCyMI7coeR670guA==} engines: {node: '>=18.14.1'} @@ -10366,6 +10701,10 @@ packages: resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} engines: {node: '>=18'} + stoppable@1.1.0: + resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} + engines: {node: '>=4', npm: '>=6'} + stream-replace-string@2.0.0: resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} @@ -10477,6 +10816,10 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -10988,13 +11331,16 @@ packages: engines: {node: '>=14.17'} hasBin: true - uWebSockets.js@https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/442087c0a01bf146acb7386910739ec81df06700: - resolution: {tarball: https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/442087c0a01bf146acb7386910739ec81df06700} - version: 20.49.0 + uWebSockets.js@https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/6609a88ffa9a16ac5158046761356ce03250a0df: + resolution: {tarball: https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/6609a88ffa9a16ac5158046761356ce03250a0df} + version: 20.51.0 ufo@1.5.3: resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + uid-safe@2.1.5: resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} engines: {node: '>= 0.8'} @@ -11018,10 +11364,17 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + undici@6.19.7: resolution: {integrity: sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==} engines: {node: '>=18.17'} + unenv-nightly@2.0.0-20241204-140205-a5d5190: + resolution: {integrity: sha512-jpmAytLeiiW01pl5bhVn9wYJ4vtiLdhGe10oXlJBuQEX8mxjxO8BlEXGHU4vr4yEikjFP1wsomTHt/CLU8kUwg==} + unenv@1.9.0: resolution: {integrity: sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==} @@ -11032,6 +11385,10 @@ packages: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + unified-engine@11.2.1: resolution: {integrity: sha512-xBAdZ8UY2X4R9Hm6X6kMne4Nz0PlpOc1oE6DPeqJnewr5Imkb8uT5Eyvy1h7xNekPL3PSWh3ZJyNrMW6jnNQBg==} @@ -11839,17 +12196,17 @@ packages: resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==} engines: {node: '>= 10.0.0'} - workerd@1.20241106.1: - resolution: {integrity: sha512-1GdKl0kDw8rrirr/ThcK66Kbl4/jd4h8uHx5g7YHBrnenY5SX1UPuop2cnCzYUxlg55kPjzIqqYslz1muRFgFw==} + workerd@1.20241205.0: + resolution: {integrity: sha512-vso/2n0c5SdBDWiD+Sx5gM7unA6SiZXRVUHDqH1euoP/9mFVHZF8icoYsNLB87b/TX8zNgpae+I5N/xFpd9v0g==} engines: {node: '>=16'} hasBin: true - wrangler@3.91.0: - resolution: {integrity: sha512-Hdzn6wbY9cz5kL85ZUvWLwLIH7nPaEVRblfms40jhRf4qQO/Zf74aFlku8rQFbe8/2aVZFaxJVfBd6JQMeMSBQ==} + wrangler@3.95.0: + resolution: {integrity: sha512-3w5852i3FNyDz421K2Qk4v5L8jjwegO5O8E1+VAQmjnm82HFNxpIRUBq0bmM7CTLvOPI/Jjcmj/eAWjQBL7QYg==} engines: {node: '>=16.17.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^4.20241106.0 + '@cloudflare/workers-types': ^4.20241205.0 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -11932,6 +12289,18 @@ packages: utf-8-validate: optional: true + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xdg-basedir@5.1.0: resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} engines: {node: '>=12'} @@ -12032,6 +12401,13 @@ packages: resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} engines: {node: '>=12.20'} + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + youch@3.3.4: + resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==} + zhead@2.2.4: resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==} @@ -12232,13 +12608,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/vue@4.5.0(astro@4.15.9(@types/node@20.14.12)(less@4.2.0)(rollup@4.21.3)(typescript@5.5.4))(rollup@4.21.3)(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4))': + '@astrojs/vue@4.5.0(astro@4.15.9(@types/node@20.14.12)(less@4.2.0)(rollup@4.21.3)(typescript@5.5.4))(rollup@4.21.3)(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4))': dependencies: - '@vitejs/plugin-vue': 5.1.4(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) - '@vitejs/plugin-vue-jsx': 4.0.0(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) + '@vitejs/plugin-vue': 5.1.4(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) + '@vitejs/plugin-vue-jsx': 4.0.0(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) '@vue/compiler-sfc': 3.4.30 astro: 4.15.9(@types/node@20.14.12)(less@4.2.0)(rollup@4.21.3)(typescript@5.5.4) - vite-plugin-vue-devtools: 7.5.2(rollup@4.21.3)(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) + vite-plugin-vue-devtools: 7.5.2(rollup@4.21.3)(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) vue: 3.5.8(typescript@5.5.4) transitivePeerDependencies: - '@nuxt/kit' @@ -12923,6 +13299,30 @@ snapshots: human-id: 1.0.2 prettier: 2.8.8 + '@cloudflare/kv-asset-handler@0.3.4': + dependencies: + mime: 3.0.0 + + '@cloudflare/workerd-darwin-64@1.20241205.0': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20241205.0': + optional: true + + '@cloudflare/workerd-linux-64@1.20241205.0': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20241205.0': + optional: true + + '@cloudflare/workerd-windows-64@1.20241205.0': + optional: true + + '@cloudflare/workers-shared@0.11.0': + dependencies: + mime: 3.0.0 + zod: 3.23.8 + '@cloudflare/workers-types@4.20241112.0': {} '@colors/colors@1.6.0': {} @@ -12976,6 +13376,16 @@ snapshots: '@emotion/hash@0.9.1': {} + '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)': + dependencies: + esbuild: 0.17.19 + + '@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19)': + dependencies: + esbuild: 0.17.19 + escape-string-regexp: 4.0.0 + rollup-plugin-node-polyfills: 0.2.1 + '@esbuild/aix-ppc64@0.19.11': optional: true @@ -12994,6 +13404,9 @@ snapshots: '@esbuild/aix-ppc64@0.23.0': optional: true + '@esbuild/android-arm64@0.17.19': + optional: true + '@esbuild/android-arm64@0.17.6': optional: true @@ -13015,6 +13428,9 @@ snapshots: '@esbuild/android-arm64@0.23.0': optional: true + '@esbuild/android-arm@0.17.19': + optional: true + '@esbuild/android-arm@0.17.6': optional: true @@ -13036,6 +13452,9 @@ snapshots: '@esbuild/android-arm@0.23.0': optional: true + '@esbuild/android-x64@0.17.19': + optional: true + '@esbuild/android-x64@0.17.6': optional: true @@ -13057,6 +13476,9 @@ snapshots: '@esbuild/android-x64@0.23.0': optional: true + '@esbuild/darwin-arm64@0.17.19': + optional: true + '@esbuild/darwin-arm64@0.17.6': optional: true @@ -13078,6 +13500,9 @@ snapshots: '@esbuild/darwin-arm64@0.23.0': optional: true + '@esbuild/darwin-x64@0.17.19': + optional: true + '@esbuild/darwin-x64@0.17.6': optional: true @@ -13099,6 +13524,9 @@ snapshots: '@esbuild/darwin-x64@0.23.0': optional: true + '@esbuild/freebsd-arm64@0.17.19': + optional: true + '@esbuild/freebsd-arm64@0.17.6': optional: true @@ -13120,6 +13548,9 @@ snapshots: '@esbuild/freebsd-arm64@0.23.0': optional: true + '@esbuild/freebsd-x64@0.17.19': + optional: true + '@esbuild/freebsd-x64@0.17.6': optional: true @@ -13141,6 +13572,9 @@ snapshots: '@esbuild/freebsd-x64@0.23.0': optional: true + '@esbuild/linux-arm64@0.17.19': + optional: true + '@esbuild/linux-arm64@0.17.6': optional: true @@ -13162,6 +13596,9 @@ snapshots: '@esbuild/linux-arm64@0.23.0': optional: true + '@esbuild/linux-arm@0.17.19': + optional: true + '@esbuild/linux-arm@0.17.6': optional: true @@ -13183,6 +13620,9 @@ snapshots: '@esbuild/linux-arm@0.23.0': optional: true + '@esbuild/linux-ia32@0.17.19': + optional: true + '@esbuild/linux-ia32@0.17.6': optional: true @@ -13204,6 +13644,9 @@ snapshots: '@esbuild/linux-ia32@0.23.0': optional: true + '@esbuild/linux-loong64@0.17.19': + optional: true + '@esbuild/linux-loong64@0.17.6': optional: true @@ -13225,6 +13668,9 @@ snapshots: '@esbuild/linux-loong64@0.23.0': optional: true + '@esbuild/linux-mips64el@0.17.19': + optional: true + '@esbuild/linux-mips64el@0.17.6': optional: true @@ -13246,6 +13692,9 @@ snapshots: '@esbuild/linux-mips64el@0.23.0': optional: true + '@esbuild/linux-ppc64@0.17.19': + optional: true + '@esbuild/linux-ppc64@0.17.6': optional: true @@ -13267,6 +13716,9 @@ snapshots: '@esbuild/linux-ppc64@0.23.0': optional: true + '@esbuild/linux-riscv64@0.17.19': + optional: true + '@esbuild/linux-riscv64@0.17.6': optional: true @@ -13288,6 +13740,9 @@ snapshots: '@esbuild/linux-riscv64@0.23.0': optional: true + '@esbuild/linux-s390x@0.17.19': + optional: true + '@esbuild/linux-s390x@0.17.6': optional: true @@ -13309,6 +13764,9 @@ snapshots: '@esbuild/linux-s390x@0.23.0': optional: true + '@esbuild/linux-x64@0.17.19': + optional: true + '@esbuild/linux-x64@0.17.6': optional: true @@ -13381,6 +13839,9 @@ snapshots: '@esbuild/openbsd-x64@0.23.0': optional: true + '@esbuild/sunos-x64@0.17.19': + optional: true + '@esbuild/sunos-x64@0.17.6': optional: true @@ -13402,6 +13863,9 @@ snapshots: '@esbuild/sunos-x64@0.23.0': optional: true + '@esbuild/win32-arm64@0.17.19': + optional: true + '@esbuild/win32-arm64@0.17.6': optional: true @@ -13423,6 +13887,9 @@ snapshots: '@esbuild/win32-arm64@0.23.0': optional: true + '@esbuild/win32-ia32@0.17.19': + optional: true + '@esbuild/win32-ia32@0.17.6': optional: true @@ -13530,6 +13997,8 @@ snapshots: ajv-formats: 3.0.1(ajv@8.12.0) fast-uri: 3.0.3 + '@fastify/busboy@2.1.1': {} + '@fastify/error@3.4.1': {} '@fastify/error@4.0.0': {} @@ -14844,7 +15313,7 @@ snapshots: '@polka/url@1.0.0-next.25': {} - '@remix-run/dev@2.10.3(@remix-run/react@2.10.3(react-dom@18.3.0(react@18.3.0))(react@18.3.0)(typescript@5.5.4))(@types/node@20.14.12)(less@4.2.0)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4))(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.12)(less@4.2.0))': + '@remix-run/dev@2.10.3(@remix-run/react@2.10.3(react-dom@18.3.0(react@18.3.0))(react@18.3.0)(typescript@5.5.4))(@types/node@20.14.12)(less@4.2.0)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4))(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.12)(less@4.2.0))(wrangler@3.95.0)': dependencies: '@babel/core': 7.24.7 '@babel/generator': 7.24.7 @@ -14903,6 +15372,7 @@ snapshots: optionalDependencies: typescript: 5.5.4 vite: 5.3.5(@types/node@20.14.12)(less@4.2.0) + wrangler: 3.95.0 transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -15094,6 +15564,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.21.3': optional: true + '@sec-ant/readable-stream@0.4.1': {} + '@shikijs/core@1.18.0': dependencies: '@shikijs/engine-javascript': 1.18.0 @@ -15127,6 +15599,8 @@ snapshots: '@sindresorhus/is@7.0.1': {} + '@sindresorhus/merge-streams@4.0.0': {} + '@sindresorhus/slugify@2.2.1': dependencies: '@sindresorhus/transliterate': 1.6.0 @@ -15662,26 +16136,26 @@ snapshots: dependencies: vite: 5.4.6(@types/node@20.14.12)(less@4.2.0) - '@vitejs/plugin-vue-jsx@4.0.0(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4))': + '@vitejs/plugin-vue-jsx@4.0.0(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4))': dependencies: '@babel/core': 7.24.7 '@babel/plugin-transform-typescript': 7.24.7(@babel/core@7.24.7) '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.24.7) - vite: 5.4.11(@types/node@20.14.12)(less@4.2.0) + vite: 5.4.6(@types/node@20.14.12)(less@4.2.0) vue: 3.5.8(typescript@5.5.4) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.1.4(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4))': - dependencies: - vite: 5.4.11(@types/node@20.14.12)(less@4.2.0) - vue: 3.5.8(typescript@5.5.4) - '@vitejs/plugin-vue@5.1.4(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.12(typescript@5.5.4))': dependencies: vite: 5.4.6(@types/node@20.14.12)(less@4.2.0) vue: 3.5.12(typescript@5.5.4) + '@vitejs/plugin-vue@5.1.4(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4))': + dependencies: + vite: 5.4.6(@types/node@20.14.12)(less@4.2.0) + vue: 3.5.8(typescript@5.5.4) + '@vitest/expect@2.1.2': dependencies: '@vitest/spy': 2.1.2 @@ -15985,19 +16459,19 @@ snapshots: '@vue/devtools-api@6.6.4': {} - '@vue/devtools-core@7.5.2(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4))': + '@vue/devtools-core@7.5.2(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.12(typescript@5.5.4))': dependencies: '@vue/devtools-kit': 7.5.2 '@vue/devtools-shared': 7.5.2 mitt: 3.0.1 nanoid: 3.3.7 pathe: 1.1.2 - vite-hot-client: 0.2.3(vite@5.4.11(@types/node@20.14.12)(less@4.2.0)) - vue: 3.5.8(typescript@5.5.4) + vite-hot-client: 0.2.3(vite@5.4.6(@types/node@20.14.12)(less@4.2.0)) + vue: 3.5.12(typescript@5.5.4) transitivePeerDependencies: - vite - '@vue/devtools-core@7.5.2(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.12(typescript@5.5.4))': + '@vue/devtools-core@7.5.2(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4))': dependencies: '@vue/devtools-kit': 7.5.2 '@vue/devtools-shared': 7.5.2 @@ -16005,7 +16479,7 @@ snapshots: nanoid: 3.3.7 pathe: 1.1.2 vite-hot-client: 0.2.3(vite@5.4.6(@types/node@20.14.12)(less@4.2.0)) - vue: 3.5.12(typescript@5.5.4) + vue: 3.5.8(typescript@5.5.4) transitivePeerDependencies: - vite @@ -16463,6 +16937,10 @@ snapshots: arrify@3.0.0: {} + as-table@1.0.55: + dependencies: + printable-characters: 1.0.42 + asap@2.0.6: {} ascii-table@0.0.9: {} @@ -16784,6 +17262,8 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + blake3-wasm@2.1.5: {} + blueimp-md5@2.19.0: {} body-parser@1.20.2: @@ -17089,6 +17569,10 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.1: + dependencies: + readdirp: 4.0.2 + chownr@1.1.4: {} chownr@2.0.0: {} @@ -17351,6 +17835,8 @@ snapshots: cookie@0.6.0: {} + cookie@0.7.2: {} + cookie@1.0.2: {} copy-anything@2.0.6: @@ -17497,6 +17983,8 @@ snapshots: cyclist@1.0.2: {} + data-uri-to-buffer@2.0.2: {} + data-uri-to-buffer@3.0.1: {} data-uri-to-buffer@4.0.1: {} @@ -17521,6 +18009,8 @@ snapshots: dataloader@1.4.0: {} + date-fns@4.1.0: {} + date-time@3.1.0: dependencies: time-zone: 1.0.0 @@ -17958,6 +18448,31 @@ snapshots: local-pkg: 0.5.0 resolve.exports: 2.0.2 + esbuild@0.17.19: + optionalDependencies: + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 + esbuild@0.17.6: optionalDependencies: '@esbuild/android-arm': 0.17.6 @@ -18478,6 +18993,8 @@ snapshots: '@types/estree-jsx': 1.0.5 '@types/unist': 3.0.2 + estree-walker@0.6.1: {} + estree-walker@2.0.2: {} estree-walker@3.0.3: @@ -18539,6 +19056,21 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + execa@9.5.2: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.3 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.0 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.2.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + exit-hook@2.2.1: {} expand-brackets@2.1.4: @@ -18828,6 +19360,10 @@ snapshots: escape-string-regexp: 5.0.0 is-unicode-supported: 1.3.0 + figures@6.1.0: + dependencies: + is-unicode-supported: 2.0.0 + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -19110,6 +19646,11 @@ snapshots: get-port@7.1.0: {} + get-source@2.0.12: + dependencies: + data-uri-to-buffer: 2.0.2 + source-map: 0.6.1 + get-stream@5.2.0: dependencies: pump: 3.0.0 @@ -19118,6 +19659,11 @@ snapshots: get-stream@8.0.1: {} + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 @@ -19159,6 +19705,8 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + glob@10.3.12: dependencies: foreground-child: 3.1.1 @@ -19696,6 +20244,8 @@ snapshots: human-signals@5.0.0: {} + human-signals@8.0.0: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -20032,6 +20582,8 @@ snapshots: is-stream@3.0.0: {} + is-stream@4.0.1: {} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.2 @@ -20100,6 +20652,8 @@ snapshots: isobject@3.0.1: {} + itty-time@1.0.6: {} + jackspeak@2.3.6: dependencies: '@isaacs/cliui': 8.0.2 @@ -20502,6 +21056,10 @@ snapshots: macos-release@3.2.0: {} + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + magic-string@0.30.11: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -21471,7 +22029,7 @@ snapshots: min-indent@1.0.1: {} - miniflare@3.20241106.1: + miniflare@3.20241205.0: dependencies: '@cspotcode/source-map-support': 0.8.1 acorn: 8.12.1 @@ -21481,7 +22039,7 @@ snapshots: glob-to-regexp: 0.4.1 stoppable: 1.1.0 undici: 5.28.4 - workerd: 1.20241106.1 + workerd: 1.20241205.0 ws: 8.18.0 youch: 3.3.4 zod: 3.23.8 @@ -21613,6 +22171,8 @@ snapshots: safe-buffer: 5.2.1 uid-safe: 2.1.5 + mustache@4.2.0: {} + mute-stream@0.0.7: {} mute-stream@1.0.0: {} @@ -21626,6 +22186,8 @@ snapshots: nan@2.19.0: optional: true + nano-spawn@0.2.0: {} + nanoassert@2.0.0: {} nanoid@3.3.7: {} @@ -22160,6 +22722,11 @@ snapshots: dependencies: path-key: 4.0.0 + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + npmlog@5.0.1: dependencies: are-we-there-yet: 2.0.0 @@ -22231,6 +22798,8 @@ snapshots: ohash@1.1.3: {} + ohash@1.1.4: {} + omit.js@2.0.2: {} on-exit-leak-free@2.1.2: {} @@ -22525,6 +23094,8 @@ snapshots: parse-ms@3.0.0: {} + parse-ms@4.0.0: {} + parse-node-version@1.0.1: {} parse5-htmlparser2-tree-adapter@7.0.0: @@ -22565,6 +23136,8 @@ snapshots: path-to-regexp@0.1.7: {} + path-to-regexp@6.3.0: {} + path-type@4.0.0: {} path-type@5.0.0: {} @@ -22850,11 +23423,17 @@ snapshots: dependencies: parse-ms: 3.0.0 + pretty-ms@9.2.0: + dependencies: + parse-ms: 4.0.0 + prettyjson@1.2.5: dependencies: colors: 1.4.0 minimist: 1.2.8 + printable-characters@1.0.42: {} + prismjs@1.29.0: {} proc-log@3.0.0: {} @@ -23194,6 +23773,8 @@ snapshots: dependencies: picomatch: 2.3.1 + readdirp@4.0.2: {} + real-require@0.2.0: {} redent@3.0.0: @@ -23619,6 +24200,11 @@ snapshots: dependencies: commander: 2.20.3 + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + semver-diff@4.0.0: dependencies: semver: 7.6.3 @@ -23943,6 +24529,8 @@ snapshots: dependencies: whatwg-url: 7.1.0 + sourcemap-codec@1.4.8: {} + space-separated-tokens@2.0.2: {} spawndamnit@2.0.0: @@ -23992,6 +24580,11 @@ snapshots: stackframe@1.3.4: {} + stacktracey@2.1.8: + dependencies: + as-table: 1.0.55 + get-source: 2.0.12 + starlight-blog@0.11.1(@astrojs/starlight@0.25.5(astro@4.15.9(@types/node@20.14.12)(less@4.2.0)(rollup@4.21.3)(typescript@5.5.4)))(astro@4.15.9(@types/node@20.14.12)(less@4.2.0)(rollup@4.21.3)(typescript@5.5.4)): dependencies: '@astrojs/rss': 4.0.5 @@ -24033,6 +24626,8 @@ snapshots: stdin-discarder@0.2.2: {} + stoppable@1.1.0: {} + stream-replace-string@2.0.0: {} stream-shift@1.0.3: {} @@ -24156,6 +24751,8 @@ snapshots: strip-final-newline@3.0.0: {} + strip-final-newline@4.0.0: {} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -24692,10 +25289,12 @@ snapshots: typescript@5.5.4: {} - uWebSockets.js@https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/442087c0a01bf146acb7386910739ec81df06700: {} + uWebSockets.js@https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/6609a88ffa9a16ac5158046761356ce03250a0df: {} ufo@1.5.3: {} + ufo@1.5.4: {} + uid-safe@2.1.5: dependencies: random-bytes: 1.0.0 @@ -24720,8 +25319,19 @@ snapshots: undici-types@5.26.5: {} + undici@5.28.4: + dependencies: + '@fastify/busboy': 2.1.1 + undici@6.19.7: {} + unenv-nightly@2.0.0-20241204-140205-a5d5190: + dependencies: + defu: 6.1.4 + ohash: 1.1.4 + pathe: 1.1.2 + ufo: 1.5.4 + unenv@1.9.0: dependencies: consola: 3.2.3 @@ -24739,6 +25349,8 @@ snapshots: unicorn-magic@0.1.0: {} + unicorn-magic@0.3.0: {} + unified-engine@11.2.1: dependencies: '@types/concat-stream': 2.0.3 @@ -25118,10 +25730,6 @@ snapshots: '@types/unist': 3.0.2 vfile-message: 4.0.2 - vite-hot-client@0.2.3(vite@5.4.11(@types/node@20.14.12)(less@4.2.0)): - dependencies: - vite: 5.4.11(@types/node@20.14.12)(less@4.2.0) - vite-hot-client@0.2.3(vite@5.4.6(@types/node@20.14.12)(less@4.2.0)): dependencies: vite: 5.4.6(@types/node@20.14.12)(less@4.2.0) @@ -25161,22 +25769,6 @@ snapshots: - supports-color - terser - vite-plugin-inspect@0.8.7(rollup@4.21.3)(vite@5.4.11(@types/node@20.14.12)(less@4.2.0)): - dependencies: - '@antfu/utils': 0.7.10 - '@rollup/pluginutils': 5.1.0(rollup@4.21.3) - debug: 4.3.7(supports-color@9.4.0) - error-stack-parser-es: 0.1.5 - fs-extra: 11.2.0 - open: 10.1.0 - perfect-debounce: 1.0.0 - picocolors: 1.1.0 - sirv: 2.0.4 - vite: 5.4.11(@types/node@20.14.12)(less@4.2.0) - transitivePeerDependencies: - - rollup - - supports-color - vite-plugin-inspect@0.8.7(rollup@4.21.3)(vite@5.4.6(@types/node@20.14.12)(less@4.2.0)): dependencies: '@antfu/utils': 0.7.10 @@ -25193,25 +25785,25 @@ snapshots: - rollup - supports-color - vite-plugin-vue-devtools@7.5.2(rollup@4.21.3)(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)): + vite-plugin-vue-devtools@7.5.2(rollup@4.21.3)(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.12(typescript@5.5.4)): dependencies: - '@vue/devtools-core': 7.5.2(vite@5.4.11(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) + '@vue/devtools-core': 7.5.2(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.12(typescript@5.5.4)) '@vue/devtools-kit': 7.5.2 '@vue/devtools-shared': 7.5.2 execa: 8.0.1 sirv: 2.0.4 - vite: 5.4.11(@types/node@20.14.12)(less@4.2.0) - vite-plugin-inspect: 0.8.7(rollup@4.21.3)(vite@5.4.11(@types/node@20.14.12)(less@4.2.0)) - vite-plugin-vue-inspector: 5.2.0(vite@5.4.11(@types/node@20.14.12)(less@4.2.0)) + vite: 5.4.6(@types/node@20.14.12)(less@4.2.0) + vite-plugin-inspect: 0.8.7(rollup@4.21.3)(vite@5.4.6(@types/node@20.14.12)(less@4.2.0)) + vite-plugin-vue-inspector: 5.2.0(vite@5.4.6(@types/node@20.14.12)(less@4.2.0)) transitivePeerDependencies: - '@nuxt/kit' - rollup - supports-color - vue - vite-plugin-vue-devtools@7.5.2(rollup@4.21.3)(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.12(typescript@5.5.4)): + vite-plugin-vue-devtools@7.5.2(rollup@4.21.3)(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)): dependencies: - '@vue/devtools-core': 7.5.2(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.12(typescript@5.5.4)) + '@vue/devtools-core': 7.5.2(vite@5.4.6(@types/node@20.14.12)(less@4.2.0))(vue@3.5.8(typescript@5.5.4)) '@vue/devtools-kit': 7.5.2 '@vue/devtools-shared': 7.5.2 execa: 8.0.1 @@ -25225,21 +25817,6 @@ snapshots: - supports-color - vue - vite-plugin-vue-inspector@5.2.0(vite@5.4.11(@types/node@20.14.12)(less@4.2.0)): - dependencies: - '@babel/core': 7.25.2 - '@babel/plugin-proposal-decorators': 7.24.1(@babel/core@7.25.2) - '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.25.2) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-transform-typescript': 7.24.7(@babel/core@7.25.2) - '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.25.2) - '@vue/compiler-dom': 3.5.12 - kolorist: 1.8.0 - magic-string: 0.30.11 - vite: 5.4.11(@types/node@20.14.12)(less@4.2.0) - transitivePeerDependencies: - - supports-color - vite-plugin-vue-inspector@5.2.0(vite@5.4.6(@types/node@20.14.12)(less@4.2.0)): dependencies: '@babel/core': 7.25.2 @@ -25711,6 +26288,41 @@ snapshots: assert-never: 1.2.1 babel-walk: 3.0.0-canary-5 + workerd@1.20241205.0: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20241205.0 + '@cloudflare/workerd-darwin-arm64': 1.20241205.0 + '@cloudflare/workerd-linux-64': 1.20241205.0 + '@cloudflare/workerd-linux-arm64': 1.20241205.0 + '@cloudflare/workerd-windows-64': 1.20241205.0 + + wrangler@3.95.0: + dependencies: + '@cloudflare/kv-asset-handler': 0.3.4 + '@cloudflare/workers-shared': 0.11.0 + '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) + '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) + blake3-wasm: 2.1.5 + chokidar: 4.0.1 + date-fns: 4.1.0 + esbuild: 0.17.19 + itty-time: 1.0.6 + miniflare: 3.20241205.0 + nanoid: 3.3.7 + path-to-regexp: 6.3.0 + resolve: 1.22.8 + selfsigned: 2.4.1 + source-map: 0.6.1 + unenv: unenv-nightly@2.0.0-20241204-140205-a5d5190 + workerd: 1.20241205.0 + xxhash-wasm: 1.0.2 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -25762,6 +26374,8 @@ snapshots: ws@8.17.1: {} + ws@8.18.0: {} + xdg-basedir@5.1.0: {} xml-name-validator@4.0.0: {} @@ -25859,6 +26473,14 @@ snapshots: yocto-queue@1.1.1: {} + yoctocolors@2.1.1: {} + + youch@3.3.4: + dependencies: + cookie: 0.7.2 + mustache: 4.2.0 + stacktracey: 2.1.8 + zhead@2.2.4: {} zip-stream@5.0.2: