@coreframe/scripts 0.1.1 → 0.1.3
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/config.d.ts +11 -1
- package/dist/config.js +1 -1
- package/dist/db/client.d.ts +14 -14
- package/dist/db/client.js +1 -1
- package/dist/db/config.d.ts +1 -2
- package/dist/db/config.js +1 -1
- package/dist/db/ensure.d.ts +5 -0
- package/dist/db/ensure.js +1 -1
- package/dist/db/local-postgres.d.ts +26 -0
- package/dist/db/local-postgres.js +1 -0
- package/dist/db/migrate-held.d.ts +4 -4
- package/dist/db/migrate-held.js +1 -1
- package/dist/db/migrate.js +1 -1
- package/dist/db/project.d.ts +24 -5
- package/dist/db/project.js +1 -1
- package/dist/db/reset.js +1 -1
- package/dist/db/schema-push.d.ts +4 -4
- package/dist/db/schema-push.js +1 -1
- package/dist/db/seed.js +1 -1
- package/dist/deploy/migrations.js +2 -2
- package/dist/deploy/pending-migrations.d.ts +3 -3
- package/dist/deploy/tauri-release.js +1 -1
- package/dist/deploy.d.ts +1 -2
- package/dist/deploy.js +1 -1
- package/dist/dev.d.ts +3 -0
- package/dist/dev.js +1 -1
- package/dist/image-generator.d.ts +14 -2
- package/dist/typecheck.js +1 -1
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
|
+
import { DatabaseDialect } from "./db/client.js";
|
|
1
2
|
import { DeployConfig } from "./deploy/config.js";
|
|
2
3
|
|
|
3
4
|
//#region config.d.ts
|
|
4
5
|
type CoreframeConfig = {
|
|
6
|
+
database?: DatabaseConfig;
|
|
5
7
|
deploy?: DeployConfig;
|
|
6
8
|
};
|
|
9
|
+
type DatabaseConfig = {
|
|
10
|
+
dialect: DatabaseDialect;
|
|
11
|
+
};
|
|
7
12
|
declare function defineConfig(config: CoreframeConfig): CoreframeConfig;
|
|
13
|
+
declare function readProjectConfig({
|
|
14
|
+
cwd
|
|
15
|
+
}?: {
|
|
16
|
+
cwd?: string;
|
|
17
|
+
}): Promise<CoreframeConfig>;
|
|
8
18
|
//#endregion
|
|
9
|
-
export { CoreframeConfig, defineConfig };
|
|
19
|
+
export { CoreframeConfig, DatabaseConfig, defineConfig, readProjectConfig };
|
package/dist/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
import{access as e}from"node:fs/promises";import{resolve as t}from"node:path";import{pathToFileURL as n}from"node:url";function r(e){return e}async function i({cwd:r=process.cwd()}={}){let i=t(r,`coreframe.config.ts`);try{await e(i)}catch{return{}}return(await import(n(i).href)).default??{}}export{r as defineConfig,i as readProjectConfig};
|
package/dist/db/client.d.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import { SQL } from "drizzle-orm";
|
|
2
2
|
|
|
3
3
|
//#region db/client.d.ts
|
|
4
|
-
type
|
|
5
|
-
type
|
|
4
|
+
type DatabaseDialect = "postgres" | "sqlite";
|
|
5
|
+
type QueryResult<Row extends Record<string, unknown> = Record<string, unknown>> = {
|
|
6
6
|
rowCount?: number | null;
|
|
7
7
|
rows: Row[];
|
|
8
8
|
};
|
|
9
|
-
type
|
|
10
|
-
dialect:
|
|
11
|
-
execute<Row extends Record<string, unknown> = Record<string, unknown>>(statement: string): Promise<
|
|
12
|
-
transaction?<Result>(run: (database:
|
|
9
|
+
type DatabaseClient = {
|
|
10
|
+
dialect: DatabaseDialect;
|
|
11
|
+
execute<Row extends Record<string, unknown> = Record<string, unknown>>(statement: string): Promise<QueryResult<Row>>;
|
|
12
|
+
transaction?<Result>(run: (database: DatabaseClient) => Promise<Result>): Promise<Result>;
|
|
13
13
|
close?(): Promise<void>;
|
|
14
14
|
};
|
|
15
|
-
type
|
|
15
|
+
type DrizzleExecutor = {
|
|
16
16
|
execute<Result = unknown>(query: SQL): Result | Promise<Result>;
|
|
17
17
|
};
|
|
18
|
-
type
|
|
18
|
+
type CreateDatabaseAdapterOptions = {
|
|
19
19
|
close?(): Promise<void>;
|
|
20
|
-
database:
|
|
21
|
-
dialect:
|
|
20
|
+
database: DrizzleExecutor;
|
|
21
|
+
dialect: DatabaseDialect;
|
|
22
22
|
};
|
|
23
|
-
declare function
|
|
23
|
+
declare function createDatabaseAdapter({
|
|
24
24
|
close,
|
|
25
25
|
database,
|
|
26
26
|
dialect
|
|
27
|
-
}:
|
|
28
|
-
declare function normalizeQueryResult<Row extends Record<string, unknown> = Record<string, unknown>>(result: unknown):
|
|
27
|
+
}: CreateDatabaseAdapterOptions): DatabaseClient;
|
|
28
|
+
declare function normalizeQueryResult<Row extends Record<string, unknown> = Record<string, unknown>>(result: unknown): QueryResult<Row>;
|
|
29
29
|
//#endregion
|
|
30
|
-
export {
|
|
30
|
+
export { CreateDatabaseAdapterOptions, DatabaseClient, DatabaseDialect, DrizzleExecutor, QueryResult, createDatabaseAdapter, normalizeQueryResult };
|
package/dist/db/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sql as e}from"drizzle-orm";function t({close:t,database:r,dialect:i}){return{dialect:i,async execute(t){return n(await r.execute(e.raw(t)))},close:t}}function n(e){return Array.isArray(e)?{rows:e}:r(e)?{rowCount:typeof e.rowCount==`number`?e.rowCount:null,rows:e.rows}:{rows:[]}}function r(e){return typeof e==`object`&&!!e&&`rows`in e&&Array.isArray(e.rows)}export{t as
|
|
1
|
+
import{sql as e}from"drizzle-orm";function t({close:t,database:r,dialect:i}){return{dialect:i,async execute(t){return n(await r.execute(e.raw(t)))},close:t}}function n(e){return Array.isArray(e)?{rows:e}:r(e)?{rowCount:typeof e.rowCount==`number`?e.rowCount:null,rows:e.rows}:{rows:[]}}function r(e){return typeof e==`object`&&!!e&&`rows`in e&&Array.isArray(e.rows)}export{t as createDatabaseAdapter,n as normalizeQueryResult};
|
package/dist/db/config.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
//#region db/config.d.ts
|
|
2
|
-
declare const LOCAL_DB_DIR: string;
|
|
3
2
|
declare const MIGRATIONS_FOLDER = "drizzle";
|
|
4
3
|
declare const HELD_MIGRATIONS_FOLDER = "drizzle-hold";
|
|
5
4
|
declare const NOW: Date;
|
|
@@ -21,4 +20,4 @@ type SeedProfile = "small" | "large" | "demo" | "test";
|
|
|
21
20
|
declare function getSeedProfile(argv?: string[]): SeedProfile;
|
|
22
21
|
declare function generatedUserId(index: number): string;
|
|
23
22
|
//#endregion
|
|
24
|
-
export { HELD_MIGRATIONS_FOLDER,
|
|
23
|
+
export { HELD_MIGRATIONS_FOLDER, MIGRATIONS_FOLDER, NOW, SEED_EMAILS, SEED_IDS, SeedProfile, generatedUserId, getSeedProfile };
|
package/dist/db/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e
|
|
1
|
+
const e=`drizzle`,t=`drizzle-hold`,n=new Date(`2026-01-15T12:00:00.000Z`),r={adminUser:`00000000-0000-4000-8000-000000000001`,viewerUser:`00000000-0000-4000-8000-000000000002`,inactiveUser:`00000000-0000-4000-8000-000000000003`,unicodeUser:`00000000-0000-4000-8000-000000000004`,longNameUser:`00000000-0000-4000-8000-000000000005`},i={adminUser:`admin@example.com`,viewerUser:`viewer@example.com`,inactiveUser:`inactive@example.com`,unicodeUser:`unicode@example.com`,longNameUser:`long-name@example.com`};function a(e=process.argv.slice(2)){if(e.includes(`--large`))return`large`;let t=e.find(e=>e.startsWith(`--profile=`))?.slice(10)??`small`;if(t===`small`||t===`large`||t===`demo`||t===`test`)return t;throw Error(`Unknown seed profile "${t}". Expected small, large, demo, or test.`)}function o(e){return`00000000-0000-4000-8000-${String(1e3+e).padStart(12,`0`)}`}export{t as HELD_MIGRATIONS_FOLDER,e as MIGRATIONS_FOLDER,n as NOW,i as SEED_EMAILS,r as SEED_IDS,o as generatedUserId,a as getSeedProfile};
|
package/dist/db/ensure.d.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { importProjectModule } from "../project.js";
|
|
2
|
+
import { createLocalPostgresDb } from "./local-postgres.js";
|
|
2
3
|
import { planLocalSchemaPush } from "./schema-push.js";
|
|
3
4
|
import { seedLocalDb } from "./seed.js";
|
|
4
5
|
import { setupLocalDb } from "./setup.js";
|
|
5
6
|
|
|
6
7
|
//#region db/ensure.d.ts
|
|
7
8
|
type EnsureLocalDbOptions = {
|
|
9
|
+
createLocalPostgresDb?: typeof createLocalPostgresDb;
|
|
10
|
+
env?: NodeJS.ProcessEnv;
|
|
8
11
|
importProjectModule?: typeof importProjectModule;
|
|
9
12
|
planLocalSchemaPush?: typeof planLocalSchemaPush;
|
|
10
13
|
seedLocalDb?: typeof seedLocalDb;
|
|
11
14
|
setupLocalDb?: typeof setupLocalDb;
|
|
12
15
|
};
|
|
13
16
|
declare function ensureLocalDb({
|
|
17
|
+
createLocalPostgresDb: createDb,
|
|
18
|
+
env,
|
|
14
19
|
importProjectModule: importModule,
|
|
15
20
|
planLocalSchemaPush: planSchemaPush,
|
|
16
21
|
seedLocalDb: seed,
|
package/dist/db/ensure.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{importProjectModule as e}from"../project.js";import{
|
|
2
|
+
import{importProjectModule as e}from"../project.js";import{SEED_EMAILS as t,SEED_IDS as n}from"./config.js";import{createLocalPostgresDb as r}from"./local-postgres.js";import{inferSchemaDialect as i,planLocalSchemaPush as a}from"./schema-push.js";import{seedLocalDb as o}from"./seed.js";import{setupLocalDb as s}from"./setup.js";import{eq as c}from"drizzle-orm";async function l(t=e){return{schema:await t(`src/db/schema.ts`)}}async function u(e,{users:r}){let[i]=await e.select({id:r.id}).from(r).where(c(r.email,t.adminUser)).limit(1);return i?.id===n.adminUser}async function d(e,{schema:t},n=a){let r=await n(i(t),t,e);return r.sqlStatements.length===0?(console.log(`Local database schema already in sync`),{appliedStatements:0,plan:r}):(console.log(`Local database schema drift detected; applying ${r.sqlStatements.length} statement(s)`),await r.apply(),console.log(`Local database schema synced`),{appliedStatements:r.sqlStatements.length,plan:r})}async function f({createLocalPostgresDb:t=r,env:n=process.env,importProjectModule:i=e,planLocalSchemaPush:c=a,seedLocalDb:u=o,setupLocalDb:f=s}={}){let m=await l(i),h=await t({env:n});try{await p(h,m.schema)?console.log(`Local database already set up`):(console.log(`Local database is missing or unseeded; running setup`),await f()),(await d(h,m,c)).appliedStatements>0&&!await p(h,m.schema)&&(console.log(`Local database seed data missing after schema sync; running seed`),await u())}finally{await h.$client.end()}}async function p(e,t){try{return await u(e,t)}catch{return!1}}import.meta.main&&f().catch(e=>{console.error(e),process.exit(1)});export{f as ensureLocalDb};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createProjectPostgresDrizzleDatabase } from "./project.js";
|
|
2
|
+
|
|
3
|
+
//#region db/local-postgres.d.ts
|
|
4
|
+
type LocalPostgresDb = Awaited<ReturnType<typeof createProjectPostgresDrizzleDatabase>> & {
|
|
5
|
+
$client: {
|
|
6
|
+
end(): Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
select(selection: Record<string, unknown>): {
|
|
9
|
+
from(table: unknown): {
|
|
10
|
+
where(condition: unknown): {
|
|
11
|
+
limit(count: number): Promise<Array<{
|
|
12
|
+
id: string;
|
|
13
|
+
}>>;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
type LocalPostgresOptions = {
|
|
19
|
+
env?: NodeJS.ProcessEnv;
|
|
20
|
+
};
|
|
21
|
+
declare function createLocalPostgresDb({
|
|
22
|
+
env
|
|
23
|
+
}?: LocalPostgresOptions): Promise<LocalPostgresDb>;
|
|
24
|
+
declare function getLocalPostgresConnectionString(env?: NodeJS.ProcessEnv): string;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { LocalPostgresDb, createLocalPostgresDb, getLocalPostgresConnectionString };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createProjectPostgresDrizzleDatabase as e}from"./project.js";async function t({env:t=process.env}={}){let r=n(t);return e({env:{...t,DATABASE_URL:r}})}function n(e=process.env){let t=e.DATABASE_URL||r(e);if(!t)throw Error(`DATABASE_URL or PGDATABASE, PGHOST, PGPORT, and PGUSER are required.`);return t}function r(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{t as createLocalPostgresDb,n as getLocalPostgresConnectionString};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DatabaseClient, DatabaseDialect } from "./client.js";
|
|
2
2
|
|
|
3
3
|
//#region db/migrate-held.d.ts
|
|
4
4
|
type MigrateHeldOptions = {
|
|
5
5
|
argv?: string[];
|
|
6
|
-
database?:
|
|
6
|
+
database?: DatabaseClient;
|
|
7
7
|
env?: NodeJS.ProcessEnv;
|
|
8
8
|
};
|
|
9
9
|
declare function migrateHeldMigrations({
|
|
@@ -12,7 +12,7 @@ declare function migrateHeldMigrations({
|
|
|
12
12
|
env
|
|
13
13
|
}?: MigrateHeldOptions): Promise<void>;
|
|
14
14
|
declare function validateHeldMigrationHeader(sql: string, relativePath: string): void;
|
|
15
|
-
declare function heldMigrationSelectQuery(dialect:
|
|
16
|
-
declare function heldMigrationInsertQuery(dialect:
|
|
15
|
+
declare function heldMigrationSelectQuery(dialect: DatabaseDialect, id: string): string;
|
|
16
|
+
declare function heldMigrationInsertQuery(dialect: DatabaseDialect, id: string, sha256: string): string;
|
|
17
17
|
//#endregion
|
|
18
18
|
export { heldMigrationInsertQuery, heldMigrationSelectQuery, migrateHeldMigrations, validateHeldMigrationHeader };
|
package/dist/db/migrate-held.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{createProjectDeployDatabase as e}from"./project.js";import{collectHeldMigrationFiles as t,formatMigrationList as n}from"../deploy/migrations.js";import{readFile as r}from"node:fs/promises";import{createHash as i}from"node:crypto";const a=`--confirm=run-held-migrations`,o=[`-- Held migration:`,`-- Safe after:`,`-- Verification:`];async function s({argv:i=process.argv.slice(2),database:o,env:s=process.env}={}){let d=await t();if(console.log(`Held migration files:`),console.log(n(d)),!i.includes(a))throw Error(`Held migrations require explicit confirmation. Re-run with ${a}.`);if(d.length===0){console.log(`No held migrations to run.`);return}let m=o??await e({env:s});try{await u(m);for(let e of d){let t=await r(e.path,`utf8`);c(t,e.relativePath);let n=l(t),i=await m.execute(f(m.dialect,e.id));if(i.rows.length===1){if(i.rows[0]?.sha256!==n)throw Error(`Held migration ${e.relativePath} changed after it was applied.`);console.log(`Skipping already-applied held migration ${e.relativePath}`);continue}console.log(`Applying held migration ${e.relativePath}`),await h(m,async r=>{await r.execute(t),await r.execute(p(m.dialect,e.id,n))})}}finally{o||await m.close?.()}}function c(e,t){let n=o.filter(t=>!e.includes(t));if(n.length>0)throw Error(`${t} is missing held migration header fields: ${n.join(`, `)}`)}function l(e){return i(`sha256`).update(e).digest(`hex`)}async function u(e){for(let t of d(e.dialect))await e.execute(t)}function d(e){switch(e){case`postgres`:return[`create schema if not exists drizzle`,`create table if not exists drizzle.__held_migrations (
|
|
3
3
|
id text primary key,
|
|
4
4
|
sha256 text not null,
|
|
5
5
|
applied_at timestamptz not null default now()
|
package/dist/db/migrate.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{MIGRATIONS_FOLDER as e}from"./config.js";import{createLocalPostgresDb as t}from"./local-postgres.js";import{access as n}from"node:fs/promises";import{resolve as r}from"node:path";import{migrate as i}from"drizzle-orm/node-postgres/migrator";const a=r(e);async function o(){await n(a);let e=await t();try{await i(e,{migrationsFolder:a}),console.log(`Applied local migrations from ${a}`)}finally{await e.$client.end()}}import.meta.main&&o().catch(e=>{console.error(e),process.exit(1)});export{o as migrateLocalDb};
|
package/dist/db/project.d.ts
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DatabaseClient, DrizzleExecutor } from "./client.js";
|
|
2
|
+
import { DatabaseConfig } from "../config.js";
|
|
3
|
+
import { importProjectModule } from "../project.js";
|
|
2
4
|
|
|
3
5
|
//#region db/project.d.ts
|
|
4
6
|
type CreateProjectDatabaseOptions = {
|
|
7
|
+
config?: DatabaseConfig;
|
|
5
8
|
env?: NodeJS.ProcessEnv;
|
|
9
|
+
importProjectDependency?: ImportProjectDependency;
|
|
10
|
+
importProjectModule?: typeof importProjectModule;
|
|
6
11
|
};
|
|
7
|
-
type
|
|
8
|
-
|
|
12
|
+
type DrizzleDatabase = DrizzleExecutor & {
|
|
13
|
+
$client?: {
|
|
14
|
+
close?(): Promise<void> | void;
|
|
15
|
+
end?(): Promise<void>;
|
|
16
|
+
};
|
|
9
17
|
};
|
|
10
|
-
|
|
18
|
+
type ImportProjectDependency = <T>(specifier: string) => Promise<T>;
|
|
19
|
+
declare function createProjectDeployDatabase({
|
|
20
|
+
config,
|
|
21
|
+
env,
|
|
22
|
+
importProjectDependency,
|
|
23
|
+
importProjectModule: importModule
|
|
24
|
+
}?: CreateProjectDatabaseOptions): Promise<DatabaseClient>;
|
|
25
|
+
declare function createProjectPostgresDrizzleDatabase({
|
|
26
|
+
env,
|
|
27
|
+
importProjectDependency,
|
|
28
|
+
importProjectModule: importModule
|
|
29
|
+
}?: CreateProjectDatabaseOptions): Promise<DrizzleDatabase>;
|
|
11
30
|
//#endregion
|
|
12
|
-
export { CreateProjectDatabaseOptions,
|
|
31
|
+
export { CreateProjectDatabaseOptions, createProjectDeployDatabase, createProjectPostgresDrizzleDatabase };
|
package/dist/db/project.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{readProjectConfig as e}from"../config.js";import{importProjectModule as t}from"../project.js";import{createDatabaseAdapter as n}from"./client.js";import{createRequire as r}from"node:module";import{resolve as i}from"node:path";import{pathToFileURL as a}from"node:url";const o=`src/db/relations.ts`;async function s({config:n,env:r=process.env,importProjectDependency:i=d,importProjectModule:a=t}={}){let o=(n??(await e()).database)?.dialect??`postgres`;if(o===`postgres`)return l({env:r,importModule:a,importProjectDependency:i});if(o===`sqlite`)return u({env:r,importModule:a,importProjectDependency:i});throw Error(`Unsupported database dialect "${o}".`)}async function c({env:e=process.env,importProjectDependency:n=d,importProjectModule:r=t}={}){let i=e.DATABASE_URL;if(!i)throw Error(`DATABASE_URL is required to create the PostgreSQL database.`);let[{drizzle:a},{relations:s}]=await Promise.all([n(`drizzle-orm/node-postgres`),r(o)]);return a({connection:{connectionString:i,max:1},relations:s})}async function l({env:e,importModule:t,importProjectDependency:r}){let i=await c({env:e,importProjectDependency:r,importProjectModule:t});return n({database:i,dialect:`postgres`,close:()=>i.$client?.end?.()??Promise.resolve()})}async function u({env:e,importModule:t,importProjectDependency:r}){let i=e.TURSO_DATABASE_URL??e.DATABASE_URL;if(!i)throw Error(`TURSO_DATABASE_URL or DATABASE_URL is required to create the deploy database.`);let[{createClient:a},{drizzle:s},{relations:c}]=await Promise.all([r(`@libsql/client`),r(`drizzle-orm/libsql`),t(o)]),l=a({url:i,authToken:e.TURSO_AUTH_TOKEN});return n({database:s({client:l,relations:c}),dialect:`sqlite`,close:async()=>{await l.close?.()}})}async function d(e){return await import(a(r(i(`package.json`)).resolve(e)).href)}export{s as createProjectDeployDatabase,c as createProjectPostgresDrizzleDatabase};
|
package/dist/db/reset.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{createLocalPostgresDb as e}from"./local-postgres.js";import{sql as t}from"drizzle-orm";async function n(){let n=await e();try{await n.execute(t`drop schema if exists public cascade`),await n.execute(t`create schema public`),console.log(`Reset local PostgreSQL schema`)}finally{await n.$client.end()}}import.meta.main&&n().catch(e=>{console.error(e),process.exit(1)});export{n as resetLocalDb};
|
package/dist/db/schema-push.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DatabaseDialect } from "./client.js";
|
|
2
2
|
|
|
3
3
|
//#region db/schema-push.d.ts
|
|
4
4
|
type SchemaPushPlan = {
|
|
@@ -15,8 +15,8 @@ type SchemaPushModule = {
|
|
|
15
15
|
schema?: string;
|
|
16
16
|
}): Promise<SchemaPushPlan>;
|
|
17
17
|
};
|
|
18
|
-
type ImportSchemaPushModule = (dialect:
|
|
19
|
-
declare function planLocalSchemaPush(dialect:
|
|
20
|
-
declare function inferSchemaDialect(schema: Record<string, unknown>):
|
|
18
|
+
type ImportSchemaPushModule = (dialect: DatabaseDialect) => Promise<SchemaPushModule>;
|
|
19
|
+
declare function planLocalSchemaPush(dialect: DatabaseDialect, schema: Record<string, unknown>, db: unknown, importModule?: ImportSchemaPushModule): Promise<SchemaPushPlan>;
|
|
20
|
+
declare function inferSchemaDialect(schema: Record<string, unknown>): DatabaseDialect;
|
|
21
21
|
//#endregion
|
|
22
22
|
export { SchemaPushModule, SchemaPushPlan, inferSchemaDialect, planLocalSchemaPush };
|
package/dist/db/schema-push.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";import{resolve as t}from"node:path";import{
|
|
1
|
+
import{createRequire as e}from"node:module";import{resolve as t}from"node:path";import{pathToFileURL as n}from"node:url";import{is as r}from"drizzle-orm";import{PgMaterializedView as i,PgTable as a,PgView as o}from"drizzle-orm/pg-core";import{SQLiteTable as s,SQLiteView as c}from"drizzle-orm/sqlite-core";const l={postgres:`drizzle-kit/payload/postgres`,sqlite:`drizzle-kit/payload/sqlite`};async function u(e,t,n,r=f){let{pushSchema:i}=await r(e);return i(t,n)}function d(e){let t=!1,n=!1;for(let r of Object.values(e))t||=p(r),n||=m(r);if(t&&n)throw Error(`Local database schema mixes PostgreSQL and SQLite entities.`);if(t)return`postgres`;if(n)return`sqlite`;throw Error(`Could not infer local database dialect from src/db/schema.ts.`)}async function f(r){return await import(n(e(t(`package.json`)).resolve(l[r])).href)}function p(e){return r(e,a)||r(e,o)||r(e,i)}function m(e){return r(e,s)||r(e,c)}export{d as inferSchemaDialect,u as planLocalSchemaPush};
|
package/dist/db/seed.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{importProjectModule as e}from"../project.js";import{
|
|
2
|
+
import{importProjectModule as e}from"../project.js";import{getSeedProfile as t}from"./config.js";import{createLocalPostgresDb as n}from"./local-postgres.js";async function r(r=t()){let[{seedUsers:i},a]=await Promise.all([e(`scripts/db/seeds/users.ts`),n()]);try{await i(a,r),console.log(`Seeded local database with "${r}" profile`)}finally{await a.$client.end()}}import.meta.main&&r().catch(e=>{console.error(e),process.exit(1)});export{r as seedLocalDb};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{HELD_MIGRATIONS_FOLDER as e,MIGRATIONS_FOLDER as t}from"../db/config.js";import{
|
|
1
|
+
import{HELD_MIGRATIONS_FOLDER as e,MIGRATIONS_FOLDER as t}from"../db/config.js";import{access as n,readFile as r,readdir as i}from"node:fs/promises";import{basename as a,join as o,relative as s,resolve as c}from"node:path";const l=[{code:`drop-schema-object`,pattern:/\bdrop\s+(?:table|view|materialized\s+view|index|sequence|type|schema|function|trigger|policy)\b/giu,reason:`drops schema that the currently deployed app may still depend on`},{code:`drop-column`,pattern:/\balter\s+table\b[^;]*?\bdrop\s+column\b/giu,reason:`removes a column that the currently deployed app may still read or write`},{code:`drop-constraint`,pattern:/\balter\s+table\b[^;]*?\bdrop\s+constraint\b/giu,reason:`removes a constraint outside the staged contract phase`},{code:`truncate`,pattern:/\btruncate\b/giu,reason:`removes data outside the deploy-safe migration path`},{code:`rename-table-or-column`,pattern:/\balter\s+table\b[^;]*?\brename(?:\s+column)?\b/giu,reason:`renames schema in a way old and new app versions cannot both address`},{code:`rewrite-column-type`,pattern:/\balter\s+table\b[^;]*?\balter\s+column\b[^;]*?\btype\b/giu,reason:`rewrites a column type outside a staged expand/contract rollout`},{code:`set-not-null`,pattern:/\balter\s+table\b[^;]*?\balter\s+column\b[^;]*?\bset\s+not\s+null\b/giu,reason:`enforces NOT NULL before a separate backfill and verification step`},{code:`set-default`,pattern:/\balter\s+table\b[^;]*?\balter\s+column\b[^;]*?\bset\s+default\b/giu,reason:`changes default write behavior while old app code may still be running`},{code:`broad-update`,pattern:/\bupdate\b/giu,reason:`changes data outside a separately reviewed backfill or held migration`},{code:`broad-delete`,pattern:/\bdelete\s+from\b/giu,reason:`removes data outside a held migration`}];async function u(e=process.cwd()){return _(c(e,t),e)}async function d(t=process.cwd()){return v(c(t,e),t)}async function f(e){return(await Promise.all(e.map(async e=>({migration:e,risks:p(await r(e.path,`utf8`))})))).filter(e=>e.risks.length>0)}function p(e){let t=S(e),n=g(t),r=[];for(let n of l)for(let i of t.matchAll(n.pattern))r.push(T(e,i,n.code,n.reason));for(let i of t.matchAll(/\balter\s+table\s+(?:if\s+exists\s+|only\s+)?(?<table>(?:"[^"]+"|\w+)(?:\s*\.\s*(?:"[^"]+"|\w+))?)\s+add\s+column\b[^;]*?\bnot\s+null\b/giu))n.has(w(i.groups?.table))||r.push(T(e,i,`add-not-null-column`,`adds a required column to an existing table before a separate compatibility rollout`));for(let i of t.matchAll(/\balter\s+table\s+(?:if\s+exists\s+|only\s+)?(?<table>(?:"[^"]+"|\w+)(?:\s*\.\s*(?:"[^"]+"|\w+))?)\s+add\s+constraint\b[^;]*?\b(?:foreign\s+key|unique|primary\s+key|check)\b/giu))n.has(w(i.groups?.table))||r.push(T(e,i,`add-constraint`,`enforces a constraint on an existing table before a separate validation step`));for(let i of t.matchAll(/\bcreate\s+unique\s+index(?:\s+concurrently)?(?:\s+if\s+not\s+exists)?\s+(?:"[^"]+"|\w+)\s+on\s+(?<table>(?:"[^"]+"|\w+)(?:\s*\.\s*(?:"[^"]+"|\w+))?)/giu))n.has(w(i.groups?.table))||r.push(T(e,i,`create-unique-index`,`adds uniqueness to existing data before a separate dedupe and validation step`));return r.sort((e,t)=>e.line-t.line||e.code.localeCompare(t.code))}function m(e){return e.flatMap(e=>e.risks.map(t=>`${e.migration.relativePath}:${t.line} ${t.code}: ${t.reason} (${t.match.trim()})`)).join(`
|
|
2
2
|
`)}function h(e){return e.length===0?`No migration files found.`:e.map(e=>`- ${e.relativePath}`).join(`
|
|
3
|
-
`)}function g(e){let t=new Set;for(let n of e.matchAll(/\bcreate\s+(?:temporary\s+|temp\s+)?table\s+(?:if\s+not\s+exists\s+)?(?<table>(?:"[^"]+"|\w+)(?:\s*\.\s*(?:"[^"]+"|\w+))?)/giu))t.add(w(n.groups?.table));return t}async function _(e,t){let n=await y(e),
|
|
3
|
+
`)}function g(e){let t=new Set;for(let n of e.matchAll(/\bcreate\s+(?:temporary\s+|temp\s+)?table\s+(?:if\s+not\s+exists\s+)?(?<table>(?:"[^"]+"|\w+)(?:\s*\.\s*(?:"[^"]+"|\w+))?)/giu))t.add(w(n.groups?.table));return t}async function _(e,t){let n=await y(e),r=[];for(let i of n){let n=o(e,i.name);if(i.isDirectory()){let e=o(n,`migration.sql`);await b(e)&&r.push(x(e,t,i.name));continue}i.isFile()&&i.name.endsWith(`.sql`)&&r.push(x(n,t,i.name.replace(/\.sql$/u,``)))}return r.sort((e,t)=>e.id.localeCompare(t.id))}async function v(e,t){return(await y(e)).filter(e=>e.isFile()&&e.name.endsWith(`.sql`)).map(n=>x(o(e,n.name),t,n.name.replace(/\.sql$/u,``))).sort((e,t)=>e.id.localeCompare(t.id))}async function y(e){try{return await i(e,{withFileTypes:!0})}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return[];throw e}}async function b(e){try{return await n(e),!0}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return!1;throw e}}function x(e,t,n=a(e,`.sql`)){return{id:n,path:e,relativePath:s(t,e)}}function S(e){return e.replace(/--[^\n\r]*/gu,C).replace(/\/\*[\s\S]*?\*\//gu,C).replace(/\$([A-Za-z_][A-Za-z0-9_]*)?\$[\s\S]*?\$\1\$/gu,C).replace(/'(?:''|[^'])*'/gu,C)}function C(e){return e.replace(/[^\n\r]/gu,` `)}function w(e){return(e??``).split(`.`).map(e=>e.trim().replace(/^"|"$/gu,``).toLowerCase()).at(-1)??``}function T(e,t,n,r){return{code:n,line:E(e,t.index??0),match:e.slice(t.index??0,(t.index??0)+t[0].length),reason:r}}function E(e,t){let n=1;for(let r=0;r<t;r+=1)e[r]===`
|
|
4
4
|
`&&(n+=1);return n}export{u as collectDeployMigrationFiles,d as collectHeldMigrationFiles,h as formatMigrationList,m as formatMigrationScanFailures,f as scanDeployMigrationFiles,p as scanMigrationSql};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DatabaseClient, DatabaseDialect } from "../db/client.js";
|
|
2
2
|
import { MigrationFile } from "./migrations.js";
|
|
3
3
|
|
|
4
4
|
//#region deploy/pending-migrations.d.ts
|
|
5
5
|
declare function filterPendingMigrations(migrations: MigrationFile[], appliedNames: Iterable<string>): MigrationFile[];
|
|
6
|
-
declare function readAppliedMigrationNames(database:
|
|
7
|
-
declare function appliedMigrationsQuery(dialect:
|
|
6
|
+
declare function readAppliedMigrationNames(database: DatabaseClient): Promise<Set<string>>;
|
|
7
|
+
declare function appliedMigrationsQuery(dialect: DatabaseDialect): "select name from drizzle.__drizzle_migrations where name is not null" | "select name from __drizzle_migrations where name is not null";
|
|
8
8
|
//#endregion
|
|
9
9
|
export { appliedMigrationsQuery, filterPendingMigrations, readAppliedMigrationNames };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{tauriReleasePlatforms as e}from"./config.js";import{basename as t,dirname as n,join as r,relative as i,resolve as a,sep as o}from"node:path";import s from"nano-spawn";import{access as c,cp as l,mkdir as u,readFile as d,rm as f,stat as p,writeFile as m}from"node:fs/promises";import{randomUUID as h}from"node:crypto";import{constants as g}from"node:fs";import{setTimeout as _}from"node:timers/promises";import{glob as v}from"tinyglobby";const y={android:{artifactGlobs:[`tauri/src-tauri/target/**/*.sig`,`tauri/gen/android/**/*.sig`],buildArgs:[`tauri`,`android`,`build`,`--target`,`aarch64-linux-android`],targetTriple:`aarch64-linux-android`,updatePlatform:`android-aarch64`},ios:{artifactGlobs:[`tauri/src-tauri/target/**/*.sig`,`tauri/gen/apple/**/*.sig`],buildArgs:[`tauri`,`ios`,`build`,`--target`,`aarch64-apple-ios`],targetTriple:`aarch64-apple-ios`,updatePlatform:`ios-aarch64`},linux:{artifactGlobs:[`tauri/src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/**/*.sig`,`tauri/src-tauri/target/release/bundle/**/*.sig`,`tauri/src-tauri/target/**/release/bundle/**/*.sig`],buildArgs:[`tauri`,`build`,`--target`,`x86_64-unknown-linux-gnu`,`--`,`--locked`],targetTriple:`x86_64-unknown-linux-gnu`,updatePlatform:`linux-x86_64`},macos:{artifactGlobs:[`tauri/src-tauri/target/aarch64-apple-darwin/release/bundle/**/*.sig`,`tauri/src-tauri/target/release/bundle/**/*.sig`,`tauri/src-tauri/target/**/release/bundle/**/*.sig`],buildArgs:[`tauri`,`build`,`--target`,`aarch64-apple-darwin`,`--`,`--locked`],targetTriple:`aarch64-apple-darwin`,updatePlatform:`darwin-aarch64`},windows:{artifactGlobs:[`tauri/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/**/*.sig`,`tauri/src-tauri/target/release/bundle/**/*.sig`,`tauri/src-tauri/target/**/release/bundle/**/*.sig`],buildArgs:[`tauri`,`build`,`--target`,`x86_64-pc-windows-msvc`,`--`,`--locked`],targetTriple:`x86_64-pc-windows-msvc`,updatePlatform:`windows-x86_64`}};function b(e){return e?e.split(/[,\s]+/u).filter(Boolean).map(e=>x(e)):[]}function x(t){if(Y(t))return t;throw Error(`Invalid Tauri release platform "${t}". Expected one of: ${e.join(`, `)}.`)}function S({args:e,config:t={},env:n}){let r=J([...t.localPlatforms??[],...b(n.TAURI_RELEASE_LOCAL_PLATFORMS),...e.tauriLocalPlatforms]),i=J([...t.workflowPlatforms??[],...b(n.TAURI_RELEASE_WORKFLOW_PLATFORMS),...e.tauriWorkflowPlatforms]),a=r.filter(e=>i.includes(e));if(a.length>0)throw Error(`Build each Tauri release platform either locally or through the workflow, not both: ${a.join(`, `)}.`);return{artifactDownloadDir:n.TAURI_RELEASE_ARTIFACT_DOWNLOAD_DIR??t.artifactDownloadDir??`.coreframe/tauri-artifacts`,b2ApplicationKey:n.B2_APPLICATION_KEY??n.B2_SECRET_ACCESS_KEY,b2ApplicationKeyId:n.B2_APPLICATION_KEY_ID??n.B2_KEY_ID??n.B2_ACCESS_KEY_ID,b2Bucket:t.b2Bucket??n.B2_BUCKET,enabled:r.length>0||i.length>0,latestManifestPath:n.TAURI_RELEASE_LATEST_MANIFEST_PATH??t.latestManifestPath??`latest.json`,localPlatforms:r,platform:I(t.platform,n),publicBaseUrl:t.publicBaseUrl??n.TAURI_RELEASE_PUBLIC_BASE_URL??n.UPDATE_PUBLIC_BASE_URL,publicPathPrefix:n.TAURI_RELEASE_PUBLIC_PATH_PREFIX??t.publicPathPrefix??n.UPDATE_PUBLIC_PATH_PREFIX??``,releaseNotesPath:n.TAURI_RELEASE_NOTES_FILE??t.releaseNotesPath,releasePath:n.TAURI_RELEASE_PATH??t.releasePath??"releases/${version}",releaseUploadDir:n.TAURI_RELEASE_UPLOAD_DIR??t.releaseUploadDir??`release-upload`,signingPrivateKey:n.TAURI_SIGNING_PRIVATE_KEY,workflowName:e.tauriWorkflowName??n.TAURI_RELEASE_WORKFLOW_NAME??t.workflowName??`tauri-release-artifacts.yml`,workflowPlatforms:i,workflowPollIntervalMs:q(n.TAURI_RELEASE_WORKFLOW_POLL_SECONDS,`TAURI_RELEASE_WORKFLOW_POLL_SECONDS`)*1e3||t.workflowPollIntervalMs||15e3,workflowRef:e.tauriWorkflowRef??n.TAURI_RELEASE_WORKFLOW_REF??t.workflowRef,workflowTimeoutMs:q(n.TAURI_RELEASE_WORKFLOW_TIMEOUT_MINUTES,`TAURI_RELEASE_WORKFLOW_TIMEOUT_MINUTES`)*6e4||t.workflowTimeoutMs||36e5}}async function C(e,t=process.cwd()){if(!e.enabled)return;let n=[[`TAURI_RELEASE_PUBLIC_BASE_URL`,e.publicBaseUrl],[`B2_APPLICATION_KEY_ID`,e.b2ApplicationKeyId],[`B2_APPLICATION_KEY`,e.b2ApplicationKey],[`B2_BUCKET`,e.b2Bucket]].flatMap(([e,t])=>t?[]:[e]);if(n.length>0)throw Error(`Missing required Tauri release configuration: ${n.join(`, `)}`);try{new URL(e.publicBaseUrl)}catch{throw Error(`Invalid TAURI_RELEASE_PUBLIC_BASE_URL: ${e.publicBaseUrl}`)}if(!await X(r(t,`tauri/src-tauri/tauri.conf.json`)))throw Error(`Tauri release platforms were requested, but tauri/src-tauri/tauri.conf.json does not exist.`);if(e.localPlatforms.length>0&&!e.signingPrivateKey)throw Error(`TAURI_SIGNING_PRIVATE_KEY is required for local Tauri release builds.`);e.workflowPlatforms.length>0&&await s(`gh`,[`workflow`,`view`,e.workflowName,`--ref`,e.workflowRef??await V()],{stdin:`ignore`}),await s(`b2`,[`version`],{stdin:`ignore`})}async function w(e,t,n=process.cwd()){if(!e.enabled)return{files:[]};let i=r(n,`tauri/src-tauri/tauri.conf.json`),a=r(n,`tauri/src-tauri/Cargo.toml`),o=r(n,`tauri/src-tauri/Cargo.lock`),s=await d(i,`utf8`),c=await d(a,`utf8`),l=R(c,a),u=[{path:i,source:s},{path:a,source:c}],f=[],p=JSON.parse(s);if(p.version=t,p.bundle={...p.bundle??{},createUpdaterArtifacts:!0},f.push({path:i,source:`${JSON.stringify(p,null,2)}\n`}),f.push({path:a,source:z(c,l,t,a)}),await X(o)){let e=await d(o,`utf8`);u.push({path:o,source:e}),f.push({path:o,source:B(e,l,t,o)})}for(let e of f)await m(e.path,e.source);return{files:u}}async function T(e){for(let t of e.files)await m(t.path,t.source)}async function E({env:e,plan:t,releaseName:n,version:r}){if(!t.enabled)return;await H(t.artifactDownloadDir),await H(t.releaseUploadDir);let i=t.workflowPlatforms.length>0?await A({plan:t,releaseName:n,version:r}):void 0;for(let n of t.localPlatforms)await N(n,t,e);if(i){let e=await j(t,i.runNameMarker);await s(`gh`,[`run`,`download`,String(e),`--dir`,t.artifactDownloadDir],{stdio:`inherit`})}return k({plan:t,version:r})}async function D(e,t){await s(`b2`,[`account`,`authorize`,e.b2ApplicationKeyId,e.b2ApplicationKey],{stdin:`ignore`});let n=(await v(`**/*`,{cwd:t.uploadDir,onlyFiles:!0})).sort((e,n)=>e===t.manifestPath?1:n===t.manifestPath?-1:e.localeCompare(n));for(let i of n)await s(`b2`,[`file`,`upload`,e.b2Bucket,r(t.uploadDir,i),i],{stdin:`ignore`}),console.log(`Uploaded ${i}`)}function O({artifacts:e,notes:t,pubDate:n=new Date,version:r}){return{...t?{notes:t}:{},platforms:Object.fromEntries(e.map(e=>[e.updatePlatform,{signature:e.signature,url:e.url}])),pub_date:n.toISOString(),version:r}}async function k({plan:e,version:i}){let a=K(e.publicPathPrefix,W(e.releasePath,i)),o=K(e.publicPathPrefix,e.latestManifestPath),s=[...e.localPlatforms,...e.workflowPlatforms],c=[];for(let o of s){let s=e.platform[o],f=e.localPlatforms.includes(o)?`.`:r(e.artifactDownloadDir,`tauri-${o}-${i}`),p=await P({globs:e.localPlatforms.includes(o)?s.artifactGlobs:[`**/*.sig`],sourceRoot:f,version:i}),m=K(a,s.updatePlatform),h=K(m,t(p.artifactPath)),g=K(m,t(p.signaturePath)),_=r(e.releaseUploadDir,...h.split(`/`)),v=r(e.releaseUploadDir,...g.split(`/`)),y=(await d(p.signaturePath,`utf8`)).trim();await u(n(_),{recursive:!0}),await l(p.artifactPath,_),await l(p.signaturePath,v),c.push({signature:y,updatePlatform:s.updatePlatform,url:G(e.publicBaseUrl,h)})}let f=O({artifacts:c,notes:e.releaseNotesPath?await d(e.releaseNotesPath,`utf8`):void 0,version:i}),p=r(e.releaseUploadDir,...o.split(`/`));return await u(n(p),{recursive:!0}),await m(p,`${JSON.stringify(f,null,2)}\n`),{manifestPath:o,uploadDir:e.releaseUploadDir}}async function A({plan:t,releaseName:n,version:r}){let i=t.workflowRef??await V(),a=`coreframe-${Date.now()}-${h().slice(0,8)}`;return await s(`gh`,[`workflow`,`run`,t.workflowName,`--ref`,i,`-f`,`release_name=${n}`,`-f`,`run_id=${a}`,`-f`,`version=${r}`,...e.flatMap(e=>[`-f`,`${e}=${t.workflowPlatforms.includes(e)?`true`:`false`}`])],{stdin:`ignore`}),{runNameMarker:a}}async function j(e,t){let n=Date.now()+e.workflowTimeoutMs;for(;Date.now()<n;){let n=await M(e,t);if(n?.status===`completed`){if(n.conclusion===`success`)return n.databaseId;throw Error(`Tauri release workflow ${n.databaseId} finished with ${n.conclusion}.`)}await _(e.workflowPollIntervalMs)}throw Error(`Timed out waiting for Tauri release workflow after ${Math.round(e.workflowTimeoutMs/6e4)} minutes.`)}async function M(e,t){let{stdout:n}=await s(`gh`,[`run`,`list`,`--workflow`,e.workflowName,`--event`,`workflow_dispatch`,`--json`,`conclusion,databaseId,displayTitle,status`,`--limit`,`50`],{stdin:`ignore`});return JSON.parse(n).find(e=>e.displayTitle.includes(t))}async function N(e,t,n){await s(`pnpm`,t.platform[e].buildArgs,{env:n,stdio:`inherit`})}async function P({globs:e,sourceRoot:t,version:n}){let r=await v(e,{cwd:t,absolute:!0,onlyFiles:!0}),i=[];for(let e of r){let t=e.replace(/\.sig$/u,``);await Z(t)&&i.push({artifactPath:t,signaturePath:e})}if(i.length===0)throw Error(`Could not find a Tauri updater artifact and .sig pair under ${t}.`);return i.sort((e,t)=>{let r=F(e.artifactPath,n);return F(t.artifactPath,n)-r||e.artifactPath.localeCompare(t.artifactPath)})[0]}function F(e,t){let n=0;return e.includes(t)&&(n+=100),/\.(app\.tar\.gz|AppImage\.tar\.gz|zip)$/u.test(e)&&(n+=10),/\.(exe|msi|dmg|AppImage|deb|rpm|apk|aab|ipa)$/u.test(e)&&(n+=5),n}function I(t={},n){return Object.fromEntries(e.map(e=>{let r=t[e]??{},i={...y[e],...r},a=n[`TAURI_RELEASE_${e.toUpperCase()}_TARGET_TRIPLE`],o=n[`TAURI_RELEASE_${e.toUpperCase()}_UPDATE_PLATFORM`],s=a??i.targetTriple,c=r.buildArgs?r.buildArgs:L(e,s);return[e,{...i,artifactGlobs:i.artifactGlobs??y[e].artifactGlobs,buildArgs:c,targetTriple:s,updatePlatform:o??i.updatePlatform}]}))}function L(e,t){return e===`android`?[`tauri`,`android`,`build`,`--target`,t]:e===`ios`?[`tauri`,`ios`,`build`,`--target`,t]:[`tauri`,`build`,`--target`,t,`--`,`--locked`]}function R(e,t){let n=/^\[package\][\s\S]*?^name = "(?<name>[^"]+)"/mu.exec(e);if(!n?.groups?.name)throw Error(`${t} is missing a [package] name.`);return n.groups.name}function z(e,t,n,r){let i=RegExp(`(^\\[package\\][\\s\\S]*?^name = "${Q(t)}"[\\s\\S]*?^version = ")[^"]+(")`,`mu`),a=e.replace(i,`$1${n}$2`);if(a===e)throw Error(`${r} is missing a package version for ${t}.`);return a}function B(e,t,n,r){let i=RegExp(`(\\[\\[package\\]\\]\\nname = "${Q(t)}"\\nversion = ")[^"]+(")`,`u`),a=e.replace(i,`$1${n}$2`);if(a===e)throw Error(`${r} is missing a package lock entry for ${t}.`);return a}async function V(){let{stdout:e}=await s(`git`,[`rev-parse`,`--abbrev-ref`,`HEAD`],{stdin:`ignore`}),t=e.trim();if(t!==`HEAD`)return t;let{stdout:n}=await s(`git`,[`rev-parse`,`HEAD`],{stdin:`ignore`});return n.trim()}async function H(e){U(e),await f(e,{force:!0,recursive:!0}),await u(e,{recursive:!0})}function U(e){let t=a(e),n=i(process.cwd(),t).split(o).join(`/`);if(n===``||n===`.`||n.startsWith(`../`)||n===`tauri`||n.startsWith(`tauri/`))throw Error(`Refusing to reset unsafe Tauri release directory: ${e}`)}function W(e,t){return e.replaceAll("${version}",t)}function G(e,t){let n=new URL(e),r=K(n.pathname.replace(/\/+$/u,``),t);return n.pathname=r.startsWith(`/`)?r:`/${r}`,n.toString()}function K(...e){return e.flatMap(e=>e.split(`/`)).map(e=>e.trim()).filter(Boolean).join(`/`)}function q(e,t){if(!e)return 0;let n=Number(e);if(!Number.isInteger(n)||n<=0)throw Error(`${t} must be a positive integer.`);return n}function J(e){return[...new Set(e)]}function Y(t){return e.includes(t)}async function X(e){try{return await c(e,g.F_OK),!0}catch{return!1}}async function Z(e){try{return(await p(e)).isFile()}catch{return!1}}function Q(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,`\\$&`)}export{k as createTauriReleaseUpload,O as createTauriUpdateManifest,x as parseTauriReleasePlatform,b as parseTauriReleasePlatformList,E as prepareTauriRelease,S as resolveTauriReleasePlan,T as restoreTauriReleaseMetadata,D as uploadTauriReleaseToB2,C as validateTauriReleasePlan,w as writeTauriReleaseMetadata};
|
|
1
|
+
import{tauriReleasePlatforms as e}from"./config.js";import{access as t,cp as n,mkdir as r,readFile as i,rm as a,stat as o,writeFile as s}from"node:fs/promises";import{basename as c,dirname as l,join as u,relative as d,resolve as f,sep as p}from"node:path";import m from"nano-spawn";import{randomUUID as h}from"node:crypto";import{constants as g}from"node:fs";import{setTimeout as _}from"node:timers/promises";import{glob as v}from"tinyglobby";const y={android:{artifactGlobs:[`tauri/src-tauri/target/**/*.sig`,`tauri/gen/android/**/*.sig`],buildArgs:[`tauri`,`android`,`build`,`--target`,`aarch64-linux-android`],targetTriple:`aarch64-linux-android`,updatePlatform:`android-aarch64`},ios:{artifactGlobs:[`tauri/src-tauri/target/**/*.sig`,`tauri/gen/apple/**/*.sig`],buildArgs:[`tauri`,`ios`,`build`,`--target`,`aarch64-apple-ios`],targetTriple:`aarch64-apple-ios`,updatePlatform:`ios-aarch64`},linux:{artifactGlobs:[`tauri/src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/**/*.sig`,`tauri/src-tauri/target/release/bundle/**/*.sig`,`tauri/src-tauri/target/**/release/bundle/**/*.sig`],buildArgs:[`tauri`,`build`,`--target`,`x86_64-unknown-linux-gnu`,`--`,`--locked`],targetTriple:`x86_64-unknown-linux-gnu`,updatePlatform:`linux-x86_64`},macos:{artifactGlobs:[`tauri/src-tauri/target/aarch64-apple-darwin/release/bundle/**/*.sig`,`tauri/src-tauri/target/release/bundle/**/*.sig`,`tauri/src-tauri/target/**/release/bundle/**/*.sig`],buildArgs:[`tauri`,`build`,`--target`,`aarch64-apple-darwin`,`--`,`--locked`],targetTriple:`aarch64-apple-darwin`,updatePlatform:`darwin-aarch64`},windows:{artifactGlobs:[`tauri/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/**/*.sig`,`tauri/src-tauri/target/release/bundle/**/*.sig`,`tauri/src-tauri/target/**/release/bundle/**/*.sig`],buildArgs:[`tauri`,`build`,`--target`,`x86_64-pc-windows-msvc`,`--`,`--locked`],targetTriple:`x86_64-pc-windows-msvc`,updatePlatform:`windows-x86_64`}};function b(e){return e?e.split(/[,\s]+/u).filter(Boolean).map(e=>x(e)):[]}function x(t){if(Y(t))return t;throw Error(`Invalid Tauri release platform "${t}". Expected one of: ${e.join(`, `)}.`)}function S({args:e,config:t={},env:n}){let r=J([...t.localPlatforms??[],...b(n.TAURI_RELEASE_LOCAL_PLATFORMS),...e.tauriLocalPlatforms]),i=J([...t.workflowPlatforms??[],...b(n.TAURI_RELEASE_WORKFLOW_PLATFORMS),...e.tauriWorkflowPlatforms]),a=r.filter(e=>i.includes(e));if(a.length>0)throw Error(`Build each Tauri release platform either locally or through the workflow, not both: ${a.join(`, `)}.`);return{artifactDownloadDir:n.TAURI_RELEASE_ARTIFACT_DOWNLOAD_DIR??t.artifactDownloadDir??`.coreframe/tauri-artifacts`,b2ApplicationKey:n.B2_APPLICATION_KEY??n.B2_SECRET_ACCESS_KEY,b2ApplicationKeyId:n.B2_APPLICATION_KEY_ID??n.B2_KEY_ID??n.B2_ACCESS_KEY_ID,b2Bucket:t.b2Bucket??n.B2_BUCKET,enabled:r.length>0||i.length>0,latestManifestPath:n.TAURI_RELEASE_LATEST_MANIFEST_PATH??t.latestManifestPath??`latest.json`,localPlatforms:r,platform:I(t.platform,n),publicBaseUrl:t.publicBaseUrl??n.TAURI_RELEASE_PUBLIC_BASE_URL??n.UPDATE_PUBLIC_BASE_URL,publicPathPrefix:n.TAURI_RELEASE_PUBLIC_PATH_PREFIX??t.publicPathPrefix??n.UPDATE_PUBLIC_PATH_PREFIX??``,releaseNotesPath:n.TAURI_RELEASE_NOTES_FILE??t.releaseNotesPath,releasePath:n.TAURI_RELEASE_PATH??t.releasePath??"releases/${version}",releaseUploadDir:n.TAURI_RELEASE_UPLOAD_DIR??t.releaseUploadDir??`release-upload`,signingPrivateKey:n.TAURI_SIGNING_PRIVATE_KEY,workflowName:e.tauriWorkflowName??n.TAURI_RELEASE_WORKFLOW_NAME??t.workflowName??`tauri-release-artifacts.yml`,workflowPlatforms:i,workflowPollIntervalMs:q(n.TAURI_RELEASE_WORKFLOW_POLL_SECONDS,`TAURI_RELEASE_WORKFLOW_POLL_SECONDS`)*1e3||t.workflowPollIntervalMs||15e3,workflowRef:e.tauriWorkflowRef??n.TAURI_RELEASE_WORKFLOW_REF??t.workflowRef,workflowTimeoutMs:q(n.TAURI_RELEASE_WORKFLOW_TIMEOUT_MINUTES,`TAURI_RELEASE_WORKFLOW_TIMEOUT_MINUTES`)*6e4||t.workflowTimeoutMs||36e5}}async function C(e,t=process.cwd()){if(!e.enabled)return;let n=[[`TAURI_RELEASE_PUBLIC_BASE_URL`,e.publicBaseUrl],[`B2_APPLICATION_KEY_ID`,e.b2ApplicationKeyId],[`B2_APPLICATION_KEY`,e.b2ApplicationKey],[`B2_BUCKET`,e.b2Bucket]].flatMap(([e,t])=>t?[]:[e]);if(n.length>0)throw Error(`Missing required Tauri release configuration: ${n.join(`, `)}`);try{new URL(e.publicBaseUrl)}catch{throw Error(`Invalid TAURI_RELEASE_PUBLIC_BASE_URL: ${e.publicBaseUrl}`)}if(!await X(u(t,`tauri/src-tauri/tauri.conf.json`)))throw Error(`Tauri release platforms were requested, but tauri/src-tauri/tauri.conf.json does not exist.`);if(e.localPlatforms.length>0&&!e.signingPrivateKey)throw Error(`TAURI_SIGNING_PRIVATE_KEY is required for local Tauri release builds.`);e.workflowPlatforms.length>0&&await m(`gh`,[`workflow`,`view`,e.workflowName,`--ref`,e.workflowRef??await V()],{stdin:`ignore`}),await m(`b2`,[`version`],{stdin:`ignore`})}async function w(e,t,n=process.cwd()){if(!e.enabled)return{files:[]};let r=u(n,`tauri/src-tauri/tauri.conf.json`),a=u(n,`tauri/src-tauri/Cargo.toml`),o=u(n,`tauri/src-tauri/Cargo.lock`),c=await i(r,`utf8`),l=await i(a,`utf8`),d=R(l,a),f=[{path:r,source:c},{path:a,source:l}],p=[],m=JSON.parse(c);if(m.version=t,m.bundle={...m.bundle??{},createUpdaterArtifacts:!0},p.push({path:r,source:`${JSON.stringify(m,null,2)}\n`}),p.push({path:a,source:z(l,d,t,a)}),await X(o)){let e=await i(o,`utf8`);f.push({path:o,source:e}),p.push({path:o,source:B(e,d,t,o)})}for(let e of p)await s(e.path,e.source);return{files:f}}async function T(e){for(let t of e.files)await s(t.path,t.source)}async function E({env:e,plan:t,releaseName:n,version:r}){if(!t.enabled)return;await H(t.artifactDownloadDir),await H(t.releaseUploadDir);let i=t.workflowPlatforms.length>0?await A({plan:t,releaseName:n,version:r}):void 0;for(let n of t.localPlatforms)await N(n,t,e);if(i){let e=await j(t,i.runNameMarker);await m(`gh`,[`run`,`download`,String(e),`--dir`,t.artifactDownloadDir],{stdio:`inherit`})}return k({plan:t,version:r})}async function D(e,t){await m(`b2`,[`account`,`authorize`,e.b2ApplicationKeyId,e.b2ApplicationKey],{stdin:`ignore`});let n=(await v(`**/*`,{cwd:t.uploadDir,onlyFiles:!0})).sort((e,n)=>e===t.manifestPath?1:n===t.manifestPath?-1:e.localeCompare(n));for(let r of n)await m(`b2`,[`file`,`upload`,e.b2Bucket,u(t.uploadDir,r),r],{stdin:`ignore`}),console.log(`Uploaded ${r}`)}function O({artifacts:e,notes:t,pubDate:n=new Date,version:r}){return{...t?{notes:t}:{},platforms:Object.fromEntries(e.map(e=>[e.updatePlatform,{signature:e.signature,url:e.url}])),pub_date:n.toISOString(),version:r}}async function k({plan:e,version:t}){let a=K(e.publicPathPrefix,W(e.releasePath,t)),o=K(e.publicPathPrefix,e.latestManifestPath),d=[...e.localPlatforms,...e.workflowPlatforms],f=[];for(let o of d){let s=e.platform[o],d=e.localPlatforms.includes(o)?`.`:u(e.artifactDownloadDir,`tauri-${o}-${t}`),p=await P({globs:e.localPlatforms.includes(o)?s.artifactGlobs:[`**/*.sig`],sourceRoot:d,version:t}),m=K(a,s.updatePlatform),h=K(m,c(p.artifactPath)),g=K(m,c(p.signaturePath)),_=u(e.releaseUploadDir,...h.split(`/`)),v=u(e.releaseUploadDir,...g.split(`/`)),y=(await i(p.signaturePath,`utf8`)).trim();await r(l(_),{recursive:!0}),await n(p.artifactPath,_),await n(p.signaturePath,v),f.push({signature:y,updatePlatform:s.updatePlatform,url:G(e.publicBaseUrl,h)})}let p=O({artifacts:f,notes:e.releaseNotesPath?await i(e.releaseNotesPath,`utf8`):void 0,version:t}),m=u(e.releaseUploadDir,...o.split(`/`));return await r(l(m),{recursive:!0}),await s(m,`${JSON.stringify(p,null,2)}\n`),{manifestPath:o,uploadDir:e.releaseUploadDir}}async function A({plan:t,releaseName:n,version:r}){let i=t.workflowRef??await V(),a=`coreframe-${Date.now()}-${h().slice(0,8)}`;return await m(`gh`,[`workflow`,`run`,t.workflowName,`--ref`,i,`-f`,`release_name=${n}`,`-f`,`run_id=${a}`,`-f`,`version=${r}`,...e.flatMap(e=>[`-f`,`${e}=${t.workflowPlatforms.includes(e)?`true`:`false`}`])],{stdin:`ignore`}),{runNameMarker:a}}async function j(e,t){let n=Date.now()+e.workflowTimeoutMs;for(;Date.now()<n;){let n=await M(e,t);if(n?.status===`completed`){if(n.conclusion===`success`)return n.databaseId;throw Error(`Tauri release workflow ${n.databaseId} finished with ${n.conclusion}.`)}await _(e.workflowPollIntervalMs)}throw Error(`Timed out waiting for Tauri release workflow after ${Math.round(e.workflowTimeoutMs/6e4)} minutes.`)}async function M(e,t){let{stdout:n}=await m(`gh`,[`run`,`list`,`--workflow`,e.workflowName,`--event`,`workflow_dispatch`,`--json`,`conclusion,databaseId,displayTitle,status`,`--limit`,`50`],{stdin:`ignore`});return JSON.parse(n).find(e=>e.displayTitle.includes(t))}async function N(e,t,n){await m(`pnpm`,t.platform[e].buildArgs,{env:n,stdio:`inherit`})}async function P({globs:e,sourceRoot:t,version:n}){let r=await v(e,{cwd:t,absolute:!0,onlyFiles:!0}),i=[];for(let e of r){let t=e.replace(/\.sig$/u,``);await Z(t)&&i.push({artifactPath:t,signaturePath:e})}if(i.length===0)throw Error(`Could not find a Tauri updater artifact and .sig pair under ${t}.`);return i.sort((e,t)=>{let r=F(e.artifactPath,n);return F(t.artifactPath,n)-r||e.artifactPath.localeCompare(t.artifactPath)})[0]}function F(e,t){let n=0;return e.includes(t)&&(n+=100),/\.(app\.tar\.gz|AppImage\.tar\.gz|zip)$/u.test(e)&&(n+=10),/\.(exe|msi|dmg|AppImage|deb|rpm|apk|aab|ipa)$/u.test(e)&&(n+=5),n}function I(t={},n){return Object.fromEntries(e.map(e=>{let r=t[e]??{},i={...y[e],...r},a=n[`TAURI_RELEASE_${e.toUpperCase()}_TARGET_TRIPLE`],o=n[`TAURI_RELEASE_${e.toUpperCase()}_UPDATE_PLATFORM`],s=a??i.targetTriple,c=r.buildArgs?r.buildArgs:L(e,s);return[e,{...i,artifactGlobs:i.artifactGlobs??y[e].artifactGlobs,buildArgs:c,targetTriple:s,updatePlatform:o??i.updatePlatform}]}))}function L(e,t){return e===`android`?[`tauri`,`android`,`build`,`--target`,t]:e===`ios`?[`tauri`,`ios`,`build`,`--target`,t]:[`tauri`,`build`,`--target`,t,`--`,`--locked`]}function R(e,t){let n=/^\[package\][\s\S]*?^name = "(?<name>[^"]+)"/mu.exec(e);if(!n?.groups?.name)throw Error(`${t} is missing a [package] name.`);return n.groups.name}function z(e,t,n,r){let i=RegExp(`(^\\[package\\][\\s\\S]*?^name = "${Q(t)}"[\\s\\S]*?^version = ")[^"]+(")`,`mu`),a=e.replace(i,`$1${n}$2`);if(a===e)throw Error(`${r} is missing a package version for ${t}.`);return a}function B(e,t,n,r){let i=RegExp(`(\\[\\[package\\]\\]\\nname = "${Q(t)}"\\nversion = ")[^"]+(")`,`u`),a=e.replace(i,`$1${n}$2`);if(a===e)throw Error(`${r} is missing a package lock entry for ${t}.`);return a}async function V(){let{stdout:e}=await m(`git`,[`rev-parse`,`--abbrev-ref`,`HEAD`],{stdin:`ignore`}),t=e.trim();if(t!==`HEAD`)return t;let{stdout:n}=await m(`git`,[`rev-parse`,`HEAD`],{stdin:`ignore`});return n.trim()}async function H(e){U(e),await a(e,{force:!0,recursive:!0}),await r(e,{recursive:!0})}function U(e){let t=f(e),n=d(process.cwd(),t).split(p).join(`/`);if(n===``||n===`.`||n.startsWith(`../`)||n===`tauri`||n.startsWith(`tauri/`))throw Error(`Refusing to reset unsafe Tauri release directory: ${e}`)}function W(e,t){return e.replaceAll("${version}",t)}function G(e,t){let n=new URL(e),r=K(n.pathname.replace(/\/+$/u,``),t);return n.pathname=r.startsWith(`/`)?r:`/${r}`,n.toString()}function K(...e){return e.flatMap(e=>e.split(`/`)).map(e=>e.trim()).filter(Boolean).join(`/`)}function q(e,t){if(!e)return 0;let n=Number(e);if(!Number.isInteger(n)||n<=0)throw Error(`${t} must be a positive integer.`);return n}function J(e){return[...new Set(e)]}function Y(t){return e.includes(t)}async function X(e){try{return await t(e,g.F_OK),!0}catch{return!1}}async function Z(e){try{return(await o(e)).isFile()}catch{return!1}}function Q(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,`\\$&`)}export{k as createTauriReleaseUpload,O as createTauriUpdateManifest,x as parseTauriReleasePlatform,b as parseTauriReleasePlatformList,E as prepareTauriRelease,S as resolveTauriReleasePlan,T as restoreTauriReleaseMetadata,D as uploadTauriReleaseToB2,C as validateTauriReleasePlan,w as writeTauriReleaseMetadata};
|
package/dist/deploy.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TauriReleasePlatform } from "./deploy/config.js";
|
|
2
|
-
import {
|
|
2
|
+
import { readProjectConfig } from "./config.js";
|
|
3
3
|
|
|
4
4
|
//#region deploy.d.ts
|
|
5
5
|
type DeployArgs = {
|
|
@@ -13,7 +13,6 @@ type DeployArgs = {
|
|
|
13
13
|
yes: boolean;
|
|
14
14
|
};
|
|
15
15
|
declare function deployProject(argv?: string[], env?: NodeJS.ProcessEnv): Promise<void>;
|
|
16
|
-
declare function readProjectConfig(): Promise<CoreframeConfig>;
|
|
17
16
|
declare function parseDeployArgs(argv: string[]): DeployArgs;
|
|
18
17
|
//#endregion
|
|
19
18
|
export { deployProject, parseDeployArgs, readProjectConfig };
|
package/dist/deploy.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{readProjectConfig as e}from"./config.js";import{createProjectDeployDatabase as t}from"./db/project.js";import{collectDeployMigrationFiles as n,formatMigrationList as r,formatMigrationScanFailures as i,scanDeployMigrationFiles as a}from"./deploy/migrations.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(n=process.argv.slice(2),r=process.env){let c=E(n),{packageJson:l,source:u}=await v(w),T=_(l.version),D=y(l.name,T),O=r.DEPLOY_ENV??`production`,A=F(r,D,l.name,T),L=await e(),R=s(L.deploy??{},r),z=f({args:c,config:R.tauriRelease,env:r}),B=!1,V={files:[]};C.intro(`Deploy ${D}`),N(c),P(r,[`POSTHOG_API_KEY`,`POSTHOG_PROJECT_ID`]),await M(),await h(z);let H=await k(await t({config:L.database,env:r})),U=await a(H);if(U.length>0)throw Error(`Pending deploy migrations contain unsafe SQL. Move unsafe statements to held migrations.\n${i(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 n(),await l(e))}async function j(e,t){if(t.length===0)return C.log.info(`No pending deploy migrations.`),!1;if(C.note(r(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 n=await C.confirm({initialValue:!0,message:`Run these deploy-safe database migrations before Cloudflare deploy?`});if(C.isCancel(n))throw C.cancel(`Deploy cancelled.`),Error(`Deploy cancelled.`);return n}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,3 +1,4 @@
|
|
|
1
|
+
import { readProjectConfig } from "./config.js";
|
|
1
2
|
import { spawn as spawn$1 } from "node:child_process";
|
|
2
3
|
|
|
3
4
|
//#region dev.d.ts
|
|
@@ -7,6 +8,7 @@ type DevServerOptions = {
|
|
|
7
8
|
env?: NodeJS.ProcessEnv;
|
|
8
9
|
logPath?: string;
|
|
9
10
|
platform?: DevPlatform;
|
|
11
|
+
readProjectConfig?: typeof readProjectConfig;
|
|
10
12
|
spawn?: Spawn;
|
|
11
13
|
};
|
|
12
14
|
type DevPlatform = "android" | "desktop" | "ios" | "web";
|
|
@@ -15,6 +17,7 @@ declare function runDevServer({
|
|
|
15
17
|
env,
|
|
16
18
|
logPath,
|
|
17
19
|
platform,
|
|
20
|
+
readProjectConfig: readConfig,
|
|
18
21
|
spawn
|
|
19
22
|
}?: DevServerOptions): Promise<void>;
|
|
20
23
|
//#endregion
|
package/dist/dev.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import e from"node:
|
|
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,6 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigEnv, FSWatcher } from "vite";
|
|
2
2
|
|
|
3
3
|
//#region image-generator.d.ts
|
|
4
|
-
declare function imageGenerator():
|
|
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
|
+
};
|
|
5
17
|
//#endregion
|
|
6
18
|
export { imageGenerator };
|
package/dist/typecheck.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import e
|
|
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};
|