@treeseed/core 0.6.31 → 0.6.33
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/dist/dev.d.ts +2 -0
- package/dist/dev.js +107 -3
- package/package.json +2 -2
- package/templates/github/deploy.workflow.yml +4 -2
package/dist/dev.d.ts
CHANGED
|
@@ -105,6 +105,7 @@ type SpawnSyncLike = typeof spawnSync;
|
|
|
105
105
|
type SignalRegistrar = (signal: NodeJS.Signals, handler: () => void) => () => void;
|
|
106
106
|
type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
|
|
107
107
|
type ProcessKiller = (pid: number, signal: NodeJS.Signals) => void;
|
|
108
|
+
type ProcessStatusChecker = (pid: number) => boolean;
|
|
108
109
|
type WatchStarter = TreeseedDevWatchStarter;
|
|
109
110
|
type TreeseedIntegratedDevDependencies = {
|
|
110
111
|
spawn: SpawnLike;
|
|
@@ -113,6 +114,7 @@ type TreeseedIntegratedDevDependencies = {
|
|
|
113
114
|
prepareEnvironment: (tenantRoot: string) => void;
|
|
114
115
|
fetch: FetchLike;
|
|
115
116
|
killProcess: ProcessKiller;
|
|
117
|
+
processIsAlive: ProcessStatusChecker;
|
|
116
118
|
write: (line: string, stream: 'stdout' | 'stderr') => void;
|
|
117
119
|
openBrowser: (url: string) => void | Promise<void>;
|
|
118
120
|
startWatch: WatchStarter;
|
package/dist/dev.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { spawn, spawnSync } from "node:child_process";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { dirname, resolve, sep } from "node:path";
|
|
@@ -32,6 +32,7 @@ const TREESEED_DEFAULT_LOCAL_SMTP_HOST = "127.0.0.1";
|
|
|
32
32
|
const TREESEED_DEFAULT_LOCAL_SMTP_PORT = 1025;
|
|
33
33
|
const TREESEED_DEFAULT_MAILPIT_UI_PORT = 8025;
|
|
34
34
|
const DEV_RELOAD_FILE = "public/__treeseed/dev-reload.json";
|
|
35
|
+
const DEV_RUNTIME_FILE = ".treeseed/generated/dev/runtime.json";
|
|
35
36
|
const DEFAULT_READINESS_TIMEOUT_MS = 9e4;
|
|
36
37
|
const DEFAULT_PROCESS_READY_GRACE_MS = 1200;
|
|
37
38
|
const DEFAULT_SHUTDOWN_GRACE_MS = 2500;
|
|
@@ -449,8 +450,12 @@ function createTreeseedIntegratedDevPlan(options = {}) {
|
|
|
449
450
|
TREESEED_API_D1_LOCAL_PERSIST_TO: mergedEnv.TREESEED_API_D1_LOCAL_PERSIST_TO ?? (usesCloudflareWebRuntime ? resolve(tenantRoot, ".treeseed", "generated", "environments", "local", ".wrangler", "state", "v3", "d1") : resolve(tenantRoot, ".wrangler", "state", "v3", "d1")),
|
|
450
451
|
TREESEED_FORM_TOKEN_SECRET: mergedEnv.TREESEED_FORM_TOKEN_SECRET ?? "treeseed-local-form-token-secret",
|
|
451
452
|
TREESEED_BETTER_AUTH_SECRET: mergedEnv.TREESEED_BETTER_AUTH_SECRET ?? "treeseed-local-better-auth-secret-minimum-32-characters",
|
|
452
|
-
TREESEED_SMTP_HOST:
|
|
453
|
-
TREESEED_SMTP_PORT:
|
|
453
|
+
TREESEED_SMTP_HOST: TREESEED_DEFAULT_LOCAL_SMTP_HOST,
|
|
454
|
+
TREESEED_SMTP_PORT: String(TREESEED_DEFAULT_LOCAL_SMTP_PORT),
|
|
455
|
+
TREESEED_SMTP_USERNAME: "",
|
|
456
|
+
TREESEED_SMTP_PASSWORD: "",
|
|
457
|
+
TREESEED_MAILPIT_SMTP_HOST: TREESEED_DEFAULT_LOCAL_SMTP_HOST,
|
|
458
|
+
TREESEED_MAILPIT_SMTP_PORT: String(TREESEED_DEFAULT_LOCAL_SMTP_PORT),
|
|
454
459
|
TREESEED_MAILPIT_UI_PORT: mergedEnv.TREESEED_MAILPIT_UI_PORT ?? String(TREESEED_DEFAULT_MAILPIT_UI_PORT),
|
|
455
460
|
TREESEED_AUTH_EMAIL_FROM: mergedEnv.TREESEED_AUTH_EMAIL_FROM ?? "Treeseed Market <auth@treeseed.local>"
|
|
456
461
|
};
|
|
@@ -583,6 +588,17 @@ function defaultPrepareEnvironment(tenantRoot) {
|
|
|
583
588
|
function defaultKillProcess(pid, signal) {
|
|
584
589
|
process.kill(pid, signal);
|
|
585
590
|
}
|
|
591
|
+
function defaultProcessIsAlive(pid) {
|
|
592
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
try {
|
|
596
|
+
process.kill(pid, 0);
|
|
597
|
+
return true;
|
|
598
|
+
} catch {
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
586
602
|
function defaultRemovePath(path) {
|
|
587
603
|
rmSync(path, { recursive: true, force: true });
|
|
588
604
|
}
|
|
@@ -662,6 +678,88 @@ function resolveLocalMachineEnv(tenantRoot) {
|
|
|
662
678
|
return {};
|
|
663
679
|
}
|
|
664
680
|
}
|
|
681
|
+
function devRuntimeStatePath(tenantRoot) {
|
|
682
|
+
return resolve(tenantRoot, DEV_RUNTIME_FILE);
|
|
683
|
+
}
|
|
684
|
+
function readDevRuntimeState(tenantRoot) {
|
|
685
|
+
try {
|
|
686
|
+
const parsed = JSON.parse(readFileSync(devRuntimeStatePath(tenantRoot), "utf8"));
|
|
687
|
+
if (!Number.isInteger(parsed.pid) || typeof parsed.tenantRoot !== "string" || typeof parsed.startedAt !== "string") {
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
690
|
+
return {
|
|
691
|
+
pid: parsed.pid,
|
|
692
|
+
tenantRoot: parsed.tenantRoot,
|
|
693
|
+
startedAt: parsed.startedAt
|
|
694
|
+
};
|
|
695
|
+
} catch {
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
function writeCurrentDevRuntimeState(tenantRoot) {
|
|
700
|
+
const outputPath = devRuntimeStatePath(tenantRoot);
|
|
701
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
702
|
+
writeFileSync(
|
|
703
|
+
outputPath,
|
|
704
|
+
`${JSON.stringify({
|
|
705
|
+
pid: process.pid,
|
|
706
|
+
tenantRoot,
|
|
707
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
708
|
+
}, null, 2)}
|
|
709
|
+
`,
|
|
710
|
+
"utf8"
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
function removeCurrentDevRuntimeState(tenantRoot) {
|
|
714
|
+
const state = readDevRuntimeState(tenantRoot);
|
|
715
|
+
if (!state || state.pid !== process.pid) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
rmSync(devRuntimeStatePath(tenantRoot), { force: true });
|
|
719
|
+
}
|
|
720
|
+
async function waitForProcessExit(pid, processIsAlive, timeoutMs) {
|
|
721
|
+
const startedAt = Date.now();
|
|
722
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
723
|
+
if (!processIsAlive(pid)) {
|
|
724
|
+
return true;
|
|
725
|
+
}
|
|
726
|
+
await delay(100);
|
|
727
|
+
}
|
|
728
|
+
return !processIsAlive(pid);
|
|
729
|
+
}
|
|
730
|
+
async function stopPreviousDevRuntime(tenantRoot, options, deps) {
|
|
731
|
+
const state = readDevRuntimeState(tenantRoot);
|
|
732
|
+
if (!state) {
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
const statePath = devRuntimeStatePath(tenantRoot);
|
|
736
|
+
if (state.pid === process.pid) {
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (!deps.processIsAlive(state.pid)) {
|
|
740
|
+
rmSync(statePath, { force: true });
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
emitEvent(options, deps.write, {
|
|
744
|
+
type: "replace",
|
|
745
|
+
message: `Stopping previous Treeseed dev runtime (${state.pid}) before starting a new one.`,
|
|
746
|
+
detail: { pid: state.pid, startedAt: state.startedAt }
|
|
747
|
+
});
|
|
748
|
+
try {
|
|
749
|
+
deps.killProcess(state.pid, "SIGTERM");
|
|
750
|
+
} catch {
|
|
751
|
+
}
|
|
752
|
+
if (await waitForProcessExit(state.pid, deps.processIsAlive, options.shutdownGraceMs ?? DEFAULT_SHUTDOWN_GRACE_MS)) {
|
|
753
|
+
rmSync(statePath, { force: true });
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
try {
|
|
757
|
+
deps.killProcess(state.pid, "SIGKILL");
|
|
758
|
+
} catch {
|
|
759
|
+
}
|
|
760
|
+
await waitForProcessExit(state.pid, deps.processIsAlive, DEFAULT_KILL_GRACE_MS);
|
|
761
|
+
rmSync(statePath, { force: true });
|
|
762
|
+
}
|
|
665
763
|
function emitEvent(options, write, event, stream = event.type === "error" ? "stderr" : "stdout") {
|
|
666
764
|
if (options.json) {
|
|
667
765
|
write(`${JSON.stringify({ schemaVersion: 1, kind: "treeseed.dev.event", ...event })}
|
|
@@ -983,6 +1081,7 @@ async function runTreeseedIntegratedDev(options = {}, deps = {}) {
|
|
|
983
1081
|
const onSignal = deps.onSignal ?? defaultSignalRegistrar;
|
|
984
1082
|
const fetchFn = deps.fetch ?? globalThis.fetch.bind(globalThis);
|
|
985
1083
|
const killProcess = deps.killProcess ?? defaultKillProcess;
|
|
1084
|
+
const processIsAlive = deps.processIsAlive ?? defaultProcessIsAlive;
|
|
986
1085
|
const openBrowser = deps.openBrowser ?? defaultOpenBrowser;
|
|
987
1086
|
const startWatch = deps.startWatch ?? startPollingWatch;
|
|
988
1087
|
const prepareEnvironment = deps.prepareEnvironment ?? defaultPrepareEnvironment;
|
|
@@ -1001,6 +1100,9 @@ async function runTreeseedIntegratedDev(options = {}, deps = {}) {
|
|
|
1001
1100
|
writePlan(plan, options, write);
|
|
1002
1101
|
return 0;
|
|
1003
1102
|
}
|
|
1103
|
+
if (readDevRuntimeState(tenantRoot)) {
|
|
1104
|
+
await stopPreviousDevRuntime(tenantRoot, options, { write, killProcess, processIsAlive });
|
|
1105
|
+
}
|
|
1004
1106
|
const resetResults = runTreeseedIntegratedDevReset(plan.reset, options, {
|
|
1005
1107
|
write,
|
|
1006
1108
|
removePath,
|
|
@@ -1021,6 +1123,7 @@ async function runTreeseedIntegratedDev(options = {}, deps = {}) {
|
|
|
1021
1123
|
emitEvent(options, write, { type: "error", message: failedSetupMessage(failedSetup), detail: failedSetup });
|
|
1022
1124
|
return 1;
|
|
1023
1125
|
}
|
|
1126
|
+
writeCurrentDevRuntimeState(tenantRoot);
|
|
1024
1127
|
const children = /* @__PURE__ */ new Map();
|
|
1025
1128
|
const commandsById = new Map(plan.commands.map((command) => [command.id, command]));
|
|
1026
1129
|
const requiredSurfaceIds = new Set(plan.readyChecks.filter((check) => check.required).map((check) => check.id));
|
|
@@ -1058,6 +1161,7 @@ async function runTreeseedIntegratedDev(options = {}, deps = {}) {
|
|
|
1058
1161
|
for (const dispose of disposers) {
|
|
1059
1162
|
dispose();
|
|
1060
1163
|
}
|
|
1164
|
+
removeCurrentDevRuntimeState(tenantRoot);
|
|
1061
1165
|
emitEvent(
|
|
1062
1166
|
options,
|
|
1063
1167
|
write,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeseed/core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.33",
|
|
4
4
|
"description": "Treeseed integrated platform starter for Astro/Starlight web runtimes and Hono API runtimes.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"@astrojs/sitemap": "3.7.0",
|
|
77
77
|
"@astrojs/starlight": "0.37.6",
|
|
78
78
|
"@tailwindcss/vite": "^4.1.4",
|
|
79
|
-
"@treeseed/sdk": "0.6.
|
|
79
|
+
"@treeseed/sdk": "0.6.32",
|
|
80
80
|
"astro": "^5.6.1",
|
|
81
81
|
"esbuild": "^0.28.0",
|
|
82
82
|
"hono": "^4.8.2",
|
|
@@ -176,9 +176,11 @@ jobs:
|
|
|
176
176
|
set -euo pipefail
|
|
177
177
|
npm run verify:local 2>&1 | tee verify.log
|
|
178
178
|
if test -f ./packages/sdk/scripts/check-build-warnings.mjs; then
|
|
179
|
-
node ./packages/sdk/scripts/check-build-warnings.mjs verify.log
|
|
179
|
+
node ./packages/sdk/scripts/check-build-warnings.mjs verify.log \
|
|
180
|
+
--allow 'Module "url" has been externalized for browser compatibility, imported by ".*libsodium-sumo.*"'
|
|
180
181
|
elif test -f ./node_modules/@treeseed/sdk/dist/scripts/check-build-warnings.js; then
|
|
181
|
-
node ./node_modules/@treeseed/sdk/dist/scripts/check-build-warnings.js verify.log
|
|
182
|
+
node ./node_modules/@treeseed/sdk/dist/scripts/check-build-warnings.js verify.log \
|
|
183
|
+
--allow 'Module "url" has been externalized for browser compatibility, imported by ".*libsodium-sumo.*"'
|
|
182
184
|
else
|
|
183
185
|
echo "Unable to resolve @treeseed/sdk warning scanner entrypoint."
|
|
184
186
|
exit 1
|