@aurios/mizzling 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +15 -0
- package/LICENSE +21 -0
- package/dist/chunk-DKDRM5WU.js +2 -0
- package/dist/cli.js +3 -3
- package/dist/index.js +1 -1
- package/package.json +38 -19
- package/src/cli.ts +26 -29
- package/src/commands/drop.ts +51 -51
- package/src/commands/generate.ts +88 -83
- package/src/commands/init.ts +1 -1
- package/src/commands/list.ts +39 -37
- package/src/commands/push.ts +54 -54
- package/src/config.ts +14 -14
- package/src/discovery.ts +33 -25
- package/test/config-expansion.test.ts +164 -0
- package/test/config.test.ts +72 -0
- package/test/define-config-integration.test.ts +49 -0
- package/test/discovery.test.ts +117 -0
- package/test/drop.test.ts +145 -0
- package/test/e2e-env.test.ts +87 -0
- package/test/e2e.test.ts +135 -0
- package/test/generate.test.ts +116 -0
- package/test/init-command.test.ts +78 -0
- package/test/init.test.ts +22 -0
- package/test/interactive.test.ts +96 -0
- package/test/list.test.ts +58 -0
- package/test/mizzling-exports.test.ts +18 -0
- package/test/push.test.ts +88 -0
- package/tsconfig.json +33 -11
- package/tsup.config.ts +5 -5
- package/vitest.config.ts +8 -0
- package/CHANGELOG.md +0 -45
- package/dist/chunk-SNI5EXF5.js +0 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
> @aurios/mizzling@1.1.2 build /home/runner/work/mizzle/mizzle/packages/mizzling
|
|
3
|
+
> tsup
|
|
4
|
+
|
|
5
|
+
[34mCLI[39m Building entry: src/cli.ts, src/index.ts
|
|
6
|
+
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
|
+
[34mCLI[39m tsup v8.5.1
|
|
8
|
+
[34mCLI[39m Using tsup config: /home/runner/work/mizzle/mizzle/packages/mizzling/tsup.config.ts
|
|
9
|
+
[34mCLI[39m Target: esnext
|
|
10
|
+
[34mCLI[39m Cleaning output folder
|
|
11
|
+
[34mESM[39m Build start
|
|
12
|
+
[32mESM[39m [1mdist/cli.js [22m[32m13.77 KB[39m
|
|
13
|
+
[32mESM[39m [1mdist/index.js [22m[32m87.00 B[39m
|
|
14
|
+
[32mESM[39m [1mdist/chunk-DKDRM5WU.js [22m[32m1.79 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 37ms
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lucas A. Ouverney
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{join as s}from"path";import{existsSync as c}from"fs";import{DynamoDBClient as a}from"@aws-sdk/client-dynamodb";import{fromIni as p}from"@aws-sdk/credential-provider-ini";import{NodeHttpHandler as f}from"@smithy/node-http-handler";import l from"http";import m from"https";function v(e){return e}function M(e){let i={keepAlive:!0,maxSockets:1/0},t={region:e.region||"us-east-1",endpoint:e.endpoint,maxAttempts:e.maxAttempts,requestHandler:new f({httpAgent:new l.Agent(i),httpsAgent:new m.Agent(i)})};return e.credentials?t.credentials=e.credentials:e.profile?t.credentials=p({profile:e.profile}):e.endpoint&&(e.endpoint.includes("localhost")||e.endpoint.includes("127.0.0.1"))&&(t.credentials={accessKeyId:"local",secretAccessKey:"local"}),new a(t)}async function h(e="mizzle.config.ts"){let t=process.env.MIZZLE_CONFIG||s(process.cwd(),e);if(!c(t))throw new Error(`Could not find ${e} in current directory.`);try{let n=await import(t),o=n.default||n;if(!o||typeof o!="object")throw new Error("Invalid config: default export must be an object");if(!o.schema)throw new Error("Invalid config: missing 'schema' path");if(!o.out)throw new Error("Invalid config: missing 'out' directory");let r={...o};return process.env.MIZZLE_REGION&&(r.region=process.env.MIZZLE_REGION),process.env.MIZZLE_ENDPOINT&&(r.endpoint=process.env.MIZZLE_ENDPOINT),process.env.MIZZLE_SCHEMA&&(r.schema=process.env.MIZZLE_SCHEMA),process.env.MIZZLE_OUT&&(r.out=process.env.MIZZLE_OUT),process.env.MIZZLE_VERBOSE&&(r.verbose=process.env.MIZZLE_VERBOSE==="true"),process.env.MIZZLE_STRICT&&(r.strict=process.env.MIZZLE_STRICT==="true"),r}catch(n){if(n instanceof Error&&n.message.startsWith("Invalid config"))throw n;let o=n instanceof Error?n.message:String(n);throw new Error(`Failed to load config: ${o}`)}}export{v as a,M as b,h as c};
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{b
|
|
2
|
+
import{b,c as N}from"./chunk-DKDRM5WU.js";import{Command as Qe}from"commander";import*as x from"@clack/prompts";var p={COLUMNS:Symbol.for("mizzle:Columns"),INDEXES:Symbol.for("mizzle:Indexes"),SORT_KEY:Symbol.for("mizzle:SortKey"),TABLE_NAME:Symbol.for("mizzle:TableName"),PARTITION_KEY:Symbol.for("mizzle:PartitionKey")},c={ENTITY_NAME:Symbol.for("mizzle:EntityName"),ENTITY_STRATEGY:Symbol.for("mizzle:EntityStrategy"),PHYSICAL_TABLE:Symbol.for("mizzle:PhysicalTable"),COLUMNS:Symbol.for("mizzle:Columns"),ENTITY_KIND:Symbol.for("mizzle:EntityKind")};var I=class{[p.TABLE_NAME]="";[p.INDEXES]=void 0;[p.PARTITION_KEY]={};[p.SORT_KEY]=void 0;static Symbol=p;constructor(n,t){this[p.TABLE_NAME]=n,this[p.PARTITION_KEY]=t.pk.build(this),this[p.SORT_KEY]=t.sk?t.sk.build(this):void 0,this[p.INDEXES]=t.indexes}},D=class{[c.ENTITY_NAME]="";[c.PHYSICAL_TABLE]={};[c.COLUMNS]={};[c.ENTITY_STRATEGY]={};static Symbol=c;constructor(n,t,o,a){this[c.ENTITY_NAME]=n,this[c.PHYSICAL_TABLE]=t,this[c.COLUMNS]=o,this[c.ENTITY_STRATEGY]=a}};import ue from"fast-glob";import{stat as pe}from"fs/promises";import{resolve as ce}from"path";async function E(e){let n=Array.isArray(e.schema)?e.schema:[e.schema],t=[],o=[],a=new Set,i=async r=>{let l=ce(process.cwd(),r);if(!a.has(l)){a.add(l);try{let s=await import(l);for(let u in s){let m=s[u];!m||typeof m!="object"||(m instanceof I||m[p.TABLE_NAME]!==void 0?t.push(m):(m instanceof D||m[c.ENTITY_NAME]!==void 0)&&o.push(m))}}catch(s){console.warn(`Failed to import schema file: ${l}`,s)}}};for(let r of n){let l=r,s=!1;try{let m=await pe(r);m.isDirectory()?l=`${r}/**/*.{ts,js,tsx,jsx}`:m.isFile()&&(s=!0)}catch{}if(s){await i(r);continue}let u=await ue(l,{absolute:!0});for(let m of u)await i(m)}return{tables:t,entities:o}}import{join as _}from"path";import{writeFile as de,readFile as Te,mkdir as fe,readdir as ye}from"fs/promises";import{existsSync as z}from"fs";var U="snapshot.json";async function j(e,n){z(e)||await fe(e,{recursive:!0});let t=_(e,U);await de(t,JSON.stringify(n,null,2),"utf-8")}async function v(e){let n=_(e,U);if(!z(n))return null;let t=await Te(n,"utf-8");return JSON.parse(t)}function M(e){let n={};for(let t of e.tables){let o=e.entities.filter(i=>i[c.PHYSICAL_TABLE]===t),a=Ce(t,o);n[a.TableName]=a}return{version:"1",tables:n}}async function Y(e){if(!z(e))return"0000";let n=await ye(e),t=-1;for(let o of n){if(!o.endsWith(".ts"))continue;let a=o.match(/^(\d{4})_/);if(a){let i=parseInt(a[1],10);i>t&&(t=i)}}return t===-1?"0000":(t+1).toString().padStart(4,"0")}function Ce(e,n){let t=e[p.TABLE_NAME],o=new Map,a=e[p.PARTITION_KEY];o.set(a.name,a.getDynamoType());let i=e[p.SORT_KEY];i&&o.set(i.name,i.getDynamoType());let r=[{AttributeName:a.name,KeyType:"HASH"}];i&&r.push({AttributeName:i.name,KeyType:"RANGE"});let l=[],s=[],u=e[p.INDEXES]||{};for(let[T,f]of Object.entries(u)){let P=f.type,d=f.config;if(P==="gsi"){if(d.pk){let S=O(d.pk,e,n);o.set(d.pk,S)}if(d.sk){let S=O(d.sk,e,n);o.set(d.sk,S)}let B={IndexName:T,KeySchema:[{AttributeName:d.pk,KeyType:"HASH"}],Projection:{ProjectionType:"ALL"}};d.sk&&B.KeySchema.push({AttributeName:d.sk,KeyType:"RANGE"}),l.push(B)}else if(P==="lsi"){if(d.sk){let S=O(d.sk,e,n);o.set(d.sk,S)}let B={IndexName:T,KeySchema:[{AttributeName:a.name,KeyType:"HASH"},{AttributeName:d.sk,KeyType:"RANGE"}],Projection:{ProjectionType:"ALL"}};s.push(B)}}let m=Array.from(o.entries()).map(([T,f])=>({AttributeName:T,AttributeType:f})).sort((T,f)=>T.AttributeName.localeCompare(f.AttributeName));l.sort((T,f)=>(T.IndexName||"").localeCompare(f.IndexName||"")),s.sort((T,f)=>(T.IndexName||"").localeCompare(f.IndexName||""));let h={TableName:t,AttributeDefinitions:m,KeySchema:r};return l.length>0&&(h.GlobalSecondaryIndexes=l),s.length>0&&(h.LocalSecondaryIndexes=s),h}function O(e,n,t){let o=n[p.PARTITION_KEY];if(o.name===e)return o.getDynamoType();let a=n[p.SORT_KEY];if(a&&a.name===e)return a.getDynamoType();for(let i of t){let r=i[c.COLUMNS];if(r){let l=r[e];if(l)return l.getDynamoType()}}throw new Error(`Could not resolve type for column '${e}' in table '${n[p.TABLE_NAME]}'. Ensure it is defined in an Entity.`)}function A(e,n){let t=[],a=M(e).tables,i=n.tables||{},r=new Set([...Object.keys(a),...Object.keys(i)]);for(let l of r){let s=a[l],u=i[l];s&&!u?t.push({type:"create",table:s}):!s&&u?t.push({type:"delete",tableName:l}):s&&u&&(ge(s,u)||t.push({type:"update",tableName:l,changes:["Changed"]}))}return t}function ge(e,n){let t=o=>{let a={...o};return a.AttributeDefinitions=[...a.AttributeDefinitions||[]].sort((i,r)=>(i.AttributeName||"").localeCompare(r.AttributeName||"")),a.GlobalSecondaryIndexes&&(a.GlobalSecondaryIndexes=[...a.GlobalSecondaryIndexes].sort((i,r)=>(i.IndexName||"").localeCompare(r.IndexName||""))),a.LocalSecondaryIndexes&&(a.LocalSecondaryIndexes=[...a.LocalSecondaryIndexes].sort((i,r)=>(i.IndexName||"").localeCompare(r.IndexName||""))),a};return JSON.stringify(t(e))===JSON.stringify(t(n))}import{join as be}from"path";import{writeFile as xe,mkdir as he}from"fs/promises";import{existsSync as Se}from"fs";import{text as Ne,isCancel as Be,cancel as Ie,intro as De,outro as $}from"@clack/prompts";async function F(e){De("Mizzle Generate");let{config:n}=e,t=e.discoverSchema||E;try{let o=await t(n),a=n.out,i=await v(a)||{version:"0",tables:{}},r=M(o),l=A(o,i);if(l.length===0){$("No changes detected.");return}console.log(`Detected ${l.length} changes.`);let s=await Y(a),u=e.name;if(u||(u=await Ne({message:"Enter migration name",placeholder:"init",initialValue:"migration",validate(f){if(f.length===0)return"Name is required"}})),Be(u)){Ie("Operation cancelled.");return}let m=`${s}_${u}.ts`;Se(a)||await he(a,{recursive:!0});let h=be(a,m),T=Ee(l);await xe(h,T),console.log(`Created migration: ${m}`),await j(a,r),$("Updated snapshot.json")}catch(o){console.error("Error generating migration:",o),process.exit(1)}}function Ee(e){let n=[],t=[];for(let o of e)o.type==="create"?(n.push(`// Create Table: ${o.table.TableName}`),n.push(`await db.createTable("${o.table.TableName}", ${JSON.stringify(o.table,null,2)});
|
|
3
3
|
`),t.unshift(`// Drop Table: ${o.table.TableName}`),t.unshift(`await db.deleteTable("${o.table.TableName}");
|
|
4
4
|
`)):o.type==="delete"?(n.push(`// Drop Table: ${o.tableName}`),n.push(`await db.deleteTable("${o.tableName}");
|
|
5
5
|
`),t.unshift(`// Create Table: ${o.tableName}`),t.unshift(`// TODO: Restore table definition for rollback
|
|
@@ -12,7 +12,7 @@ export async function up(db: Mizzle) {
|
|
|
12
12
|
export async function down(db: Mizzle) {
|
|
13
13
|
${t.join(" ")}
|
|
14
14
|
}
|
|
15
|
-
`}import{existsSync as
|
|
15
|
+
`}import{existsSync as Me,writeFileSync as Ae}from"fs";import{join as ke}from"path";import{intro as we,outro as Ke,text as k,isCancel as w,cancel as K}from"@clack/prompts";async function H(){let e=ke(process.cwd(),"mizzle.config.ts");if(Me(e)){console.log("mizzle.config.ts already exists in the current directory. Aborting.");return}we("Mizzle Initialization");let n=await k({message:"Where is your schema file or directory located?",placeholder:"./src/schema.ts",initialValue:"./src/schema.ts",validate:r=>{if(!r)return"Schema path is required"}});if(w(n)){K("Operation cancelled.");return}let t=await k({message:"Where should Mizzle store migrations and snapshots?",placeholder:"./migrations",initialValue:"./migrations",validate:r=>{if(!r)return"Output directory is required"}});if(w(t)){K("Operation cancelled.");return}let o=await k({message:"Which AWS region do you want to use?",placeholder:"us-east-1",initialValue:"us-east-1"});if(w(o)){K("Operation cancelled.");return}let a=await k({message:"Do you want to use a custom endpoint (e.g., for local development)?",placeholder:"http://localhost:8000 (optional)"});if(w(a)){K("Operation cancelled.");return}let i=`import { defineConfig } from "@aurios/mizzle";
|
|
16
16
|
|
|
17
17
|
export default defineConfig({
|
|
18
18
|
schema: "${n}",
|
|
@@ -20,4 +20,4 @@ export default defineConfig({
|
|
|
20
20
|
region: "${o}",
|
|
21
21
|
${a?`endpoint: "${a}",`:'// endpoint: "http://localhost:8000",'}
|
|
22
22
|
});
|
|
23
|
-
`;
|
|
23
|
+
`;Ae(e,i),Ke("mizzle.config.ts created successfully!")}import{ListTablesCommand as Le,DescribeTableCommand as Re}from"@aws-sdk/client-dynamodb";async function L(e){let n={},t,o=[];do{let a=await e.send(new Le({ExclusiveStartTableName:t}));a.TableNames&&o.push(...a.TableNames),t=a.LastEvaluatedTableName}while(t);for(let a of o)try{let i=await e.send(new Re({TableName:a}));if(i.Table){let r=Oe(i.Table);n[a]=r}}catch(i){console.warn(`Failed to describe table ${a}:`,i)}return{version:"remote",tables:n}}function Oe(e){let n={TableName:e.TableName,AttributeDefinitions:e.AttributeDefinitions?.map(t=>({AttributeName:t.AttributeName,AttributeType:t.AttributeType})).sort((t,o)=>t.AttributeName.localeCompare(o.AttributeName))||[],KeySchema:e.KeySchema?.map(t=>({AttributeName:t.AttributeName,KeyType:t.KeyType}))||[]};return e.GlobalSecondaryIndexes&&e.GlobalSecondaryIndexes.length>0&&(n.GlobalSecondaryIndexes=e.GlobalSecondaryIndexes.map(t=>({IndexName:t.IndexName,KeySchema:t.KeySchema?.map(o=>({AttributeName:o.AttributeName,KeyType:o.KeyType})),Projection:t.Projection?{ProjectionType:t.Projection.ProjectionType}:void 0})).sort((t,o)=>t.IndexName.localeCompare(o.IndexName))),e.LocalSecondaryIndexes&&e.LocalSecondaryIndexes.length>0&&(n.LocalSecondaryIndexes=e.LocalSecondaryIndexes.map(t=>({IndexName:t.IndexName,KeySchema:t.KeySchema?.map(o=>({AttributeName:o.AttributeName,KeyType:o.KeyType})),Projection:t.Projection?{ProjectionType:t.Projection.ProjectionType}:void 0})).sort((t,o)=>t.IndexName.localeCompare(o.IndexName))),n}import{CreateTableCommand as ze}from"@aws-sdk/client-dynamodb";import{confirm as Pe,isCancel as _e,cancel as Ue,intro as je,outro as G,spinner as ve}from"@clack/prompts";async function V(e){je("Mizzle Push");let{config:n,force:t}=e,o=e.discoverSchema||E,a=e.client||b(n);try{let i=await o(n),r=await L(a),l=A(i,r);if(l.length===0){G("Remote is up to date.");return}console.log(`Pushing ${l.length} changes to remote...`);let s=t;if(s||(s=await Pe({message:"Do you want to apply these changes?"})),_e(s)||!s){Ue("Operation cancelled.");return}let u=ve();u.start("Pushing changes...");for(let m of l)m.type==="create"?(u.message(`Creating table: ${m.table.TableName}`),await a.send(new ze({TableName:m.table.TableName,AttributeDefinitions:m.table.AttributeDefinitions,KeySchema:m.table.KeySchema,GlobalSecondaryIndexes:m.table.GlobalSecondaryIndexes,LocalSecondaryIndexes:m.table.LocalSecondaryIndexes,BillingMode:"PAY_PER_REQUEST"}))):m.type==="delete"?console.log(`Untracked table found: ${m.tableName} (Skipping deletion)`):m.type==="update"&&u.message(`Updating table: ${m.tableName} (Not fully implemented)`);u.stop("Push complete."),G("Done")}catch(i){console.error("Error pushing changes:",i),process.exit(1)}}import"@aws-sdk/client-dynamodb";import{intro as Ye,outro as q,spinner as $e}from"@clack/prompts";async function J(e){Ye("Mizzle List Tables");let n=e.client||b(e.config),t=$e();t.start("Fetching remote tables...");try{let o=await L(n);t.stop("Fetched remote tables.");let a=Object.values(o.tables);if(a.length===0){console.log("No tables found in the remote environment."),q("Done");return}console.log(`Found ${a.length} tables:`);for(let i of a){console.log(`- ${i.TableName}`);let r=i.KeySchema.find(s=>s.KeyType==="HASH")?.AttributeName,l=i.KeySchema.find(s=>s.KeyType==="RANGE")?.AttributeName;console.log(` PK: ${r}, SK: ${l||"(none)"}`),i.GlobalSecondaryIndexes&&i.GlobalSecondaryIndexes.length>0&&console.log(` GSIs: ${i.GlobalSecondaryIndexes.map(s=>s.IndexName).join(", ")}`)}q("Done")}catch(o){t.stop("Failed to fetch tables."),console.error("Error listing tables:",o),process.exit(1)}}import{ListTablesCommand as Fe,DeleteTableCommand as He}from"@aws-sdk/client-dynamodb";import{intro as Ge,outro as R,multiselect as Ve,confirm as qe,isCancel as W,cancel as Je,spinner as We}from"@clack/prompts";async function Q(e){Ge("Mizzle Drop Tables");let n=e.client||b(e.config);try{let t=new Fe({}),a=(await n.send(t)).TableNames||[];if(a.length===0){console.log("No tables found in the remote environment."),R("Done");return}let i=await Ve({message:"Select tables to DELETE (This action is irreversible!)",options:a.map(u=>({value:u,label:u}))});if(W(i)){Je("Operation cancelled.");return}let r=i;if(r.length===0){console.log("No tables selected."),R("Done");return}let l=await qe({message:`Are you SURE you want to delete ${r.length} table(s)?`});if(W(l)||!l){console.log("Operation cancelled."),R("Done");return}let s=We();s.start("Deleting tables...");for(let u of r)s.message(`Deleting ${u}...`),await n.send(new He({TableName:u}));s.stop("All selected tables deleted."),R("Done")}catch(t){console.error("Error dropping tables:",t),process.exit(1)}}var g=new Qe;g.name("mizzle").description("Mizzle Migration CLI").version("0.0.1");g.command("init").description("Initialize Mizzle configuration").action(async()=>{try{await H()}catch(e){let n=e instanceof Error?e.message:String(e);x.log.error(n),process.exit(1)}});g.command("generate").description("Generate a new migration snapshot and script").option("-n, --name <name>","Migration name").action(async e=>{try{let n=await N();await F({config:n,name:e.name})}catch(n){let t=n instanceof Error?n.message:String(n);x.log.error(t),process.exit(1)}});g.command("push").description("Directly apply schema changes to the target DynamoDB environment").option("-y, --yes","Skip confirmation").action(async e=>{try{let n=await N();await V({config:n,force:e.yes})}catch(n){let t=n instanceof Error?n.message:String(n);x.log.error(t),process.exit(1)}});g.command("list").description("List all existing DynamoDB tables in the environment").action(async()=>{try{let e=await N();await J({config:e})}catch(e){let n=e instanceof Error?e.message:String(e);x.log.error(n),process.exit(1)}});g.command("drop").description("Interactive command to select and delete DynamoDB tables").action(async()=>{try{let e=await N();await Q({config:e})}catch(e){let n=e instanceof Error?e.message:String(e);x.log.error(n),process.exit(1)}});g.parse();
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as e}from"./chunk-
|
|
2
|
+
import{a as e}from"./chunk-DKDRM5WU.js";export{e as defineConfig};
|
package/package.json
CHANGED
|
@@ -1,40 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aurios/mizzling",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
},
|
|
9
|
-
"exports": {
|
|
10
|
-
".": "./dist/index.js"
|
|
3
|
+
"version": "1.1.2",
|
|
4
|
+
"description": "A CLI tool for managing Mizzle projects",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public",
|
|
7
|
+
"provenance": true
|
|
11
8
|
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"aws",
|
|
11
|
+
"database",
|
|
12
|
+
"dynamodb",
|
|
13
|
+
"mizzle",
|
|
14
|
+
"nosql",
|
|
15
|
+
"orm",
|
|
16
|
+
"singletable",
|
|
17
|
+
"ts",
|
|
18
|
+
"typescript"
|
|
19
|
+
],
|
|
20
|
+
"homepage": "https://mizzle-docs.vercel.app",
|
|
21
|
+
"license": "MIT",
|
|
12
22
|
"author": {
|
|
13
23
|
"name": "Lucas",
|
|
14
24
|
"url": "https://github.com/realfakenerd"
|
|
15
25
|
},
|
|
16
26
|
"repository": {
|
|
17
|
-
"
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/realfakenerd/mizzle.git",
|
|
29
|
+
"directory": "packages/mizzling"
|
|
18
30
|
},
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
"bin": {
|
|
32
|
+
"mizzling": "./dist/cli.js"
|
|
33
|
+
},
|
|
34
|
+
"type": "module",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": "./dist/index.js"
|
|
23
37
|
},
|
|
24
38
|
"dependencies": {
|
|
25
39
|
"@aws-sdk/client-dynamodb": "3.962.0",
|
|
26
40
|
"@aws-sdk/credential-provider-ini": "3.962.0",
|
|
27
41
|
"@aws-sdk/lib-dynamodb": "3.962.0",
|
|
28
42
|
"@clack/prompts": "^0.11.0",
|
|
29
|
-
"@mizzle/shared": "workspace:*",
|
|
30
43
|
"@smithy/node-http-handler": "^4.4.7",
|
|
31
44
|
"commander": "^14.0.2",
|
|
32
45
|
"fast-glob": "^3.3.3"
|
|
33
46
|
},
|
|
34
47
|
"devDependencies": {
|
|
35
|
-
"
|
|
36
|
-
"@mizzle
|
|
37
|
-
"@
|
|
38
|
-
"
|
|
48
|
+
"tsup": "^8.5.1",
|
|
49
|
+
"@aurios/mizzle": "1.1.3",
|
|
50
|
+
"@repo/shared": "0.0.3",
|
|
51
|
+
"@repo/typescript-config": "0.0.0",
|
|
52
|
+
"@repo/vitest-config": "0.0.0"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"check": "tsc --noEmit",
|
|
56
|
+
"build": "tsup",
|
|
57
|
+
"test": "vitest run"
|
|
39
58
|
}
|
|
40
|
-
}
|
|
59
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -9,21 +9,18 @@ import { dropCommand } from "./commands/drop";
|
|
|
9
9
|
|
|
10
10
|
const program = new Command();
|
|
11
11
|
|
|
12
|
-
program
|
|
13
|
-
.name("mizzle")
|
|
14
|
-
.description("Mizzle Migration CLI")
|
|
15
|
-
.version("0.0.1");
|
|
12
|
+
program.name("mizzle").description("Mizzle Migration CLI").version("0.0.1");
|
|
16
13
|
|
|
17
14
|
program
|
|
18
15
|
.command("init")
|
|
19
16
|
.description("Initialize Mizzle configuration")
|
|
20
17
|
.action(async () => {
|
|
21
18
|
try {
|
|
22
|
-
|
|
19
|
+
await initCommand();
|
|
23
20
|
} catch (e) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
22
|
+
p.log.error(message);
|
|
23
|
+
process.exit(1);
|
|
27
24
|
}
|
|
28
25
|
});
|
|
29
26
|
|
|
@@ -33,12 +30,12 @@ program
|
|
|
33
30
|
.option("-n, --name <name>", "Migration name")
|
|
34
31
|
.action(async (options) => {
|
|
35
32
|
try {
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
const config = await loadConfig();
|
|
34
|
+
await generateCommand({ config, name: options.name });
|
|
38
35
|
} catch (e) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
37
|
+
p.log.error(message);
|
|
38
|
+
process.exit(1);
|
|
42
39
|
}
|
|
43
40
|
});
|
|
44
41
|
|
|
@@ -48,12 +45,12 @@ program
|
|
|
48
45
|
.option("-y, --yes", "Skip confirmation")
|
|
49
46
|
.action(async (options) => {
|
|
50
47
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
const config = await loadConfig();
|
|
49
|
+
await pushCommand({ config, force: options.yes });
|
|
53
50
|
} catch (e) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
52
|
+
p.log.error(message);
|
|
53
|
+
process.exit(1);
|
|
57
54
|
}
|
|
58
55
|
});
|
|
59
56
|
|
|
@@ -62,12 +59,12 @@ program
|
|
|
62
59
|
.description("List all existing DynamoDB tables in the environment")
|
|
63
60
|
.action(async () => {
|
|
64
61
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
const config = await loadConfig();
|
|
63
|
+
await listCommand({ config });
|
|
67
64
|
} catch (e) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
66
|
+
p.log.error(message);
|
|
67
|
+
process.exit(1);
|
|
71
68
|
}
|
|
72
69
|
});
|
|
73
70
|
|
|
@@ -76,13 +73,13 @@ program
|
|
|
76
73
|
.description("Interactive command to select and delete DynamoDB tables")
|
|
77
74
|
.action(async () => {
|
|
78
75
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
const config = await loadConfig();
|
|
77
|
+
await dropCommand({ config });
|
|
81
78
|
} catch (e) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
80
|
+
p.log.error(message);
|
|
81
|
+
process.exit(1);
|
|
85
82
|
}
|
|
86
83
|
});
|
|
87
84
|
|
|
88
|
-
program.parse();
|
|
85
|
+
program.parse();
|
package/src/commands/drop.ts
CHANGED
|
@@ -3,69 +3,69 @@ import { DynamoDBClient, ListTablesCommand, DeleteTableCommand } from "@aws-sdk/
|
|
|
3
3
|
import { intro, outro, multiselect, confirm, isCancel, cancel, spinner } from "@clack/prompts";
|
|
4
4
|
|
|
5
5
|
interface DropOptions {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
config: MizzleConfig;
|
|
7
|
+
client?: DynamoDBClient;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export async function dropCommand(options: DropOptions) {
|
|
11
|
-
|
|
11
|
+
intro("Mizzle Drop Tables");
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
// 1. Fetch tables
|
|
17
|
-
const listCmd = new ListTablesCommand({});
|
|
18
|
-
const listRes = await client.send(listCmd);
|
|
19
|
-
const tableNames = listRes.TableNames || [];
|
|
13
|
+
const client = options.client || getClient(options.config);
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
try {
|
|
16
|
+
// 1. Fetch tables
|
|
17
|
+
const listCmd = new ListTablesCommand({});
|
|
18
|
+
const listRes = await client.send(listCmd);
|
|
19
|
+
const tableNames = listRes.TableNames || [];
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
if (tableNames.length === 0) {
|
|
22
|
+
console.log("No tables found in the remote environment.");
|
|
23
|
+
outro("Done");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
32
26
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
// 2. Select tables
|
|
28
|
+
const selectedTables = await multiselect({
|
|
29
|
+
message: "Select tables to DELETE (This action is irreversible!)",
|
|
30
|
+
options: tableNames.map((name) => ({ value: name, label: name })),
|
|
31
|
+
});
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
33
|
+
if (isCancel(selectedTables)) {
|
|
34
|
+
cancel("Operation cancelled.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
const tablesToDelete = selectedTables as string[];
|
|
39
|
+
if (tablesToDelete.length === 0) {
|
|
40
|
+
console.log("No tables selected.");
|
|
41
|
+
outro("Done");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
49
44
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
45
|
+
// 3. Confirm
|
|
46
|
+
const confirmed = await confirm({
|
|
47
|
+
message: `Are you SURE you want to delete ${tablesToDelete.length} table(s)?`,
|
|
48
|
+
});
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
51
|
+
console.log("Operation cancelled.");
|
|
52
|
+
outro("Done");
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
56
|
+
// 4. Delete
|
|
57
|
+
const s = spinner();
|
|
58
|
+
s.start("Deleting tables...");
|
|
64
59
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
console.error("Error dropping tables:", error);
|
|
69
|
-
process.exit(1);
|
|
60
|
+
for (const tableName of tablesToDelete) {
|
|
61
|
+
s.message(`Deleting ${tableName}...`);
|
|
62
|
+
await client.send(new DeleteTableCommand({ TableName: tableName }));
|
|
70
63
|
}
|
|
64
|
+
|
|
65
|
+
s.stop("All selected tables deleted.");
|
|
66
|
+
outro("Done");
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error("Error dropping tables:", error);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
71
|
}
|