void 0.10.10 → 0.10.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_PROMPT.md +4 -0
- package/README.md +1 -1
- package/dist/{agents-Bmr5tFFb.mjs → agents-CtgBYqld.mjs} +1 -1
- package/dist/{auth-cmd-Cw1edJdZ.mjs → auth-cmd-BqsdZJp5.mjs} +3 -3
- package/dist/{better-auth-shared-BvnM9px6.d.mts → better-auth-shared-DealXecJ.d.mts} +1 -1
- package/dist/{build-cmd-C6kNDJBv.mjs → build-cmd-Bujrv5q-.mjs} +3 -3
- package/dist/{cache-DIUSnIjJ.mjs → cache-C11V8Fxq.mjs} +3 -3
- package/dist/{cancel-deploy-BosnzEHC.mjs → cancel-deploy-fwFYF04b.mjs} +2 -2
- package/dist/cli/cli.mjs +124 -41
- package/dist/cli/env-schema-probe.d.mts +96 -0
- package/dist/cli/env-schema-probe.mjs +272 -0
- package/dist/{client-C9FG6Vzc.mjs → client-Gb71-XkG.mjs} +12 -2
- package/dist/{config-BcAeIPe3.mjs → config-BkTvs43g.mjs} +15 -2
- package/dist/{config-BdUctCZD.mjs → config-CutEMNGJ.mjs} +3 -3
- package/dist/{create-project-CjYX23M_.mjs → create-project-DsYvl3TB.mjs} +3 -3
- package/dist/{db-BvKV34IK.mjs → db-DOiJMRt2.mjs} +27 -27
- package/dist/{delete-CThKLXfi.mjs → delete-mh6p-zkQ.mjs} +3 -3
- package/dist/deploy-u7Rv9q_q.mjs +7126 -0
- package/dist/{discover-BuVVSAum.mjs → discover-CJHyvYfR.mjs} +2 -2
- package/dist/dist-DaKKDf8D.mjs +41 -0
- package/dist/{domain-DMrBabBQ.mjs → domain-DiaNQbrl.mjs} +2 -2
- package/dist/entry-D7yy4xVH.mjs +100 -0
- package/dist/{env-BfG7O71F.mjs → env-CZy5MorI.mjs} +5 -5
- package/dist/env-mask-Dd47NbR6.mjs +90 -0
- package/dist/env-public-BfiLcMBk.d.mts +140 -0
- package/dist/{env-types-D51bnR-c.mjs → env-types-QBj-ndax.mjs} +2 -2
- package/dist/env-validation-Dea3v3ej.mjs +1069 -0
- package/dist/{gen-Bee261SV.mjs → gen-o_w-8yI8.mjs} +8 -8
- package/dist/{git-metadata-CBKaL0v5.mjs → git-metadata-D-gurjzG.mjs} +6 -5
- package/dist/{github-cmd-DfeFEasr.mjs → github-cmd-DKcGUNsj.mjs} +4 -4
- package/dist/{handler-imD0UVDT.d.mts → handler-Cjh8uM3Y.d.mts} +1 -1
- package/dist/{headers-CTAjX-UO.mjs → headers-nsHIFixA.mjs} +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +98 -52
- package/dist/{init-xfwW7cLp.mjs → init-3rgHKBVi.mjs} +13 -14
- package/dist/{link-Co136MEs.mjs → link-CdGHSIy-.mjs} +4 -4
- package/dist/{list-BKDjA3M5.mjs → list-CPwFDZ_c.mjs} +3 -3
- package/dist/{login-CrOTnR_6.mjs → login-BT3H8PN3.mjs} +2 -2
- package/dist/{logs-DlAg25ww.mjs → logs-Bt313ax7.mjs} +3 -2
- package/dist/{mcp-BNjMGMB0.mjs → mcp-DoM3_nhd.mjs} +7 -2
- package/dist/{node-CnE-SZCk.mjs → node-Da0UcsGA.mjs} +5 -5
- package/dist/{package-json-B0NuUWGd.mjs → package-json-Cx1osYo6.mjs} +1 -1
- package/dist/pages/client.d.mts +1 -1
- package/dist/pages/index.d.mts +1 -23
- package/dist/pages/index.mjs +5 -5
- package/dist/pages/islands-plugin.mjs +2 -2
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/{plugin-inference-CJxi_fWI.mjs → plugin-inference-DMeavIJ6.mjs} +4 -98
- package/dist/{prepare-BRyC4TCC.mjs → prepare-BoKHgMNx.mjs} +10 -10
- package/dist/preset-BjyR3lzz.mjs +592 -0
- package/dist/{project-cmd-B2bcKefD.mjs → project-cmd-D_w-4w5B.mjs} +13 -9
- package/dist/{project-paths-tpdR1mJR.mjs → project-paths-BQd7OmIo.mjs} +1 -1
- package/dist/project-paths-GpziKeQQ.d.mts +25 -0
- package/dist/{project-tsconfig-D9uSVVpA.mjs → project-tsconfig-B-QtXjLQ.mjs} +2 -2
- package/dist/{protocol-6hTJ04T1.d.mts → protocol-Bnb0LFp3.d.mts} +1 -1
- package/dist/provision-rShh6MKY.mjs +2557 -0
- package/dist/requests-B8sZxaFM.mjs +50 -0
- package/dist/{resolve-project-D2HI3TrG.mjs → resolve-project-BBMtLLV9.mjs} +1 -1
- package/dist/{rollback-9dfmB-YZ.mjs → rollback-CkvTFXx5.mjs} +2 -2
- package/dist/{route-types-CfKfhbIg.mjs → route-types-COI2DsZv.mjs} +2 -2
- package/dist/{runner-h272wcPj.mjs → runner-kapo9aPs.mjs} +3 -3
- package/dist/{runner-pg-waxJOnBb.mjs → runner-pg-CHM76xuC.mjs} +1 -1
- package/dist/runtime/better-auth-pg.d.mts +1 -1
- package/dist/runtime/better-auth.d.mts +1 -1
- package/dist/runtime/env-public.d.mts +1 -139
- package/dist/runtime/env-public.mjs +2 -90
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +1 -1
- package/dist/runtime/ws.d.mts +2 -2
- package/dist/{scan-Dp_Gyzs3.mjs → scan-DEwlM_Xy.mjs} +2 -2
- package/dist/{scan-i7Yz54fv.mjs → scan-DYXkrasO.mjs} +4 -4
- package/dist/{secret-DeMnMcV0.mjs → secret-Dt32J6RI.mjs} +3 -3
- package/dist/{skills-DsdNDtX3.mjs → skills-CLjN0uUO.mjs} +2 -2
- package/dist/{subcommand-prompt-DtES-oP6.mjs → subcommand-prompt-BzV8iQZo.mjs} +1 -1
- package/dist/sveltekit.mjs +1 -1
- package/dist/{validate-DT7nFMlf.mjs → validate-Cw_RLeTj.mjs} +1 -1
- package/dist/{yarn-pnp-CW8LB6g_.mjs → yarn-pnp-DJn3SAHF.mjs} +1 -1
- package/getting-started-prompt.txt +3 -1
- package/package.json +5 -3
- package/schema.json +5 -0
- package/skills/void/SKILL.md +34 -33
- package/skills/void/docs/guide/app-types.md +43 -0
- package/skills/void/docs/guide/auth.md +8 -0
- package/skills/void/docs/guide/deployment.md +1 -1
- package/skills/void/docs/guide/edge/static-assets.md +23 -0
- package/skills/void/docs/guide/env-vars.md +14 -6
- package/skills/void/docs/guide/queues.md +4 -0
- package/skills/void/docs/integrations/cloudflare.md +64 -5
- package/skills/void/docs/integrations/frameworks/overview.md +1 -0
- package/skills/void/docs/node_modules/void/AGENT_PROMPT.md +4 -0
- package/skills/void/docs/node_modules/void/README.md +1 -1
- package/skills/void/docs/node_modules/void/node_modules/@types/proper-lockfile/README.md +51 -0
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/pathslash/README.md +64 -0
- package/skills/void/docs/node_modules/void/node_modules/pathslash/README.md +64 -0
- package/skills/void/docs/node_modules/void/node_modules/proper-lockfile/CHANGELOG.md +108 -0
- package/skills/void/docs/node_modules/void/node_modules/proper-lockfile/README.md +183 -0
- package/skills/void/docs/node_modules/void/skills/void/SKILL.md +34 -33
- package/skills/void/docs/node_modules/void/test/e2e/README.md +85 -0
- package/skills/void/docs/reference/cli.md +74 -14
- package/skills/void/docs/reference/config.md +27 -1
- package/dist/deploy-B02JyKP9.mjs +0 -3748
- package/dist/dotenv-D_UbC_vc.mjs +0 -173
- package/dist/env-validation-CeC2FL66.mjs +0 -163
- package/dist/pathe.M-eThtNZ-CQzLbt4c.mjs +0 -150
- package/dist/preset-CVvwCeIy.mjs +0 -208
- package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/pathe/README.md +0 -73
- package/skills/void/docs/node_modules/void/node_modules/pathe/README.md +0 -73
|
@@ -73,6 +73,48 @@ At the edge, the resolution order is:
|
|
|
73
73
|
|
|
74
74
|
**Deploy:** `void deploy` or `void deploy --dir <path>` uploads static files directly. Assets are served from the edge with automatic caching.
|
|
75
75
|
|
|
76
|
+
## Adding a backend to a static site
|
|
77
|
+
|
|
78
|
+
A static site generator plus a few API routes is a Void app, not a static site. Auto-detection sees the SSG dependency first (priority 2 below), so if you leave `inference.appType` unset, `void deploy` refuses rather than deploying the site and silently dropping `routes/`. Tell it which you meant.
|
|
79
|
+
|
|
80
|
+
To deploy the site **and** the backend, run both builds from one command and let Void's build fold the generated site into its client output:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
// void.json
|
|
84
|
+
{
|
|
85
|
+
"inference": {
|
|
86
|
+
"appType": "void",
|
|
87
|
+
"build": "vitepress build && vite build"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
// vite.config.ts
|
|
94
|
+
import { defineConfig } from 'vite';
|
|
95
|
+
import { voidPlugin } from 'void';
|
|
96
|
+
|
|
97
|
+
export default defineConfig({
|
|
98
|
+
plugins: [voidPlugin()],
|
|
99
|
+
// The SSG's output becomes the static assets of the Void build.
|
|
100
|
+
publicDir: '.vitepress/dist',
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`vitepress build` emits the site, then `vite build` copies `publicDir` into `dist/client` and emits the worker into `dist/ssr`. Keep `voidPlugin()` in the **root** `vite.config.ts` only — not in the generator's own config (e.g. `.vitepress/config.ts`).
|
|
105
|
+
|
|
106
|
+
Because the worker now owns unmatched requests, add [`routing.notFound`](../reference/config.md#routing-notfound) if you want the generator's `404.html` instead of the SPA-style `index.html` fallback:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{ "routing": { "notFound": "404-page" } }
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
To deploy the static output only and **not** the backend, say so explicitly:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{ "inference": { "appType": "static" } }
|
|
116
|
+
```
|
|
117
|
+
|
|
76
118
|
## Auto-Detection
|
|
77
119
|
|
|
78
120
|
When running `void deploy` and no `inference.appType` is set in `void.json`, the detection logic runs in this order:
|
|
@@ -81,6 +123,7 @@ When running `void deploy` and no `inference.appType` is set in `void.json`, the
|
|
|
81
123
|
| -------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
82
124
|
| 1 | `--dir` flag | Static (or SPA with `--spa`) |
|
|
83
125
|
| 2 | Known SSG in dependencies (`vitepress`, `@docusaurus/core`) | Static, builds with SSG CLI |
|
|
126
|
+
| 2a | ...and backend files also exist | Refused — set `inference.appType` yourself |
|
|
84
127
|
| 3 | `@tanstack/react-start`, `@react-router/dev`, `@sveltejs/kit`, `nuxt`, `@analogjs/platform`, or `astro` in deps | Framework |
|
|
85
128
|
| 4 | Backend files exist (`routes/`, `pages/`, `middleware/`, `crons/`, `queues/`, SSR entry) | Void app |
|
|
86
129
|
| 5 | `vite` or `vite-plus` in dependencies, no backend files | SPA, builds with `vite build` or `vp build` |
|
|
@@ -249,6 +249,14 @@ Void manages Better Auth migrations as part of the normal Void migration flow:
|
|
|
249
249
|
- deploy runs auth migrations together with app migrations
|
|
250
250
|
- users do not run a separate Better Auth CLI path
|
|
251
251
|
|
|
252
|
+
This applies to `void deploy` (the managed platform), which creates the Better Auth
|
|
253
|
+
tables at runtime after dispatch. Deploying to your own Cloudflare account with
|
|
254
|
+
[`--backend cloudflare`](/integrations/cloudflare) does **not** run that step: there,
|
|
255
|
+
your checked-in `db/migrations/*.sql` must already produce the Better Auth schema, and
|
|
256
|
+
deploy fails closed if they do not. Define the tables in `db/schema.ts` and run
|
|
257
|
+
`void db generate` — Drizzle's `.unique()` and `.references()` are opt-in, and the
|
|
258
|
+
constraints are verified too. See [#274](https://github.com/voidzero-dev/void/issues/274).
|
|
259
|
+
|
|
252
260
|
## Unsupported Modes
|
|
253
261
|
|
|
254
262
|
Void-managed Better Auth is supported only for Cloudflare Void apps in v1.
|
|
@@ -106,6 +106,6 @@ Connect the repository to your project once with `void github connect <project>
|
|
|
106
106
|
|
|
107
107
|
## Other Targets
|
|
108
108
|
|
|
109
|
-
If you prefer to deploy directly to your own Cloudflare account instead of using Void's managed platform,
|
|
109
|
+
If you prefer to deploy directly to your own Cloudflare account instead of using Void's managed platform, run `void deploy --backend cloudflare` (add `--provision` on the first deploy to create the D1/KV/R2/Queues/Hyperdrive resources your app needs). This uses your local wrangler auth and root `wrangler.jsonc` -- pin an account (`account_id` or `CLOUDFLARE_ACCOUNT_ID`) and keep real secrets in `wrangler secret put` rather than `.env`. `wrangler login` is enough to authenticate, with one exception: provisioning a **Hyperdrive** config for the first time needs `CLOUDFLARE_API_TOKEN`, because wrangler exposes no machine-readable Hyperdrive list for Void to check against (an already-provisioned Hyperdrive app deploys fine under `wrangler login`). In v1 it deploys **full Void apps on the Cloudflare Workers target** (D1/KV/R2/Queues/Hyperdrive; auth and ISR on D1/SQLite); framework SSR (TanStack Start, React Router, vinext, SvelteKit, Nuxt, Analog, Astro), static/SPA/SSG apps (including `output: "static"`), WebSocket/Durable Object apps (`*.ws.ts`), a custom `migrations_pattern`, `--skip-build`, `node`/`bun`/`deno` targets, and PostgreSQL apps with auth all fail closed with guidance. Auth apps must ship checked-in migrations that produce the Better Auth schema. Provision is a single-operator, dev-machine step and is disabled in CI. See the [Cloudflare integration guide](../integrations/cloudflare.md#deploy-to-your-own-cloudflare-account) for the full walk-through and scope.
|
|
110
110
|
|
|
111
111
|
To deploy to Node.js, Bun, or Deno instead of Cloudflare, set [`target`](../reference/config.md) in `void.json`. This builds a standalone server you can run anywhere, including Docker, Railway, and Fly.io. These targets do not have access to Void platform features such as D1, KV, R2, built-in auth, Workers AI, or cron scheduling. See the [Node.js, Bun, and Deno guide](../integrations/nodejs-bun-deno.md).
|
|
@@ -97,6 +97,29 @@ This is the path needed for preview auth and other middleware. Cloudflare's plat
|
|
|
97
97
|
|
|
98
98
|
For Void apps with only `/api` routes, Void keeps the platform SPA fallback and scopes `run_worker_first` to `/api` and `/api/*`. Static assets and non-API SPA navigations stay on the asset platform. API requests, including browser document navigations such as OAuth callbacks, reach the worker instead of being rewritten to `index.html`.
|
|
99
99
|
|
|
100
|
+
### Unmatched requests
|
|
101
|
+
|
|
102
|
+
`not_found_handling` decides what the asset layer does with a request that matched no asset and no worker route. Void infers it:
|
|
103
|
+
|
|
104
|
+
| App shape | Inferred value | Result for an unknown URL |
|
|
105
|
+
| ------------------------------------------------- | -------------------------------- | -------------------------------- |
|
|
106
|
+
| Pages or SSR | `none` | The worker's own 404 |
|
|
107
|
+
| Worker owns HTML, no `pages/`, no SSR entry | `none` + worker fallback | `index.html` with status **200** |
|
|
108
|
+
| Asset-first (only `/api` routes, or none) | `single-page-application` | `index.html` with status **200** |
|
|
109
|
+
| Framework deploy (SvelteKit, Nuxt, Analog, Astro) | `none` — pinned, not overridable | The framework worker's own 404 |
|
|
110
|
+
|
|
111
|
+
The middle row is a worker with `middleware/`, a route outside `/api`, a document websocket, or Live, but no `pages/` and no SSR entry. `run_worker_first: ['/**']` sends everything to the worker, which bypasses the platform's SPA switch, so the generated worker does that fallback itself for HTML navigations — after your middleware has run, so auth gates and OAuth callbacks still see the request first.
|
|
112
|
+
|
|
113
|
+
The SPA fallback is right for a single-page app, where deep links must boot the client router. It is wrong for a site whose HTML was generated per page: unknown URLs return 200 instead of 404, and the generator's `404.html` is never served. Nothing in a built asset tree distinguishes the two, so Void does not guess — override it with [`routing.notFound`](../../reference/config.md#routing-notfound):
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{ "routing": { "notFound": "404-page" } }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Accepted values are `"single-page-application"`, `"404-page"`, and `"none"`. `run_worker_first` keeps its inferred value, so API routes, auth, and `/__void/*` still reach the worker first. Setting anything other than `"single-page-application"` also turns off the worker-side `index.html` fallback described above — otherwise it would answer the request before `not_found_handling` was ever consulted. With `"404-page"` the worker serves whatever the asset binding returns for the unmatched path, which is Cloudflare's nearest `404.html` — but only for HTML navigations (requests whose `Accept` includes `text/html`), so an API route that deliberately returns a 404 keeps its own body, status and headers. If the build has no `404.html`, the worker's own 404 is kept.
|
|
120
|
+
|
|
121
|
+
The last row is the exception: `routing.notFound` is **ignored** for SvelteKit, Nuxt, Analog, and Astro deploys, and `void deploy` warns when you set it. Those deploys emit no `run_worker_first`, so the asset layer already answers first and real prerendered files win — `not_found_handling` would only change what the framework's own `env.ASSETS.fetch()` delegation returns, where `"single-page-application"` turns genuine 404s into the prerendered home page at 200 and `"404-page"` takes the 404 away from the framework's own error route. TanStack Start and React Router deploys are not affected; they follow the rows above.
|
|
122
|
+
|
|
100
123
|
### Generated config
|
|
101
124
|
|
|
102
125
|
Void owns the generated asset routing policy during dev and build. If a root `wrangler.jsonc` contains stale `not_found_handling` or `run_worker_first` values, Void replaces those fields so generated config cannot accidentally change which layer sees a request first.
|
|
@@ -109,15 +109,23 @@ In practice `env.ts` should only import schema helpers from `void/env` and — a
|
|
|
109
109
|
|
|
110
110
|
Void uses Vite's standard `.env` convention to populate the schema:
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
|
115
|
-
|
|
|
116
|
-
| `.env
|
|
117
|
-
| `.env.
|
|
112
|
+
Whether a file's values ship depends on which deploy path you use:
|
|
113
|
+
|
|
114
|
+
| File | Loaded in dev | Shipped by `void deploy` | Shipped by `--backend cloudflare` |
|
|
115
|
+
| ----------------------- | ------------- | ------------------------ | --------------------------------- |
|
|
116
|
+
| `.env` | yes | yes (`plain_text`) | yes (worker `vars`) |
|
|
117
|
+
| `.env.local` | yes | no | **yes** (worker `vars`) |
|
|
118
|
+
| `.env.production` | yes | yes (`plain_text`) | yes (worker `vars`) |
|
|
119
|
+
| `.env.production.local` | yes | no | **yes** (worker `vars`) |
|
|
118
120
|
|
|
119
121
|
`.local` files are gitignored by convention — use them for secrets you don't want in source control.
|
|
120
122
|
|
|
123
|
+
::: warning `.local` files are not deploy-excluded on `--backend cloudflare`
|
|
124
|
+
Managed `void deploy` reads only `.env` and `.env.production`, so a `.local` file keeps secrets off the platform. The self-host `void deploy --backend cloudflare` path instead runs Vite's production env loading, which reads all four files and bakes them into the worker's `vars` as plaintext. A value that is also `export`ed in the shell with the same value is stripped back out, so this bites hardest in CI, where the variable usually only exists in the file.
|
|
125
|
+
|
|
126
|
+
On that path, keep real secrets out of every `.env*` file and use `wrangler secret put <NAME>` instead. See [Cloudflare deploy](/integrations/cloudflare).
|
|
127
|
+
:::
|
|
128
|
+
|
|
121
129
|
### Dotenv variable expansion
|
|
122
130
|
|
|
123
131
|
Values can reference other keys defined in the same (or earlier-precedence) `.env` file using `${VAR}` or `$VAR`:
|
|
@@ -10,6 +10,10 @@ Void supports Cloudflare Queues for asynchronous message processing from a top-l
|
|
|
10
10
|
|
|
11
11
|
Create files in `queues/**/*.ts`; `.mts`, `.js`, and `.mjs` also work. The queue name is inferred from the filename. For example, `queues/emails.ts` creates a queue named `"emails"`, and `queues/order/notifications.ts` creates `"order/notifications"`.
|
|
12
12
|
|
|
13
|
+
::: warning Nested files produce a name that cannot be deployed
|
|
14
|
+
Cloudflare queue names allow only letters, digits and `-`, so a name containing `/` is rejected when the queue is provisioned — on both the managed platform and a self-hosted `--backend cloudflare` deploy. Nested files work in local development, but keep queue files flat (`queues/order-notifications.ts` → `"order-notifications"`) for any app you intend to deploy.
|
|
15
|
+
:::
|
|
16
|
+
|
|
13
17
|
Each queue file should export a default handler wrapped with [`defineQueue`](../reference/api.md#definequeuet-handler). The generic `<T>` parameter defines the message body type. That is the type of each `msg.body` in the batch, and it is also used by the typed `queues` proxy for `send()` calls.
|
|
14
18
|
|
|
15
19
|
```ts
|
|
@@ -214,9 +214,68 @@ When deploying via `void deploy` (to the Void platform), the `wrangler.json` in
|
|
|
214
214
|
|
|
215
215
|
## Deploy to your own Cloudflare account
|
|
216
216
|
|
|
217
|
-
Void's default deployment path is `void deploy`, which uploads to the Void platform. But the generated worker is a standard Cloudflare Worker -- you can deploy it directly to your own account
|
|
217
|
+
Void's default deployment path is `void deploy`, which uploads to the Void platform. But the generated worker is a standard Cloudflare Worker -- you can deploy it directly to your own account. Two paths get you there:
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
- **[`void deploy --backend cloudflare`](#one-command-void-deploy-backend-cloudflare)** -- a first-class flow that provisions bindings, applies remote migrations, checks secrets, builds, and runs `wrangler deploy` for you.
|
|
220
|
+
- **[Manual `vite build && wrangler deploy`](#manual-build-and-deploy-with-wrangler)** -- create resources and edit `wrangler.jsonc` yourself, then build and deploy with wrangler directly.
|
|
221
|
+
|
|
222
|
+
Either way, the [Local development](#local-development), [AI](#ai-self-host), and [ISR](#isr-self-host) notes below apply.
|
|
223
|
+
|
|
224
|
+
### One command: `void deploy --backend cloudflare`
|
|
225
|
+
|
|
226
|
+
`void deploy --backend cloudflare` deploys the built worker to **your own** Cloudflare account. It uses your local wrangler auth and your root `wrangler.jsonc` -- there is no Void login or linked project.
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Deploy using the resources already declared in wrangler.jsonc
|
|
230
|
+
void deploy --backend cloudflare
|
|
231
|
+
|
|
232
|
+
# Create any missing resources first, then deploy
|
|
233
|
+
void deploy --backend cloudflare --provision
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Prerequisites**
|
|
237
|
+
|
|
238
|
+
- **Pin an account.** Set `account_id` in your root `wrangler.jsonc`, or export `CLOUDFLARE_ACCOUNT_ID`. A multi-account token otherwise makes wrangler prompt (or error in CI), which Void cannot intercept -- so the account must be pinned first.
|
|
239
|
+
- **Authenticate wrangler.** Run `wrangler login`, or set `CLOUDFLARE_API_TOKEN`. Deploy needs a token with `Workers Scripts:Edit` plus read on the resources you bind. `--provision` additionally needs per-product `*:Edit` (D1, KV, R2, Queues, Hyperdrive).
|
|
240
|
+
- **`CLOUDFLARE_API_TOKEN` is required to provision a Hyperdrive config for the first time.** `wrangler login` covers every other resource, but wrangler exposes no machine-readable Hyperdrive list, so Void checks whether the config already exists over the Cloudflare REST API -- which an OAuth session cannot authenticate. Without a token `--provision` stops **before** touching your account rather than risk minting a duplicate config. Either export `CLOUDFLARE_API_TOKEN` (with Hyperdrive edit permission), or create the Hyperdrive config yourself and add its id to the `hyperdrive` binding in `wrangler.jsonc` -- deploying an **already-provisioned** Hyperdrive app needs no token and works under `wrangler login` alone.
|
|
241
|
+
- **Docker**, if your app uses the sandbox -- the build needs it locally.
|
|
242
|
+
|
|
243
|
+
**What it does** (in order): settles the app class (a full Void app on the Cloudflare Workers target -- see [scope](#scope-and-limitations)) before any account operation; pins the account and confirms wrangler auth; provisions or drift-checks resources; **builds**; then, against the artifact the build actually emitted, warns on plaintext vars, gates on missing required secrets, checks the auth schema, and validates migrations; then applies remote D1 migrations for SQLite apps (and verifies none remain pending); then runs `wrangler deploy` on exactly the artifact it verified.
|
|
244
|
+
|
|
245
|
+
Note that **the build runs before the secret, auth-schema, and migration gates** -- those gates read the real emitted worker, so there has to be one to read. A missing production secret or a bad migration is therefore reported _after_ the build has run, which is worth knowing if your build hooks are slow or have side effects. In exchange, nothing remote is touched until every ground-truth gate has passed: remote D1 migrations are applied only afterwards, so a failed gate leaves your account, your database, and your live worker exactly as they were.
|
|
246
|
+
|
|
247
|
+
**Trust boundary: the build runs your project's code.** Exactly like the manual `vite build && wrangler deploy` below, this backend runs your project's build -- your config, every Vite plugin, and every build dependency -- with filesystem access before the credentialed deploy. Deploy narrows what that build can quietly change: it runs the build with your Cloudflare credentials scrubbed, verifies the emitted `wrangler.json` against a pre-build snapshot of your account, name, and binding identities, and checks that the wrangler CLI it is about to run with your token was not modified during the build. Those checks catch a build that tampers with the deploy target or the uploader. They do not sandbox the build itself, so a fully-compromised build dependency remains a trust boundary -- the same one you accept running `vite build` by hand. Vet your dependencies as you would for any deploy; stronger build isolation is future work.
|
|
248
|
+
|
|
249
|
+
Without `--provision`, deploy is a **drift check**: if a binding your source needs is not yet in `wrangler.jsonc` with a real id, deploy stops and names each missing resource, telling you to run `--provision` once. Queues carry no id in the config, so deploy instead checks each one against your account (`wrangler queues info`) at the same point -- a queue that does not exist stops the deploy before anything is built or migrated.
|
|
250
|
+
|
|
251
|
+
**`--provision`** creates any D1 database, KV namespace, R2 bucket, Queues, Hyperdrive config, and the ISR cache namespace your source needs, then lets wrangler write the real ids into your root `wrangler.jsonc`. It is **idempotent** -- it reads existing ids first, so re-running creates nothing that already exists.
|
|
252
|
+
|
|
253
|
+
#### Scope and limitations
|
|
254
|
+
|
|
255
|
+
- **Supported apps (v1): full Void apps on the Cloudflare Workers target only** -- worker-bearing apps that run Void's routing (`routes/` and/or `pages/`), with D1 (SQLite) and/or KV, R2, Queues, and Hyperdrive, plus auth on D1/SQLite and ISR. Everything else fails closed **before** any account operation, with guidance:
|
|
256
|
+
- **Framework SSR is not supported here (yet).** The whole framework path -- TanStack Start, React Router, vinext (and SvelteKit, Nuxt, Analog, Astro) -- is deferred in v1. Deploy them with `void deploy` (the managed platform) or the framework's own Cloudflare adapter. Framework SSR support for this backend is a follow-up.
|
|
257
|
+
- **Static-only / SPA / SSG apps are not supported here** -- including unconfigured ones, `output: "static"` in `void.json`, and `--dir` / `--spa` deploys. Deploy those with `void deploy` (the managed platform) or host the built assets on Cloudflare Pages / any static host.
|
|
258
|
+
- **WebSocket / Durable Object routes (`*.ws.ts`) are not supported here (yet).** A WebSocket route makes the build emit a key-value-backed Durable Object namespace (a `new_classes` migration), which a fresh Cloudflare account -- and every Workers Free account -- refuses to create. Deploy those with `void deploy`. SQLite-backed WebSocket support for this backend is a follow-up.
|
|
259
|
+
- **Custom `migrations_pattern` is not supported here.** v1 deploys only Void's default migration convention -- `db/migrations/*.sql` with wrangler's default pattern (leave `migrations_pattern` unset). Remove a custom `migrations_pattern` from the D1 binding, or deploy with `void deploy`. Supporting custom patterns is a follow-up.
|
|
260
|
+
- **Non-Cloudflare targets (`node` / `bun` / `deno`) are not supported here** -- this backend deploys Cloudflare Workers only.
|
|
261
|
+
- **`--skip-build` is not supported here.** Every check on this path validates the artifact the build emits -- the worker `vars` in `dist/ssr/wrangler.json` and the generated auth schema -- so skipping the build would leave them reading a stale or missing artifact instead of the worker being uploaded. Drop `--skip-build`, or use `void deploy` (the managed platform), which supports it.
|
|
262
|
+
- **PostgreSQL apps with auth enabled are not supported here.** This backend verifies + applies auth tables through remote D1 (SQLite) migrations only, so it cannot provision or verify the Better Auth schema on Postgres/Hyperdrive. Deploy with `void deploy`, or use D1 for the auth app.
|
|
263
|
+
- **PostgreSQL apps with checked-in migrations are not supported here.** This backend applies only remote D1 (SQLite) migrations. A PostgreSQL app's `db/migrations/*.sql` are applied over Hyperdrive by the managed platform (`void deploy`) at deploy time; this self-host backend never runs them, so it would deploy against an unmigrated database. Deploy with `void deploy`, or apply the migrations yourself against your Postgres and remove them from `db/migrations/`. (A pg app _without_ auth **and** with an externally-managed schema — no checked-in migrations — still deploys.)
|
|
264
|
+
- **Auth requires checked-in migrations that produce the Better Auth schema.** The managed platform creates the Better Auth tables at runtime after deploy; this self-host backend never runs that step. Deploy reads the required Better Auth schema from the one the build itself generated (`.void/better-auth-schema.ts`, so configured renames and plugin tables are already reflected), then verifies the checked-in `db/migrations/*.sql` produce it by applying them to an in-memory SQLite database. Names alone are not enough: it also checks the constraints that carry correctness -- every auth table's `id` must be uniquely constrained (a `PRIMARY KEY` or a `UNIQUE` constraint/index; SQLite refuses a foreign key whose parent key is not unique, failing at runtime with `foreign key mismatch`), every field the schema marks `unique` must be covered by a unique constraint (a column-level `UNIQUE` or a single-column unique index both count, under any index name), and every field with a `references` target must have a matching foreign key. Column types, non-unique indexes and the exact `ON DELETE` action are deliberately not asserted. If a check fails, deploy fails closed naming the offending `table.column` -- fix the schema in `db/schema.ts` (Drizzle's `.primaryKey()`, `.unique()` and `.references()` are opt-in), run `void db generate`, commit the migration, or deploy with `void deploy`.
|
|
265
|
+
- **Migrations must apply in the same order Void validated.** Deploy checks that the files wrangler will apply to remote D1 (and the order it applies them, by numeric prefix) exactly match Void's `db/migrations/*.sql` set -- no stray files (e.g. `seed.sql`), same content, same order. Zero-pad your migration prefixes (`0001_`, `0002_`, ...) so numeric and lexicographic order agree; deploy fails closed on a mismatch.
|
|
266
|
+
- **Provision is a single-operator, dev-machine action.** The lock guarding it is per local config path only; it does not coordinate across machines or CI hosts. Two people provisioning the same account at once could create duplicate resources.
|
|
267
|
+
- **Provision fails closed in CI.** In non-interactive shells, `--provision` is disabled unless your committed `wrangler.jsonc` already covers every resource (a provable no-op). The workflow is: provision **locally**, commit the updated `wrangler.jsonc`, then let CI run `void deploy --backend cloudflare` (deploy itself is CI-safe).
|
|
268
|
+
- **Your `wrangler.jsonc` is rewritten on provision.** Wrangler preserves your comments but normalizes the whole file's indentation when it writes the new ids -- expect that in the diff.
|
|
269
|
+
- **Your `.env*` values ship as plaintext.** The build bakes them into the worker's `vars`. This backend runs Vite's production env loading, so **all four** of `.env`, `.env.local`, `.env.production` and `.env.production.local` are loaded and shipped -- including the `.local` files, which are gitignored but **not** deploy-excluded here (unlike managed `void deploy`, which reads only `.env` and `.env.production`). The one exception: a value that is also present in the shell environment with the same value is stripped back out, so a var you `export` in CI does not get baked in. Move real secrets to `wrangler secret put <NAME>` so they are never written into `wrangler.json`. Deploy warns on likely-plaintext secrets -- by key name, and by value shape for credential-bearing connection URLs such as `DATABASE_URL` -- and hard-blocks on missing required secrets.
|
|
270
|
+
- **First deploy of a new worker.** A worker that has never been deployed has no remote secrets to list yet, so the secret gate prints the still-unset required key names and the `wrangler secret put <NAME>` commands that bootstrap them on the draft worker (or add a value to `.env` / `.env.production` and rerun).
|
|
271
|
+
|
|
272
|
+
The manual steps below are the by-hand equivalent -- reach for them when you want to manage resources and `wrangler.jsonc` yourself.
|
|
273
|
+
|
|
274
|
+
### Manual: build and deploy with wrangler
|
|
275
|
+
|
|
276
|
+
Prefer to manage everything by hand? Create the resources, write `wrangler.jsonc`, and run `wrangler deploy` yourself.
|
|
277
|
+
|
|
278
|
+
#### 1. Create your resources
|
|
220
279
|
|
|
221
280
|
Create whatever bindings your app uses:
|
|
222
281
|
|
|
@@ -231,7 +290,7 @@ wrangler kv namespace create KV
|
|
|
231
290
|
wrangler r2 bucket create my-app-storage
|
|
232
291
|
```
|
|
233
292
|
|
|
234
|
-
|
|
293
|
+
#### 2. Add a `wrangler.jsonc`
|
|
235
294
|
|
|
236
295
|
Create `wrangler.jsonc` in your project root with the resource IDs from step 1:
|
|
237
296
|
|
|
@@ -264,7 +323,7 @@ Create `wrangler.jsonc` in your project root with the resource IDs from step 1:
|
|
|
264
323
|
|
|
265
324
|
Only include the bindings your app actually uses. You can also add service bindings, custom routes, environment overrides, and any other standard wrangler fields -- they all flow through to the build output. You don't need `main` or `assets` -- those are set by the plugin.
|
|
266
325
|
|
|
267
|
-
|
|
326
|
+
#### 3. Run migrations
|
|
268
327
|
|
|
269
328
|
If your app uses D1, apply migrations before deploying:
|
|
270
329
|
|
|
@@ -274,7 +333,7 @@ wrangler d1 migrations apply my-app-db --remote
|
|
|
274
333
|
|
|
275
334
|
This uses the same `db/migrations/` directory that Void uses locally. `my-app-db` is the database name from your `wrangler.jsonc`; using the database name avoids accidentally applying migrations to the wrong binding.
|
|
276
335
|
|
|
277
|
-
|
|
336
|
+
#### 4. Build and deploy
|
|
278
337
|
|
|
279
338
|
```bash
|
|
280
339
|
vite build && wrangler deploy
|
|
@@ -77,6 +77,7 @@ Most configuration is inferred automatically. Use `void.json` to override defaul
|
|
|
77
77
|
| `routing.prerender` | Paths to prerender as static HTML at deploy time |
|
|
78
78
|
| `routing.revalidate` | Default revalidation TTL in seconds for cached responses |
|
|
79
79
|
| `inference.bindings` | Override inferred bindings. You only need this if auto-detection is not doing what you want. Accepts `true` or a custom binding name such as `"db": "MY_DB"`. |
|
|
80
|
+
| `routing.notFound` | **Ignored.** SvelteKit, Nuxt, Analog, and Astro pin `not_found_handling` to `"none"` — the framework worker owns unmatched HTML. `void deploy` warns if set. |
|
|
80
81
|
|
|
81
82
|
See [Configuration](../../reference/config.md) for the full reference.
|
|
82
83
|
|
|
@@ -12,4 +12,8 @@ Rewrites and redirects: declare static rules in `void.json` under `routing.redir
|
|
|
12
12
|
|
|
13
13
|
Logs: surface app-level errors that should show up under `void project logs --level error` via `import { logger } from "void/log"` and `logger.error(msg, fields?)` (also `.warn` / `.info`). Anything caught and only persisted to your own DB is invisible to Cloudflare Tail; route it through `logger.*` or `console.*` so the platform can see it.
|
|
14
14
|
|
|
15
|
+
Requests: `void project logs` only has rows when a worker actually ran. 5xx generated by the edge router, and every request to a static/SPA project, produce no log line at all. Use `void project requests --status 5xx --range 12h` to see those — it lists status, method, and duration for every request the edge served, whether or not a worker was invoked.
|
|
16
|
+
|
|
17
|
+
Self-host deploy: `void deploy` targets the Void platform; to deploy to the user's OWN Cloudflare account instead, use `void deploy --backend cloudflare` (add `--provision` on the first deploy to create the D1/KV/R2/Queues/Hyperdrive resources the source needs). It uses local wrangler auth, so pin an account (`account_id` in `wrangler.jsonc` or `CLOUDFLARE_ACCOUNT_ID`) and keep real secrets in `wrangler secret put` — every `.env*` file this backend loads (`.env`, `.env.local`, `.env.production`, `.env.production.local`) ships as plaintext worker vars, `.local` included. Provisioning a Hyperdrive config reads `DATABASE_URL` from the shell, not from `.env*`. v1 supports full Void apps on the Cloudflare Workers target only (D1/KV/R2/Queues/Hyperdrive; auth and ISR on D1/SQLite); framework SSR of every kind (TanStack Start, React Router, vinext, SvelteKit, Nuxt, Analog, Astro), static/SPA/SSG apps (including `output: "static"`), WebSocket/Durable Object apps (`*.ws.ts`), a custom `migrations_pattern`, node/bun/deno targets, and PostgreSQL apps with auth all fail closed with guidance. Auth apps must ship checked-in migrations that produce the Better Auth schema. `--provision` is a single-operator, dev-machine step and is disabled in CI.
|
|
18
|
+
|
|
15
19
|
Full docs are in `node_modules/void/docs/`. If you have the `void` skill available, use it for a complete API reference covering project structure, routing, pages mode, database, auth, typed fetch, KV, storage, queues, cron jobs, CLI, configuration, and deployment.
|
|
@@ -42,7 +42,7 @@ export default defineConfig({
|
|
|
42
42
|
- `void auth login` — platform auth
|
|
43
43
|
- `void deploy` — build and deploy
|
|
44
44
|
- `void db *` — local DB and migration commands
|
|
45
|
-
- `void project *` — link, status, logs, rollback, delete
|
|
45
|
+
- `void project *` — link, status, logs, requests, rollback, delete
|
|
46
46
|
|
|
47
47
|
Runtime helpers include:
|
|
48
48
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Installation
|
|
2
|
+
> `npm install --save @types/proper-lockfile`
|
|
3
|
+
|
|
4
|
+
# Summary
|
|
5
|
+
This package contains type definitions for proper-lockfile (https://github.com/moxystudio/node-proper-lockfile).
|
|
6
|
+
|
|
7
|
+
# Details
|
|
8
|
+
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/proper-lockfile.
|
|
9
|
+
## [index.d.ts](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/proper-lockfile/index.d.ts)
|
|
10
|
+
````ts
|
|
11
|
+
import { OperationOptions } from "retry";
|
|
12
|
+
|
|
13
|
+
export interface LockOptions {
|
|
14
|
+
stale?: number | undefined; // default: 10000
|
|
15
|
+
update?: number | undefined; // default: stale/2
|
|
16
|
+
retries?: number | OperationOptions | undefined; // default: 0
|
|
17
|
+
realpath?: boolean | undefined; // default: true
|
|
18
|
+
fs?: any; // default: graceful-fs
|
|
19
|
+
onCompromised?: ((err: Error) => any) | undefined; // default: (err) => throw err
|
|
20
|
+
lockfilePath?: string | undefined; // default: `${file}.lock`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface UnlockOptions {
|
|
24
|
+
realpath?: boolean | undefined; // default: true
|
|
25
|
+
fs?: any; // default: graceful-fs
|
|
26
|
+
lockfilePath?: string | undefined; // default: `${file}.lock`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface CheckOptions {
|
|
30
|
+
stale?: number | undefined; // default: 10000
|
|
31
|
+
realpath?: boolean | undefined; // default: true
|
|
32
|
+
fs?: any; // default: graceful-fs
|
|
33
|
+
lockfilePath?: string | undefined; // default: `${file}.lock`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function lock(file: string, options?: LockOptions): Promise<() => Promise<void>>;
|
|
37
|
+
export function unlock(file: string, options?: UnlockOptions): Promise<void>;
|
|
38
|
+
export function check(file: string, options?: CheckOptions): Promise<boolean>;
|
|
39
|
+
|
|
40
|
+
export function lockSync(file: string, options?: LockOptions): () => void;
|
|
41
|
+
export function unlockSync(file: string, options?: UnlockOptions): void;
|
|
42
|
+
export function checkSync(file: string, options?: CheckOptions): boolean;
|
|
43
|
+
|
|
44
|
+
````
|
|
45
|
+
|
|
46
|
+
### Additional Details
|
|
47
|
+
* Last updated: Tue, 07 Nov 2023 09:09:39 GMT
|
|
48
|
+
* Dependencies: [@types/retry](https://npmjs.com/package/@types/retry)
|
|
49
|
+
|
|
50
|
+
# Credits
|
|
51
|
+
These definitions were written by [Nikita Volodin](https://github.com/qlonik), [Linus Unnebäck](https://github.com/LinusU), and [ulrichb](https://github.com/ulrichb).
|
package/skills/void/docs/node_modules/void/node_modules/@void/md/node_modules/pathslash/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# pathslash
|
|
2
|
+
|
|
3
|
+
> `node:path`, platform-correct, with forward-slash output.
|
|
4
|
+
|
|
5
|
+
`pathslash` is a tiny wrapper around `node:path` that always outputs forward slashes (`/`) while keeping the correct per-platform semantics. It never reimplements path logic. Every function delegates to `node:path` and only flips the separators in the result.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
- **Forward slashes everywhere.** On Windows, the `win32` functions output `/` instead of `\`, which is what bundlers, route maps, and URLs expect.
|
|
10
|
+
- **Correct semantics for free.** Drive letters, UNC paths, and case-insensitive `relative` behave exactly as in `node:path`, because they _are_ `node:path`.
|
|
11
|
+
- **POSIX-safe.** On POSIX, a backslash is a valid filename character, so it is never rewritten there.
|
|
12
|
+
- **A typed drop-in.** Same API and types as `node:path`.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm i pathslash
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
The default export and the top-level named exports follow the host platform, exactly like `node:path`:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import path, { join } from "pathslash";
|
|
26
|
+
|
|
27
|
+
join("src", "a.ts"); // 'src/a.ts'
|
|
28
|
+
path.sep; // '/'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
To force a specific platform, use the `win32` and `posix` namespaces. They work on any host OS:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { win32, posix } from "pathslash";
|
|
35
|
+
|
|
36
|
+
win32.join("C:\\a", "b"); // 'C:/a/b' (forward slashes)
|
|
37
|
+
win32.normalize("C:\\a\\..\\b"); // 'C:/b'
|
|
38
|
+
win32.relative("C:/Foo/Bar", "C:/foo/baz"); // '../baz' (case-insensitive)
|
|
39
|
+
|
|
40
|
+
posix.join("a", "b\\c"); // 'a/b\\c' (backslash kept)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### `toSlash(path)`
|
|
44
|
+
|
|
45
|
+
Safely normalizes separators to `/`. On Windows it converts `\` to `/`. On POSIX it returns the path unchanged, because a backslash is a valid filename character there and rewriting it would corrupt the path. Use it for paths that come from outside this package, such as `process.cwd()`:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { toSlash } from "pathslash";
|
|
49
|
+
|
|
50
|
+
toSlash("C:\\a\\b"); // 'C:/a/b' on Windows, unchanged on POSIX
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Notes
|
|
54
|
+
|
|
55
|
+
- `win32.sep` is `"/"` instead of `"\\"`, and `win32.delimiter` stays `";"`.
|
|
56
|
+
- `\\?\` (extended-length) paths stay verbatim. `toSlash` and every `win32.*` function leave them untouched, because a forward slash is a literal character there, not a separator.
|
|
57
|
+
- `toNamespacedPath` always returns a native, backslash path, since `\\?\` paths are only valid with backslashes.
|
|
58
|
+
- `matchesGlob` mirrors `node:path`. It exists only on Node versions that ship it (22.5+) and is `undefined` on older ones.
|
|
59
|
+
- The types are a drop-in too: `import type { ParsedPath, FormatInputPathObject, PlatformPath } from "pathslash"`.
|
|
60
|
+
- Everything else matches `node:path`, separators aside.
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# pathslash
|
|
2
|
+
|
|
3
|
+
> `node:path`, platform-correct, with forward-slash output.
|
|
4
|
+
|
|
5
|
+
`pathslash` is a tiny wrapper around `node:path` that always outputs forward slashes (`/`) while keeping the correct per-platform semantics. It never reimplements path logic. Every function delegates to `node:path` and only flips the separators in the result.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
- **Forward slashes everywhere.** On Windows, the `win32` functions output `/` instead of `\`, which is what bundlers, route maps, and URLs expect.
|
|
10
|
+
- **Correct semantics for free.** Drive letters, UNC paths, and case-insensitive `relative` behave exactly as in `node:path`, because they _are_ `node:path`.
|
|
11
|
+
- **POSIX-safe.** On POSIX, a backslash is a valid filename character, so it is never rewritten there.
|
|
12
|
+
- **A typed drop-in.** Same API and types as `node:path`.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm i pathslash
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
The default export and the top-level named exports follow the host platform, exactly like `node:path`:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import path, { join } from "pathslash";
|
|
26
|
+
|
|
27
|
+
join("src", "a.ts"); // 'src/a.ts'
|
|
28
|
+
path.sep; // '/'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
To force a specific platform, use the `win32` and `posix` namespaces. They work on any host OS:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { win32, posix } from "pathslash";
|
|
35
|
+
|
|
36
|
+
win32.join("C:\\a", "b"); // 'C:/a/b' (forward slashes)
|
|
37
|
+
win32.normalize("C:\\a\\..\\b"); // 'C:/b'
|
|
38
|
+
win32.relative("C:/Foo/Bar", "C:/foo/baz"); // '../baz' (case-insensitive)
|
|
39
|
+
|
|
40
|
+
posix.join("a", "b\\c"); // 'a/b\\c' (backslash kept)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### `toSlash(path)`
|
|
44
|
+
|
|
45
|
+
Safely normalizes separators to `/`. On Windows it converts `\` to `/`. On POSIX it returns the path unchanged, because a backslash is a valid filename character there and rewriting it would corrupt the path. Use it for paths that come from outside this package, such as `process.cwd()`:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { toSlash } from "pathslash";
|
|
49
|
+
|
|
50
|
+
toSlash("C:\\a\\b"); // 'C:/a/b' on Windows, unchanged on POSIX
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Notes
|
|
54
|
+
|
|
55
|
+
- `win32.sep` is `"/"` instead of `"\\"`, and `win32.delimiter` stays `";"`.
|
|
56
|
+
- `\\?\` (extended-length) paths stay verbatim. `toSlash` and every `win32.*` function leave them untouched, because a forward slash is a literal character there, not a separator.
|
|
57
|
+
- `toNamespacedPath` always returns a native, backslash path, since `\\?\` paths are only valid with backslashes.
|
|
58
|
+
- `matchesGlob` mirrors `node:path`. It exists only on Node versions that ship it (22.5+) and is `undefined` on older ones.
|
|
59
|
+
- The types are a drop-in too: `import type { ParsedPath, FormatInputPathObject, PlatformPath } from "pathslash"`.
|
|
60
|
+
- Everything else matches `node:path`, separators aside.
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
|
+
|
|
5
|
+
<a name="4.1.2"></a>
|
|
6
|
+
## [4.1.2](https://github.com/moxystudio/node-proper-lockfile/compare/v4.1.1...v4.1.2) (2021-01-25)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* fix node 14 updating graceful-fs ([#102](https://github.com/moxystudio/node-proper-lockfile/issues/102)) ([b0d988e](https://github.com/moxystudio/node-proper-lockfile/commit/b0d988e))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
<a name="4.1.1"></a>
|
|
16
|
+
## [4.1.1](https://github.com/moxystudio/node-proper-lockfile/compare/v4.1.0...v4.1.1) (2019-04-03)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* fix mtime precision on some filesystems ([#88](https://github.com/moxystudio/node-proper-lockfile/issues/88)) ([f266158](https://github.com/moxystudio/node-proper-lockfile/commit/f266158)), closes [#82](https://github.com/moxystudio/node-proper-lockfile/issues/82) [#87](https://github.com/moxystudio/node-proper-lockfile/issues/87)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
<a name="4.1.0"></a>
|
|
26
|
+
# [4.1.0](https://github.com/moxystudio/node-proper-lockfile/compare/v4.0.0...v4.1.0) (2019-03-18)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
* allow second precision in mtime comparison ([#78](https://github.com/moxystudio/node-proper-lockfile/issues/78)) ([b2816a6](https://github.com/moxystudio/node-proper-lockfile/commit/b2816a6))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
<a name="4.0.0"></a>
|
|
36
|
+
# [4.0.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.2.0...v4.0.0) (2019-03-12)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Bug Fixes
|
|
40
|
+
|
|
41
|
+
* fix typo in error message ([#68](https://github.com/moxystudio/node-proper-lockfile/issues/68)) ([b91cb55](https://github.com/moxystudio/node-proper-lockfile/commit/b91cb55))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### Features
|
|
45
|
+
|
|
46
|
+
* make staleness check more robust ([#74](https://github.com/moxystudio/node-proper-lockfile/issues/74)) ([9cc0973](https://github.com/moxystudio/node-proper-lockfile/commit/9cc0973)), closes [#71](https://github.com/moxystudio/node-proper-lockfile/issues/71) [/github.com/ipfs/js-ipfs-repo/issues/188#issuecomment-468682971](https://github.com//github.com/ipfs/js-ipfs-repo/issues/188/issues/issuecomment-468682971)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### BREAKING CHANGES
|
|
50
|
+
|
|
51
|
+
* We were marking the lock as compromised when system went into sleep or if the event loop was busy taking too long to run the internals timers, Now we keep track of the mtime updated by the current process, and if we lose some cycles in the update process but recover and the mtime is still ours we do not mark the lock as compromised.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
<a name="3.2.0"></a>
|
|
56
|
+
# [3.2.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.1.0...v3.2.0) (2018-11-19)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### Features
|
|
60
|
+
|
|
61
|
+
* add lock path option ([#66](https://github.com/moxystudio/node-proper-lockfile/issues/66)) ([32f1b8d](https://github.com/moxystudio/node-proper-lockfile/commit/32f1b8d))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
<a name="3.1.0"></a>
|
|
66
|
+
# [3.1.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.2...v3.1.0) (2018-11-15)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
### Bug Fixes
|
|
70
|
+
|
|
71
|
+
* **package:** update retry to version 0.12.0 ([#50](https://github.com/moxystudio/node-proper-lockfile/issues/50)) ([d400b98](https://github.com/moxystudio/node-proper-lockfile/commit/d400b98))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### Features
|
|
75
|
+
|
|
76
|
+
* add signal exit ([#65](https://github.com/moxystudio/node-proper-lockfile/issues/65)) ([f20bc45](https://github.com/moxystudio/node-proper-lockfile/commit/f20bc45))
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
<a name="3.0.2"></a>
|
|
81
|
+
## [3.0.2](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.1...v3.0.2) (2018-01-30)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
<a name="3.0.1"></a>
|
|
86
|
+
## [3.0.1](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.0...v3.0.1) (2018-01-20)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
### Bug Fixes
|
|
90
|
+
|
|
91
|
+
* restore ability to use lockfile() directly ([0ef8fbc](https://github.com/moxystudio/node-proper-lockfile/commit/0ef8fbc))
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
<a name="3.0.0"></a>
|
|
96
|
+
# [3.0.0](https://github.com/moxystudio/node-proper-lockfile/compare/v2.0.1...v3.0.0) (2018-01-20)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
### Chores
|
|
100
|
+
|
|
101
|
+
* update project to latest node lts ([b1d43e5](https://github.com/moxystudio/node-proper-lockfile/commit/b1d43e5))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
### BREAKING CHANGES
|
|
105
|
+
|
|
106
|
+
* remove callback support
|
|
107
|
+
* use of node lts language features such as object spread
|
|
108
|
+
* compromised function in lock() has been moved to an option
|