create-kelpie 0.14.0 → 0.15.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/README.md +2 -0
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +1 -0
- package/dist/scaffold.js.map +1 -1
- package/package.json +1 -1
- package/src/scaffold.ts +1 -0
- package/templates/README.md +15 -1
- package/templates/package.json +1 -0
- package/templates/src/migrate.ts +3 -1
- package/templates/src/server.ts +27 -6
- package/templates/src/worker.ts +71 -0
package/README.md
CHANGED
|
@@ -20,6 +20,8 @@ package.json @kelpie/server and @kelpie/ui, pinned to this version
|
|
|
20
20
|
kelpie.config.ts the server module list
|
|
21
21
|
kelpie.ui.config.ts the UI module list
|
|
22
22
|
src/server.ts the entry point: config, modules, migrations, serve
|
|
23
|
+
src/migrate.ts `npm run migrate`: applies core and pg-boss migrations
|
|
24
|
+
src/worker.ts `npm run worker`: pg-boss consumer, for scaling jobs apart from HTTP
|
|
23
25
|
src/reseal.ts re-seals stored secrets after a SECRET_ENCRYPTION_KEY change
|
|
24
26
|
web/index.html the web entry
|
|
25
27
|
web/main.tsx
|
package/dist/scaffold.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,0FAA0F;IAC1F,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,qEAAqE;IACrE,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;IACpC,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,wEAAwE;AACxE,qBAAa,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,0FAA0F;IAC1F,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,qEAAqE;IACrE,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;IACpC,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,wEAAwE;AACxE,qBAAa,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AA8DD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAkBtD;AAED,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,MAAM,EAAE,CAsBpE"}
|
package/dist/scaffold.js
CHANGED
|
@@ -30,6 +30,7 @@ const TEMPLATE_FILES = new Map([
|
|
|
30
30
|
['kelpie.ui.config.ts', 'kelpie.ui.config.ts'],
|
|
31
31
|
['src/server.ts', 'src/server.ts'],
|
|
32
32
|
['src/migrate.ts', 'src/migrate.ts'],
|
|
33
|
+
['src/worker.ts', 'src/worker.ts'],
|
|
33
34
|
['src/reseal.ts', 'src/reseal.ts'],
|
|
34
35
|
['web/index.html', 'web/index.html'],
|
|
35
36
|
['web/main.tsx', 'web/main.tsx'],
|
package/dist/scaffold.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/scaffold.ts
CHANGED
|
@@ -51,6 +51,7 @@ const TEMPLATE_FILES: ReadonlyMap<string, string> = new Map([
|
|
|
51
51
|
['kelpie.ui.config.ts', 'kelpie.ui.config.ts'],
|
|
52
52
|
['src/server.ts', 'src/server.ts'],
|
|
53
53
|
['src/migrate.ts', 'src/migrate.ts'],
|
|
54
|
+
['src/worker.ts', 'src/worker.ts'],
|
|
54
55
|
['src/reseal.ts', 'src/reseal.ts'],
|
|
55
56
|
['web/index.html', 'web/index.html'],
|
|
56
57
|
['web/main.tsx', 'web/main.tsx'],
|
package/templates/README.md
CHANGED
|
@@ -128,7 +128,21 @@ stops rather than answering every browser with a blank page.
|
|
|
128
128
|
|
|
129
129
|
Migrations apply at boot. Running more than one instance makes that a race, so
|
|
130
130
|
migrate once with `npm run migrate` in a release step, then start the instances
|
|
131
|
-
with `--no-migrate`. That command is forward-only and safe to re-run.
|
|
131
|
+
with `--no-migrate`. That command is forward-only and safe to re-run. It also
|
|
132
|
+
applies pg-boss's own schema, so the worker has the tables it needs.
|
|
133
|
+
|
|
134
|
+
Background jobs run on pg-boss. The default deployment runs the work loops
|
|
135
|
+
inline from `npm start`, so one process both serves and works. To scale the two
|
|
136
|
+
sides on their own — for example when a slow handler must not compete with
|
|
137
|
+
request handling — run a second process alongside:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
WEB_BUNDLE_DIR=./dist npm start -- --no-worker # HTTP only, still enqueues
|
|
141
|
+
npm run worker # pg-boss consumer, no HTTP
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Both processes read the same `.env`, connect to the same database, and load
|
|
145
|
+
the same modules. Neither owns state the other needs.
|
|
132
146
|
|
|
133
147
|
TLS, reverse proxies, systemd, health checks, and backups:
|
|
134
148
|
[docs/self-hosting/production.md](https://github.com/velvet-tiger/kelpie/blob/main/docs/self-hosting/production.md).
|
package/templates/package.json
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"dev:web": "vite",
|
|
13
13
|
"start": "node --env-file-if-exists=.env src/server.ts",
|
|
14
14
|
"migrate": "node --env-file-if-exists=.env src/migrate.ts",
|
|
15
|
+
"worker": "node --env-file-if-exists=.env src/worker.ts",
|
|
15
16
|
"reseal": "node --env-file-if-exists=.env src/reseal.ts",
|
|
16
17
|
"build": "vite build",
|
|
17
18
|
"typecheck": "tsc --project tsconfig.server.json && tsc --project tsconfig.web.json"
|
package/templates/src/migrate.ts
CHANGED
|
@@ -24,10 +24,12 @@ function reportFatal(message: string): void {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
async function migrate(): Promise<void> {
|
|
27
|
-
const { database, contributions, logger } = await bootAssembly(kelpieConfig, process.env)
|
|
27
|
+
const { database, contributions, jobs, logger } = await bootAssembly(kelpieConfig, process.env)
|
|
28
28
|
|
|
29
29
|
try {
|
|
30
30
|
await runMigrations(database.db, contributions.schemas, logger)
|
|
31
|
+
await jobs.migrate()
|
|
32
|
+
logger.info('pg-boss schema migrated')
|
|
31
33
|
} finally {
|
|
32
34
|
await database.close()
|
|
33
35
|
}
|
package/templates/src/server.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
resolveClientIpFrom,
|
|
11
11
|
runMigrations,
|
|
12
12
|
serveWebBundle,
|
|
13
|
+
startWorker,
|
|
13
14
|
} from '@kelpie/server'
|
|
14
15
|
|
|
15
16
|
import kelpieConfig from '../kelpie.config.ts'
|
|
@@ -25,6 +26,11 @@ import kelpieConfig from '../kelpie.config.ts'
|
|
|
25
26
|
*
|
|
26
27
|
* `--no-migrate` skips the migration step, for deployments where `npm run migrate`
|
|
27
28
|
* migrates once in a release step and many instances then start.
|
|
29
|
+
*
|
|
30
|
+
* `--no-worker` skips the pg-boss `work()` loops. This process still opens the
|
|
31
|
+
* boss instance so a service can enqueue jobs inside its own transaction; the
|
|
32
|
+
* work loops themselves live in the separate `worker` process (`src/worker.ts`).
|
|
33
|
+
* The default is to run both inline, so one container both serves and works.
|
|
28
34
|
*/
|
|
29
35
|
|
|
30
36
|
function reportFatal(message: string): void {
|
|
@@ -32,15 +38,26 @@ function reportFatal(message: string): void {
|
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
async function start(): Promise<void> {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
process.env,
|
|
38
|
-
)
|
|
41
|
+
const boot = await bootAssembly(kelpieConfig, process.env)
|
|
42
|
+
const { config, logger, database, createId, credentials, contributions, jobs } = boot
|
|
39
43
|
|
|
40
44
|
if (process.argv.includes('--no-migrate')) {
|
|
41
45
|
logger.info('skipping migrations', { reason: '--no-migrate' })
|
|
42
46
|
} else {
|
|
43
47
|
await runMigrations(database.db, contributions.schemas, logger)
|
|
48
|
+
await jobs.migrate()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// The API always opens a boss instance: a service enqueues jobs inside its
|
|
52
|
+
// own transaction on request, so `boss.send` must be reachable even when
|
|
53
|
+
// this process runs no work loops. `startWorker` on top adds the `work()`
|
|
54
|
+
// calls; `--no-worker` skips them, for deployments that run a separate
|
|
55
|
+
// `src/worker.ts` process alongside.
|
|
56
|
+
if (process.argv.includes('--no-worker')) {
|
|
57
|
+
logger.info('skipping inline worker', { reason: '--no-worker' })
|
|
58
|
+
await jobs.start()
|
|
59
|
+
} else {
|
|
60
|
+
await startWorker(boot)
|
|
44
61
|
}
|
|
45
62
|
|
|
46
63
|
const app = createApp({
|
|
@@ -81,8 +98,12 @@ async function start(): Promise<void> {
|
|
|
81
98
|
logger.info('shutting down', { signal })
|
|
82
99
|
server.close(() => {
|
|
83
100
|
// Drain before closing the pool: a handler mid-flight may still be writing.
|
|
84
|
-
|
|
85
|
-
|
|
101
|
+
// Order: stop the job worker (waits for in-flight jobs), drain the event
|
|
102
|
+
// bus (which may still be delivering post-commit handlers), then close
|
|
103
|
+
// the database.
|
|
104
|
+
void jobs
|
|
105
|
+
.stop()
|
|
106
|
+
.then(() => contributions.events.drain())
|
|
86
107
|
.then(() => database.close())
|
|
87
108
|
.then(() => process.exit(0))
|
|
88
109
|
})
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigurationError,
|
|
3
|
+
ModuleBootError,
|
|
4
|
+
ModuleConfigFileError,
|
|
5
|
+
bootAssembly,
|
|
6
|
+
startWorker,
|
|
7
|
+
} from '@kelpie/server'
|
|
8
|
+
|
|
9
|
+
import kelpieConfig from '../kelpie.config.ts'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The worker entry point. Runs the pg-boss consumer without ever calling
|
|
13
|
+
* `createApp`, so there is no HTTP surface here.
|
|
14
|
+
*
|
|
15
|
+
* The default deployment runs the work loops inline from `src/server.ts`, so
|
|
16
|
+
* one container both serves and works. Start this process alongside a
|
|
17
|
+
* `server.ts` running with `--no-worker` when the two should scale on their
|
|
18
|
+
* own — for example, when a slow handler must not compete with request
|
|
19
|
+
* handling. Both processes share the same image, the same secrets, and the
|
|
20
|
+
* same `@kelpie/server` build.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
function reportFatal(message: string): void {
|
|
24
|
+
process.stderr.write(`${message}\n`)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function main(): Promise<void> {
|
|
28
|
+
const boot = await bootAssembly(kelpieConfig, process.env)
|
|
29
|
+
|
|
30
|
+
await startWorker(boot)
|
|
31
|
+
|
|
32
|
+
const shutdown = (signal: string): void => {
|
|
33
|
+
boot.logger.info('shutting down worker', { signal })
|
|
34
|
+
void boot.jobs
|
|
35
|
+
.stop()
|
|
36
|
+
.then(() => boot.contributions.events.drain())
|
|
37
|
+
.then(() => boot.database.close())
|
|
38
|
+
.then(() => process.exit(0))
|
|
39
|
+
.catch((error: unknown) => {
|
|
40
|
+
boot.logger.error('worker shutdown failed', { error })
|
|
41
|
+
process.exit(1)
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
process.on('SIGINT', () => shutdown('SIGINT'))
|
|
46
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
await main()
|
|
51
|
+
} catch (error: unknown) {
|
|
52
|
+
if (error instanceof ConfigurationError) {
|
|
53
|
+
reportFatal(error.message)
|
|
54
|
+
reportFatal('Check .env against the table in README.md.')
|
|
55
|
+
process.exit(1)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (error instanceof ModuleConfigFileError) {
|
|
59
|
+
reportFatal(error.message)
|
|
60
|
+
reportFatal('Fix the file at KELPIE_MODULE_CONFIG_PATH, or unset it to let workspaces decide for themselves.')
|
|
61
|
+
process.exit(1)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (error instanceof ModuleBootError) {
|
|
65
|
+
reportFatal(error.message)
|
|
66
|
+
reportFatal('Fix the module list in kelpie.config.ts, or the configuration it needs.')
|
|
67
|
+
process.exit(1)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
throw error
|
|
71
|
+
}
|