void 0.10.10 → 0.10.11
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-BdUctCZD.mjs → config-CutEMNGJ.mjs} +3 -3
- package/dist/{config-BcAeIPe3.mjs → config-E03l1C_h.mjs} +2 -2
- package/dist/{create-project-CjYX23M_.mjs → create-project-DsYvl3TB.mjs} +3 -3
- package/dist/{db-BvKV34IK.mjs → db-PZBsLSGb.mjs} +27 -27
- package/dist/{delete-CThKLXfi.mjs → delete-mh6p-zkQ.mjs} +3 -3
- package/dist/deploy-DT8wsPZd.mjs +6990 -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-AAHU02L6.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-BdDlGhbN.mjs +1069 -0
- package/dist/{gen-Bee261SV.mjs → gen-oup1xBN0.mjs} +8 -8
- package/dist/{github-cmd-DfeFEasr.mjs → github-cmd-BdNaOVNa.mjs} +3 -3
- package/dist/{handler-imD0UVDT.d.mts → handler-Cjh8uM3Y.d.mts} +1 -1
- package/dist/{headers-CTAjX-UO.mjs → headers-BQknpzkn.mjs} +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +41 -33
- package/dist/{init-xfwW7cLp.mjs → init-Dl2PKuQn.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-BDx8pmhq.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-DOBTY0o4.mjs} +10 -10
- package/dist/preset-BGrvB4Bl.mjs +539 -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-BLrCEBbI.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/skills/void/SKILL.md +34 -33
- package/skills/void/docs/guide/auth.md +8 -0
- package/skills/void/docs/guide/deployment.md +1 -1
- 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/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/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
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# proper-lockfile
|
|
2
|
+
|
|
3
|
+
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][codecov-image]][codecov-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]
|
|
4
|
+
|
|
5
|
+
[npm-url]:https://npmjs.org/package/proper-lockfile
|
|
6
|
+
[downloads-image]:https://img.shields.io/npm/dm/proper-lockfile.svg
|
|
7
|
+
[npm-image]:https://img.shields.io/npm/v/proper-lockfile.svg
|
|
8
|
+
[travis-url]:https://travis-ci.org/moxystudio/node-proper-lockfile
|
|
9
|
+
[travis-image]:https://img.shields.io/travis/moxystudio/node-proper-lockfile/master.svg
|
|
10
|
+
[codecov-url]:https://codecov.io/gh/moxystudio/node-proper-lockfile
|
|
11
|
+
[codecov-image]:https://img.shields.io/codecov/c/github/moxystudio/node-proper-lockfile/master.svg
|
|
12
|
+
[david-dm-url]:https://david-dm.org/moxystudio/node-proper-lockfile
|
|
13
|
+
[david-dm-image]:https://img.shields.io/david/moxystudio/node-proper-lockfile.svg
|
|
14
|
+
[david-dm-dev-url]:https://david-dm.org/moxystudio/node-proper-lockfile?type=dev
|
|
15
|
+
[david-dm-dev-image]:https://img.shields.io/david/dev/moxystudio/node-proper-lockfile.svg
|
|
16
|
+
|
|
17
|
+
An inter-process and inter-machine lockfile utility that works on a local or network file system.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
`$ npm install proper-lockfile`
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Design
|
|
26
|
+
|
|
27
|
+
There are various ways to achieve [file locking](http://en.wikipedia.org/wiki/File_locking).
|
|
28
|
+
|
|
29
|
+
This library utilizes the `mkdir` strategy which works atomically on any kind of file system, even network based ones.
|
|
30
|
+
The lockfile path is based on the file path you are trying to lock by suffixing it with `.lock`.
|
|
31
|
+
|
|
32
|
+
When a lock is successfully acquired, the lockfile's `mtime` (modified time) is periodically updated to prevent staleness. This allows to effectively check if a lock is stale by checking its `mtime` against a stale threshold. If the update of the mtime fails several times, the lock might be compromised. The `mtime` is [supported](http://en.wikipedia.org/wiki/Comparison_of_file_systems) in almost every `filesystem`.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Comparison
|
|
36
|
+
|
|
37
|
+
This library is similar to [lockfile](https://github.com/isaacs/lockfile) but the latter has some drawbacks:
|
|
38
|
+
|
|
39
|
+
- It relies on `open` with `O_EXCL` flag which has problems in network file systems. `proper-lockfile` uses `mkdir` which doesn't have this issue.
|
|
40
|
+
|
|
41
|
+
> O_EXCL is broken on NFS file systems; programs which rely on it for performing locking tasks will contain a race condition.
|
|
42
|
+
|
|
43
|
+
- The lockfile staleness check is done via `ctime` (creation time) which is unsuitable for long running processes. `proper-lockfile` constantly updates lockfiles `mtime` to do proper staleness check.
|
|
44
|
+
|
|
45
|
+
- It does not check if the lockfile was compromised which can lead to undesirable situations. `proper-lockfile` checks the lockfile when updating the `mtime`.
|
|
46
|
+
|
|
47
|
+
- It has a default value of `0` for the stale option which isn't good because any crash or process kill that the package can't handle gracefully will leave the lock active forever.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
### Compromised
|
|
51
|
+
|
|
52
|
+
`proper-lockfile` does not detect cases in which:
|
|
53
|
+
|
|
54
|
+
- A `lockfile` is manually removed and someone else acquires the lock right after
|
|
55
|
+
- Different `stale`/`update` values are being used for the same file, possibly causing two locks to be acquired on the same file
|
|
56
|
+
|
|
57
|
+
`proper-lockfile` detects cases in which:
|
|
58
|
+
|
|
59
|
+
- Updates to the `lockfile` fail
|
|
60
|
+
- Updates take longer than expected, possibly causing the lock to become stale for a certain amount of time
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
As you see, the first two are a consequence of bad usage. Technically, it was possible to detect the first two but it would introduce complexity and eventual race conditions.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Usage
|
|
67
|
+
|
|
68
|
+
### .lock(file, [options])
|
|
69
|
+
|
|
70
|
+
Tries to acquire a lock on `file` or rejects the promise on error.
|
|
71
|
+
|
|
72
|
+
If the lock succeeds, a `release` function is provided that should be called when you want to release the lock. The `release` function also rejects the promise on error (e.g. when the lock was already compromised).
|
|
73
|
+
|
|
74
|
+
Available options:
|
|
75
|
+
|
|
76
|
+
- `stale`: Duration in milliseconds in which the lock is considered stale, defaults to `10000` (minimum value is `5000`)
|
|
77
|
+
- `update`: The interval in milliseconds in which the lockfile's `mtime` will be updated, defaults to `stale/2` (minimum value is `1000`, maximum value is `stale/2`)
|
|
78
|
+
- `retries`: The number of retries or a [retry](https://www.npmjs.org/package/retry) options object, defaults to `0`
|
|
79
|
+
- `realpath`: Resolve symlinks using realpath, defaults to `true` (note that if `true`, the `file` must exist previously)
|
|
80
|
+
- `fs`: A custom fs to use, defaults to `graceful-fs`
|
|
81
|
+
- `onCompromised`: Called if the lock gets compromised, defaults to a function that simply throws the error which will probably cause the process to die
|
|
82
|
+
- `lockfilePath`: Custom lockfile path. e.g.: If you want to lock a directory and create the lock file inside it, you can pass `file` as `<dir path>` and `options.lockfilePath` as `<dir path>/dir.lock`
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
const lockfile = require('proper-lockfile');
|
|
87
|
+
|
|
88
|
+
lockfile.lock('some/file')
|
|
89
|
+
.then((release) => {
|
|
90
|
+
// Do something while the file is locked
|
|
91
|
+
|
|
92
|
+
// Call the provided release function when you're done,
|
|
93
|
+
// which will also return a promise
|
|
94
|
+
return release();
|
|
95
|
+
})
|
|
96
|
+
.catch((e) => {
|
|
97
|
+
// either lock could not be acquired
|
|
98
|
+
// or releasing it failed
|
|
99
|
+
console.error(e)
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Alternatively, you may use lockfile('some/file') directly.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
### .unlock(file, [options])
|
|
107
|
+
|
|
108
|
+
Releases a previously acquired lock on `file` or rejects the promise on error.
|
|
109
|
+
|
|
110
|
+
Whenever possible you should use the `release` function instead (as exemplified above). Still there are cases in which it's hard to keep a reference to it around code. In those cases `unlock()` might be handy.
|
|
111
|
+
|
|
112
|
+
Available options:
|
|
113
|
+
|
|
114
|
+
- `realpath`: Resolve symlinks using realpath, defaults to `true` (note that if `true`, the `file` must exist previously)
|
|
115
|
+
- `fs`: A custom fs to use, defaults to `graceful-fs`
|
|
116
|
+
- `lockfilePath`: Custom lockfile path. e.g.: If you want to lock a directory and create the lock file inside it, you can pass `file` as `<dir path>` and `options.lockfilePath` as `<dir path>/dir.lock`
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
const lockfile = require('proper-lockfile');
|
|
121
|
+
|
|
122
|
+
lockfile.lock('some/file')
|
|
123
|
+
.then(() => {
|
|
124
|
+
// Do something while the file is locked
|
|
125
|
+
|
|
126
|
+
// Later..
|
|
127
|
+
return lockfile.unlock('some/file');
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### .check(file, [options])
|
|
132
|
+
|
|
133
|
+
Check if the file is locked and its lockfile is not stale, rejects the promise on error.
|
|
134
|
+
|
|
135
|
+
Available options:
|
|
136
|
+
|
|
137
|
+
- `stale`: Duration in milliseconds in which the lock is considered stale, defaults to `10000` (minimum value is `5000`)
|
|
138
|
+
- `realpath`: Resolve symlinks using realpath, defaults to `true` (note that if `true`, the `file` must exist previously)
|
|
139
|
+
- `fs`: A custom fs to use, defaults to `graceful-fs`
|
|
140
|
+
- `lockfilePath`: Custom lockfile path. e.g.: If you want to lock a directory and create the lock file inside it, you can pass `file` as `<dir path>` and `options.lockfilePath` as `<dir path>/dir.lock`
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
const lockfile = require('proper-lockfile');
|
|
145
|
+
|
|
146
|
+
lockfile.check('some/file')
|
|
147
|
+
.then((isLocked) => {
|
|
148
|
+
// isLocked will be true if 'some/file' is locked, false otherwise
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### .lockSync(file, [options])
|
|
153
|
+
|
|
154
|
+
Sync version of `.lock()`.
|
|
155
|
+
Returns the `release` function or throws on error.
|
|
156
|
+
|
|
157
|
+
### .unlockSync(file, [options])
|
|
158
|
+
|
|
159
|
+
Sync version of `.unlock()`.
|
|
160
|
+
Throws on error.
|
|
161
|
+
|
|
162
|
+
### .checkSync(file, [options])
|
|
163
|
+
|
|
164
|
+
Sync version of `.check()`.
|
|
165
|
+
Returns a boolean or throws on error.
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
## Graceful exit
|
|
169
|
+
|
|
170
|
+
`proper-lockfile` automatically removes locks if the process exits, except if the process is killed with SIGKILL or it crashes due to a VM fatal error (e.g.: out of memory).
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
## Tests
|
|
174
|
+
|
|
175
|
+
`$ npm test`
|
|
176
|
+
`$ npm test -- --watch` during development
|
|
177
|
+
|
|
178
|
+
The test suite is very extensive. There's even a stress test to guarantee exclusiveness of locks.
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
Released under the [MIT License](https://www.opensource.org/licenses/mit-license.php).
|
|
@@ -32,39 +32,40 @@ Then ask what to do next.
|
|
|
32
32
|
|
|
33
33
|
## Task Routing
|
|
34
34
|
|
|
35
|
-
| User intent
|
|
36
|
-
|
|
|
37
|
-
| CLI command syntax, flags, env vars
|
|
38
|
-
| Initial setup, onboarding, first app
|
|
39
|
-
| App type detection and mode behavior
|
|
40
|
-
| Server/API routing and middleware
|
|
41
|
-
| Pages mode, loader/action, forms, layouts
|
|
42
|
-
| Database and migrations
|
|
43
|
-
| Typed fetch and end-to-end typing
|
|
44
|
-
| Authentication
|
|
45
|
-
| Cloudflare runtime bindings and config
|
|
46
|
-
| AI inference (Workers AI, providers)
|
|
47
|
-
| KV / storage / queues / cron jobs
|
|
48
|
-
| SSR and caching
|
|
49
|
-
| Rewrites, redirects, fallbacks
|
|
50
|
-
| Static site generation
|
|
51
|
-
| Deployment and CI
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
35
|
+
| User intent | Docs file(s) |
|
|
36
|
+
| ------------------------------------------ | ----------------------------------------------------------------------------------------- |
|
|
37
|
+
| CLI command syntax, flags, env vars | `docs/reference/cli.md` |
|
|
38
|
+
| Initial setup, onboarding, first app | `docs/guide/quickstart.md`, `docs/reference/cli.md` |
|
|
39
|
+
| App type detection and mode behavior | `docs/guide/app-types.md`, `docs/reference/config.md` |
|
|
40
|
+
| Server/API routing and middleware | `docs/guide/server-routing.md`, `docs/integrations/hono.md` |
|
|
41
|
+
| Pages mode, loader/action, forms, layouts | `docs/guide/pages-routing/*.md`, `docs/guide/type-safety.md` |
|
|
42
|
+
| Database and migrations | `docs/guide/database.md`, `docs/guide/type-safety.md` |
|
|
43
|
+
| Typed fetch and end-to-end typing | `docs/guide/typed-fetch.md`, `docs/guide/type-safety.md` |
|
|
44
|
+
| Authentication | `docs/guide/auth.md`, `docs/guide/env-vars.md` |
|
|
45
|
+
| Cloudflare runtime bindings and config | `docs/integrations/cloudflare.md`, `docs/reference/config.md`, `docs/guide/env-vars.md` |
|
|
46
|
+
| AI inference (Workers AI, providers) | `docs/guide/ai.md` |
|
|
47
|
+
| KV / storage / queues / cron jobs | `docs/guide/kv.md`, `docs/guide/storage.md`, `docs/guide/queues.md`, `docs/guide/jobs.md` |
|
|
48
|
+
| SSR and caching | `docs/guide/ssr.md`, `docs/guide/edge/*.md` |
|
|
49
|
+
| Rewrites, redirects, fallbacks | `docs/guide/edge/rewrites.md`, `docs/guide/edge/redirects.md`, `docs/reference/config.md` |
|
|
50
|
+
| Static site generation | `docs/guide/ssg.md` |
|
|
51
|
+
| Deployment and CI | `docs/guide/deployment.md`, `docs/reference/cli.md` |
|
|
52
|
+
| Self-host deploy to own Cloudflare account | `docs/integrations/cloudflare.md`, `docs/reference/cli.md` |
|
|
53
|
+
| Project status, deployment history | `docs/reference/cli.md` |
|
|
54
|
+
| Cache purging | `docs/reference/cli.md` |
|
|
55
|
+
| Project logs, runtime errors | `docs/reference/cli.md` |
|
|
56
|
+
| Secrets management (put/sync/delete) | `docs/reference/cli.md`, `docs/guide/env-vars.md` |
|
|
57
|
+
| Typed env vars (`defineEnv`, `env.ts`) | `docs/guide/env-vars.md` |
|
|
58
|
+
| Custom domain setup | `docs/reference/cli.md` |
|
|
59
|
+
| Database status, reset, seed, export | `docs/reference/cli.md`, `docs/guide/database.md` |
|
|
60
|
+
| Auth login/logout/whoami | `docs/reference/cli.md` |
|
|
61
|
+
| Overview / introduction | `docs/guide/index.md` |
|
|
62
|
+
| API surface details | `docs/reference/api.md` |
|
|
63
|
+
| Meta framework integration | `docs/integrations/frameworks/*.md` |
|
|
64
|
+
| Coding agent setup | `docs/integrations/agents.md` |
|
|
65
|
+
| Node.js / Bun / Deno targets | `docs/integrations/nodejs-bun-deno.md` |
|
|
66
|
+
| ORMs and external databases | `docs/integrations/orms-and-external-dbs.md` |
|
|
67
|
+
| Project structure and conventions | `docs/reference/structure.md` |
|
|
68
|
+
| Resource/binding inference | `docs/reference/resource-inference.md` |
|
|
68
69
|
|
|
69
70
|
## Working Rules
|
|
70
71
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# `packages/void/test/e2e`
|
|
2
|
+
|
|
3
|
+
Gated live-account end-to-end tests. These run REAL Cloudflare operations against a REAL account, so
|
|
4
|
+
they **skip unless credentials are present**. Locally that means exporting the env vars below; in CI
|
|
5
|
+
they run on **pushes to `main`** (see [In CI](#in-ci)).
|
|
6
|
+
|
|
7
|
+
## `cloudflare-deploy-live.test.ts`
|
|
8
|
+
|
|
9
|
+
Deploys `playground/spa` (D1 + KV + cron) to the target account via `void deploy --backend cloudflare`,
|
|
10
|
+
verifies the live worker answers HTTP 200, then deletes the worker and every resource it created.
|
|
11
|
+
|
|
12
|
+
It does **not** drive `--provision`: that path fails closed in non-interactive shells by design (a
|
|
13
|
+
spawned CLI has no TTY, and CI cannot commit back the ids a create would mint). So the test plays the
|
|
14
|
+
provisioner's role itself — it creates the id-bearing D1 + KV directly with `wrangler … create`,
|
|
15
|
+
writes their real ids into the app's root config exactly as `--provision` would, then runs the
|
|
16
|
+
CI-safe `void deploy --backend cloudflare` (no `--provision`). That exercises the real
|
|
17
|
+
build → tamper-guard → remote-migrations → `wrangler deploy` pipeline end to end.
|
|
18
|
+
|
|
19
|
+
### Prerequisites
|
|
20
|
+
|
|
21
|
+
The suite is skipped unless BOTH env vars are set:
|
|
22
|
+
|
|
23
|
+
| Env var | Purpose |
|
|
24
|
+
| ------------------------ | -------------------------------------------------------------------------- |
|
|
25
|
+
| `VOID_E2E_CF_TOKEN` | Cloudflare API token that can create + delete Workers Scripts, D1, and KV. |
|
|
26
|
+
| `VOID_E2E_CF_ACCOUNT_ID` | Cloudflare account id to deploy into. |
|
|
27
|
+
|
|
28
|
+
The token needs, on that account, **Workers Scripts: Edit**, **D1: Edit**, and **Workers KV Storage:
|
|
29
|
+
Edit** (Edit implies read, covering the ownership/teardown list calls). Cron triggers ride along with
|
|
30
|
+
the worker deploy — no extra permission.
|
|
31
|
+
|
|
32
|
+
The account must also have a **workers.dev subdomain** already registered (with its wildcard TLS cert
|
|
33
|
+
provisioned). Without one, `wrangler deploy` uploads the worker but cannot publish a public URL, and
|
|
34
|
+
the HTTP-200 assertion has nothing to hit. Opening the Workers & Pages dashboard once registers a
|
|
35
|
+
subdomain automatically; a freshly-registered subdomain takes a few minutes for its cert to go live,
|
|
36
|
+
during which the first run may see a TLS handshake failure — rerun once the cert is ready.
|
|
37
|
+
|
|
38
|
+
With no env vars the suite SKIPS cleanly (0 run, N skipped).
|
|
39
|
+
|
|
40
|
+
### Running it
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
# Ensure the CLI is built first (dist/cli/cli.mjs):
|
|
44
|
+
vp run build:core
|
|
45
|
+
|
|
46
|
+
VOID_E2E_CF_TOKEN=... VOID_E2E_CF_ACCOUNT_ID=... vp test run packages/void/test/e2e
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### In CI
|
|
50
|
+
|
|
51
|
+
`VOID_E2E_CF_TOKEN` and `VOID_E2E_CF_ACCOUNT_ID` are **environment secrets** on the `cloudflare-e2e`
|
|
52
|
+
GitHub Environment (not repo secrets), and a dedicated `live-e2e` job in `.github/workflows/ci.yml`
|
|
53
|
+
consumes them — the main `test` job carries no creds at all. Two layers keep the account token off
|
|
54
|
+
untrusted code:
|
|
55
|
+
|
|
56
|
+
- The `live-e2e` job runs only on a direct push to `main` (`github.event_name == 'push' && github.ref
|
|
57
|
+
== 'refs/heads/main'`), so `pull_request` runs, tag pushes, and `workflow_call` (release) skip it.
|
|
58
|
+
- The `cloudflare-e2e` environment's deployment branch policy allows `main` **only**, enforced by
|
|
59
|
+
GitHub server-side on the run's ref. A `pull_request` run's ref is `refs/pull/<n>/merge`, so it can
|
|
60
|
+
never reach the secret **even if a PR edits this workflow** — the expression-level gate alone would
|
|
61
|
+
be bypassable that way; the environment ref-check is the real boundary.
|
|
62
|
+
|
|
63
|
+
So the credentialed live deploy runs on every merge to `main`; everywhere else the creds are empty and
|
|
64
|
+
the suite SKIPS (the `test` job still imports the file and skips it). The `live-e2e` job itself is
|
|
65
|
+
fail-closed — a preflight step errors if either credential is empty (a missing, deleted, or
|
|
66
|
+
not-yet-rotated secret), so a misconfigured gate is loud instead of a silent green skip. Each
|
|
67
|
+
`live-e2e` run also gets `VOID_E2E_RUN_ID = <run-id>-<attempt>` for the unique per-run resource names
|
|
68
|
+
below.
|
|
69
|
+
|
|
70
|
+
### Resource naming & cleanup
|
|
71
|
+
|
|
72
|
+
Each run derives a UNIQUE resource name — `void-e2e-cf-deploy-<suffix>` — so overlapping runs never
|
|
73
|
+
collide on remote resources. The suffix is `VOID_E2E_RUN_ID` (CI: `<run-id>-<attempt>`) or, locally, a
|
|
74
|
+
timestamp + random. Derived names mirror the provisioner: `<name>-db` (D1), `<name>-kv` (KV). The
|
|
75
|
+
shared `void-e2e-cf-deploy-` prefix keeps every resource greppable, so an orphan from a hard-killed run
|
|
76
|
+
is easy to find and `wrangler delete`. A pre-run ownership gate refuses to start if the run's names
|
|
77
|
+
already exist (failing closed on any lookup it cannot confirm), so the test never adopts or deletes a
|
|
78
|
+
resource it does not own. Teardown runs even when the deploy or an assertion fails.
|
|
79
|
+
|
|
80
|
+
> **Local concurrency:** unique names isolate _remote_ resources, but a run also snapshots and
|
|
81
|
+
> overwrites the shared `playground/spa/wrangler.jsonc` and builds in place. Do **not** run two live
|
|
82
|
+
> e2e invocations against the same checkout at once — they would race that file. CI is unaffected (each
|
|
83
|
+
> runner is an isolated checkout, and only the single `main`-push `live-e2e` job deploys). The deploy
|
|
84
|
+
> test also asserts the returned host's worker label equals this run's `WORKER_NAME`, so a clobbered
|
|
85
|
+
> overlay fails loudly instead of validating another run's worker.
|
|
@@ -32,6 +32,7 @@ Use this page as a command reference. If you are setting up a project for the fi
|
|
|
32
32
|
| `void auth login` | Authenticate with Void |
|
|
33
33
|
| `void project link` | Link directory to a project |
|
|
34
34
|
| `void project logs` | Show runtime logs from deployed project |
|
|
35
|
+
| `void project requests` | Show request-level traffic (status, method, timing) |
|
|
35
36
|
| `void project rollback` | Roll back to a previous deployment |
|
|
36
37
|
| `void project cancel` | Cancel an active deployment |
|
|
37
38
|
| `void project purge-cache` | Purge all cached pages |
|
|
@@ -162,12 +163,12 @@ void project logs [--level <level>] [--filter <text>] [--range <duration>] [--de
|
|
|
162
163
|
|
|
163
164
|
Show runtime logs from the deployed project. Uses the linked project from `.void/project.json`.
|
|
164
165
|
|
|
165
|
-
| Flag | Purpose
|
|
166
|
-
| -------------------- |
|
|
167
|
-
| `--range <duration>` | How far back to look. Format: `<number><unit>` (m/h/d). Max 7d.
|
|
168
|
-
| `--level <level>` | Filter by log level. One of `error`, `warn`, `info`, `log`, `debug`, `all`. `error` also includes uncaught exceptions
|
|
169
|
-
| `--filter <text>` | Case-insensitive **substring** match against log message text and exception name/message — not a level filter. Shows the full request entry on any hit.
|
|
170
|
-
| `--deployment <id>` | Filter logs to a specific deployment ID.
|
|
166
|
+
| Flag | Purpose | Default |
|
|
167
|
+
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
|
168
|
+
| `--range <duration>` | How far back to look. Format: `<number><unit>` (m/h/d). Max 7d. | `1h` |
|
|
169
|
+
| `--level <level>` | Filter by log level. One of `error`, `warn`, `info`, `log`, `debug`, `all`. `error` also includes uncaught exceptions, non-`ok` outcomes, and any 5xx response — even when the worker neither threw nor logged. | `all` |
|
|
170
|
+
| `--filter <text>` | Case-insensitive **substring** match against log message text and exception name/message — not a level filter. Shows the full request entry on any hit. | none |
|
|
171
|
+
| `--deployment <id>` | Filter logs to a specific deployment ID. | none |
|
|
171
172
|
|
|
172
173
|
Output shows one line per request (`HH:MM:SS METHOD URL STATUS`) with indented console log and exception lines beneath. Errors and exceptions are colored red, warnings yellow.
|
|
173
174
|
|
|
@@ -178,7 +179,32 @@ void project logs --level error --range 12h
|
|
|
178
179
|
void project logs --level error --filter websocket
|
|
179
180
|
```
|
|
180
181
|
|
|
181
|
-
Tip: `void project logs` only sees what Cloudflare Tail captures — top-level `console.*` calls and uncaught throws. Application errors caught and persisted to your own DB are invisible to tail. Surface them via `console.error(...)` or `void/log`'s `logger.error(...)` so they show up under `--level error`.
|
|
182
|
+
Tip: `void project logs` only sees what Cloudflare Tail captures — top-level `console.*` calls and uncaught throws. Application errors caught and persisted to your own DB are invisible to tail. Surface them via `console.error(...)` or `void/log`'s `logger.error(...)` so they show up under `--level error`. For 5xx that never reach your worker at all (edge-router errors, static/SPA projects), use `void project requests --status 5xx`.
|
|
183
|
+
|
|
184
|
+
### `void project requests`
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
void project requests [--status <filter>] [--range <duration>]
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Show request-level traffic recorded at the edge for the linked project: one line per request with time, method, HTTP status, request type, and server timing. Unlike `void project logs` (which only has rows for invoked user workers), this reads the edge request-metering data, so it also surfaces:
|
|
191
|
+
|
|
192
|
+
- **5xx the edge router generated itself** — missing deployment manifest, static-asset read timeouts, SSR dispatch timeouts — which never invoke your worker and so never appear in logs.
|
|
193
|
+
- **Requests to static/SPA projects**, which are served directly from storage and never run a worker.
|
|
194
|
+
|
|
195
|
+
| Flag | Purpose | Default |
|
|
196
|
+
| -------------------- | --------------------------------------------------------------------------------------------- | ------- |
|
|
197
|
+
| `--status <filter>` | Filter by status: a class (`2xx`, `3xx`, `4xx`, `5xx`) or an exact 3-digit code (e.g. `500`). | none |
|
|
198
|
+
| `--range <duration>` | How far back to look. Format: `<number><unit>` (m/h/d). Max 7d. | `1h` |
|
|
199
|
+
|
|
200
|
+
Output shows one line per request (`HH:MM:SS METHOD STATUS TYPE DURATION`). 5xx are colored red, 4xx yellow. Note: request paths are not recorded, so this view shows status and type rather than URLs — use `void project logs` for per-URL, per-log detail on requests that do reach your worker.
|
|
201
|
+
|
|
202
|
+
Examples:
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
void project requests --status 5xx
|
|
206
|
+
void project requests --range 24h
|
|
207
|
+
```
|
|
182
208
|
|
|
183
209
|
### `void project rollback [deployId]`
|
|
184
210
|
|
|
@@ -226,19 +252,22 @@ If `--project` is provided, purges that project's cache instead of the linked pr
|
|
|
226
252
|
|
|
227
253
|
```
|
|
228
254
|
void deploy [--project <name>] [--dir <path>] [--spa] [--skip-build] [--debug]
|
|
255
|
+
void deploy --backend cloudflare [--provision]
|
|
229
256
|
```
|
|
230
257
|
|
|
231
258
|
Auto-detects your project type and chooses the right pipeline. See [Supported App Types](../guide/app-types.md) and [Deployment](../guide/deployment.md) for details.
|
|
232
259
|
|
|
233
260
|
For Drizzle projects, deploy performs a read-only schema drift check. If a new migration would be generated, deploy stops and tells you to run `void db generate`, review the migration, commit it yourself, and rerun `void deploy`.
|
|
234
261
|
|
|
235
|
-
| Flag
|
|
236
|
-
|
|
|
237
|
-
| `--project <name>`
|
|
238
|
-
| `--dir <path>`
|
|
239
|
-
| `--spa`
|
|
240
|
-
| `--skip-build`
|
|
241
|
-
| `--
|
|
262
|
+
| Flag | Purpose |
|
|
263
|
+
| ---------------------- | -------------------------------------------------------------------------------------------- |
|
|
264
|
+
| `--project <name>` | Target a specific project by slug; not supported with `--backend cloudflare` |
|
|
265
|
+
| `--dir <path>` | Deploy a pre-built static directory (skips build); not supported with `--backend cloudflare` |
|
|
266
|
+
| `--spa` | Use SPA mode instead of SSG for static deploys; not supported with `--backend cloudflare` |
|
|
267
|
+
| `--skip-build` | Skip the build step (use existing build output); not supported with `--backend cloudflare` |
|
|
268
|
+
| `--backend cloudflare` | Deploy to your own Cloudflare account instead of the Void platform |
|
|
269
|
+
| `--provision` | Create missing bindings (D1/KV/R2/Queues/Hyperdrive); requires `--backend cloudflare` |
|
|
270
|
+
| `--debug` | Mirror the structured deploy log to stderr (also written to `~/.void/logs/`) |
|
|
242
271
|
|
|
243
272
|
Every deploy writes a structured JSONL trace to `~/.void/logs/deploy-<timestamp>.jsonl` regardless of `--debug`. On failure the path is printed at the end of the error message so you can attach it when reporting platform issues. `VOID_DEPLOY_DEBUG=1` is accepted as an alternate trigger for stderr mirroring.
|
|
244
273
|
|
|
@@ -252,6 +281,37 @@ If no project is linked and no override is provided, CLI prompts to link or crea
|
|
|
252
281
|
|
|
253
282
|
That fallback is mainly for projects that skipped Void project setup during `void init`.
|
|
254
283
|
|
|
284
|
+
### `void deploy --backend cloudflare`
|
|
285
|
+
|
|
286
|
+
Deploy the built worker straight to **your own** Cloudflare account instead of the Void platform. This path uses your local `wrangler` auth and your root `wrangler.jsonc` — no Void login or linked project is involved.
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
void deploy --backend cloudflare # deploy using resources already in wrangler.jsonc
|
|
290
|
+
void deploy --backend cloudflare --provision # create any missing resources first, then deploy
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Prerequisites:
|
|
294
|
+
|
|
295
|
+
- A Cloudflare account must be **pinned**: 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.
|
|
296
|
+
- Authenticate wrangler (`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).
|
|
297
|
+
- `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 for an existing config over the Cloudflare REST API, which OAuth cannot authenticate. Without a token, `--provision` stops before touching your account. Alternatively create the Hyperdrive config yourself and put its id in `wrangler.jsonc` — deploying an already-provisioned Hyperdrive app needs no token.
|
|
298
|
+
- `--skip-build` is **not supported** with `--backend cloudflare`: this backend validates the artifact the build emits (worker `vars` in `dist/ssr/wrangler.json`, the generated auth schema), so there is nothing to check without a fresh build.
|
|
299
|
+
- `--project`, `--dir` and `--spa` are **not supported** with `--backend cloudflare` either, and are rejected rather than ignored: no Void project is resolved on this path, and it uploads the worker your build emits rather than a static directory.
|
|
300
|
+
- Local Docker is required to build apps that use the sandbox.
|
|
301
|
+
|
|
302
|
+
What it does, in order: settles the app class before any account op (v1 supports **full Void apps on the Cloudflare Workers target** -- worker-bearing apps running Void's routing, with D1/KV/R2/Queues/Hyperdrive and, on D1/SQLite, auth + ISR; framework SSR of every kind, static/SPA/SSG apps, node/bun/deno targets, and PostgreSQL apps with auth or with checked-in migrations all fail closed with guidance), pins the account and checks auth, provisions or drift-checks resources, **builds**, then gates on the artifact the build emitted — production secrets checked against the build's effective mode/envDir, the auth schema, and migration validation — then applies remote D1 migrations for SQLite apps (verifying the applied set equals the validated set and none remain pending), and finally runs `wrangler deploy` on exactly the verified artifact. Auth apps must ship checked-in migrations that produce the Better Auth schema — the managed platform's runtime auth-migration step does not run on this backend.
|
|
303
|
+
|
|
304
|
+
The build deliberately comes **before** the secret, auth-schema, and migration gates, because those gates inspect the real emitted worker rather than a prediction of it. A missing secret or a bad migration surfaces after the build has run — relevant when a build is expensive or has side effects. Remote D1 migrations run only once every gate has passed, so a failed gate mutates nothing remote.
|
|
305
|
+
|
|
306
|
+
`--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** — re-running creates nothing that already exists (it reads existing ids first). Notes:
|
|
307
|
+
|
|
308
|
+
- **Provision is a single-operator, dev-machine action.** The lock that guards it is per local config path only; it does not coordinate across machines. Two people provisioning the same account at once could create duplicate resources. `--provision` also **fails closed in CI / non-interactive shells** unless your committed `wrangler.jsonc` already covers every resource (a provable no-op). Provision locally, commit the updated `wrangler.jsonc`, then let CI run `void deploy --backend cloudflare`.
|
|
309
|
+
- **Your `wrangler.jsonc` is rewritten.** When wrangler writes the new ids, it preserves your comments but normalizes the whole file's indentation — expect that in the diff.
|
|
310
|
+
- **Your `.env*` values ship as plaintext.** All four of `.env`, `.env.local`, `.env.production` and `.env.production.local` are loaded by this backend and baked into the worker's `vars` — the `.local` files included, unlike managed `void deploy`. A value also present in the shell environment is stripped back out. Move real secrets to `wrangler secret put <NAME>` so they are not committed into `wrangler.json`. Deploy warns on likely-plaintext secrets and hard-blocks on missing required secrets.
|
|
311
|
+
- **First deploy of a not-yet-deployed worker:** its remote secrets can't be listed yet, so the secret gate prints the required key names and the `wrangler secret put <NAME>` commands to bootstrap them on the draft worker before deploying (or add a value to `.env` / `.env.production` and rerun).
|
|
312
|
+
|
|
313
|
+
See the [Cloudflare integration guide](../integrations/cloudflare.md#deploy-to-your-own-cloudflare-account) for the full walk-through.
|
|
314
|
+
|
|
255
315
|
## Database
|
|
256
316
|
|
|
257
317
|
### `void db push`
|