@coreframe/scripts 0.1.0 → 0.1.2

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.
Files changed (96) hide show
  1. package/dist/config.d.ts +18 -4
  2. package/dist/config.js +1 -3
  3. package/dist/coreframe.d.ts +243 -241
  4. package/dist/coreframe.js +1 -239
  5. package/dist/db/client.d.ts +26 -18
  6. package/dist/db/client.js +1 -29
  7. package/dist/db/config.d.ts +22 -19
  8. package/dist/db/config.js +1 -32
  9. package/dist/db/drizzle-kit.d.ts +6 -5
  10. package/dist/db/drizzle-kit.js +1 -21
  11. package/dist/db/ensure.d.ts +20 -2
  12. package/dist/db/ensure.js +1 -39
  13. package/dist/db/migrate-held.d.ts +16 -10
  14. package/dist/db/migrate-held.js +3 -112
  15. package/dist/db/migrate.d.ts +4 -2
  16. package/dist/db/migrate.js +1 -24
  17. package/dist/db/project.d.ts +19 -7
  18. package/dist/db/project.js +1 -9
  19. package/dist/db/reset.d.ts +4 -2
  20. package/dist/db/reset.js +1 -18
  21. package/dist/db/schema-push.d.ts +22 -0
  22. package/dist/db/schema-push.js +1 -0
  23. package/dist/db/seed.d.ts +6 -3
  24. package/dist/db/seed.js +1 -22
  25. package/dist/db/setup.d.ts +6 -3
  26. package/dist/db/setup.js +1 -14
  27. package/dist/deploy/check-migrations.d.ts +4 -2
  28. package/dist/deploy/check-migrations.js +1 -17
  29. package/dist/deploy/checks.d.ts +6 -2
  30. package/dist/deploy/checks.js +1 -27
  31. package/dist/deploy/config.d.ts +47 -44
  32. package/dist/deploy/config.js +1 -9
  33. package/dist/deploy/migrations.d.ts +21 -18
  34. package/dist/deploy/migrations.js +4 -203
  35. package/dist/deploy/pending-migrations.d.ts +9 -5
  36. package/dist/deploy/pending-migrations.js +1 -30
  37. package/dist/deploy/tauri-release.d.ts +93 -73
  38. package/dist/deploy/tauri-release.js +1 -512
  39. package/dist/deploy/version.d.ts +15 -13
  40. package/dist/deploy/version.js +1 -41
  41. package/dist/deploy.d.ts +16 -15
  42. package/dist/deploy.js +1 -246
  43. package/dist/dev.d.ts +23 -12
  44. package/dist/dev.js +1 -95
  45. package/dist/image-generator.d.ts +18 -2
  46. package/dist/image-generator.js +1 -59
  47. package/dist/project.d.ts +4 -1
  48. package/dist/project.js +1 -13
  49. package/dist/typecheck.d.ts +4 -2
  50. package/dist/typecheck.js +1 -44
  51. package/dist/upgrade/check-skill-current.d.ts +10 -5
  52. package/dist/upgrade/check-skill-current.js +1 -87
  53. package/dist/upgrade/ensure-template-remote.d.ts +10 -5
  54. package/dist/upgrade/ensure-template-remote.js +1 -56
  55. package/dist/upgrade/fast-forward-template-files.d.ts +8 -6
  56. package/dist/upgrade/fast-forward-template-files.js +1 -279
  57. package/package.json +7 -2
  58. package/config.test.ts +0 -15
  59. package/config.ts +0 -9
  60. package/coreframe.ts +0 -272
  61. package/db/client.ts +0 -72
  62. package/db/config.ts +0 -41
  63. package/db/drizzle-kit.test.ts +0 -27
  64. package/db/drizzle-kit.ts +0 -39
  65. package/db/ensure.ts +0 -67
  66. package/db/migrate-held.test.ts +0 -81
  67. package/db/migrate-held.ts +0 -166
  68. package/db/migrate.ts +0 -39
  69. package/db/project.ts +0 -28
  70. package/db/reset.ts +0 -24
  71. package/db/seed.ts +0 -38
  72. package/db/setup.ts +0 -18
  73. package/deploy/check-migrations.ts +0 -31
  74. package/deploy/checks.ts +0 -38
  75. package/deploy/config.test.ts +0 -24
  76. package/deploy/config.ts +0 -68
  77. package/deploy/migrations.test.ts +0 -110
  78. package/deploy/migrations.ts +0 -317
  79. package/deploy/pending-migrations.test.ts +0 -93
  80. package/deploy/pending-migrations.ts +0 -45
  81. package/deploy/tauri-release.test.ts +0 -196
  82. package/deploy/tauri-release.ts +0 -816
  83. package/deploy/version.test.ts +0 -29
  84. package/deploy/version.ts +0 -65
  85. package/deploy.test.ts +0 -101
  86. package/deploy.ts +0 -346
  87. package/dev.test.ts +0 -153
  88. package/dev.ts +0 -155
  89. package/image-generator.ts +0 -84
  90. package/project.ts +0 -6
  91. package/tsconfig.build.json +0 -12
  92. package/tsconfig.json +0 -20
  93. package/typecheck.ts +0 -55
  94. package/upgrade/check-skill-current.ts +0 -112
  95. package/upgrade/ensure-template-remote.ts +0 -79
  96. package/upgrade/fast-forward-template-files.ts +0 -408
package/dist/deploy.js CHANGED
@@ -1,247 +1,2 @@
1
1
  #!/usr/bin/env node
2
- var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
3
- if (typeof path === "string" && /^\.\.?\//.test(path)) {
4
- return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
5
- return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
6
- });
7
- }
8
- return path;
9
- };
10
- import { access, writeFile } from "node:fs/promises";
11
- import { resolve } from "node:path";
12
- import { pathToFileURL } from "node:url";
13
- import * as clack from "@clack/prompts";
14
- import nanoSpawn from "nano-spawn";
15
- import { createProjectDeployDatabase } from "./db/project.js";
16
- import { runPostDeployChecks } from "./deploy/checks.js";
17
- import { resolveDeployConfig } from "./deploy/config.js";
18
- import { collectDeployMigrationFiles, formatMigrationList, formatMigrationScanFailures, scanDeployMigrationFiles, } from "./deploy/migrations.js";
19
- import { filterPendingMigrations, readAppliedMigrationNames } from "./deploy/pending-migrations.js";
20
- import { parseTauriReleasePlatform, prepareTauriRelease, resolveTauriReleasePlan, restoreTauriReleaseMetadata, uploadTauriReleaseToB2, validateTauriReleasePlan, writeTauriReleaseMetadata, } from "./deploy/tauri-release.js";
21
- import { nextReleaseVersion, readPackageJson, releaseName, writePackageVersion, } from "./deploy/version.js";
22
- const packagePath = "package.json";
23
- const projectConfigPath = "coreframe.config.ts";
24
- export async function deployProject(argv = process.argv.slice(2), env = process.env) {
25
- const args = parseDeployArgs(argv);
26
- const { packageJson, source: originalPackageSource } = await readPackageJson(packagePath);
27
- const version = nextReleaseVersion(packageJson.version);
28
- const name = releaseName(packageJson.name, version);
29
- const environment = env.DEPLOY_ENV ?? "production";
30
- const releaseEnv = createReleaseEnv(env, name, packageJson.name, version);
31
- const projectConfig = await readProjectConfig();
32
- const config = resolveDeployConfig(projectConfig.deploy ?? {}, env);
33
- const tauriReleasePlan = resolveTauriReleasePlan({
34
- args,
35
- config: config.tauriRelease,
36
- env,
37
- });
38
- let externalMutated = false;
39
- let tauriMetadataSnapshot = { files: [] };
40
- clack.intro(`Deploy ${name}`);
41
- validateDeployArgs(args);
42
- requireEnv(env, ["POSTHOG_API_KEY", "POSTHOG_PROJECT_ID"]);
43
- await ensureCleanGit();
44
- await validateTauriReleasePlan(tauriReleasePlan);
45
- const database = await createProjectDeployDatabase({ env });
46
- const pendingMigrations = await collectPendingMigrationsWithClose(database);
47
- const migrationFailures = await scanDeployMigrationFiles(pendingMigrations);
48
- if (migrationFailures.length > 0) {
49
- throw new Error(`Pending deploy migrations contain unsafe SQL. Move unsafe statements to held migrations.\n${formatMigrationScanFailures(migrationFailures)}`);
50
- }
51
- const shouldRunMigrations = await chooseMigrationExecution(args, pendingMigrations);
52
- try {
53
- await writePackageVersion(packagePath, packageJson, version);
54
- tauriMetadataSnapshot = await writeTauriReleaseMetadata(tauriReleasePlan, version);
55
- clack.log.step("Running pre-deploy build");
56
- await nanoSpawn("pnpm", ["build"], {
57
- env: createBuildCheckEnv(releaseEnv),
58
- stdio: "inherit",
59
- });
60
- const tauriRelease = tauriReleasePlan.enabled
61
- ? await prepareTauriRelease({
62
- env: createBuildCheckEnv(releaseEnv),
63
- plan: tauriReleasePlan,
64
- releaseName: name,
65
- version,
66
- })
67
- : undefined;
68
- clack.log.step("Running release build and uploading PostHog source maps");
69
- externalMutated = true;
70
- await nanoSpawn("pnpm", ["build"], {
71
- env: releaseEnv,
72
- stdio: "inherit",
73
- });
74
- if (shouldRunMigrations) {
75
- clack.log.step("Running deploy-safe database migrations");
76
- await nanoSpawn("pnpm", ["db", "migrate"], {
77
- env: releaseEnv,
78
- stdio: "inherit",
79
- });
80
- }
81
- clack.log.step("Deploying Worker and static assets to Cloudflare");
82
- await nanoSpawn("pnpm", [
83
- "exec",
84
- "wrangler",
85
- "deploy",
86
- "--strict",
87
- "--keep-vars",
88
- "--tag",
89
- name,
90
- "--message",
91
- `Deploy ${name}`,
92
- "--var",
93
- `POSTHOG_RELEASE:${name}`,
94
- ], {
95
- env: releaseEnv,
96
- stdio: "inherit",
97
- });
98
- if (!args.skipPostDeployChecks) {
99
- clack.log.step("Running post-deploy checks");
100
- await runPostDeployChecks(config, {
101
- environment,
102
- productionUrl: config.productionUrl,
103
- releaseName: name,
104
- version,
105
- });
106
- }
107
- if (tauriRelease) {
108
- clack.log.step("Uploading Tauri release artifacts to Backblaze B2");
109
- await uploadTauriReleaseToB2(tauriReleasePlan, tauriRelease);
110
- }
111
- clack.outro(`Deployed ${name}`);
112
- }
113
- catch (error) {
114
- if (!externalMutated) {
115
- await writeFile(packagePath, originalPackageSource);
116
- await restoreTauriReleaseMetadata(tauriMetadataSnapshot);
117
- }
118
- throw error;
119
- }
120
- }
121
- export async function readProjectConfig() {
122
- const configPath = resolve(projectConfigPath);
123
- try {
124
- await access(configPath);
125
- }
126
- catch {
127
- return {};
128
- }
129
- const configUrl = pathToFileURL(configPath).href;
130
- const module = (await import(__rewriteRelativeImportExtension(configUrl)));
131
- return module.default ?? {};
132
- }
133
- export function parseDeployArgs(argv) {
134
- return {
135
- runMigrations: argv.includes("--run-migrations") || argv.includes("--yes"),
136
- skipMigrations: argv.includes("--skip-migrations"),
137
- skipPostDeployChecks: argv.includes("--skip-post-deploy-checks"),
138
- tauriLocalPlatforms: parseRepeatedOption(argv, "--tauri-local-platform").map((platform) => parseTauriReleasePlatform(platform)),
139
- tauriWorkflowName: parseOptionalOption(argv, "--tauri-workflow-name"),
140
- tauriWorkflowPlatforms: parseRepeatedOption(argv, "--tauri-workflow-platform").map((platform) => parseTauriReleasePlatform(platform)),
141
- tauriWorkflowRef: parseOptionalOption(argv, "--tauri-workflow-ref"),
142
- yes: argv.includes("--yes"),
143
- };
144
- }
145
- function parseRepeatedOption(argv, name) {
146
- const values = [];
147
- for (let index = 0; index < argv.length; index += 1) {
148
- const arg = argv[index];
149
- if (arg === name) {
150
- const value = argv[index + 1];
151
- if (!value || value.startsWith("--")) {
152
- throw new Error(`${name} requires a value.`);
153
- }
154
- values.push(...value.split(",").filter(Boolean));
155
- index += 1;
156
- continue;
157
- }
158
- if (arg.startsWith(`${name}=`)) {
159
- values.push(...arg
160
- .slice(name.length + 1)
161
- .split(",")
162
- .filter(Boolean));
163
- }
164
- }
165
- return values;
166
- }
167
- function parseOptionalOption(argv, name) {
168
- const values = parseRepeatedOption(argv, name);
169
- if (values.length > 1) {
170
- throw new Error(`${name} can only be provided once.`);
171
- }
172
- return values[0];
173
- }
174
- async function collectPendingMigrationsWithClose(database) {
175
- try {
176
- return await collectPendingMigrations(database);
177
- }
178
- finally {
179
- await database.close?.();
180
- }
181
- }
182
- async function collectPendingMigrations(database) {
183
- const migrations = await collectDeployMigrationFiles();
184
- const appliedMigrations = await readAppliedMigrationNames(database);
185
- return filterPendingMigrations(migrations, appliedMigrations);
186
- }
187
- async function chooseMigrationExecution(args, pendingMigrations) {
188
- if (pendingMigrations.length === 0) {
189
- clack.log.info("No pending deploy migrations.");
190
- return false;
191
- }
192
- clack.note(formatMigrationList(pendingMigrations), "Pending deploy migrations");
193
- if (args.runMigrations) {
194
- return true;
195
- }
196
- if (args.skipMigrations) {
197
- return false;
198
- }
199
- if (!process.stdout.isTTY) {
200
- throw new Error("Pending migrations require --run-migrations or --skip-migrations in noninteractive deploys.");
201
- }
202
- const answer = await clack.confirm({
203
- initialValue: true,
204
- message: "Run these deploy-safe database migrations before Cloudflare deploy?",
205
- });
206
- if (clack.isCancel(answer)) {
207
- clack.cancel("Deploy cancelled.");
208
- throw new Error("Deploy cancelled.");
209
- }
210
- return answer;
211
- }
212
- async function ensureCleanGit() {
213
- const { stdout: status } = await nanoSpawn("git", ["status", "--porcelain"], { stdin: "ignore" });
214
- if (status.trim().length > 0) {
215
- throw new Error("Deploy requires a clean git tree before the release version is applied.");
216
- }
217
- }
218
- function validateDeployArgs(args) {
219
- if (args.runMigrations && args.skipMigrations) {
220
- throw new Error("Use only one of --run-migrations, --skip-migrations, or --yes.");
221
- }
222
- }
223
- function requireEnv(env, names) {
224
- const missing = names.filter((name) => !env[name]);
225
- if (missing.length > 0) {
226
- throw new Error(`Missing required deploy environment variables: ${missing.join(", ")}`);
227
- }
228
- return Object.fromEntries(names.map((name) => [name, env[name]]));
229
- }
230
- function createReleaseEnv(env, name, packageName, version) {
231
- return {
232
- ...env,
233
- POSTHOG_RELEASE: name,
234
- POSTHOG_RELEASE_NAME: env.POSTHOG_RELEASE_NAME ?? packageName,
235
- POSTHOG_RELEASE_VERSION: env.POSTHOG_RELEASE_VERSION ?? version,
236
- };
237
- }
238
- function createBuildCheckEnv(env) {
239
- const { POSTHOG_API_KEY: _apiKey, POSTHOG_PROJECT_ID: _projectId, ...buildEnv } = env;
240
- return buildEnv;
241
- }
242
- if (import.meta.main) {
243
- deployProject().catch((error) => {
244
- console.error(error);
245
- process.exit(1);
246
- });
247
- }
2
+ import{readProjectConfig as e}from"./config.js";import{collectDeployMigrationFiles as t,formatMigrationList as n,formatMigrationScanFailures as r,scanDeployMigrationFiles as i}from"./deploy/migrations.js";import{createProjectDeployDatabase as a}from"./db/project.js";import{runPostDeployChecks as o}from"./deploy/checks.js";import{resolveDeployConfig as s}from"./deploy/config.js";import{filterPendingMigrations as c,readAppliedMigrationNames as l}from"./deploy/pending-migrations.js";import{parseTauriReleasePlatform as u,prepareTauriRelease as d,resolveTauriReleasePlan as f,restoreTauriReleaseMetadata as p,uploadTauriReleaseToB2 as m,validateTauriReleasePlan as h,writeTauriReleaseMetadata as g}from"./deploy/tauri-release.js";import{nextReleaseVersion as _,readPackageJson as v,releaseName as y,writePackageVersion as b}from"./deploy/version.js";import{writeFile as x}from"node:fs/promises";import S from"nano-spawn";import*as C from"@clack/prompts";const w=`package.json`;async function T(t=process.argv.slice(2),n=process.env){let c=E(t),{packageJson:l,source:u}=await v(w),T=_(l.version),D=y(l.name,T),O=n.DEPLOY_ENV??`production`,A=F(n,D,l.name,T),L=await e(),R=s(L.deploy??{},n),z=f({args:c,config:R.tauriRelease,env:n}),B=!1,V={files:[]};C.intro(`Deploy ${D}`),N(c),P(n,[`POSTHOG_API_KEY`,`POSTHOG_PROJECT_ID`]),await M(),await h(z);let H=await k(await a({config:L.database,env:n})),U=await i(H);if(U.length>0)throw Error(`Pending deploy migrations contain unsafe SQL. Move unsafe statements to held migrations.\n${r(U)}`);let W=await j(c,H);try{await b(w,l,T),V=await g(z,T),C.log.step(`Running pre-deploy build`),await S(`pnpm`,[`build`],{env:I(A),stdio:`inherit`});let e=z.enabled?await d({env:I(A),plan:z,releaseName:D,version:T}):void 0;C.log.step(`Running release build and uploading PostHog source maps`),B=!0,await S(`pnpm`,[`build`],{env:A,stdio:`inherit`}),W&&(C.log.step(`Running deploy-safe database migrations`),await S(`pnpm`,[`db`,`migrate`],{env:A,stdio:`inherit`})),C.log.step(`Deploying Worker and static assets to Cloudflare`),await S(`pnpm`,[`exec`,`wrangler`,`deploy`,`--strict`,`--keep-vars`,`--tag`,D,`--message`,`Deploy ${D}`,`--var`,`POSTHOG_RELEASE:${D}`],{env:A,stdio:`inherit`}),c.skipPostDeployChecks||(C.log.step(`Running post-deploy checks`),await o(R,{environment:O,productionUrl:R.productionUrl,releaseName:D,version:T})),e&&(C.log.step(`Uploading Tauri release artifacts to Backblaze B2`),await m(z,e)),C.outro(`Deployed ${D}`)}catch(e){throw B||(await x(w,u),await p(V)),e}}function E(e){return{runMigrations:e.includes(`--run-migrations`)||e.includes(`--yes`),skipMigrations:e.includes(`--skip-migrations`),skipPostDeployChecks:e.includes(`--skip-post-deploy-checks`),tauriLocalPlatforms:D(e,`--tauri-local-platform`).map(e=>u(e)),tauriWorkflowName:O(e,`--tauri-workflow-name`),tauriWorkflowPlatforms:D(e,`--tauri-workflow-platform`).map(e=>u(e)),tauriWorkflowRef:O(e,`--tauri-workflow-ref`),yes:e.includes(`--yes`)}}function D(e,t){let n=[];for(let r=0;r<e.length;r+=1){let i=e[r];if(i===t){let i=e[r+1];if(!i||i.startsWith(`--`))throw Error(`${t} requires a value.`);n.push(...i.split(`,`).filter(Boolean)),r+=1;continue}i.startsWith(`${t}=`)&&n.push(...i.slice(t.length+1).split(`,`).filter(Boolean))}return n}function O(e,t){let n=D(e,t);if(n.length>1)throw Error(`${t} can only be provided once.`);return n[0]}async function k(e){try{return await A(e)}finally{await e.close?.()}}async function A(e){return c(await t(),await l(e))}async function j(e,t){if(t.length===0)return C.log.info(`No pending deploy migrations.`),!1;if(C.note(n(t),`Pending deploy migrations`),e.runMigrations)return!0;if(e.skipMigrations)return!1;if(!process.stdout.isTTY)throw Error(`Pending migrations require --run-migrations or --skip-migrations in noninteractive deploys.`);let r=await C.confirm({initialValue:!0,message:`Run these deploy-safe database migrations before Cloudflare deploy?`});if(C.isCancel(r))throw C.cancel(`Deploy cancelled.`),Error(`Deploy cancelled.`);return r}async function M(){let{stdout:e}=await S(`git`,[`status`,`--porcelain`],{stdin:`ignore`});if(e.trim().length>0)throw Error(`Deploy requires a clean git tree before the release version is applied.`)}function N(e){if(e.runMigrations&&e.skipMigrations)throw Error(`Use only one of --run-migrations, --skip-migrations, or --yes.`)}function P(e,t){let n=t.filter(t=>!e[t]);if(n.length>0)throw Error(`Missing required deploy environment variables: ${n.join(`, `)}`);return Object.fromEntries(t.map(t=>[t,e[t]]))}function F(e,t,n,r){return{...e,POSTHOG_RELEASE:t,POSTHOG_RELEASE_NAME:e.POSTHOG_RELEASE_NAME??n,POSTHOG_RELEASE_VERSION:e.POSTHOG_RELEASE_VERSION??r}}function I(e){let{POSTHOG_API_KEY:t,POSTHOG_PROJECT_ID:n,...r}=e;return r}import.meta.main&&T().catch(e=>{console.error(e),process.exit(1)});export{T as deployProject,E as parseDeployArgs,e as readProjectConfig};
package/dist/dev.d.ts CHANGED
@@ -1,13 +1,24 @@
1
- #!/usr/bin/env node
2
- import { spawn as nodeSpawn } from "node:child_process";
3
- type Spawn = typeof nodeSpawn;
4
- export type DevServerOptions = {
5
- cwd?: string;
6
- env?: NodeJS.ProcessEnv;
7
- logPath?: string;
8
- platform?: DevPlatform;
9
- spawn?: Spawn;
1
+ import { readProjectConfig } from "./config.js";
2
+ import { spawn as spawn$1 } from "node:child_process";
3
+
4
+ //#region dev.d.ts
5
+ type Spawn = typeof spawn$1;
6
+ type DevServerOptions = {
7
+ cwd?: string;
8
+ env?: NodeJS.ProcessEnv;
9
+ logPath?: string;
10
+ platform?: DevPlatform;
11
+ readProjectConfig?: typeof readProjectConfig;
12
+ spawn?: Spawn;
10
13
  };
11
- export type DevPlatform = "android" | "desktop" | "ios" | "web";
12
- export declare function runDevServer({ cwd, env, logPath, platform, spawn, }?: DevServerOptions): Promise<void>;
13
- export {};
14
+ type DevPlatform = "android" | "desktop" | "ios" | "web";
15
+ declare function runDevServer({
16
+ cwd,
17
+ env,
18
+ logPath,
19
+ platform,
20
+ readProjectConfig: readConfig,
21
+ spawn
22
+ }?: DevServerOptions): Promise<void>;
23
+ //#endregion
24
+ export { DevPlatform, DevServerOptions, runDevServer };
package/dist/dev.js CHANGED
@@ -1,96 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import { spawn as nodeSpawn } from "node:child_process";
3
- import { createWriteStream } from "node:fs";
4
- import { mkdir } from "node:fs/promises";
5
- import path from "node:path";
6
- import process from "node:process";
7
- const defaultLogPath = ".agents/logs/dev-server.log";
8
- const nodeModulesBinPath = path.resolve("node_modules", ".bin");
9
- const pnpmCommand = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
10
- const reactRouterCommand = process.platform === "win32" ? "react-router.cmd" : "react-router";
11
- export async function runDevServer({ cwd = process.cwd(), env = process.env, logPath = defaultLogPath, platform = "web", spawn = nodeSpawn, } = {}) {
12
- const pathEnvValue = env.PATH ?? env.Path ?? "";
13
- const shouldTee = !("TAURI_ENV_PLATFORM" in env);
14
- const log = shouldTee ? await createDevLog(logPath) : undefined;
15
- try {
16
- if (platform === "web") {
17
- await runDevProcess(spawn, pnpmCommand, ["db", "ensure"], {
18
- cwd,
19
- env,
20
- log,
21
- });
22
- await runDevProcess(spawn, reactRouterCommand, ["dev"], {
23
- cwd,
24
- env: {
25
- ...env,
26
- CLOUDFLARE_ENV: "development",
27
- PATH: nodeModulesBinPath + path.delimiter + pathEnvValue,
28
- },
29
- log,
30
- });
31
- return;
32
- }
33
- await runDevProcess(spawn, pnpmCommand, tauriDevArgs(platform), {
34
- cwd,
35
- env,
36
- log,
37
- });
38
- }
39
- finally {
40
- await closeLog(log);
41
- }
42
- }
43
- async function createDevLog(logPath) {
44
- await mkdir(path.dirname(logPath), { recursive: true });
45
- return createWriteStream(logPath, { flags: "w" });
46
- }
47
- function closeLog(log) {
48
- if (!log) {
49
- return Promise.resolve();
50
- }
51
- return new Promise((resolve, reject) => {
52
- log.once("error", reject);
53
- log.end(resolve);
54
- });
55
- }
56
- function tauriDevArgs(platform) {
57
- return ["--dir=tauri", "tauri", ...(platform === "desktop" ? [] : [platform]), "dev"];
58
- }
59
- function runDevProcess(spawn, command, args, { cwd, env, log, }) {
60
- return new Promise((resolve, reject) => {
61
- const child = spawn(command, args, {
62
- cwd,
63
- env,
64
- stdio: log ? ["inherit", "pipe", "pipe"] : "inherit",
65
- });
66
- if (log) {
67
- if (!child.stdout || !child.stderr) {
68
- reject(new Error(`${[command, ...args].join(" ")} did not provide output streams`));
69
- return;
70
- }
71
- child.stdout.on("data", (chunk) => {
72
- process.stdout.write(chunk);
73
- log.write(chunk);
74
- });
75
- child.stderr.on("data", (chunk) => {
76
- process.stderr.write(chunk);
77
- log.write(chunk);
78
- });
79
- }
80
- child.on("error", reject);
81
- child.on("close", (code, signal) => {
82
- if (code === 0) {
83
- resolve();
84
- return;
85
- }
86
- const commandText = [command, ...args].join(" ");
87
- reject(new Error(`${commandText} failed${signal ? ` with signal ${signal}` : ` with exit code ${code ?? 1}`}`));
88
- });
89
- });
90
- }
91
- if (import.meta.main) {
92
- runDevServer().catch((error) => {
93
- console.error(error);
94
- process.exit(1);
95
- });
96
- }
2
+ import{readProjectConfig as e}from"./config.js";import{mkdir as t}from"node:fs/promises";import n from"node:path";import r from"node:process";import{createWriteStream as i}from"node:fs";import{spawn as a}from"node:child_process";const o=n.resolve(`node_modules`,`.bin`),s=r.platform===`win32`?`pnpm.cmd`:`pnpm`,c=r.platform===`win32`?`react-router.cmd`:`react-router`,l=r.platform===`win32`?`turso.cmd`:`turso`;async function u({cwd:t=r.cwd(),env:i=r.env,logPath:u=`.agents/logs/dev-server.log`,platform:_=`web`,readProjectConfig:v=e,spawn:y=a}={}){let b=i.PATH??i.Path??``,x=`TAURI_ENV_PLATFORM`in i?void 0:await f(u),S;try{if(_===`web`){(await v({cwd:t})).database?.dialect===`sqlite`&&(S=g(y,l,[`dev`],{cwd:t,env:i,log:x})),await h(y,s,[`db`,`ensure`],{cwd:t,env:i,log:x}),await d(h(y,c,[`dev`],{cwd:t,env:{...i,CLOUDFLARE_ENV:`development`,PATH:o+n.delimiter+b},log:x}),S);return}await h(y,s,m(_),{cwd:t,env:i,log:x})}finally{await S?.stop(),await p(x)}}async function d(e,t){if(!t){await e;return}await Promise.race([e,t.exited.then(()=>{throw Error(`turso dev exited before the web dev server stopped`)},e=>{throw e})])}async function f(e){return await t(n.dirname(e),{recursive:!0}),i(e,{flags:`w`})}function p(e){return e?new Promise((t,n)=>{e.once(`error`,n),e.end(t)}):Promise.resolve()}function m(e){return[`--dir=tauri`,`tauri`,...e===`desktop`?[]:[e],`dev`]}function h(e,t,n,{cwd:r,env:i,log:a}){return g(e,t,n,{cwd:r,env:i,log:a}).exited}function g(e,t,n,{cwd:i,env:a,log:o}){let s=!1,c=e(t,n,{cwd:i,env:a,stdio:o?[`inherit`,`pipe`,`pipe`]:`inherit`}),l=new Promise((e,i)=>{if(o){if(!c.stdout||!c.stderr){i(Error(`${[t,...n].join(` `)} did not provide output streams`));return}c.stdout.on(`data`,e=>{r.stdout.write(e),o.write(e)}),c.stderr.on(`data`,e=>{r.stderr.write(e),o.write(e)})}c.on(`error`,e=>{s=!0,i(e)}),c.on(`close`,(r,a)=>{if(s=!0,r===0){e();return}let o=[t,...n].join(` `);i(Error(`${o} failed${a?` with signal ${a}`:` with exit code ${r??1}`}`))})});return l.catch(()=>void 0),{exited:l,async stop(){s||c.kill?.(`SIGTERM`);try{await l}catch{}}}}import.meta.main&&u().catch(e=>{console.error(e),r.exit(1)});export{u as runDevServer};
@@ -1,2 +1,18 @@
1
- import type { Plugin } from "vite";
2
- export declare function imageGenerator(): Plugin;
1
+ import { ConfigEnv, FSWatcher } from "vite";
2
+
3
+ //#region image-generator.d.ts
4
+ declare function imageGenerator(): {
5
+ name: string;
6
+ configResolved(config: {
7
+ command: ConfigEnv["command"];
8
+ }): void;
9
+ configureServer(server: {
10
+ watcher: FSWatcher;
11
+ }): Promise<void>;
12
+ applyToEnvironment(environment: {
13
+ name: string;
14
+ }): boolean;
15
+ buildStart(): Promise<void>;
16
+ };
17
+ //#endregion
18
+ export { imageGenerator };
@@ -1,59 +1 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { glob } from "tinyglobby";
4
- export function imageGenerator() {
5
- return {
6
- name: "image-generator",
7
- async buildStart() {
8
- const files = await glob(["src/**/*@3x.{png,webp}", "public/**/*@3x.{png,webp}"]);
9
- console.log(`[image-generator] Found ${files.length} @3x images.`);
10
- await Promise.all(files.map((file) => generateDensityImages(file)));
11
- },
12
- };
13
- }
14
- async function generateDensityImages(file) {
15
- const dir = path.dirname(file);
16
- const ext = path.extname(file);
17
- const base = path.basename(file, `@3x${ext}`);
18
- const outputImages = [
19
- {
20
- outputPath: path.join(dir, `${base}@2x${ext}`),
21
- scale: 2 / 3,
22
- },
23
- {
24
- outputPath: path.join(dir, `${base}@1x${ext}`),
25
- scale: 1 / 3,
26
- },
27
- ].filter((image) => !fs.existsSync(image.outputPath));
28
- if (outputImages.length === 0) {
29
- return;
30
- }
31
- const { default: sharp } = await import("sharp");
32
- let width;
33
- try {
34
- width = (await sharp(file).metadata()).width;
35
- }
36
- catch (error) {
37
- console.error(`[image-generator] Failed to read metadata for ${file}`, error);
38
- return;
39
- }
40
- if (!width) {
41
- console.error(`[image-generator] Skipping ${file}; image width could not be read.`);
42
- return;
43
- }
44
- await Promise.all(outputImages.map((image) => generateDensityImage({
45
- file,
46
- outputPath: image.outputPath,
47
- sharp,
48
- width: Math.round(width * image.scale),
49
- })));
50
- }
51
- async function generateDensityImage(options) {
52
- try {
53
- console.log(`[image-generator] Generating ${options.outputPath} (${options.width}w)`);
54
- await options.sharp(options.file).resize({ width: options.width }).toFile(options.outputPath);
55
- }
56
- catch (error) {
57
- console.error(`[image-generator] Failed to process ${options.file} for ${options.outputPath}`, error);
58
- }
59
- }
1
+ import e from"node:path";import t from"node:fs";import{glob as n}from"tinyglobby";function r(){let e;return{name:`image-generator`,configResolved(t){e=t.command},async configureServer(e){await i(),e.watcher.on(`add`,e=>{a(e)&&o(e)}),e.watcher.on(`change`,e=>{a(e)&&o(e,{overwrite:!0})})},applyToEnvironment(e){return e.name===`client`},async buildStart(){e===`build`&&await i()}}}async function i(){let e=await n([`src/**/*@3x.{png,webp}`,`public/**/*@3x.{png,webp}`]);console.log(`[image-generator] Found ${e.length} @3x images.`),await Promise.all(e.map(e=>o(e)))}function a(e){return/@3x\.(png|webp)$/.test(e)}async function o(n,r={}){let i=e.dirname(n),a=e.extname(n),o=e.basename(n,`@3x${a}`),c=[{outputPath:e.join(i,`${o}@2x${a}`),scale:2/3},{outputPath:e.join(i,`${o}@1x${a}`),scale:1/3}].filter(e=>r.overwrite||!t.existsSync(e.outputPath));if(c.length===0)return;let{default:l}=await import(`sharp`),u;try{u=(await l(n).metadata()).width}catch(e){console.error(`[image-generator] Failed to read metadata for ${n}`,e);return}if(!u){console.error(`[image-generator] Skipping ${n}; image width could not be read.`);return}await Promise.all(c.map(e=>s({file:n,outputPath:e.outputPath,sharp:l,width:Math.round(u*e.scale)})))}async function s(e){try{console.log(`[image-generator] Generating ${e.outputPath} (${e.width}w)`),await e.sharp(e.file).resize({width:e.width}).toFile(e.outputPath)}catch(t){console.error(`[image-generator] Failed to process ${e.file} for ${e.outputPath}`,t)}}export{r as imageGenerator};
package/dist/project.d.ts CHANGED
@@ -1 +1,4 @@
1
- export declare function importProjectModule<T>(path: string): Promise<T>;
1
+ //#region project.d.ts
2
+ declare function importProjectModule<T>(path: string): Promise<T>;
3
+ //#endregion
4
+ export { importProjectModule };
package/dist/project.js CHANGED
@@ -1,13 +1 @@
1
- var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
- if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
- return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
- return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
- });
6
- }
7
- return path;
8
- };
9
- import { resolve } from "node:path";
10
- import { pathToFileURL } from "node:url";
11
- export async function importProjectModule(path) {
12
- return (await import(__rewriteRelativeImportExtension(pathToFileURL(resolve(process.cwd(), path)).href)));
13
- }
1
+ import{resolve as e}from"node:path";import{pathToFileURL as t}from"node:url";async function n(n){return await import(t(e(process.cwd(),n)).href)}export{n as importProjectModule};
@@ -1,2 +1,4 @@
1
- #!/usr/bin/env node
2
- export declare function typecheckProject(): Promise<void>;
1
+ //#region typecheck.d.ts
2
+ declare function typecheckProject(): Promise<void>;
3
+ //#endregion
4
+ export { typecheckProject };
package/dist/typecheck.js CHANGED
@@ -1,45 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import { access } from "node:fs/promises";
3
- import path from "node:path";
4
- import process from "node:process";
5
- import { supervise } from "procband";
6
- const nodeModulesBinPath = path.resolve("node_modules", ".bin");
7
- process.env.PATH = nodeModulesBinPath + path.delimiter + process.env.PATH;
8
- const tscCommand = process.platform === "win32" ? "tsc.cmd" : "tsc";
9
- const projects = [
10
- { name: "scripts", path: "scripts/tsconfig.json" },
11
- { name: "shared", path: "src/shared/tsconfig.json" },
12
- { name: "api", path: "src/api/tsconfig.json" },
13
- { name: "worker", path: "src/api/worker/tsconfig.json" },
14
- { name: "web", path: "src/web/tsconfig.json" },
15
- ];
16
- export async function typecheckProject() {
17
- const existingProjects = [];
18
- for (const project of projects) {
19
- try {
20
- await access(project.path);
21
- existingProjects.push(project);
22
- }
23
- catch (error) {
24
- if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
25
- throw error;
26
- }
27
- }
28
- }
29
- const checks = existingProjects.map((project) => supervise({
30
- name: project.name,
31
- command: tscCommand,
32
- args: ["-p", project.path],
33
- }));
34
- const results = await Promise.all(checks.map((check) => check.wait()));
35
- const failed = results.filter((result) => result.exitCode !== 0);
36
- if (failed.length > 0) {
37
- process.exitCode = failed[0].exitCode;
38
- }
39
- }
40
- if (import.meta.main) {
41
- typecheckProject().catch((error) => {
42
- console.error(error);
43
- process.exit(1);
44
- });
45
- }
2
+ import{access as e}from"node:fs/promises";import t from"node:path";import n from"node:process";import{supervise as r}from"procband";const i=t.resolve(`node_modules`,`.bin`);n.env.PATH=i+t.delimiter+n.env.PATH;const a=n.platform===`win32`?`tsc.cmd`:`tsc`,o=[{name:`scripts`,path:`scripts/tsconfig.json`},{name:`shared`,path:`src/shared/tsconfig.json`},{name:`api`,path:`src/api/tsconfig.json`},{name:`worker`,path:`src/api/worker/tsconfig.json`},{name:`web`,path:`src/web/tsconfig.json`}];async function s(){let t=[];for(let n of o)try{await e(n.path),t.push(n)}catch(e){if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e}let i=t.map(e=>r({name:e.name,command:a,args:[`-p`,e.path]})),s=(await Promise.all(i.map(e=>e.wait()))).filter(e=>e.exitCode!==0);s.length>0&&(n.exitCode=s[0].exitCode)}import.meta.main&&s().catch(e=>{console.error(e),n.exit(1)});export{s as typecheckProject};
@@ -1,6 +1,11 @@
1
- #!/usr/bin/env node
2
- export type CheckUpgradeSkillOptions = {
3
- apply: boolean;
4
- target: string;
1
+ //#region upgrade/check-skill-current.d.ts
2
+ type CheckUpgradeSkillOptions = {
3
+ apply: boolean;
4
+ target: string;
5
5
  };
6
- export declare function checkUpgradeSkillCurrent({ apply, target }: CheckUpgradeSkillOptions): 0 | 20;
6
+ declare function checkUpgradeSkillCurrent({
7
+ apply,
8
+ target
9
+ }: CheckUpgradeSkillOptions): 0 | 20;
10
+ //#endregion
11
+ export { CheckUpgradeSkillOptions, checkUpgradeSkillCurrent };
@@ -1,88 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import { spawnSync } from "node:child_process";
3
- import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- const skillPath = ".agents/skills/coreframe-upgrade/SKILL.md";
7
- function git(args, options = {}) {
8
- return spawnSync("git", args, options);
9
- }
10
- function errorDetail(result) {
11
- return result.stderr.toString("utf8").trim() || result.stdout.toString("utf8").trim();
12
- }
13
- function readGitFile(ref, path) {
14
- const result = git(["show", `${ref}:${path}`], { encoding: "utf8" });
15
- if (result.status !== 0) {
16
- const detail = errorDetail(result);
17
- throw new Error(`Could not read ${path} at ${ref}.${detail ? ` ${detail}` : ""}`);
18
- }
19
- return result.stdout.toString();
20
- }
21
- function getRepoRoot() {
22
- const result = git(["rev-parse", "--show-toplevel"], { encoding: "utf8" });
23
- if (result.status !== 0) {
24
- const detail = errorDetail(result);
25
- throw new Error(`Could not find git repository root.${detail ? ` ${detail}` : ""}`);
26
- }
27
- return result.stdout.toString().trim();
28
- }
29
- function printDiff(localPath, targetText) {
30
- const dir = mkdtempSync(join(tmpdir(), "coreframe-upgrade-skill-"));
31
- const targetPath = join(dir, "SKILL.md");
32
- try {
33
- writeFileSync(targetPath, targetText);
34
- const diff = git([
35
- "--no-pager",
36
- "diff",
37
- "--no-index",
38
- "--color=never",
39
- "--",
40
- localPath,
41
- targetPath,
42
- ]);
43
- const output = errorDetail(diff);
44
- if (output) {
45
- console.log(output);
46
- }
47
- }
48
- finally {
49
- rmSync(dir, { force: true, recursive: true });
50
- }
51
- }
52
- export function checkUpgradeSkillCurrent({ apply, target }) {
53
- const repoRoot = getRepoRoot();
54
- const localPath = join(repoRoot, skillPath);
55
- if (!existsSync(localPath)) {
56
- throw new Error(`Local ${skillPath} does not exist.`);
57
- }
58
- const localText = readFileSync(localPath, "utf8");
59
- const targetText = readGitFile(target, skillPath);
60
- if (localText === targetText) {
61
- console.log(`Coreframe upgrade skill matches ${target}:${skillPath}.`);
62
- return 0;
63
- }
64
- if (apply) {
65
- writeFileSync(localPath, targetText);
66
- console.error(`Updated ${skillPath} from ${target}. Reread it before continuing the upgrade.`);
67
- return 20;
68
- }
69
- console.error(`Coreframe upgrade skill differs from ${target}:${skillPath}.`);
70
- console.error(`Run again with --apply to update it, then reread ${skillPath} before continuing.`);
71
- printDiff(localPath, targetText);
72
- return 20;
73
- }
74
- if (import.meta.main) {
75
- const targetIndex = process.argv.indexOf("--target");
76
- const target = targetIndex === -1 ? null : process.argv[targetIndex + 1];
77
- if (!target) {
78
- console.error("Usage: coreframe upgrade check-skill-current --target <git-ref> [--apply]");
79
- process.exit(64);
80
- }
81
- try {
82
- process.exit(checkUpgradeSkillCurrent({ apply: process.argv.includes("--apply"), target }));
83
- }
84
- catch (error) {
85
- console.error(error instanceof Error ? error.message : String(error));
86
- process.exit(65);
87
- }
88
- }
2
+ import{join as e}from"node:path";import{existsSync as t,mkdtempSync as n,readFileSync as r,rmSync as i,writeFileSync as a}from"node:fs";import{spawnSync as o}from"node:child_process";import{tmpdir as s}from"node:os";const c=`.agents/skills/coreframe-upgrade/SKILL.md`;function l(e,t={}){return o(`git`,e,t)}function u(e){return e.stderr.toString(`utf8`).trim()||e.stdout.toString(`utf8`).trim()}function d(e,t){let n=l([`show`,`${e}:${t}`],{encoding:`utf8`});if(n.status!==0){let r=u(n);throw Error(`Could not read ${t} at ${e}.${r?` ${r}`:``}`)}return n.stdout.toString()}function f(){let e=l([`rev-parse`,`--show-toplevel`],{encoding:`utf8`});if(e.status!==0){let t=u(e);throw Error(`Could not find git repository root.${t?` ${t}`:``}`)}return e.stdout.toString().trim()}function p(t,r){let o=n(e(s(),`coreframe-upgrade-skill-`)),c=e(o,`SKILL.md`);try{a(c,r);let e=u(l([`--no-pager`,`diff`,`--no-index`,`--color=never`,`--`,t,c]));e&&console.log(e)}finally{i(o,{force:!0,recursive:!0})}}function m({apply:n,target:i}){let o=e(f(),c);if(!t(o))throw Error(`Local ${c} does not exist.`);let s=r(o,`utf8`),l=d(i,c);return s===l?(console.log(`Coreframe upgrade skill matches ${i}:${c}.`),0):n?(a(o,l),console.error(`Updated ${c} from ${i}. Reread it before continuing the upgrade.`),20):(console.error(`Coreframe upgrade skill differs from ${i}:${c}.`),console.error(`Run again with --apply to update it, then reread ${c} before continuing.`),p(o,l),20)}if(import.meta.main){let e=process.argv.indexOf(`--target`),t=e===-1?null:process.argv[e+1];t||(console.error(`Usage: coreframe upgrade check-skill-current --target <git-ref> [--apply]`),process.exit(64));try{process.exit(m({apply:process.argv.includes(`--apply`),target:t}))}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(65)}}export{m as checkUpgradeSkillCurrent};