@coreframe/scripts 0.1.8 → 0.1.9

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.
@@ -53,6 +53,7 @@ declare const coreframeCli: Partial<import("cmd-ts/dist/cjs/argparser").Register
53
53
  } | {
54
54
  command: "dev";
55
55
  args: {
56
+ https: boolean;
56
57
  platform: "ios" | "android" | "web" | "desktop" | undefined;
57
58
  };
58
59
  } | {
@@ -177,6 +178,7 @@ declare const coreframeCli: Partial<import("cmd-ts/dist/cjs/argparser").Register
177
178
  } | {
178
179
  command: "dev";
179
180
  args: {
181
+ https: boolean;
180
182
  platform: "ios" | "android" | "web" | "desktop" | undefined;
181
183
  };
182
184
  } | {
package/dist/coreframe.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{addAsset as e,buildAssets as t,checkAssets as n,printAssetResult as r,publishAssets as i}from"./assets.js";import{runDrizzleKitCommand as a}from"./db/drizzle-kit.js";import{seedLocalDb as o}from"./db/seed.js";import{migrateLocalDb as s}from"./db/migrate.js";import{resetLocalDb as c}from"./db/reset.js";import{setupLocalDb as l}from"./db/setup.js";import{ensureLocalDb as u}from"./db/ensure.js";import{migrateHeldMigrations as d}from"./db/migrate-held.js";import{checkSchemaPush as f}from"./db/schema-check.js";import{tauriReleasePlatforms as p}from"./deploy/config.js";import{deployProject as m}from"./deploy.js";import{checkDeployMigrations as h}from"./deploy/check-migrations.js";import{devPlatforms as g,runDevServer as _}from"./dev.js";import{typecheckProject as v}from"./typecheck.js";import{checkUpgradeSkillCurrent as y}from"./upgrade/check-skill-current.js";import{ensureTemplateRemote as b}from"./upgrade/ensure-template-remote.js";import{fastForwardTemplateFiles as x}from"./upgrade/fast-forward-template-files.js";import{array as S,binary as C,command as w,flag as T,multioption as E,oneOf as D,option as O,optional as k,positional as A,rest as j,run as M,string as N,subcommands as P}from"cmd-ts";const F=P({name:`coreframe`,cmds:{assets:P({name:`assets`,cmds:{add:w({name:`add`,args:{file:A({type:N,displayName:`file`,description:`Source image to add to the asset library.`}),id:O({long:`id`,type:N,description:`Logical asset ID, such as blog/my-post/hero.`}),alt:O({long:`alt`,type:N,description:`Required alt text for the asset.`}),json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({alt:t,file:n,id:i,json:a})=>r(await e({alt:t,file:n,id:i,json:a}),a)}),build:w({name:`build`,args:{id:O({long:`id`,type:k(N),description:`Build only one logical asset ID.`}),noPull:T({long:`no-pull`,description:`Do not perform targeted Git LFS pulls for missing source objects.`,defaultValue:()=>!1}),json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({id:e,json:n,noPull:i})=>r(await t({id:e,json:n,pull:!i}),n)}),check:w({name:`check`,args:{fix:T({long:`fix`,description:`Build missing generated variants when possible.`,defaultValue:()=>!1}),json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({fix:e,json:t})=>{let i=await n({fix:e,json:t});r(i,t),i.ok||(process.exitCode=1)}}),publish:w({name:`publish`,args:{outputDir:O({long:`output-dir`,type:k(N),description:`Directory for additive local publish output. Defaults to COREFRAME_ASSETS_PUBLISH_DIR or release-upload/assets.`}),json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e,outputDir:t})=>{let n=await i({json:e,outputDir:t});r(n,e),n.ok||(process.exitCode=1)}}),status:w({name:`status`,args:{json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e})=>{let t=await n({json:e});r(t,e),t.ok||(process.exitCode=1)}})}}),deploy:w({name:`deploy`,args:{runMigrations:T({long:`run-migrations`,description:`Run pending deploy-safe database migrations before deploying.`,defaultValue:()=>!1}),skipMigrations:T({long:`skip-migrations`,description:`Deploy without running pending deploy-safe database migrations.`,defaultValue:()=>!1}),skipPostDeployChecks:T({long:`skip-post-deploy-checks`,description:`Skip post-deploy checks after Cloudflare deployment.`,defaultValue:()=>!1}),tauriLocalPlatforms:E({long:`tauri-local-platform`,type:S(D(p)),description:`Build one Tauri release platform locally. Repeat for multiple platforms.`,defaultValue:()=>[]}),tauriWorkflowName:O({long:`tauri-workflow-name`,type:k(N),description:`GitHub Actions workflow file or name for remote Tauri release builds.`}),tauriWorkflowPlatforms:E({long:`tauri-workflow-platform`,type:S(D(p)),description:`Build one Tauri release platform with GitHub Actions. Repeat for multiple platforms.`,defaultValue:()=>[]}),tauriWorkflowRef:O({long:`tauri-workflow-ref`,type:k(N),description:`Git ref used when dispatching remote Tauri release builds.`}),yes:T({long:`yes`,short:`y`,description:`Approve noninteractive deploy prompts.`,defaultValue:()=>!1})},handler:({runMigrations:e,skipMigrations:t,skipPostDeployChecks:n,tauriLocalPlatforms:r,tauriWorkflowName:i,tauriWorkflowPlatforms:a,tauriWorkflowRef:o,yes:s})=>m([...e?[`--run-migrations`]:[],...t?[`--skip-migrations`]:[],...n?[`--skip-post-deploy-checks`]:[],...r.flatMap(e=>[`--tauri-local-platform`,e]),...i?[`--tauri-workflow-name`,i]:[],...a.flatMap(e=>[`--tauri-workflow-platform`,e]),...o?[`--tauri-workflow-ref`,o]:[],...s?[`--yes`]:[]])}),typecheck:w({name:`typecheck`,args:{},handler:v}),dev:w({name:`dev`,args:{platform:A({type:k(D(g)),displayName:`platform`,description:`Development target platform. Defaults to web.`})},handler:({platform:e})=>_({platform:e??`web`})}),upgrade:P({name:`upgrade`,cmds:{"ensure-template-remote":w({name:`ensure-template-remote`,args:{remote:O({long:`remote`,type:N,defaultValue:()=>`template`,description:`Remote name to ensure.`}),noFetch:T({long:`no-fetch`,description:`Do not fetch the remote after ensuring it exists.`,defaultValue:()=>!1})},handler:({noFetch:e,remote:t})=>b({fetch:!e,remote:t})}),"check-skill-current":w({name:`check-skill-current`,args:{target:O({long:`target`,type:N,description:`Target Coreframe template git ref.`}),apply:T({long:`apply`,description:`Replace the local upgrade skill with the target version when it differs.`,defaultValue:()=>!1})},handler:({apply:e,target:t})=>{process.exitCode=y({apply:e,target:t})}}),"fast-forward-template-files":w({name:`fast-forward-template-files`,args:{target:O({long:`target`,type:N,description:`Target Coreframe template git ref.`}),base:O({long:`base`,type:k(N),description:`Previous Coreframe template git ref. Defaults to package.json engines.coreframe.`}),apply:T({long:`apply`,description:`Write clean fast-forwards to the worktree.`,defaultValue:()=>!1})},handler:({apply:e,base:t,target:n})=>x({apply:e,base:t,target:n})})}}),db:P({name:`db`,cmds:{ensure:w({name:`ensure`,args:{},handler:u}),generate:w({name:`generate`,args:{args:j({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit generate.`})},handler:({args:e})=>a(`generate`,e)}),migrate:w({name:`migrate`,args:{args:j({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit migrate.`})},handler:({args:e})=>a(`migrate`,e)}),"migrate-held":w({name:`migrate-held`,args:{confirm:O({long:`confirm`,type:k(D([`run-held-migrations`])),description:`Required confirmation value for held migrations.`})},handler:({confirm:e})=>d({argv:e?[`--confirm=${e}`]:[]})}),"migrate-local":w({name:`migrate-local`,args:{},handler:s}),"migrations-check":w({name:`migrations-check`,args:{},handler:h}),reset:w({name:`reset`,args:{},handler:c}),seed:w({name:`seed`,args:{},handler:()=>o()}),"schema-check":w({name:`schema-check`,args:{seed:T({long:`seed`,description:`Run the configured project seed against the throwaway database.`,defaultValue:()=>!1})},handler:({seed:e})=>f({seed:e})}),setup:w({name:`setup`,args:{},handler:()=>l()}),studio:w({name:`studio`,args:{args:j({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit studio.`})},handler:({args:e})=>a(`studio`,e)})}})}});import.meta.main&&M(C(F),process.argv);export{F as coreframeCli};
2
+ import{addAsset as e,buildAssets as t,checkAssets as n,printAssetResult as r,publishAssets as i}from"./assets.js";import{runDrizzleKitCommand as a}from"./db/drizzle-kit.js";import{seedLocalDb as o}from"./db/seed.js";import{migrateLocalDb as s}from"./db/migrate.js";import{resetLocalDb as c}from"./db/reset.js";import{setupLocalDb as l}from"./db/setup.js";import{ensureLocalDb as u}from"./db/ensure.js";import{migrateHeldMigrations as d}from"./db/migrate-held.js";import{checkSchemaPush as f}from"./db/schema-check.js";import{tauriReleasePlatforms as p}from"./deploy/config.js";import{deployProject as m}from"./deploy.js";import{checkDeployMigrations as h}from"./deploy/check-migrations.js";import{devPlatforms as g,runDevServer as _}from"./dev.js";import{typecheckProject as v}from"./typecheck.js";import{checkUpgradeSkillCurrent as y}from"./upgrade/check-skill-current.js";import{ensureTemplateRemote as b}from"./upgrade/ensure-template-remote.js";import{fastForwardTemplateFiles as x}from"./upgrade/fast-forward-template-files.js";import{array as S,binary as C,command as w,flag as T,multioption as E,oneOf as D,option as O,optional as k,positional as A,rest as j,run as M,string as N,subcommands as P}from"cmd-ts";const F=P({name:`coreframe`,cmds:{assets:P({name:`assets`,cmds:{add:w({name:`add`,args:{file:A({type:N,displayName:`file`,description:`Source image to add to the asset library.`}),id:O({long:`id`,type:N,description:`Logical asset ID, such as blog/my-post/hero.`}),alt:O({long:`alt`,type:N,description:`Required alt text for the asset.`}),json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({alt:t,file:n,id:i,json:a})=>r(await e({alt:t,file:n,id:i,json:a}),a)}),build:w({name:`build`,args:{id:O({long:`id`,type:k(N),description:`Build only one logical asset ID.`}),noPull:T({long:`no-pull`,description:`Do not perform targeted Git LFS pulls for missing source objects.`,defaultValue:()=>!1}),json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({id:e,json:n,noPull:i})=>r(await t({id:e,json:n,pull:!i}),n)}),check:w({name:`check`,args:{fix:T({long:`fix`,description:`Build missing generated variants when possible.`,defaultValue:()=>!1}),json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({fix:e,json:t})=>{let i=await n({fix:e,json:t});r(i,t),i.ok||(process.exitCode=1)}}),publish:w({name:`publish`,args:{outputDir:O({long:`output-dir`,type:k(N),description:`Directory for additive local publish output. Defaults to COREFRAME_ASSETS_PUBLISH_DIR or release-upload/assets.`}),json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e,outputDir:t})=>{let n=await i({json:e,outputDir:t});r(n,e),n.ok||(process.exitCode=1)}}),status:w({name:`status`,args:{json:T({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e})=>{let t=await n({json:e});r(t,e),t.ok||(process.exitCode=1)}})}}),deploy:w({name:`deploy`,args:{runMigrations:T({long:`run-migrations`,description:`Run pending deploy-safe database migrations before deploying.`,defaultValue:()=>!1}),skipMigrations:T({long:`skip-migrations`,description:`Deploy without running pending deploy-safe database migrations.`,defaultValue:()=>!1}),skipPostDeployChecks:T({long:`skip-post-deploy-checks`,description:`Skip post-deploy checks after Cloudflare deployment.`,defaultValue:()=>!1}),tauriLocalPlatforms:E({long:`tauri-local-platform`,type:S(D(p)),description:`Build one Tauri release platform locally. Repeat for multiple platforms.`,defaultValue:()=>[]}),tauriWorkflowName:O({long:`tauri-workflow-name`,type:k(N),description:`GitHub Actions workflow file or name for remote Tauri release builds.`}),tauriWorkflowPlatforms:E({long:`tauri-workflow-platform`,type:S(D(p)),description:`Build one Tauri release platform with GitHub Actions. Repeat for multiple platforms.`,defaultValue:()=>[]}),tauriWorkflowRef:O({long:`tauri-workflow-ref`,type:k(N),description:`Git ref used when dispatching remote Tauri release builds.`}),yes:T({long:`yes`,short:`y`,description:`Approve noninteractive deploy prompts.`,defaultValue:()=>!1})},handler:({runMigrations:e,skipMigrations:t,skipPostDeployChecks:n,tauriLocalPlatforms:r,tauriWorkflowName:i,tauriWorkflowPlatforms:a,tauriWorkflowRef:o,yes:s})=>m([...e?[`--run-migrations`]:[],...t?[`--skip-migrations`]:[],...n?[`--skip-post-deploy-checks`]:[],...r.flatMap(e=>[`--tauri-local-platform`,e]),...i?[`--tauri-workflow-name`,i]:[],...a.flatMap(e=>[`--tauri-workflow-platform`,e]),...o?[`--tauri-workflow-ref`,o]:[],...s?[`--yes`]:[]])}),typecheck:w({name:`typecheck`,args:{},handler:v}),dev:w({name:`dev`,args:{https:T({long:`https`,description:`Serve the web app over locally trusted HTTPS.`,defaultValue:()=>!1}),platform:A({type:k(D(g)),displayName:`platform`,description:`Development target platform. Defaults to web.`})},handler:({https:e,platform:t})=>_({https:e,platform:t??`web`})}),upgrade:P({name:`upgrade`,cmds:{"ensure-template-remote":w({name:`ensure-template-remote`,args:{remote:O({long:`remote`,type:N,defaultValue:()=>`template`,description:`Remote name to ensure.`}),noFetch:T({long:`no-fetch`,description:`Do not fetch the remote after ensuring it exists.`,defaultValue:()=>!1})},handler:({noFetch:e,remote:t})=>b({fetch:!e,remote:t})}),"check-skill-current":w({name:`check-skill-current`,args:{target:O({long:`target`,type:N,description:`Target Coreframe template git ref.`}),apply:T({long:`apply`,description:`Replace the local upgrade skill with the target version when it differs.`,defaultValue:()=>!1})},handler:({apply:e,target:t})=>{process.exitCode=y({apply:e,target:t})}}),"fast-forward-template-files":w({name:`fast-forward-template-files`,args:{target:O({long:`target`,type:N,description:`Target Coreframe template git ref.`}),base:O({long:`base`,type:k(N),description:`Previous Coreframe template git ref. Defaults to package.json engines.coreframe.`}),apply:T({long:`apply`,description:`Write clean fast-forwards to the worktree.`,defaultValue:()=>!1})},handler:({apply:e,base:t,target:n})=>x({apply:e,base:t,target:n})})}}),db:P({name:`db`,cmds:{ensure:w({name:`ensure`,args:{},handler:u}),generate:w({name:`generate`,args:{args:j({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit generate.`})},handler:({args:e})=>a(`generate`,e)}),migrate:w({name:`migrate`,args:{args:j({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit migrate.`})},handler:({args:e})=>a(`migrate`,e)}),"migrate-held":w({name:`migrate-held`,args:{confirm:O({long:`confirm`,type:k(D([`run-held-migrations`])),description:`Required confirmation value for held migrations.`})},handler:({confirm:e})=>d({argv:e?[`--confirm=${e}`]:[]})}),"migrate-local":w({name:`migrate-local`,args:{},handler:s}),"migrations-check":w({name:`migrations-check`,args:{},handler:h}),reset:w({name:`reset`,args:{},handler:c}),seed:w({name:`seed`,args:{},handler:()=>o()}),"schema-check":w({name:`schema-check`,args:{seed:T({long:`seed`,description:`Run the configured project seed against the throwaway database.`,defaultValue:()=>!1})},handler:({seed:e})=>f({seed:e})}),setup:w({name:`setup`,args:{},handler:()=>l()}),studio:w({name:`studio`,args:{args:j({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit studio.`})},handler:({args:e})=>a(`studio`,e)})}})}});import.meta.main&&M(C(F),process.argv);export{F as coreframeCli};
@@ -2,7 +2,7 @@ import { createProjectPostgresDrizzleDatabase } from "./project.js";
2
2
  import { CoreframeConfig, readProjectConfig } from "../config.js";
3
3
  import { readFile, rm } from "node:fs/promises";
4
4
  import { tmpdir } from "node:os";
5
- import { LocalPostgresEnv, startPostgres } from "local-postgres";
5
+ import { LocalPostgresEnv, PostgresOutputTarget, startPostgres } from "local-postgres";
6
6
 
7
7
  //#region db/local-postgres.d.ts
8
8
  declare const LOCAL_POSTGRES_ENV_FLAG = "COREFRAME_LOCAL_POSTGRES";
@@ -32,6 +32,7 @@ type StartProjectPostgresOptions = {
32
32
  cwd?: string;
33
33
  env?: NodeJS.ProcessEnv;
34
34
  kill?: typeof process.kill;
35
+ postgresOutput?: PostgresOutputTarget;
35
36
  readProjectConfig?: typeof readProjectConfig;
36
37
  readFile?: typeof readFile;
37
38
  rm?: typeof rm;
@@ -46,6 +47,7 @@ declare function startProjectPostgres({
46
47
  cwd,
47
48
  env,
48
49
  kill,
50
+ postgresOutput,
49
51
  readProjectConfig,
50
52
  readFile,
51
53
  rm,
@@ -1,2 +1,2 @@
1
- import{readProjectConfig as e}from"../config.js";import{createProjectPostgresDrizzleDatabase as t}from"./project.js";import{mkdtemp as n,readFile as r,rm as i}from"node:fs/promises";import a from"node:path";import{tmpdir as o}from"node:os";import{startPostgres as s}from"local-postgres";const c=`COREFRAME_LOCAL_POSTGRES`,l=`coreframe`,u={name:`coreframe`,password:`coreframe`},d={kill:process.kill,mkdtemp:n,readFile:r,readProjectConfig:e,rm:i,startPostgres:s,tmpdir:o};async function f({config:e,cwd:t=process.cwd(),env:n=process.env,kill:r=d.kill,readProjectConfig:i=d.readProjectConfig,readFile:o=d.readFile,rm:s=d.rm,startPostgres:c=d.startPostgres}={}){if(n.COREFRAME_LOCAL_POSTGRES===`1`||((e??await i({cwd:t})).database?.dialect??`postgres`)!==`postgres`)return _(n);let f=a.resolve(t,`.postgres`),p=await v(f,o,r);if(p!==void 0)throw Error(`PostgreSQL is already running for this project (PID ${p}). Stop the other top-level \`coreframe dev\` process before starting another.`);let m=a.join(f,`postgres.log`);await s(m,{force:!0});let h;try{h=await c({dataDir:f,database:l,log:{filePath:m},postgres:{strategy:`prefer-local`},superuser:u})}catch(e){throw await y(e,m,o)}return g(n,h)}async function p({config:e,cwd:t=process.cwd(),env:n=process.env,mkdtemp:r=d.mkdtemp,readProjectConfig:i=d.readProjectConfig,rm:o=d.rm,startPostgres:s=d.startPostgres,tmpdir:c=d.tmpdir}={}){let f=(e??await i({cwd:t})).database?.dialect??`postgres`;if(f!==`postgres`)throw Error(`Temporary schema push checks require PostgreSQL, but this project uses ${f}.`);let p=await r(a.join(c(),`coreframe-schema-check-`));try{let e=g(n,await s({dataDir:p,database:l,log:`ignore`,postgres:{strategy:`prefer-local`},superuser:u}));return{env:e.env,async[Symbol.asyncDispose](){try{await e[Symbol.asyncDispose]()}finally{await o(p,{force:!0,recursive:!0})}}}}catch(e){throw await o(p,{force:!0,recursive:!0}),e}}function m(e,t){return{...e,...t,[c]:`1`}}async function h({env:e=process.env}={}){let n=x(e);return t({env:{...e,DATABASE_URL:n}})}function g(e,t){return{env:m(e,t.env),async[Symbol.asyncDispose](){await t[Symbol.asyncDispose]()}}}function _(e){return{env:e,async[Symbol.asyncDispose](){}}}async function v(e,t,n){let r;try{r=await t(a.join(e,`postmaster.pid`),`utf8`)}catch{return}let i=Number(r.split(`
2
- `,1)[0]);if(!(!Number.isSafeInteger(i)||i<=0))try{return n(i,0),i}catch(e){return b(e)&&e.code===`EPERM`?i:void 0}}async function y(e,t,n){let r=e instanceof Error?e.message:String(e),i;try{i=(await n(t,`utf8`)).trim()||void 0}catch{}let a=i?`\n\nPostgreSQL output:\n${i}`:``;return Error(`Local PostgreSQL failed to start: ${r}${a}\n\nPostgreSQL log: ${t}`,{cause:e})}function b(e){return e instanceof Error}function x(e=process.env){let t=e.DATABASE_URL||S(e);if(!t)throw Error(`DATABASE_URL or PGDATABASE, PGHOST, PGPORT, and PGUSER are required.`);return t}function S(e){let{PGDATABASE:t,PGHOST:n,PGPASSWORD:r,PGPORT:i,PGUSER:a}=e;if(!t||!n||!i||!a)return;let o=new URL(`postgresql://${n}:${i}/${t}`);return o.username=a,r&&(o.password=r),o.href}export{c as LOCAL_POSTGRES_ENV_FLAG,h as createLocalPostgresDb,m as createLocalPostgresEnv,x as getLocalPostgresConnectionString,f as startProjectPostgres,p as startTemporaryProjectPostgres};
1
+ import{readProjectConfig as e}from"../config.js";import{createProjectPostgresDrizzleDatabase as t}from"./project.js";import{mkdtemp as n,readFile as r,rm as i}from"node:fs/promises";import a from"node:path";import{tmpdir as o}from"node:os";import{startPostgres as s}from"local-postgres";const c=`COREFRAME_LOCAL_POSTGRES`,l=`coreframe`,u={name:`coreframe`,password:`coreframe`},d={kill:process.kill,mkdtemp:n,readFile:r,readProjectConfig:e,rm:i,startPostgres:s,tmpdir:o};async function f({config:e,cwd:t=process.cwd(),env:n=process.env,kill:r=d.kill,postgresOutput:i,readProjectConfig:o=d.readProjectConfig,readFile:s=d.readFile,rm:c=d.rm,startPostgres:f=d.startPostgres}={}){if(n.COREFRAME_LOCAL_POSTGRES===`1`||((e??await o({cwd:t})).database?.dialect??`postgres`)!==`postgres`)return _(n);let p=a.resolve(t,`.coreframe/postgres`),m=await v(p,s,r);if(m!==void 0)throw Error(`PostgreSQL is already running for this project (PID ${m}). Stop the other top-level \`coreframe dev\` process before starting another.`);let h=a.join(p,`postgres.log`);await c(h,{force:!0});let b;try{b=await f({dataDir:p,database:l,postgresOutput:i??{filePath:h},postgres:{strategy:`prefer-local`},superuser:u})}catch(e){throw await y(e,i?void 0:h,s)}return g(n,b)}async function p({config:e,cwd:t=process.cwd(),env:n=process.env,mkdtemp:r=d.mkdtemp,readProjectConfig:i=d.readProjectConfig,rm:o=d.rm,startPostgres:s=d.startPostgres,tmpdir:c=d.tmpdir}={}){let f=(e??await i({cwd:t})).database?.dialect??`postgres`;if(f!==`postgres`)throw Error(`Temporary schema push checks require PostgreSQL, but this project uses ${f}.`);let p=await r(a.join(c(),`coreframe-schema-check-`));try{let e=g(n,await s({dataDir:p,database:l,postgresOutput:`ignore`,postgres:{strategy:`prefer-local`},superuser:u}));return{env:e.env,async[Symbol.asyncDispose](){try{await e[Symbol.asyncDispose]()}finally{await o(p,{force:!0,recursive:!0})}}}}catch(e){throw await o(p,{force:!0,recursive:!0}),e}}function m(e,t){return{...e,...t,[c]:`1`}}async function h({env:e=process.env}={}){let n=x(e);return t({env:{...e,DATABASE_URL:n}})}function g(e,t){return{env:m(e,t.env),async[Symbol.asyncDispose](){await t[Symbol.asyncDispose]()}}}function _(e){return{env:e,async[Symbol.asyncDispose](){}}}async function v(e,t,n){let r;try{r=await t(a.join(e,`postmaster.pid`),`utf8`)}catch{return}let i=Number(r.split(`
2
+ `,1)[0]);if(!(!Number.isSafeInteger(i)||i<=0))try{return n(i,0),i}catch(e){return b(e)&&e.code===`EPERM`?i:void 0}}async function y(e,t,n){let r=e instanceof Error?e.message:String(e),i;if(t)try{i=(await n(t,`utf8`)).trim()||void 0}catch{}let a=i?`\n\nPostgreSQL output:\n${i}`:``,o=t?`\n\nPostgreSQL log: ${t}`:``;return Error(`Local PostgreSQL failed to start: ${r}${a}${o}`,{cause:e})}function b(e){return e instanceof Error}function x(e=process.env){let t=e.DATABASE_URL||S(e);if(!t)throw Error(`DATABASE_URL or PGDATABASE, PGHOST, PGPORT, and PGUSER are required.`);return t}function S(e){let{PGDATABASE:t,PGHOST:n,PGPASSWORD:r,PGPORT:i,PGUSER:a}=e;if(!t||!n||!i||!a)return;let o=new URL(`postgresql://${n}:${i}/${t}`);return o.username=a,r&&(o.password=r),o.href}export{c as LOCAL_POSTGRES_ENV_FLAG,h as createLocalPostgresDb,m as createLocalPostgresEnv,x as getLocalPostgresConnectionString,f as startProjectPostgres,p as startTemporaryProjectPostgres};
@@ -0,0 +1,20 @@
1
+ import nanoSpawn from "nano-spawn";
2
+ import { UserConfig } from "vite";
3
+
4
+ //#region dev-https.d.ts
5
+ declare const devHttpsCertEnv = "COREFRAME_HTTPS_CERT";
6
+ declare const devHttpsKeyEnv = "COREFRAME_HTTPS_KEY";
7
+ type PrepareDevHttpsOptions = {
8
+ cwd?: string;
9
+ spawn?: typeof nanoSpawn;
10
+ };
11
+ declare function prepareDevHttps({
12
+ cwd,
13
+ spawn
14
+ }?: PrepareDevHttpsOptions): Promise<{
15
+ cert: string;
16
+ key: string;
17
+ }>;
18
+ declare function coreframeDevHttpsConfig(env?: NodeJS.ProcessEnv): UserConfig;
19
+ //#endregion
20
+ export { coreframeDevHttpsConfig, devHttpsCertEnv, devHttpsKeyEnv, prepareDevHttps };
@@ -0,0 +1 @@
1
+ import{access as e,chmod as t,mkdir as n}from"node:fs/promises";import r from"node:path";import i from"nano-spawn";import{readFileSync as a}from"node:fs";const o=`COREFRAME_HTTPS_CERT`,s=`COREFRAME_HTTPS_KEY`;async function c({cwd:a=process.cwd(),spawn:o=i}={}){let s=r.resolve(a,`.coreframe`,`https`),c=r.join(s,`localhost.pem`),l=r.join(s,`localhost-key.pem`);if(!await u(c,l)){let i;try{i=(await o(`mkcert`,[`-CAROOT`],{stdin:`ignore`})).stdout.trim()}catch{throw Error("Local HTTPS requires mkcert. Install it, run `mkcert -install`, then retry `coreframe dev --https`.")}try{await e(r.join(i,`rootCA.pem`))}catch{throw Error("The mkcert local CA is not initialized. Run `mkcert -install`, then retry `coreframe dev --https`.")}await n(s,{recursive:!0}),await o(`mkcert`,[`-cert-file`,c,`-key-file`,l,`localhost`,`127.0.0.1`,`::1`],{stdin:`ignore`}),process.platform!==`win32`&&await t(l,384)}return{cert:c,key:l}}function l(e=process.env){let t=e[o],n=e[s];if(!t&&!n)return{};if(!t||!n)throw Error(`${o} and ${s} must be set together.`);return{server:{https:{cert:a(t),key:a(n)}}}}async function u(...t){try{return await Promise.all(t.map(t=>e(t))),!0}catch{return!1}}export{l as coreframeDevHttpsConfig,o as devHttpsCertEnv,s as devHttpsKeyEnv,c as prepareDevHttps};
package/dist/dev.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { startProjectPostgres } from "./db/local-postgres.js";
2
+ import { prepareDevHttps } from "./dev-https.js";
2
3
  import { CoreframeConfig, readProjectConfig } from "./config.js";
3
4
 
4
5
  //#region dev.d.ts
@@ -6,7 +7,9 @@ type DevServerOptions = {
6
7
  cwd?: string;
7
8
  env?: NodeJS.ProcessEnv;
8
9
  getAvailablePort?: typeof getAvailablePort;
10
+ https?: boolean;
9
11
  platform?: DevPlatform;
12
+ prepareDevHttps?: typeof prepareDevHttps;
10
13
  readProjectConfig?: typeof readProjectConfig;
11
14
  startProjectPostgres?: typeof startProjectPostgres;
12
15
  webPort?: number;
@@ -18,7 +21,9 @@ declare function runDevServer({
18
21
  cwd,
19
22
  env,
20
23
  getAvailablePort,
24
+ https,
21
25
  platform,
26
+ prepareDevHttps,
22
27
  readProjectConfig,
23
28
  startProjectPostgres,
24
29
  webPort
package/dist/dev.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{readProjectConfig as e}from"./config.js";import{startProjectPostgres as t}from"./db/local-postgres.js";import n from"./_virtual/_@oxc-project_runtime@0.138.0/helpers/esm/usingCtx.js";import{mkdir as r}from"node:fs/promises";import i from"node:path";import a from"node:process";import{createServer as o}from"node:net";import{supervise as s}from"procband";const c=[`web`,`desktop`,`ios`,`android`];function l(e){let t=e.dev?.platforms??[`web`];for(let e of t)if(!c.includes(e))throw Error(`Invalid development platform "${String(e)}". Expected one of: ${c.join(`, `)}.`);return[...new Set(t)]}const u=i.resolve(`node_modules`,`.bin`),d=a.platform===`win32`?`pnpm.cmd`:`pnpm`,f=a.platform===`win32`?`react-router.cmd`:`react-router`,p=a.platform===`win32`?`turso.cmd`:`turso`,m={getAvailablePort:_,readProjectConfig:e,startProjectPostgres:t};async function h({cwd:e=a.cwd(),env:t=a.env,getAvailablePort:o=m.getAvailablePort,platform:c=`web`,readProjectConfig:l=m.readProjectConfig,startProjectPostgres:h=m.startProjectPostgres,webPort:_}={}){let x=t.PATH??t.Path??``,S=c===`web`?_??b(t.COREFRAME_WEB_PORT):void 0,C,w=t;try{if(c===`web`){let a=await l({cwd:e});if(a.database?.dialect===`sqlite`){let n=await o(),a=i.resolve(e,`.coreframe`),c=i.join(a,`turso.db`);await r(a,{recursive:!0}),w={...t,TURSO_DATABASE_URL:`http://127.0.0.1:${n}`},C=s({name:`turso-dev`,command:p,args:[`dev`,`--port`,String(n),`--db-file`,c],cwd:e,env:t}),await C.waitFor(`listening`),await s({name:`db-ensure`,command:d,args:[`db`,`ensure`],cwd:e,env:w,prefix:!1}).expectSuccess()}if(g(a))try{var T=n();let r=T.a(await h({config:a,cwd:e,env:t})).env;await s({name:`db-ensure`,command:d,args:[`db`,`ensure`],cwd:e,env:r,prefix:!1}).expectSuccess(),await s({name:`web-dev`,command:f,args:y(S),cwd:e,env:{...r,CLOUDFLARE_ENV:`development`,PATH:u+i.delimiter+x}}).expectSuccess();return}catch(e){T.e=e}finally{await T.d()}await s({name:`web-dev`,command:f,args:y(S),cwd:e,env:{...w,CLOUDFLARE_ENV:`development`,PATH:u+i.delimiter+x}}).expectSuccess();return}let a=v(c);await s({name:[`tauri`,...a.slice(2)].join(`-`),command:d,args:a,cwd:e,env:t}).expectSuccess()}finally{C&&C.kill(`SIGTERM`)}}function g(e){return(e.database?.dialect??`postgres`)===`postgres`}async function _(){let e=o();try{await new Promise((t,n)=>{e.once(`error`,n),e.listen(0,`127.0.0.1`,t)});let t=e.address();if(!t||typeof t==`string`)throw Error(`Could not allocate a port for Turso dev.`);return t.port}finally{e.listening&&await new Promise((t,n)=>{e.close(e=>e?n(e):t())})}}function v(e){return[`--dir=tauri`,`tauri`,...e===`desktop`?[]:[e],`dev`]}function y(e){return e===void 0?[`dev`]:[`dev`,`--port`,String(e)]}function b(e){if(e===void 0)return;let t=Number(e);if(!Number.isInteger(t)||t<=0||t>65535)throw Error(`COREFRAME_WEB_PORT must be a valid TCP port.`);return t}import.meta.main&&h({env:{...a.env,FORCE_COLOR:`1`}}).catch(e=>{console.error(e),a.exit(1)});export{c as devPlatforms,l as resolveDevPlatforms,h as runDevServer};
2
+ import{readProjectConfig as e}from"./config.js";import{startProjectPostgres as t}from"./db/local-postgres.js";import n from"./_virtual/_@oxc-project_runtime@0.138.0/helpers/esm/usingCtx.js";import{devHttpsCertEnv as r,devHttpsKeyEnv as i,prepareDevHttps as a}from"./dev-https.js";import{mkdir as o}from"node:fs/promises";import s from"node:path";import c from"node:process";import{createServer as l}from"node:net";import{PassThrough as u}from"node:stream";import{supervise as d}from"procband";const f=[`web`,`desktop`,`ios`,`android`];function p(e){let t=e.dev?.platforms??[`web`];for(let e of t)if(!f.includes(e))throw Error(`Invalid development platform "${String(e)}". Expected one of: ${f.join(`, `)}.`);return[...new Set(t)]}const m=s.resolve(`node_modules`,`.bin`),h=c.platform===`win32`?`pnpm.cmd`:`pnpm`,g=c.platform===`win32`?`react-router.cmd`:`react-router`,_=c.platform===`win32`?`turso.cmd`:`turso`,v={getAvailablePort:x,prepareDevHttps:a,readProjectConfig:e,startProjectPostgres:t};async function y({cwd:e=c.cwd(),env:t=c.env,getAvailablePort:a=v.getAvailablePort,https:l=!1,platform:f=`web`,prepareDevHttps:p=v.prepareDevHttps,readProjectConfig:y=v.readProjectConfig,startProjectPostgres:x=v.startProjectPostgres,webPort:T}={}){let E=t.PATH??t.Path??``,D=f===`web`?T??w(t.COREFRAME_WEB_PORT):void 0,O,k=t;if(l&&f!==`web`)throw Error(`Local HTTPS is only supported for the web development platform.`);try{if(f===`web`){let f=await y({cwd:e}),v=l?await p({cwd:e}):void 0;if(k=v?{...t,[r]:v.cert,[i]:v.key}:t,f.database?.dialect===`sqlite`){let n=await a(),r=s.resolve(e,`.coreframe`),i=s.join(r,`turso.db`);await o(r,{recursive:!0}),k={...k,TURSO_DATABASE_URL:`http://127.0.0.1:${n}`},O=d({name:`turso`,command:_,args:[`dev`,`--port`,String(n),`--db-file`,i],cwd:e,env:t}),await O.waitFor(`listening`),await d({name:`db`,command:h,args:[`db`,`ensure`],cwd:e,env:k,prefix:!1}).expectSuccess()}if(b(f)){let t=new u,r=d({name:`postgres`,command:c.execPath,args:[`-e`,`process.stdin.pipe(process.stdout)`],cwd:e,stdin:t});try{try{var A=n();let r=A.a(await x({config:f,cwd:e,env:k,postgresOutput:t})).env;await d({name:`db`,command:h,args:[`db`,`ensure`],cwd:e,env:r,prefix:!1}).expectSuccess(),await d({name:`web`,command:g,args:C(D),cwd:e,env:{...r,CLOUDFLARE_ENV:`development`,PATH:m+s.delimiter+E}}).expectSuccess()}catch(e){A.e=e}finally{await A.d()}}finally{t.end(),await r.expectSuccess()}return}await d({name:`web`,command:g,args:C(D),cwd:e,env:{...k,CLOUDFLARE_ENV:`development`,PATH:m+s.delimiter+E}}).expectSuccess();return}let v=S(f);await d({name:f,command:h,args:v,cwd:e,env:t}).expectSuccess()}finally{O&&O.kill(`SIGTERM`)}}function b(e){return(e.database?.dialect??`postgres`)===`postgres`}async function x(){let e=l();try{await new Promise((t,n)=>{e.once(`error`,n),e.listen(0,`127.0.0.1`,t)});let t=e.address();if(!t||typeof t==`string`)throw Error(`Could not allocate a port for Turso dev.`);return t.port}finally{e.listening&&await new Promise((t,n)=>{e.close(e=>e?n(e):t())})}}function S(e){return[`--dir=tauri`,`tauri`,...e===`desktop`?[]:[e],`dev`]}function C(e){return e===void 0?[`dev`]:[`dev`,`--port`,String(e)]}function w(e){if(e===void 0)return;let t=Number(e);if(!Number.isInteger(t)||t<=0||t>65535)throw Error(`COREFRAME_WEB_PORT must be a valid TCP port.`);return t}import.meta.main&&y({env:{...c.env,FORCE_COLOR:`1`}}).catch(e=>{console.error(e),c.exit(1)});export{f as devPlatforms,p as resolveDevPlatforms,y as runDevServer};
package/package.json CHANGED
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "name": "@coreframe/scripts",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/airlock-labs/coreframe.git",
7
+ "directory": "scripts"
8
+ },
4
9
  "bin": {
5
10
  "coreframe": "./bin/coreframe.js"
6
11
  },
@@ -9,11 +14,6 @@
9
14
  "dist/"
10
15
  ],
11
16
  "type": "module",
12
- "repository": {
13
- "type": "git",
14
- "url": "git+https://github.com/airlock-labs/coreframe.git",
15
- "directory": "scripts"
16
- },
17
17
  "exports": {
18
18
  "./*": {
19
19
  "types": "./dist/*.d.ts",
@@ -31,7 +31,7 @@
31
31
  "@clack/prompts": "^1.6.0",
32
32
  "cmd-ts": "0.15.0",
33
33
  "drizzle-orm": "1.0.0-rc.4",
34
- "local-postgres": "0.2.0",
34
+ "local-postgres": "0.3.0",
35
35
  "nano-spawn": "^2.1.0",
36
36
  "procband": "^0.3.6",
37
37
  "tinyglobby": "^0.2.17"