@yannelli/zoomies 0.0.0
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/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/cli/client.d.ts +77 -0
- package/dist/cli/client.d.ts.map +1 -0
- package/dist/cli/client.js +300 -0
- package/dist/cli/client.js.map +1 -0
- package/dist/cli/commands/certs.d.ts +11 -0
- package/dist/cli/commands/certs.d.ts.map +1 -0
- package/dist/cli/commands/certs.js +110 -0
- package/dist/cli/commands/certs.js.map +1 -0
- package/dist/cli/commands/flags.d.ts +29 -0
- package/dist/cli/commands/flags.d.ts.map +1 -0
- package/dist/cli/commands/flags.js +104 -0
- package/dist/cli/commands/flags.js.map +1 -0
- package/dist/cli/commands/reload.d.ts +11 -0
- package/dist/cli/commands/reload.d.ts.map +1 -0
- package/dist/cli/commands/reload.js +35 -0
- package/dist/cli/commands/reload.js.map +1 -0
- package/dist/cli/commands/sites.d.ts +11 -0
- package/dist/cli/commands/sites.d.ts.map +1 -0
- package/dist/cli/commands/sites.js +221 -0
- package/dist/cli/commands/sites.js.map +1 -0
- package/dist/cli/commands/status.d.ts +10 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +41 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/upstreams.d.ts +21 -0
- package/dist/cli/commands/upstreams.d.ts.map +1 -0
- package/dist/cli/commands/upstreams.js +248 -0
- package/dist/cli/commands/upstreams.js.map +1 -0
- package/dist/cli/dispatcher.d.ts +45 -0
- package/dist/cli/dispatcher.d.ts.map +1 -0
- package/dist/cli/dispatcher.js +192 -0
- package/dist/cli/dispatcher.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/server/api/db-context.d.ts +50 -0
- package/dist/server/api/db-context.d.ts.map +1 -0
- package/dist/server/api/db-context.js +76 -0
- package/dist/server/api/db-context.js.map +1 -0
- package/dist/server/api/error-mapping.d.ts +19 -0
- package/dist/server/api/error-mapping.d.ts.map +1 -0
- package/dist/server/api/error-mapping.js +56 -0
- package/dist/server/api/error-mapping.js.map +1 -0
- package/dist/server/api/handlers/site-cert.d.ts +49 -0
- package/dist/server/api/handlers/site-cert.d.ts.map +1 -0
- package/dist/server/api/handlers/site-cert.js +54 -0
- package/dist/server/api/handlers/site-cert.js.map +1 -0
- package/dist/server/api/handlers/sites.d.ts +67 -0
- package/dist/server/api/handlers/sites.d.ts.map +1 -0
- package/dist/server/api/handlers/sites.js +78 -0
- package/dist/server/api/handlers/sites.js.map +1 -0
- package/dist/server/api/handlers/upstreams.d.ts +64 -0
- package/dist/server/api/handlers/upstreams.d.ts.map +1 -0
- package/dist/server/api/handlers/upstreams.js +97 -0
- package/dist/server/api/handlers/upstreams.js.map +1 -0
- package/dist/server/auth/require-token.d.ts +24 -0
- package/dist/server/auth/require-token.d.ts.map +1 -0
- package/dist/server/auth/require-token.js +98 -0
- package/dist/server/auth/require-token.js.map +1 -0
- package/dist/server/certs/acme-account.d.ts +37 -0
- package/dist/server/certs/acme-account.d.ts.map +1 -0
- package/dist/server/certs/acme-account.js +49 -0
- package/dist/server/certs/acme-account.js.map +1 -0
- package/dist/server/certs/challenge-store.d.ts +53 -0
- package/dist/server/certs/challenge-store.d.ts.map +1 -0
- package/dist/server/certs/challenge-store.js +66 -0
- package/dist/server/certs/challenge-store.js.map +1 -0
- package/dist/server/certs/issue.d.ts +106 -0
- package/dist/server/certs/issue.d.ts.map +1 -0
- package/dist/server/certs/issue.js +107 -0
- package/dist/server/certs/issue.js.map +1 -0
- package/dist/server/certs/renew.d.ts +34 -0
- package/dist/server/certs/renew.d.ts.map +1 -0
- package/dist/server/certs/renew.js +36 -0
- package/dist/server/certs/renew.js.map +1 -0
- package/dist/server/certs/scheduler.d.ts +68 -0
- package/dist/server/certs/scheduler.d.ts.map +1 -0
- package/dist/server/certs/scheduler.js +76 -0
- package/dist/server/certs/scheduler.js.map +1 -0
- package/dist/server/db/connection.d.ts +10 -0
- package/dist/server/db/connection.d.ts.map +1 -0
- package/dist/server/db/connection.js +16 -0
- package/dist/server/db/connection.js.map +1 -0
- package/dist/server/db/migrate.d.ts +12 -0
- package/dist/server/db/migrate.d.ts.map +1 -0
- package/dist/server/db/migrate.js +37 -0
- package/dist/server/db/migrate.js.map +1 -0
- package/dist/server/db/migrations/0001_init.sql +42 -0
- package/dist/server/domain/cert.d.ts +17 -0
- package/dist/server/domain/cert.d.ts.map +1 -0
- package/dist/server/domain/cert.js +22 -0
- package/dist/server/domain/cert.js.map +1 -0
- package/dist/server/domain/errors.d.ts +36 -0
- package/dist/server/domain/errors.d.ts.map +1 -0
- package/dist/server/domain/errors.js +37 -0
- package/dist/server/domain/errors.js.map +1 -0
- package/dist/server/domain/site.d.ts +15 -0
- package/dist/server/domain/site.d.ts.map +1 -0
- package/dist/server/domain/site.js +25 -0
- package/dist/server/domain/site.js.map +1 -0
- package/dist/server/domain/upstream.d.ts +25 -0
- package/dist/server/domain/upstream.d.ts.map +1 -0
- package/dist/server/domain/upstream.js +24 -0
- package/dist/server/domain/upstream.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +4 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/reload/atomic-write.d.ts +44 -0
- package/dist/server/reload/atomic-write.d.ts.map +1 -0
- package/dist/server/reload/atomic-write.js +151 -0
- package/dist/server/reload/atomic-write.js.map +1 -0
- package/dist/server/reload/health-probe.d.ts +62 -0
- package/dist/server/reload/health-probe.d.ts.map +1 -0
- package/dist/server/reload/health-probe.js +105 -0
- package/dist/server/reload/health-probe.js.map +1 -0
- package/dist/server/reload/reload.d.ts +118 -0
- package/dist/server/reload/reload.d.ts.map +1 -0
- package/dist/server/reload/reload.js +232 -0
- package/dist/server/reload/reload.js.map +1 -0
- package/dist/server/renderer/render-bundle.d.ts +18 -0
- package/dist/server/renderer/render-bundle.d.ts.map +1 -0
- package/dist/server/renderer/render-bundle.js +32 -0
- package/dist/server/renderer/render-bundle.js.map +1 -0
- package/dist/server/renderer/render-site.d.ts +5 -0
- package/dist/server/renderer/render-site.d.ts.map +1 -0
- package/dist/server/renderer/render-site.js +144 -0
- package/dist/server/renderer/render-site.js.map +1 -0
- package/dist/server/repositories/cert-repository.d.ts +19 -0
- package/dist/server/repositories/cert-repository.d.ts.map +1 -0
- package/dist/server/repositories/cert-repository.js +112 -0
- package/dist/server/repositories/cert-repository.js.map +1 -0
- package/dist/server/repositories/site-repository.d.ts +17 -0
- package/dist/server/repositories/site-repository.d.ts.map +1 -0
- package/dist/server/repositories/site-repository.js +122 -0
- package/dist/server/repositories/site-repository.js.map +1 -0
- package/dist/server/repositories/upstream-repository.d.ts +22 -0
- package/dist/server/repositories/upstream-repository.d.ts.map +1 -0
- package/dist/server/repositories/upstream-repository.js +142 -0
- package/dist/server/repositories/upstream-repository.js.map +1 -0
- package/dist/server/validator/nginx-binary.d.ts +9 -0
- package/dist/server/validator/nginx-binary.d.ts.map +1 -0
- package/dist/server/validator/nginx-binary.js +11 -0
- package/dist/server/validator/nginx-binary.js.map +1 -0
- package/dist/server/validator/validate.d.ts +29 -0
- package/dist/server/validator/validate.d.ts.map +1 -0
- package/dist/server/validator/validate.js +69 -0
- package/dist/server/validator/validate.js.map +1 -0
- package/dist/server/worker/main.d.ts +43 -0
- package/dist/server/worker/main.d.ts.map +1 -0
- package/dist/server/worker/main.js +181 -0
- package/dist/server/worker/main.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Long-running renewal worker entrypoint.
|
|
4
|
+
*
|
|
5
|
+
* `main()` runs an outer loop that calls {@link runRenewalCheck} every
|
|
6
|
+
* {@link WorkerOptions.intervalMs} (default 6 hours), resolves the production
|
|
7
|
+
* dependencies from the environment once on startup, and races the wait
|
|
8
|
+
* between iterations against a SIGTERM/SIGINT-driven abort promise so the
|
|
9
|
+
* worker shuts down promptly on signal.
|
|
10
|
+
*
|
|
11
|
+
* Shutdown semantics: we never interrupt a renewal mid-flight. The signal
|
|
12
|
+
* handlers flip a flag and resolve the abort promise — the loop reads it
|
|
13
|
+
* **after** the current `runRenewalCheck` returns, then exits cleanly. Let's
|
|
14
|
+
* Encrypt orders are stateful and a half-completed order tends to consume
|
|
15
|
+
* rate limit without producing a usable cert, so the cost of a clean wait
|
|
16
|
+
* is worth more than a few seconds of shutdown latency.
|
|
17
|
+
*
|
|
18
|
+
* Importable + runnable: the bottom of this file uses the same
|
|
19
|
+
* `import.meta.url === pathToFileURL(process.argv[1]).href` shim as
|
|
20
|
+
* `src/index.ts`, so it works both as `node dist/server/worker/main.js` and
|
|
21
|
+
* as an imported module from tests.
|
|
22
|
+
*
|
|
23
|
+
* The leading `#!/usr/bin/env node` shebang must stay on line 1 for the
|
|
24
|
+
* `zoomies-worker` bin entry to be directly executable; TypeScript happily
|
|
25
|
+
* carries the line through to the emitted JS as a comment-shaped no-op.
|
|
26
|
+
*/
|
|
27
|
+
import { mkdir } from 'node:fs/promises';
|
|
28
|
+
import { resolve, join } from 'node:path';
|
|
29
|
+
import { pathToFileURL } from 'node:url';
|
|
30
|
+
import { getDb } from '../api/db-context.js';
|
|
31
|
+
import { CertRepository } from '../repositories/cert-repository.js';
|
|
32
|
+
import { loadOrCreateAccount } from '../certs/acme-account.js';
|
|
33
|
+
import { createChallengeStore } from '../certs/challenge-store.js';
|
|
34
|
+
import { renewCertificate } from '../certs/renew.js';
|
|
35
|
+
import { runRenewalCheck } from '../certs/scheduler.js';
|
|
36
|
+
const DEFAULT_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
37
|
+
const DEFAULT_DIRECTORY_URL = 'https://acme-v02.api.letsencrypt.org/directory';
|
|
38
|
+
function readConfigFromEnv() {
|
|
39
|
+
const contactEmail = process.env.ZOOMIES_ACME_EMAIL;
|
|
40
|
+
if (contactEmail === undefined || contactEmail === '') {
|
|
41
|
+
throw new Error('ZOOMIES_ACME_EMAIL is required — set it to a contact email registered with the ACME directory');
|
|
42
|
+
}
|
|
43
|
+
const directoryUrl = process.env.ZOOMIES_ACME_DIRECTORY_URL ?? DEFAULT_DIRECTORY_URL;
|
|
44
|
+
const stateDir = process.env.ZOOMIES_STATE_DIR ?? join(process.cwd(), '.zoomies');
|
|
45
|
+
const certDir = process.env.ZOOMIES_CERT_DIR ?? join(stateDir, 'certs');
|
|
46
|
+
return { contactEmail, directoryUrl, stateDir, certDir };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve a SIGTERM/SIGINT-driven abort promise. Returns an object the
|
|
50
|
+
* caller can `await` and an `attach` that wires the handlers so signal
|
|
51
|
+
* delivery resolves the promise.
|
|
52
|
+
*
|
|
53
|
+
* Calling `dispose()` removes the handlers; tests don't use this (smoke
|
|
54
|
+
* test runs with `once: true`) but the production loop does after exit.
|
|
55
|
+
*/
|
|
56
|
+
function createAbortSignal() {
|
|
57
|
+
let resolveWait;
|
|
58
|
+
const wait = new Promise((r) => {
|
|
59
|
+
resolveWait = r;
|
|
60
|
+
});
|
|
61
|
+
const onSignal = (signal) => {
|
|
62
|
+
console.info(`zoomies: received ${signal}, shutting down after current renewal check`);
|
|
63
|
+
resolveWait();
|
|
64
|
+
};
|
|
65
|
+
const onTerm = () => onSignal('SIGTERM');
|
|
66
|
+
const onInt = () => onSignal('SIGINT');
|
|
67
|
+
process.once('SIGTERM', onTerm);
|
|
68
|
+
process.once('SIGINT', onInt);
|
|
69
|
+
return {
|
|
70
|
+
wait,
|
|
71
|
+
dispose: () => {
|
|
72
|
+
process.off('SIGTERM', onTerm);
|
|
73
|
+
process.off('SIGINT', onInt);
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Wait for `ms` milliseconds OR for the abort promise to resolve, whichever
|
|
79
|
+
* happens first. The `setTimeout` is `unref`'d so it never holds the event
|
|
80
|
+
* loop open past a shutdown signal.
|
|
81
|
+
*/
|
|
82
|
+
async function waitOrAbort(ms, abort) {
|
|
83
|
+
let timer;
|
|
84
|
+
const sleep = new Promise((resolveSleep) => {
|
|
85
|
+
timer = setTimeout(resolveSleep, ms);
|
|
86
|
+
timer.unref();
|
|
87
|
+
});
|
|
88
|
+
try {
|
|
89
|
+
await Promise.race([sleep, abort]);
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
if (timer !== undefined) {
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Build a `renew(cert)` closure pre-bound to the production dependencies.
|
|
99
|
+
*
|
|
100
|
+
* The scheduler only knows about `Cert -> Promise<Cert>`, so the worker
|
|
101
|
+
* owns the responsibility of capturing the ACME account, challenge store,
|
|
102
|
+
* cert directory, and cert repository.
|
|
103
|
+
*/
|
|
104
|
+
function bindRenew(args) {
|
|
105
|
+
return (cert) => renewCertificate({
|
|
106
|
+
cert,
|
|
107
|
+
certRepo: args.certRepo,
|
|
108
|
+
domain: cert.domain,
|
|
109
|
+
account: args.account,
|
|
110
|
+
challengeStore: args.challengeStore,
|
|
111
|
+
certDir: args.certDir,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Worker entrypoint. Resolves the production deps from the environment,
|
|
116
|
+
* then loops `runRenewalCheck` on the configured cadence until a shutdown
|
|
117
|
+
* signal is received (or `opts.once` is true).
|
|
118
|
+
*/
|
|
119
|
+
export async function main(opts) {
|
|
120
|
+
const intervalMs = opts?.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
121
|
+
const once = opts?.once ?? false;
|
|
122
|
+
const config = readConfigFromEnv();
|
|
123
|
+
// Make sure the state, cert, and ACME challenge directories exist before
|
|
124
|
+
// any code reaches for them. `recursive: true` makes this idempotent.
|
|
125
|
+
await mkdir(config.certDir, { recursive: true });
|
|
126
|
+
const challengeStore = createChallengeStore({ stateDir: config.stateDir });
|
|
127
|
+
await mkdir(challengeStore.basePath, { recursive: true });
|
|
128
|
+
const account = await loadOrCreateAccount({
|
|
129
|
+
accountKeyPath: join(config.stateDir, 'acme-account.key'),
|
|
130
|
+
contactEmail: config.contactEmail,
|
|
131
|
+
directoryUrl: config.directoryUrl,
|
|
132
|
+
});
|
|
133
|
+
const certRepo = new CertRepository(getDb());
|
|
134
|
+
const renew = bindRenew({
|
|
135
|
+
account,
|
|
136
|
+
challengeStore,
|
|
137
|
+
certDir: config.certDir,
|
|
138
|
+
certRepo,
|
|
139
|
+
});
|
|
140
|
+
// TODO: signal handling smoke test — currently exercised manually with
|
|
141
|
+
// `kill -TERM <pid>`. Hard to automate without a child-process harness.
|
|
142
|
+
const abort = once ? null : createAbortSignal();
|
|
143
|
+
console.info('zoomies-worker: starting', {
|
|
144
|
+
directoryUrl: config.directoryUrl,
|
|
145
|
+
certDir: config.certDir,
|
|
146
|
+
intervalMs,
|
|
147
|
+
once,
|
|
148
|
+
});
|
|
149
|
+
try {
|
|
150
|
+
while (true) {
|
|
151
|
+
const result = await runRenewalCheck({ deps: { certRepo, renew } });
|
|
152
|
+
console.info('zoomies-worker: renewal check complete', result);
|
|
153
|
+
if (once || abort === null) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// Race the sleep against the abort promise. If a signal was already
|
|
157
|
+
// delivered while the renewal check was running, this resolves on the
|
|
158
|
+
// next microtask and the loop exits.
|
|
159
|
+
await waitOrAbort(intervalMs, abort.wait);
|
|
160
|
+
const aborted = await Promise.race([abort.wait.then(() => true), Promise.resolve(false)]);
|
|
161
|
+
if (aborted) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
abort?.dispose();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Entrypoint shim — mirrors src/index.ts so the patterns stay consistent.
|
|
171
|
+
// `pathToFileURL` normalises the argv path so Windows + POSIX both match.
|
|
172
|
+
const entryArg = process.argv[1];
|
|
173
|
+
const entryUrl = entryArg ? pathToFileURL(resolve(entryArg)).href : undefined;
|
|
174
|
+
const isEntrypoint = entryUrl !== undefined && import.meta.url === entryUrl;
|
|
175
|
+
if (isEntrypoint) {
|
|
176
|
+
main().catch((err) => {
|
|
177
|
+
console.error('zoomies-worker: fatal error', err);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../../src/server/worker/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yannelli/zoomies",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Control plane for NGINX reverse proxy: config rendering, validation, and reload orchestration.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"zoomies": "dist/index.js",
|
|
9
|
+
"zoomies-worker": "dist/server/worker/main.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"dist/server/db/migrations/*.sql",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=22"
|
|
19
|
+
},
|
|
20
|
+
"packageManager": "pnpm@10.33.0",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"dev": "next dev",
|
|
23
|
+
"build": "pnpm run build:web && pnpm run build:cli",
|
|
24
|
+
"build:web": "next build",
|
|
25
|
+
"build:cli": "tsc -p tsconfig.cli.json && node scripts/copy-migrations.mjs",
|
|
26
|
+
"start": "next start",
|
|
27
|
+
"cli": "tsx src/index.ts",
|
|
28
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.cli.json --noEmit",
|
|
29
|
+
"lint": "eslint .",
|
|
30
|
+
"format": "prettier --write .",
|
|
31
|
+
"format:check": "prettier --check .",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"nginx",
|
|
37
|
+
"reverse-proxy",
|
|
38
|
+
"proxy-manager",
|
|
39
|
+
"control-plane"
|
|
40
|
+
],
|
|
41
|
+
"author": "Ryan Yannelli",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/yannelli/zoomies.git"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"acme-client": "^5.4.0",
|
|
49
|
+
"better-sqlite3": "^12.10.0",
|
|
50
|
+
"class-variance-authority": "^0.7.1",
|
|
51
|
+
"clsx": "^2.1.1",
|
|
52
|
+
"execa": "^9.6.1",
|
|
53
|
+
"next": "^15.0.0",
|
|
54
|
+
"react": "^19.0.0",
|
|
55
|
+
"react-dom": "^19.0.0",
|
|
56
|
+
"tailwind-merge": "^2.5.5",
|
|
57
|
+
"zod": "^4.4.3"
|
|
58
|
+
},
|
|
59
|
+
"pnpm": {
|
|
60
|
+
"onlyBuiltDependencies": [
|
|
61
|
+
"better-sqlite3"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@eslint/eslintrc": "^3.2.0",
|
|
66
|
+
"@eslint/js": "^9.18.0",
|
|
67
|
+
"@tailwindcss/postcss": "^4.0.0",
|
|
68
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
69
|
+
"@types/node": "^22.10.5",
|
|
70
|
+
"@types/react": "^19.0.0",
|
|
71
|
+
"@types/react-dom": "^19.0.0",
|
|
72
|
+
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
|
73
|
+
"@typescript-eslint/parser": "^8.20.0",
|
|
74
|
+
"eslint": "^9.18.0",
|
|
75
|
+
"eslint-config-next": "^15.0.0",
|
|
76
|
+
"postcss": "^8.4.49",
|
|
77
|
+
"prettier": "^3.4.2",
|
|
78
|
+
"tailwindcss": "^4.0.0",
|
|
79
|
+
"tsx": "^4.19.2",
|
|
80
|
+
"typescript": "^5.7.3",
|
|
81
|
+
"typescript-eslint": "^8.20.0",
|
|
82
|
+
"vitest": "^2.1.8"
|
|
83
|
+
}
|
|
84
|
+
}
|