@cedarjs/cli-data-migrate 7.0.0 → 8.0.0-canary.3263

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/bin.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- var j=(t,i,r)=>()=>{if(r)throw r[0];try{return t&&(i=t(t=0)),i}catch(a){throw r=[a],a}};import g from"node:fs";import{createRequire as C}from"node:module";import c from"node:path";import{Listr as S}from"listr2";import{registerApiSideBabelHook as D}from"@cedarjs/babel-config";import{colors as m}from"@cedarjs/cli-helpers";import{getPaths as b,getDataMigrationsPath as $}from"@cedarjs/project-config";async function y({importDbClientFromDist:t,distPath:i}){let r,a=!1;if(t){if(!g.existsSync(i)){console.warn(`Can't find api dist at ${i}. You may need to build first: yarn cedar build api`),process.exitCode=1;return}let s=c.join(i,"lib"),d=c.join(s,"db.js");if(!g.existsSync(d)){console.error(`Can't find db.js at ${d}. CedarJS expects the db.js file to be in the ${s} directory`),process.exitCode=1;return}r=(await import(d)).db}else D(),a=!0,r=h(c.join(b().api.lib,"db")).db;let n=await P(r);if(!n.length){console.info(m.success(`
3
- ${L}
4
- `)),process.exitCode=0;return}let o={run:0,skipped:0,error:0},e=n.map(s=>{let d=c.basename(s.path,".js");return{title:d,skip(){return o.error>0?(o.skipped++,!0):!1},async task(){a||D();try{let{startedAt:f,finishedAt:A}=await I(r,s.path);o.run++,await R(r,{version:s.version,name:d,startedAt:f,finishedAt:A})}catch(f){o.error++,console.error(m.error(`Error in data migration: ${f.message}`))}}}}),p=new S(e,{renderer:"verbose"});try{await p.run(),await r.$disconnect(),console.log(),M(o),console.log(),o.error&&(process.exitCode=1)}catch{process.exitCode=1,await r.$disconnect(),console.log(),M(o),console.log()}}async function P(t){let i=await $(b().api.prismaConfig);if(!g.existsSync(i))return[];let r=g.readdirSync(i).filter(e=>["js",".ts"].some(p=>e.endsWith(p))).map(e=>{let[p]=e.split("-");return{version:p,path:c.join(i,e)}}),n=(await t.rW_DataMigration.findMany({orderBy:{version:"asc"}})).map(e=>e.version.toString());return r.filter(({version:e})=>!n.includes(e)).sort(_)}function _(t,i){let r=parseInt(t.version),a=parseInt(i.version);return r>a?1:r<a?-1:0}async function I(t,i){let r=h(i),a=new Date;return await r.default({db:t}),{startedAt:a,finishedAt:new Date}}async function R(t,{version:i,name:r,startedAt:a,finishedAt:n}){await t.rW_DataMigration.create({data:{version:i,name:r,startedAt:a,finishedAt:n}})}function M(t){t.run&&console.info(m.success(`${t.run} data migration(s) completed successfully.`)),t.error&&console.error(m.error(`${t.error} data migration(s) exited with errors.`)),t.skipped&&console.warn(m.warning(`${t.skipped} data migration(s) skipped due to previous error.`))}var h,L,w=j(()=>{"use strict";h=C(import.meta.url);L="No pending data migrations run, already up-to-date."});import v from"path";import{config as N}from"dotenv-defaults";import{hideBin as O}from"yargs/helpers";import U from"yargs/yargs";import{getPaths as x}from"@cedarjs/project-config";import{terminalLink as k}from"termi-link";import{getPaths as E,projectIsEsm as W}from"@cedarjs/project-config";var l="Run any outstanding Data Migrations against the database";function u(t){return t.option("import-db-client-from-dist",{type:"boolean",alias:["db-from-dist"],description:"Import the db client from dist",default:!1}).option("dist-path",{type:"string",alias:"d",description:"Path to the api dist directory",default:E().api.dist}).epilogue(`Also see the ${k("CedarJS CLI Reference","https://cedarjs.com/docs/cli-commands#datamigrate-up")}`)}w();process.env.CEDAR_ENV_FILES_LOADED||(N({path:v.join(x().base,".env"),defaults:v.join(x().base,".env.defaults"),multiline:!0}),process.env.CEDAR_ENV_FILES_LOADED="true");U(O(process.argv)).scriptName("data-migrate").command("$0",l,u,y).parse();
2
+ var I=(t,n,r)=>()=>{if(r)throw r[0];try{return t&&(n=t(t=0)),n}catch(e){throw r=[e],e}};import d from"node:fs";import m from"node:path";import{Listr as k}from"listr2";import{createServer as _,isRunnableDevEnvironment as L}from"vite";import{colors as f}from"@cedarjs/cli-helpers/colors";import{getPaths as l,getDataMigrationsPath as N,resolveFile as O,importStatementPath as v}from"@cedarjs/project-config";function V(t){if(d.existsSync(t)&&d.statSync(t).isFile())return t;let n=/\.jsx?$/.test(t)?t.replace(/\.jsx?$/,""):t;for(let r of[".ts",".tsx",".js",".jsx"])if(d.existsSync(n+r))return n+r;if(d.existsSync(t)&&d.statSync(t).isDirectory())for(let r of["index",m.basename(t)])for(let e of[".ts",".tsx",".js",".jsx"]){let o=m.join(t,r+e);if(d.existsSync(o))return o}return t}async function x({importDbClientFromDist:t,distPath:n}){let r,e=null,o;async function g(){e||(o||(o=await import("@cedarjs/vite")),e=await _({mode:"production",optimizeDeps:{noDiscovery:!0,include:void 0},server:{hmr:!1,watch:null},environments:{nodeRunnerEnv:{}},resolve:{alias:[{find:/^api\//,replacement:l().api.base+"/"},{find:/^src\//,replacement:"src/",customResolver:(a,p,u)=>{let y=v(l().api.base);if(p?.startsWith(y)){let D=v(l().api.src),b=a.replace("src",D);return{id:V(b)}}return null}}]},plugins:[o.cedarCjsCompatPlugin(),o.cedarjsResolveCedarStyleImportsPlugin(),o.cedarImportDirPlugin(),o.cedarAutoImportsPlugin()]}));let i=e.environments.nodeRunnerEnv;if(!i||!L(i))throw new Error("Vite environment is not runnable.");return i.runner}if(t){if(!d.existsSync(n)){console.warn(`Can't find api dist at ${n}. You may need to build first: yarn cedar build api`),process.exitCode=1;return}let i=m.join(n,"lib"),a=m.join(i,"db.js");if(!d.existsSync(a)){console.error(`Can't find db.js at ${a}. CedarJS expects the db.js file to be in the ${i} directory`),process.exitCode=1;return}r=(await import(a)).db}else{let i=O(m.join(l().api.lib,"db"));if(!i){console.error(`Can't find your db file in ${l().api.lib}`),process.exitCode=1;return}try{r=(await(await g()).import(i)).db}catch(a){throw await e?.close(),a}}let s=await B(r);if(!s.length){console.info(f.success(`
3
+ ${W}
4
+ `)),process.exitCode=0,await e?.close();return}let c={run:0,skipped:0,error:0},C=s.map(i=>{let a=m.basename(i.path,".js");return{title:a,skip(){return c.error>0?(c.skipped++,!0):!1},async task(){try{let{startedAt:p,finishedAt:u}=await A(r,i.path);c.run++,await F(r,{version:i.version,name:a,startedAt:p,finishedAt:u})}catch(p){c.error++;let u=p instanceof Error?p.message:String(p);console.error(f.error(`Error in data migration: ${u}`))}}}}),E=new k(C,{renderer:"verbose"});try{await E.run(),await r.$disconnect(),console.log(),w(c),console.log(),c.error&&(process.exitCode=1)}catch{process.exitCode=1,await r.$disconnect(),console.log(),w(c),console.log()}finally{e&&await e.close()}async function A(i,a){let y=(await(await g()).import(a)).default,D=new Date;return await y({db:i}),{startedAt:D,finishedAt:new Date}}}async function B(t){let n=await N(l().api.prismaConfig);if(!d.existsSync(n))return[];let r=d.readdirSync(n).filter(s=>["js",".ts"].some(c=>s.endsWith(c))).map(s=>{let[c]=s.split("-");return{version:c,path:m.join(n,s)}}),o=(await t.rW_DataMigration.findMany({orderBy:{version:"asc"}})).map(s=>s.version.toString());return r.filter(({version:s})=>!o.includes(s)).sort(U)}function U(t,n){let r=parseInt(t.version),e=parseInt(n.version);return r>e?1:r<e?-1:0}async function F(t,{version:n,name:r,startedAt:e,finishedAt:o}){await t.rW_DataMigration.create({data:{version:n,name:r,startedAt:e,finishedAt:o}})}function w(t){t.run&&console.info(f.success(`${t.run} data migration(s) completed successfully.`)),t.error&&console.error(f.error(`${t.error} data migration(s) exited with errors.`)),t.skipped&&console.warn(f.warning(`${t.skipped} data migration(s) skipped due to previous error.`))}var W,j=I(()=>{"use strict";W="No pending data migrations run, already up-to-date."});import S from"path";import{config as G}from"dotenv-defaults";import{hideBin as J}from"yargs/helpers";import T from"yargs/yargs";import{getPaths as P}from"@cedarjs/project-config";import{terminalLink as $}from"termi-link";import{getPaths as R}from"@cedarjs/project-config";var h="Run any outstanding Data Migrations against the database";function M(t){return t.option("import-db-client-from-dist",{type:"boolean",alias:["db-from-dist"],description:"Import the db client from dist",default:!1}).option("dist-path",{type:"string",alias:"d",description:"Path to the api dist directory",default:R().api.dist}).epilogue(`Also see the ${$("CedarJS CLI Reference","https://cedarjs.com/docs/cli-commands#datamigrate-up")}`)}j();process.env.CEDAR_ENV_FILES_LOADED||(G({path:S.join(P().base,".env"),defaults:S.join(P().base,".env.defaults"),multiline:!0}),process.env.CEDAR_ENV_FILES_LOADED="true");T(J(process.argv)).scriptName("data-migrate").command("$0",h,M,x).parse();
@@ -2,7 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import execa from "execa";
4
4
  import { Listr } from "listr2";
5
- import { colors as c } from "@cedarjs/cli-helpers";
5
+ import { colors as c } from "@cedarjs/cli-helpers/colors";
6
6
  import {
7
7
  getPaths,
8
8
  getSchemaPath,
@@ -1 +1 @@
1
- {"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../../src/commands/up.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAIjC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAEvD,eAAO,MAAM,OAAO,OAAO,CAAA;AAC3B,eAAO,MAAM,WAAW,6DACoC,CAAA;AAE5D,wBAAgB,OAAO,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAoBzC;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ1E"}
1
+ {"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../../src/commands/up.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAIjC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAEvD,eAAO,MAAM,OAAO,OAAO,CAAA;AAC3B,eAAO,MAAM,WAAW,6DACoC,CAAA;AAE5D,wBAAgB,OAAO,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAoBzC;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1E"}
@@ -1,5 +1,5 @@
1
1
  import { terminalLink } from "termi-link";
2
- import { getPaths, projectIsEsm } from "@cedarjs/project-config";
2
+ import { getPaths } from "@cedarjs/project-config";
3
3
  const command = "up";
4
4
  const description = "Run any outstanding Data Migrations against the database";
5
5
  function builder(yargs) {
@@ -21,13 +21,8 @@ function builder(yargs) {
21
21
  );
22
22
  }
23
23
  async function handler(options) {
24
- if (projectIsEsm()) {
25
- const { handler: dataMigrateUpHandler } = await import("./upHandlerEsm.js");
26
- await dataMigrateUpHandler(options);
27
- } else {
28
- const { handler: dataMigrateUpHandler } = await import("./upHandler.js");
29
- await dataMigrateUpHandler(options);
30
- }
24
+ const { handler: dataMigrateUpHandler } = await import("./upHandler.js");
25
+ await dataMigrateUpHandler(options);
31
26
  }
32
27
  export {
33
28
  builder,
@@ -1 +1 @@
1
- {"version":3,"file":"upHandler.d.ts","sourceRoot":"","sources":["../../src/commands/upHandler.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,oBAAoB,EAAiB,MAAM,aAAa,CAAA;AA2BtE,wBAAsB,OAAO,CAAC,EAC5B,sBAAsB,EACtB,QAAQ,GACT,EAAE,oBAAoB,iBA2GtB;AA8ED,eAAO,MAAM,6BAA6B,wDACa,CAAA"}
1
+ {"version":3,"file":"upHandler.d.ts","sourceRoot":"","sources":["../../src/commands/upHandler.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAiB,MAAM,aAAa,CAAA;AAsCtE,wBAAsB,OAAO,CAAC,EAC5B,sBAAsB,EACtB,QAAQ,GACT,EAAE,oBAAoB,iBAoMtB;AA6DD,eAAO,MAAM,6BAA6B,wDACa,CAAA"}
@@ -1,17 +1,97 @@
1
1
  import fs from "node:fs";
2
- import { createRequire } from "node:module";
3
2
  import path from "node:path";
4
3
  import { Listr } from "listr2";
5
- import { registerApiSideBabelHook } from "@cedarjs/babel-config";
6
- import { colors as c } from "@cedarjs/cli-helpers";
7
- import { getPaths, getDataMigrationsPath } from "@cedarjs/project-config";
8
- const require2 = createRequire(import.meta.url);
4
+ import { createServer, isRunnableDevEnvironment } from "vite";
5
+ import { colors as c } from "@cedarjs/cli-helpers/colors";
6
+ import {
7
+ getPaths,
8
+ getDataMigrationsPath,
9
+ resolveFile,
10
+ importStatementPath
11
+ } from "@cedarjs/project-config";
12
+ function resolveId(id) {
13
+ if (fs.existsSync(id) && fs.statSync(id).isFile()) {
14
+ return id;
15
+ }
16
+ const withoutExt = /\.jsx?$/.test(id) ? id.replace(/\.jsx?$/, "") : id;
17
+ for (const ext of [".ts", ".tsx", ".js", ".jsx"]) {
18
+ if (fs.existsSync(withoutExt + ext)) {
19
+ return withoutExt + ext;
20
+ }
21
+ }
22
+ if (fs.existsSync(id) && fs.statSync(id).isDirectory()) {
23
+ for (const base of ["index", path.basename(id)]) {
24
+ for (const ext of [".ts", ".tsx", ".js", ".jsx"]) {
25
+ const candidate = path.join(id, base + ext);
26
+ if (fs.existsSync(candidate)) {
27
+ return candidate;
28
+ }
29
+ }
30
+ }
31
+ }
32
+ return id;
33
+ }
9
34
  async function handler({
10
35
  importDbClientFromDist,
11
36
  distPath
12
37
  }) {
13
38
  let db;
14
- let requireHookRegistered = false;
39
+ let server = null;
40
+ let cedarPlugins;
41
+ async function getRunner() {
42
+ if (!server) {
43
+ if (!cedarPlugins) {
44
+ const mod = await import("@cedarjs/vite");
45
+ cedarPlugins = mod;
46
+ }
47
+ server = await createServer({
48
+ mode: "production",
49
+ optimizeDeps: {
50
+ noDiscovery: true,
51
+ include: void 0
52
+ },
53
+ server: {
54
+ hmr: false,
55
+ watch: null
56
+ },
57
+ environments: {
58
+ nodeRunnerEnv: {}
59
+ },
60
+ resolve: {
61
+ alias: [
62
+ {
63
+ find: /^api\//,
64
+ replacement: getPaths().api.base + "/"
65
+ },
66
+ {
67
+ find: /^src\//,
68
+ replacement: "src/",
69
+ customResolver: (id, importer, _options) => {
70
+ const apiImportBase = importStatementPath(getPaths().api.base);
71
+ if (importer?.startsWith(apiImportBase)) {
72
+ const apiImportSrc = importStatementPath(getPaths().api.src);
73
+ const apiId = id.replace("src", apiImportSrc);
74
+ return { id: resolveId(apiId) };
75
+ }
76
+ return null;
77
+ }
78
+ }
79
+ ]
80
+ },
81
+ plugins: [
82
+ cedarPlugins.cedarCjsCompatPlugin(),
83
+ cedarPlugins.cedarjsResolveCedarStyleImportsPlugin(),
84
+ cedarPlugins.cedarImportDirPlugin(),
85
+ cedarPlugins.cedarAutoImportsPlugin()
86
+ ]
87
+ });
88
+ }
89
+ const env = server.environments.nodeRunnerEnv;
90
+ if (!env || !isRunnableDevEnvironment(env)) {
91
+ throw new Error("Vite environment is not runnable.");
92
+ }
93
+ return env.runner;
94
+ }
15
95
  if (importDbClientFromDist) {
16
96
  if (!fs.existsSync(distPath)) {
17
97
  console.warn(
@@ -31,9 +111,20 @@ async function handler({
31
111
  }
32
112
  db = (await import(distLibDbPath)).db;
33
113
  } else {
34
- registerApiSideBabelHook();
35
- requireHookRegistered = true;
36
- db = require2(path.join(getPaths().api.lib, "db")).db;
114
+ const dbPath = resolveFile(path.join(getPaths().api.lib, "db"));
115
+ if (!dbPath) {
116
+ console.error(`Can't find your db file in ${getPaths().api.lib}`);
117
+ process.exitCode = 1;
118
+ return;
119
+ }
120
+ try {
121
+ const runner = await getRunner();
122
+ const dbModule = await runner.import(dbPath);
123
+ db = dbModule.db;
124
+ } catch (e) {
125
+ await server?.close();
126
+ throw e;
127
+ }
37
128
  }
38
129
  const pendingDataMigrations = await getPendingDataMigrations(db);
39
130
  if (!pendingDataMigrations.length) {
@@ -41,6 +132,7 @@ async function handler({
41
132
  ${NO_PENDING_MIGRATIONS_MESSAGE}
42
133
  `));
43
134
  process.exitCode = 0;
135
+ await server?.close();
44
136
  return;
45
137
  }
46
138
  const counters = { run: 0, skipped: 0, error: 0 };
@@ -57,9 +149,6 @@ ${NO_PENDING_MIGRATIONS_MESSAGE}
57
149
  }
58
150
  },
59
151
  async task() {
60
- if (!requireHookRegistered) {
61
- registerApiSideBabelHook();
62
- }
63
152
  try {
64
153
  const { startedAt, finishedAt } = await runDataMigration(
65
154
  db,
@@ -74,9 +163,8 @@ ${NO_PENDING_MIGRATIONS_MESSAGE}
74
163
  });
75
164
  } catch (e) {
76
165
  counters.error++;
77
- console.error(
78
- c.error(`Error in data migration: ${e.message}`)
79
- );
166
+ const message = e instanceof Error ? e.message : String(e);
167
+ console.error(c.error(`Error in data migration: ${message}`));
80
168
  }
81
169
  }
82
170
  };
@@ -99,6 +187,19 @@ ${NO_PENDING_MIGRATIONS_MESSAGE}
99
187
  console.log();
100
188
  reportDataMigrations(counters);
101
189
  console.log();
190
+ } finally {
191
+ if (server) {
192
+ await server.close();
193
+ }
194
+ }
195
+ async function runDataMigration(db2, dataMigrationPath) {
196
+ const runner = await getRunner();
197
+ const dataMigrationModule = await runner.import(dataMigrationPath);
198
+ const dataMigration = dataMigrationModule.default;
199
+ const startedAt = /* @__PURE__ */ new Date();
200
+ await dataMigration({ db: db2 });
201
+ const finishedAt = /* @__PURE__ */ new Date();
202
+ return { startedAt, finishedAt };
102
203
  }
103
204
  }
104
205
  async function getPendingDataMigrations(db) {
@@ -143,13 +244,6 @@ function sortDataMigrationsByVersion(dataMigrationA, dataMigrationB) {
143
244
  }
144
245
  return 0;
145
246
  }
146
- async function runDataMigration(db, dataMigrationPath) {
147
- const dataMigration = require2(dataMigrationPath);
148
- const startedAt = /* @__PURE__ */ new Date();
149
- await dataMigration.default({ db });
150
- const finishedAt = /* @__PURE__ */ new Date();
151
- return { startedAt, finishedAt };
152
- }
153
247
  const NO_PENDING_MIGRATIONS_MESSAGE = "No pending data migrations run, already up-to-date.";
154
248
  async function recordDataMigration(db, { version, name, startedAt, finishedAt }) {
155
249
  await db.rW_DataMigration.create({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/cli-data-migrate",
3
- "version": "7.0.0",
3
+ "version": "8.0.0-canary.3263",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/cedarjs/cedar.git",
@@ -26,10 +26,9 @@
26
26
  "test:unit": "vitest run src"
27
27
  },
28
28
  "dependencies": {
29
- "@cedarjs/babel-config": "7.0.0",
30
- "@cedarjs/cli-helpers": "7.0.0",
31
- "@cedarjs/project-config": "7.0.0",
32
- "@cedarjs/vite": "7.0.0",
29
+ "@cedarjs/cli-helpers": "8.0.0-canary.3263",
30
+ "@cedarjs/project-config": "8.0.0-canary.3263",
31
+ "@cedarjs/vite": "8.0.0-canary.3263",
33
32
  "dotenv-defaults": "5.0.2",
34
33
  "execa": "5.1.1",
35
34
  "listr2": "10.2.2",
@@ -38,10 +37,10 @@
38
37
  "yargs": "17.7.3"
39
38
  },
40
39
  "devDependencies": {
41
- "@cedarjs/framework-tools": "7.0.0",
42
- "@prisma/client": "7.8.0",
40
+ "@cedarjs/framework-tools": "8.0.0-canary.3263",
41
+ "@prisma/client": "7.10.0",
43
42
  "@types/yargs": "17.0.35",
44
- "memfs": "4.78.1",
43
+ "memfs": "4.79.0",
45
44
  "typescript": "5.9.3",
46
45
  "vitest": "4.1.11"
47
46
  },
@@ -1,4 +0,0 @@
1
- import type { DataMigrateUpOptions } from '../types.js';
2
- export declare function handler({ importDbClientFromDist, distPath, }: DataMigrateUpOptions): Promise<void>;
3
- export declare const NO_PENDING_MIGRATIONS_MESSAGE = "No pending data migrations run, already up-to-date.";
4
- //# sourceMappingURL=upHandlerEsm.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"upHandlerEsm.d.ts","sourceRoot":"","sources":["../../src/commands/upHandlerEsm.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAiB,MAAM,aAAa,CAAA;AAsCtE,wBAAsB,OAAO,CAAC,EAC5B,sBAAsB,EACtB,QAAQ,GACT,EAAE,oBAAoB,iBAoMtB;AA6DD,eAAO,MAAM,6BAA6B,wDACa,CAAA"}
@@ -1,275 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { Listr } from "listr2";
4
- import { createServer, isRunnableDevEnvironment } from "vite";
5
- import { colors as c } from "@cedarjs/cli-helpers";
6
- import {
7
- getPaths,
8
- getDataMigrationsPath,
9
- resolveFile,
10
- importStatementPath
11
- } from "@cedarjs/project-config";
12
- function resolveId(id) {
13
- if (fs.existsSync(id) && fs.statSync(id).isFile()) {
14
- return id;
15
- }
16
- const withoutExt = /\.jsx?$/.test(id) ? id.replace(/\.jsx?$/, "") : id;
17
- for (const ext of [".ts", ".tsx", ".js", ".jsx"]) {
18
- if (fs.existsSync(withoutExt + ext)) {
19
- return withoutExt + ext;
20
- }
21
- }
22
- if (fs.existsSync(id) && fs.statSync(id).isDirectory()) {
23
- for (const base of ["index", path.basename(id)]) {
24
- for (const ext of [".ts", ".tsx", ".js", ".jsx"]) {
25
- const candidate = path.join(id, base + ext);
26
- if (fs.existsSync(candidate)) {
27
- return candidate;
28
- }
29
- }
30
- }
31
- }
32
- return id;
33
- }
34
- async function handler({
35
- importDbClientFromDist,
36
- distPath
37
- }) {
38
- let db;
39
- let server = null;
40
- let cedarPlugins;
41
- async function getRunner() {
42
- if (!server) {
43
- if (!cedarPlugins) {
44
- const mod = await import("@cedarjs/vite");
45
- cedarPlugins = mod;
46
- }
47
- server = await createServer({
48
- mode: "production",
49
- optimizeDeps: {
50
- noDiscovery: true,
51
- include: void 0
52
- },
53
- server: {
54
- hmr: false,
55
- watch: null
56
- },
57
- environments: {
58
- nodeRunnerEnv: {}
59
- },
60
- resolve: {
61
- alias: [
62
- {
63
- find: /^api\//,
64
- replacement: getPaths().api.base + "/"
65
- },
66
- {
67
- find: /^src\//,
68
- replacement: "src/",
69
- customResolver: (id, importer, _options) => {
70
- const apiImportBase = importStatementPath(getPaths().api.base);
71
- if (importer?.startsWith(apiImportBase)) {
72
- const apiImportSrc = importStatementPath(getPaths().api.src);
73
- const apiId = id.replace("src", apiImportSrc);
74
- return { id: resolveId(apiId) };
75
- }
76
- return null;
77
- }
78
- }
79
- ]
80
- },
81
- plugins: [
82
- cedarPlugins.cedarCjsCompatPlugin(),
83
- cedarPlugins.cedarjsResolveCedarStyleImportsPlugin(),
84
- cedarPlugins.cedarImportDirPlugin(),
85
- cedarPlugins.cedarAutoImportsPlugin()
86
- ]
87
- });
88
- }
89
- const env = server.environments.nodeRunnerEnv;
90
- if (!env || !isRunnableDevEnvironment(env)) {
91
- throw new Error("Vite environment is not runnable.");
92
- }
93
- return env.runner;
94
- }
95
- if (importDbClientFromDist) {
96
- if (!fs.existsSync(distPath)) {
97
- console.warn(
98
- `Can't find api dist at ${distPath}. You may need to build first: yarn cedar build api`
99
- );
100
- process.exitCode = 1;
101
- return;
102
- }
103
- const distLibPath = path.join(distPath, "lib");
104
- const distLibDbPath = path.join(distLibPath, "db.js");
105
- if (!fs.existsSync(distLibDbPath)) {
106
- console.error(
107
- `Can't find db.js at ${distLibDbPath}. CedarJS expects the db.js file to be in the ${distLibPath} directory`
108
- );
109
- process.exitCode = 1;
110
- return;
111
- }
112
- db = (await import(distLibDbPath)).db;
113
- } else {
114
- const dbPath = resolveFile(path.join(getPaths().api.lib, "db"));
115
- if (!dbPath) {
116
- console.error(`Can't find your db file in ${getPaths().api.lib}`);
117
- process.exitCode = 1;
118
- return;
119
- }
120
- try {
121
- const runner = await getRunner();
122
- const dbModule = await runner.import(dbPath);
123
- db = dbModule.db;
124
- } catch (e) {
125
- await server?.close();
126
- throw e;
127
- }
128
- }
129
- const pendingDataMigrations = await getPendingDataMigrations(db);
130
- if (!pendingDataMigrations.length) {
131
- console.info(c.success(`
132
- ${NO_PENDING_MIGRATIONS_MESSAGE}
133
- `));
134
- process.exitCode = 0;
135
- await server?.close();
136
- return;
137
- }
138
- const counters = { run: 0, skipped: 0, error: 0 };
139
- const dataMigrationTasks = pendingDataMigrations.map((dataMigration) => {
140
- const dataMigrationName = path.basename(dataMigration.path, ".js");
141
- return {
142
- title: dataMigrationName,
143
- skip() {
144
- if (counters.error > 0) {
145
- counters.skipped++;
146
- return true;
147
- } else {
148
- return false;
149
- }
150
- },
151
- async task() {
152
- try {
153
- const { startedAt, finishedAt } = await runDataMigration(
154
- db,
155
- dataMigration.path
156
- );
157
- counters.run++;
158
- await recordDataMigration(db, {
159
- version: dataMigration.version,
160
- name: dataMigrationName,
161
- startedAt,
162
- finishedAt
163
- });
164
- } catch (e) {
165
- counters.error++;
166
- const message = e instanceof Error ? e.message : String(e);
167
- console.error(c.error(`Error in data migration: ${message}`));
168
- }
169
- }
170
- };
171
- });
172
- const tasks = new Listr(dataMigrationTasks, {
173
- renderer: "verbose"
174
- });
175
- try {
176
- await tasks.run();
177
- await db.$disconnect();
178
- console.log();
179
- reportDataMigrations(counters);
180
- console.log();
181
- if (counters.error) {
182
- process.exitCode = 1;
183
- }
184
- } catch {
185
- process.exitCode = 1;
186
- await db.$disconnect();
187
- console.log();
188
- reportDataMigrations(counters);
189
- console.log();
190
- } finally {
191
- if (server) {
192
- await server.close();
193
- }
194
- }
195
- async function runDataMigration(db2, dataMigrationPath) {
196
- const runner = await getRunner();
197
- const dataMigrationModule = await runner.import(dataMigrationPath);
198
- const dataMigration = dataMigrationModule.default;
199
- const startedAt = /* @__PURE__ */ new Date();
200
- await dataMigration({ db: db2 });
201
- const finishedAt = /* @__PURE__ */ new Date();
202
- return { startedAt, finishedAt };
203
- }
204
- }
205
- async function getPendingDataMigrations(db) {
206
- const dataMigrationsPath = await getDataMigrationsPath(
207
- getPaths().api.prismaConfig
208
- );
209
- if (!fs.existsSync(dataMigrationsPath)) {
210
- return [];
211
- }
212
- const dataMigrations = fs.readdirSync(dataMigrationsPath).filter(
213
- (dataMigrationFileName) => ["js", ".ts"].some(
214
- (extension) => dataMigrationFileName.endsWith(extension)
215
- )
216
- ).map((dataMigrationFileName) => {
217
- const [version] = dataMigrationFileName.split("-");
218
- return {
219
- version,
220
- path: path.join(dataMigrationsPath, dataMigrationFileName)
221
- };
222
- });
223
- const ranDataMigrations = await db.rW_DataMigration.findMany(
224
- {
225
- orderBy: { version: "asc" }
226
- }
227
- );
228
- const ranDataMigrationVersions = ranDataMigrations.map(
229
- (dataMigration) => dataMigration.version.toString()
230
- );
231
- const pendingDataMigrations = dataMigrations.filter(({ version }) => {
232
- return !ranDataMigrationVersions.includes(version);
233
- }).sort(sortDataMigrationsByVersion);
234
- return pendingDataMigrations;
235
- }
236
- function sortDataMigrationsByVersion(dataMigrationA, dataMigrationB) {
237
- const aVersion = parseInt(dataMigrationA.version);
238
- const bVersion = parseInt(dataMigrationB.version);
239
- if (aVersion > bVersion) {
240
- return 1;
241
- }
242
- if (aVersion < bVersion) {
243
- return -1;
244
- }
245
- return 0;
246
- }
247
- const NO_PENDING_MIGRATIONS_MESSAGE = "No pending data migrations run, already up-to-date.";
248
- async function recordDataMigration(db, { version, name, startedAt, finishedAt }) {
249
- await db.rW_DataMigration.create({
250
- data: { version, name, startedAt, finishedAt }
251
- });
252
- }
253
- function reportDataMigrations(counters) {
254
- if (counters.run) {
255
- console.info(
256
- c.success(`${counters.run} data migration(s) completed successfully.`)
257
- );
258
- }
259
- if (counters.error) {
260
- console.error(
261
- c.error(`${counters.error} data migration(s) exited with errors.`)
262
- );
263
- }
264
- if (counters.skipped) {
265
- console.warn(
266
- c.warning(
267
- `${counters.skipped} data migration(s) skipped due to previous error.`
268
- )
269
- );
270
- }
271
- }
272
- export {
273
- NO_PENDING_MIGRATIONS_MESSAGE,
274
- handler
275
- };