UNPKG

@calljmp/cli

Version:
10 lines (9 loc) 6.14 kB
"use strict";var A=Object.create;var u=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var R=(n,r)=>{for(var o in r)u(n,o,{get:r[o],enumerable:!0})},T=(n,r,o,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of k(r))!M.call(n,i)&&i!==o&&u(n,i,{get:()=>r[i],enumerable:!(a=I(r,i))||a.enumerable});return n};var f=(n,r,o)=>(o=n!=null?A(S(n)):{},T(r||!n||!n.__esModule?u(o,"default",{value:n,enumerable:!0}):o,n)),U=n=>T(u({},"__esModule",{value:!0}),n);var C={};R(C,{MIGRATION_TABLE:()=>L,collectMigrations:()=>j,dataToInsertStatements:()=>q,migrateLocal:()=>F,migrateRemote:()=>O});module.exports=U(C);var h=f(require("ora")),t=f(require("chalk")),$=f(require("enquirer")),y=f(require("fs/promises")),v=f(require("path")),w=f(require("crypto")),m=f(require("../../logger")),x=f(require("../../server")),E=f(require("../../sql")),N=require("../../database");const L="_calljmp_migrations";async function j(n){const r=/^(\d+)[-_]([a-zA-Z0-9-_]+)\.sql$/,o=await y.default.readdir(n.migrations).catch(()=>[]).then(a=>a.map(i=>{const e=i.match(r);return e?{file:v.default.join(n.migrations,i),version:parseInt(e[1],10),name:e[2]}:null}).filter(i=>i!==null));return o.sort((a,i)=>a.version-i.version),o}async function O(n,r,o){(!n.accessToken||!n.projectId)&&(m.default.error(t.default.red("Project is not linked. Please run `setup` command first.")),process.exit(1));const a=new N.Database({baseUrl:n.baseUrl,accessToken:n.accessToken,projectId:n.projectId}),i=await a.query(`SELECT * FROM ${r}`).catch(()=>({rows:[]})).then(({rows:l})=>l.map(s=>({name:s.name,hash:s.hash,version:s.version}))),e=async l=>{const s=l.map(g=>g.trim().endsWith(";")?g:g+";").join(` `),c=w.default.createHash("md5").update(s).digest("hex"),d=await a.migrate({etag:c});let p=d;for(!d.completed&&d.uploadUrl&&d.filename&&(p=await a.ingest({etag:c,file:new Blob([s],{type:"text/plain"}),filename:d.filename,uploadUrl:d.uploadUrl}));!p.completed;){if(!p.bookmark)throw new Error("Migration bookmark is missing. Please check the migration status.");const g=await a.migrationStatus({bookmark:p.bookmark});p.completed=g.completed}};m.default.info(t.default.yellow("WARNING: You are about to apply migrations to the remote database.")),m.default.info(t.default.yellow("This operation may modify the production database.")),m.default.info(""),await b(r,i,o,e)}async function F(n,r,o){const a=await x.create({database:n.data});try{await a.ready;const i=await a.getD1Database("DATABASE"),e=await i.prepare(`SELECT * FROM ${r}`).all().catch(()=>({results:[]})).then(({results:s})=>s.map(c=>({name:c.name,hash:c.hash,version:c.version})));await b(r,e,o,async s=>{await i.batch(s.map(c=>i.prepare(c)))})}catch(i){i instanceof Error?m.default.error(i):m.default.error(t.default.red("Unknown error occurred!")),process.exit(1)}finally{await a.dispose()}}async function b(n,r,o,a){m.default.info("Migration status:"),m.default.info(t.default.dim("\u250C"+"\u2500".repeat(18)+"\u252C"+"\u2500".repeat(32)+"\u252C"+"\u2500".repeat(17)+"\u252C"+"\u2500".repeat(17)+"\u2510")),m.default.info(t.default.dim("\u2502 ")+t.default.bold("Version".padEnd(16))+t.default.dim(" \u2502 ")+t.default.bold("Name".padEnd(30))+t.default.dim(" \u2502 ")+t.default.bold("Status".padEnd(15))+t.default.dim(" \u2502 ")+t.default.bold("Action".padEnd(15))+t.default.dim(" \u2502")),m.default.info(t.default.dim("\u251C"+"\u2500".repeat(18)+"\u253C"+"\u2500".repeat(32)+"\u253C"+"\u2500".repeat(17)+"\u253C"+"\u2500".repeat(17)+"\u2524"));for(const e of o){const l=r.some(c=>c.name===e.name),s=!l;m.default.info(t.default.dim("\u2502 ")+String(e.version).padEnd(16)+t.default.dim(" \u2502 ")+e.name.padEnd(30)+t.default.dim(" \u2502 ")+(l?t.default.green("Applied".padEnd(15)):t.default.gray("Not applied".padEnd(15)))+t.default.dim(" \u2502 ")+(s?t.default.yellow("Will apply".padEnd(15)):t.default.gray("No action".padEnd(15)))+t.default.dim(" \u2502"))}m.default.info(t.default.dim("\u2514"+"\u2500".repeat(18)+"\u2534"+"\u2500".repeat(32)+"\u2534"+"\u2500".repeat(17)+"\u2534"+"\u2500".repeat(17)+"\u2518")),m.default.info(t.default.dim(`Applied migrations: ${r.length}/${o.length}`));const i=o.filter(e=>!r.some(l=>l.name===e.name));if(i.length>0){const{confirm:e}=await $.default.prompt({type:"confirm",name:"confirm",message:`Do you want to apply ${i.length} migration${i.length>1?"s":""}?`,initial:!0});if(!e){m.default.info(t.default.yellow("Aborting migration."));return}}if(i.length>0){const e=(0,h.default)(t.default.yellow("Preparing migrations...")).start();try{const l=` CREATE TABLE IF NOT EXISTS ${n} ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, version INTEGER NOT NULL, hash TEXT NOT NULL ); `;await a([l])}finally{e.stop()}}for(const e of o){const l=(0,E.default)(await y.default.readFile(e.file,"utf-8")).filter(p=>p.trim()!=="").join(";"),s=await w.default.subtle.digest("SHA-256",Buffer.from(l,"utf-8")).then(p=>Buffer.from(p).toString("hex")),c=r.find(p=>p.name===e.name);if(c){if(c.hash!=s){m.default.error(t.default.red(`Migration ${e.version} (${e.name}) has been modified. Please revert the changes or create a new migration.`));continue}m.default.info(t.default.gray(`\u2713 ${e.version}: ${e.name}`));continue}const d=(0,h.default)(t.default.yellow(`Applying migration ${e.version}: ${e.name}...`)).start();try{const p=[l,`INSERT INTO ${n} (name, version, hash) VALUES ('${e.name}', ${e.version}, '${s}')`].join(";"),g=(0,E.default)(p);await a(g),d.stop(),m.default.info(t.default.green(`\u2713 ${e.version}: ${e.name}`))}catch(p){throw d.stop(),m.default.error(t.default.red(`\u2717 ${e.version}: ${e.name}`)),p}}}function q(n,r){if(r.length===0)return[];const o=Object.keys(r[0]);return r.map(i=>{const e=o.map(l=>{const s=i[l];return typeof s=="string"?`'${s.replace(/'/g,"''")}'`:String(s)});return`INSERT INTO ${n} (${o.join(", ")}) VALUES (${e.join(", ")});`})}0&&(module.exports={MIGRATION_TABLE,collectMigrations,dataToInsertStatements,migrateLocal,migrateRemote});