@schemavaults/dbh 0.11.0 → 0.11.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/README.md +1 -1
- package/dist-cli/build-db-migrations.js +12 -12
- package/package.json +1 -1
- package/.claude/hooks/install-deps-in-fresh-environment.sh +0 -5
- package/.claude/settings.json +0 -15
- package/.claude/skills/database-migrations/SKILL.md +0 -244
- package/CLAUDE.md +0 -41
- package/eslint.config.cjs +0 -56
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Ensure that you have both `postgres` and a `postgres-ws-proxy` containers runnin
|
|
|
20
20
|
|
|
21
21
|
You'll likely want to replace the `build:` sections for the services in the e2e test example `.yml` file with `image:`. For example, use `image: postgres:17.7` for the `postgres` service. For the proxy, you can pull the docker image from `ghcr.io/schemavaults/dbh/postgres-ws-proxy`; use the version number equal to your `@schemavaults/dbh` npm package installation:
|
|
22
22
|
```md
|
|
23
|
-
# NPM Package: @schemavaults/dbh@0.11.
|
|
23
|
+
# NPM Package: @schemavaults/dbh@0.11.2 => ghcr.io/schemavaults/dbh/postgres-ws-proxy:0.11.2
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
### In your application server code
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
3
|
-
`)}displayWidth(z){return
|
|
2
|
+
var Qz=Object.create;var{getPrototypeOf:Bz,defineProperty:v,getOwnPropertyNames:Gz}=Object;var Uz=Object.prototype.hasOwnProperty;function qz(z){return this[z]}var Tz,Hz,_z=(z,J,X)=>{var Y=z!=null&&typeof z==="object";if(Y){var Z=J?Tz??=new WeakMap:Hz??=new WeakMap,$=Z.get(z);if($)return $}X=z!=null?Qz(Bz(z)):{};let Q=J||!z||!z.__esModule?v(X,"default",{value:z,enumerable:!0}):X;for(let G of Gz(z))if(!Uz.call(Q,G))v(Q,G,{get:qz.bind(z,G),enumerable:!0});if(Y)Z.set(z,Q);return Q};var M=(z,J)=>()=>(J||z((J={exports:{}}).exports,J),J.exports);var R=import.meta.require;var P=M((Lz)=>{class F extends Error{constructor(z,J,X){super(X);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=J,this.exitCode=z,this.nestedError=void 0}}class h extends F{constructor(z){super(1,"commander.invalidArgument",z);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}}Lz.CommanderError=F;Lz.InvalidArgumentError=h});var S=M((Rz)=>{var{InvalidArgumentError:jz}=P();class u{constructor(z,J){switch(this.description=J||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,z[0]){case"<":this.required=!0,this._name=z.slice(1,-1);break;case"[":this.required=!1,this._name=z.slice(1,-1);break;default:this.required=!0,this._name=z;break}if(this._name.endsWith("..."))this.variadic=!0,this._name=this._name.slice(0,-3)}name(){return this._name}_collectValue(z,J){if(J===this.defaultValue||!Array.isArray(J))return[z];return J.push(z),J}default(z,J){return this.defaultValue=z,this.defaultValueDescription=J,this}argParser(z){return this.parseArg=z,this}choices(z){return this.argChoices=z.slice(),this.parseArg=(J,X)=>{if(!this.argChoices.includes(J))throw new jz(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._collectValue(J,X);return J},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}}function Mz(z){let J=z.name()+(z.variadic===!0?"...":"");return z.required?"<"+J+">":"["+J+"]"}Rz.Argument=u;Rz.humanReadableArgName=Mz});var y=M((Ez)=>{var{humanReadableArgName:Vz}=S();class g{constructor(){this.helpWidth=void 0,this.minWidthToWrap=40,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}prepareContext(z){this.helpWidth=this.helpWidth??z.helpWidth??80}visibleCommands(z){let J=z.commands.filter((Y)=>!Y._hidden),X=z._getHelpCommand();if(X&&!X._hidden)J.push(X);if(this.sortSubcommands)J.sort((Y,Z)=>{return Y.name().localeCompare(Z.name())});return J}compareOptions(z,J){let X=(Y)=>{return Y.short?Y.short.replace(/^-/,""):Y.long.replace(/^--/,"")};return X(z).localeCompare(X(J))}visibleOptions(z){let J=z.options.filter((Y)=>!Y.hidden),X=z._getHelpOption();if(X&&!X.hidden){let Y=X.short&&z._findOption(X.short),Z=X.long&&z._findOption(X.long);if(!Y&&!Z)J.push(X);else if(X.long&&!Z)J.push(z.createOption(X.long,X.description));else if(X.short&&!Y)J.push(z.createOption(X.short,X.description))}if(this.sortOptions)J.sort(this.compareOptions);return J}visibleGlobalOptions(z){if(!this.showGlobalOptions)return[];let J=[];for(let X=z.parent;X;X=X.parent){let Y=X.options.filter((Z)=>!Z.hidden);J.push(...Y)}if(this.sortOptions)J.sort(this.compareOptions);return J}visibleArguments(z){if(z._argsDescription)z.registeredArguments.forEach((J)=>{J.description=J.description||z._argsDescription[J.name()]||""});if(z.registeredArguments.find((J)=>J.description))return z.registeredArguments;return[]}subcommandTerm(z){let J=z.registeredArguments.map((X)=>Vz(X)).join(" ");return z._name+(z._aliases[0]?"|"+z._aliases[0]:"")+(z.options.length?" [options]":"")+(J?" "+J:"")}optionTerm(z){return z.flags}argumentTerm(z){return z.name()}longestSubcommandTermLength(z,J){return J.visibleCommands(z).reduce((X,Y)=>{return Math.max(X,this.displayWidth(J.styleSubcommandTerm(J.subcommandTerm(Y))))},0)}longestOptionTermLength(z,J){return J.visibleOptions(z).reduce((X,Y)=>{return Math.max(X,this.displayWidth(J.styleOptionTerm(J.optionTerm(Y))))},0)}longestGlobalOptionTermLength(z,J){return J.visibleGlobalOptions(z).reduce((X,Y)=>{return Math.max(X,this.displayWidth(J.styleOptionTerm(J.optionTerm(Y))))},0)}longestArgumentTermLength(z,J){return J.visibleArguments(z).reduce((X,Y)=>{return Math.max(X,this.displayWidth(J.styleArgumentTerm(J.argumentTerm(Y))))},0)}commandUsage(z){let J=z._name;if(z._aliases[0])J=J+"|"+z._aliases[0];let X="";for(let Y=z.parent;Y;Y=Y.parent)X=Y.name()+" "+X;return X+J+" "+z.usage()}commandDescription(z){return z.description()}subcommandDescription(z){return z.summary()||z.description()}optionDescription(z){let J=[];if(z.argChoices)J.push(`choices: ${z.argChoices.map((X)=>JSON.stringify(X)).join(", ")}`);if(z.defaultValue!==void 0){if(z.required||z.optional||z.isBoolean()&&typeof z.defaultValue==="boolean")J.push(`default: ${z.defaultValueDescription||JSON.stringify(z.defaultValue)}`)}if(z.presetArg!==void 0&&z.optional)J.push(`preset: ${JSON.stringify(z.presetArg)}`);if(z.envVar!==void 0)J.push(`env: ${z.envVar}`);if(J.length>0){let X=`(${J.join(", ")})`;if(z.description)return`${z.description} ${X}`;return X}return z.description}argumentDescription(z){let J=[];if(z.argChoices)J.push(`choices: ${z.argChoices.map((X)=>JSON.stringify(X)).join(", ")}`);if(z.defaultValue!==void 0)J.push(`default: ${z.defaultValueDescription||JSON.stringify(z.defaultValue)}`);if(J.length>0){let X=`(${J.join(", ")})`;if(z.description)return`${z.description} ${X}`;return X}return z.description}formatItemList(z,J,X){if(J.length===0)return[];return[X.styleTitle(z),...J,""]}groupItems(z,J,X){let Y=new Map;return z.forEach((Z)=>{let $=X(Z);if(!Y.has($))Y.set($,[])}),J.forEach((Z)=>{let $=X(Z);if(!Y.has($))Y.set($,[]);Y.get($).push(Z)}),Y}formatHelp(z,J){let X=J.padWidth(z,J),Y=J.helpWidth??80;function Z(U,T){return J.formatItem(U,X,T,J)}let $=[`${J.styleTitle("Usage:")} ${J.styleUsage(J.commandUsage(z))}`,""],Q=J.commandDescription(z);if(Q.length>0)$=$.concat([J.boxWrap(J.styleCommandDescription(Q),Y),""]);let G=J.visibleArguments(z).map((U)=>{return Z(J.styleArgumentTerm(J.argumentTerm(U)),J.styleArgumentDescription(J.argumentDescription(U)))});if($=$.concat(this.formatItemList("Arguments:",G,J)),this.groupItems(z.options,J.visibleOptions(z),(U)=>U.helpGroupHeading??"Options:").forEach((U,T)=>{let L=U.map((W)=>{return Z(J.styleOptionTerm(J.optionTerm(W)),J.styleOptionDescription(J.optionDescription(W)))});$=$.concat(this.formatItemList(T,L,J))}),J.showGlobalOptions){let U=J.visibleGlobalOptions(z).map((T)=>{return Z(J.styleOptionTerm(J.optionTerm(T)),J.styleOptionDescription(J.optionDescription(T)))});$=$.concat(this.formatItemList("Global Options:",U,J))}return this.groupItems(z.commands,J.visibleCommands(z),(U)=>U.helpGroup()||"Commands:").forEach((U,T)=>{let L=U.map((W)=>{return Z(J.styleSubcommandTerm(J.subcommandTerm(W)),J.styleSubcommandDescription(J.subcommandDescription(W)))});$=$.concat(this.formatItemList(T,L,J))}),$.join(`
|
|
3
|
+
`)}displayWidth(z){return c(z).length}styleTitle(z){return z}styleUsage(z){return z.split(" ").map((J)=>{if(J==="[options]")return this.styleOptionText(J);if(J==="[command]")return this.styleSubcommandText(J);if(J[0]==="["||J[0]==="<")return this.styleArgumentText(J);return this.styleCommandText(J)}).join(" ")}styleCommandDescription(z){return this.styleDescriptionText(z)}styleOptionDescription(z){return this.styleDescriptionText(z)}styleSubcommandDescription(z){return this.styleDescriptionText(z)}styleArgumentDescription(z){return this.styleDescriptionText(z)}styleDescriptionText(z){return z}styleOptionTerm(z){return this.styleOptionText(z)}styleSubcommandTerm(z){return z.split(" ").map((J)=>{if(J==="[options]")return this.styleOptionText(J);if(J[0]==="["||J[0]==="<")return this.styleArgumentText(J);return this.styleSubcommandText(J)}).join(" ")}styleArgumentTerm(z){return this.styleArgumentText(z)}styleOptionText(z){return z}styleArgumentText(z){return z}styleSubcommandText(z){return z}styleCommandText(z){return z}padWidth(z,J){return Math.max(J.longestOptionTermLength(z,J),J.longestGlobalOptionTermLength(z,J),J.longestSubcommandTermLength(z,J),J.longestArgumentTermLength(z,J))}preformatted(z){return/\n[^\S\r\n]/.test(z)}formatItem(z,J,X,Y){let $=" ".repeat(2);if(!X)return $+z;let Q=z.padEnd(J+z.length-Y.displayWidth(z)),G=2,B=(this.helpWidth??80)-J-G-2,U;if(B<this.minWidthToWrap||Y.preformatted(X))U=X;else U=Y.boxWrap(X,B).replace(/\n/g,`
|
|
4
4
|
`+" ".repeat(J+G));return $+Q+" ".repeat(G)+U.replace(/\n/g,`
|
|
5
5
|
${$}`)}boxWrap(z,J){if(J<this.minWidthToWrap)return z;let X=z.split(/\r\n|\n/),Y=/[\s]*[^\s]+/g,Z=[];return X.forEach(($)=>{let Q=$.match(Y);if(Q===null){Z.push("");return}let G=[Q.shift()],q=this.displayWidth(G[0]);Q.forEach((B)=>{let U=this.displayWidth(B);if(q+U<=J){G.push(B),q+=U;return}Z.push(G.join(""));let T=B.trimStart();G=[T],q=this.displayWidth(T)}),Z.push(G.join(""))}),Z.join(`
|
|
6
|
-
`)}}function
|
|
6
|
+
`)}}function c(z){let J=/\x1b\[\d*(;\d*)*m/g;return z.replace(J,"")}Ez.Help=g;Ez.stripColor=c});var A=M((yz)=>{var{InvalidArgumentError:Dz}=P();class m{constructor(z,J){this.flags=z,this.description=J||"",this.required=z.includes("<"),this.optional=z.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(z),this.mandatory=!1;let X=Fz(z);if(this.short=X.shortFlag,this.long=X.longFlag,this.negate=!1,this.long)this.negate=this.long.startsWith("--no-");this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0,this.helpGroupHeading=void 0}default(z,J){return this.defaultValue=z,this.defaultValueDescription=J,this}preset(z){return this.presetArg=z,this}conflicts(z){return this.conflictsWith=this.conflictsWith.concat(z),this}implies(z){let J=z;if(typeof z==="string")J={[z]:!0};return this.implied=Object.assign(this.implied||{},J),this}env(z){return this.envVar=z,this}argParser(z){return this.parseArg=z,this}makeOptionMandatory(z=!0){return this.mandatory=!!z,this}hideHelp(z=!0){return this.hidden=!!z,this}_collectValue(z,J){if(J===this.defaultValue||!Array.isArray(J))return[z];return J.push(z),J}choices(z){return this.argChoices=z.slice(),this.parseArg=(J,X)=>{if(!this.argChoices.includes(J))throw new Dz(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._collectValue(J,X);return J},this}name(){if(this.long)return this.long.replace(/^--/,"");return this.short.replace(/^-/,"")}attributeName(){if(this.negate)return l(this.name().replace(/^no-/,""));return l(this.name())}helpGroup(z){return this.helpGroupHeading=z,this}is(z){return this.short===z||this.long===z}isBoolean(){return!this.required&&!this.optional&&!this.negate}}class d{constructor(z){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,z.forEach((J)=>{if(J.negate)this.negativeOptions.set(J.attributeName(),J);else this.positiveOptions.set(J.attributeName(),J)}),this.negativeOptions.forEach((J,X)=>{if(this.positiveOptions.has(X))this.dualOptions.add(X)})}valueFromOption(z,J){let X=J.attributeName();if(!this.dualOptions.has(X))return!0;let Y=this.negativeOptions.get(X).presetArg,Z=Y!==void 0?Y:!1;return J.negate===(Z===z)}}function l(z){return z.split("-").reduce((J,X)=>{return J+X[0].toUpperCase()+X.slice(1)})}function Fz(z){let J,X,Y=/^-[^-]$/,Z=/^--[^-]/,$=z.split(/[ |,]+/).concat("guard");if(Y.test($[0]))J=$.shift();if(Z.test($[0]))X=$.shift();if(!J&&Y.test($[0]))J=$.shift();if(!J&&Z.test($[0]))J=X,X=$.shift();if($[0].startsWith("-")){let Q=$[0],G=`option creation failed due to '${Q}' in option flags '${z}'`;if(/^-[^-][^-]/.test(Q))throw Error(`${G}
|
|
7
7
|
- a short flag is a single dash and a single character
|
|
8
8
|
- either use a single dash and a single character (for a short flag)
|
|
9
9
|
- or use a double dash for a long option (and can have two, like '--ws, --workspace')`);if(Y.test(Q))throw Error(`${G}
|
|
10
10
|
- too many short flags`);if(Z.test(Q))throw Error(`${G}
|
|
11
11
|
- too many long flags`);throw Error(`${G}
|
|
12
|
-
- unrecognised flag format`)}if(J===void 0&&X===void 0)throw Error(`option creation failed due to no flags found in '${z}'.`);return{shortFlag:J,longFlag:X}}
|
|
12
|
+
- unrecognised flag format`)}if(J===void 0&&X===void 0)throw Error(`option creation failed due to no flags found in '${z}'.`);return{shortFlag:J,longFlag:X}}yz.Option=m;yz.DualOptions=d});var p=M((Oz)=>{function kz(z,J){if(Math.abs(z.length-J.length)>3)return Math.max(z.length,J.length);let X=[];for(let Y=0;Y<=z.length;Y++)X[Y]=[Y];for(let Y=0;Y<=J.length;Y++)X[0][Y]=Y;for(let Y=1;Y<=J.length;Y++)for(let Z=1;Z<=z.length;Z++){let $=1;if(z[Z-1]===J[Y-1])$=0;else $=1;if(X[Z][Y]=Math.min(X[Z-1][Y]+1,X[Z][Y-1]+1,X[Z-1][Y-1]+$),Z>1&&Y>1&&z[Z-1]===J[Y-2]&&z[Z-2]===J[Y-1])X[Z][Y]=Math.min(X[Z][Y],X[Z-2][Y-2]+1)}return X[z.length][J.length]}function Cz(z,J){if(!J||J.length===0)return"";J=Array.from(new Set(J));let X=z.startsWith("--");if(X)z=z.slice(2),J=J.map((Q)=>Q.slice(2));let Y=[],Z=3,$=0.4;if(J.forEach((Q)=>{if(Q.length<=1)return;let G=kz(z,Q),q=Math.max(z.length,Q.length);if((q-G)/q>$){if(G<Z)Z=G,Y=[Q];else if(G===Z)Y.push(Q)}}),Y.sort((Q,G)=>Q.localeCompare(G)),X)Y=Y.map((Q)=>`--${Q}`);if(Y.length>1)return`
|
|
13
13
|
(Did you mean one of ${Y.join(", ")}?)`;if(Y.length===1)return`
|
|
14
|
-
(Did you mean ${Y[0]}?)`;return""}
|
|
15
|
-
- specify the name in Command constructor or using .name()`);if(J=J||{},J.isDefault)this._defaultCommandName=z._name;if(J.noHelp||J.hidden)z._hidden=!0;return this._registerCommand(z),z.parent=this,z._checkForBrokenPassThrough(),this}createArgument(z,J){return new
|
|
16
|
-
Expecting one of '${X.join("', '")}'`);if(this._lifeCycleHooks[z])this._lifeCycleHooks[z].push(J);else this._lifeCycleHooks[z]=[J];return this}exitOverride(z){if(z)this._exitCallback=z;else this._exitCallback=(J)=>{if(J.code!=="commander.executeSubCommandAsync")throw J};return this}_exit(z,J,X){if(this._exitCallback)this._exitCallback(new
|
|
17
|
-
- already used by option '${J.flags}'`)}this._initOptionGroup(z),this.options.push(z)}_registerCommand(z){let J=(Y)=>{return[Y.name()].concat(Y.aliases())},X=J(z).find((Y)=>this._findCommand(Y));if(X){let Y=J(this._findCommand(X)).join("|"),Z=J(z).join("|");throw Error(`cannot add command '${Z}' as already have command '${Y}'`)}this._initCommandGroup(z),this.commands.push(z)}addOption(z){this._registerOption(z);let J=z.name(),X=z.attributeName();if(z.negate){let Z=z.long.replace(/^--no-/,"--");if(!this._findOption(Z))this.setOptionValueWithSource(X,z.defaultValue===void 0?!0:z.defaultValue,"default")}else if(z.defaultValue!==void 0)this.setOptionValueWithSource(X,z.defaultValue,"default");let Y=(Z,$,Q)=>{if(Z==null&&z.presetArg!==void 0)Z=z.presetArg;let G=this.getOptionValue(X);if(Z!==null&&z.parseArg)Z=this._callParseArg(z,Z,G,$);else if(Z!==null&&z.variadic)Z=z._collectValue(Z,G);if(Z==null)if(z.negate)Z=!1;else if(z.isBoolean()||z.optional)Z=!0;else Z="";this.setOptionValueWithSource(X,Z,Q)};if(this.on("option:"+J,(Z)=>{let $=`error: option '${z.flags}' argument '${Z}' is invalid.`;Y(Z,$,"cli")}),z.envVar)this.on("optionEnv:"+J,(Z)=>{let $=`error: option '${z.flags}' value '${Z}' from env '${z.envVar}' is invalid.`;Y(Z,$,"env")});return this}_optionEx(z,J,X,Y,Z){if(typeof J==="object"&&J instanceof
|
|
14
|
+
(Did you mean ${Y[0]}?)`;return""}Oz.suggestSimilar=Cz});var n=M((cz)=>{var fz=R("events").EventEmitter,w=R("child_process"),K=R("path"),N=R("fs"),H=R("process"),{Argument:bz,humanReadableArgName:vz}=S(),{CommanderError:k}=P(),{Help:hz,stripColor:uz}=y(),{Option:s,DualOptions:gz}=A(),{suggestSimilar:i}=p();class O extends fz{constructor(z){super();this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!1,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=z||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._savedState=null,this._outputConfiguration={writeOut:(J)=>H.stdout.write(J),writeErr:(J)=>H.stderr.write(J),outputError:(J,X)=>X(J),getOutHelpWidth:()=>H.stdout.isTTY?H.stdout.columns:void 0,getErrHelpWidth:()=>H.stderr.isTTY?H.stderr.columns:void 0,getOutHasColors:()=>C()??(H.stdout.isTTY&&H.stdout.hasColors?.()),getErrHasColors:()=>C()??(H.stderr.isTTY&&H.stderr.hasColors?.()),stripColor:(J)=>uz(J)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={},this._helpGroupHeading=void 0,this._defaultCommandGroup=void 0,this._defaultOptionGroup=void 0}copyInheritedSettings(z){return this._outputConfiguration=z._outputConfiguration,this._helpOption=z._helpOption,this._helpCommand=z._helpCommand,this._helpConfiguration=z._helpConfiguration,this._exitCallback=z._exitCallback,this._storeOptionsAsProperties=z._storeOptionsAsProperties,this._combineFlagAndOptionalValue=z._combineFlagAndOptionalValue,this._allowExcessArguments=z._allowExcessArguments,this._enablePositionalOptions=z._enablePositionalOptions,this._showHelpAfterError=z._showHelpAfterError,this._showSuggestionAfterError=z._showSuggestionAfterError,this}_getCommandAndAncestors(){let z=[];for(let J=this;J;J=J.parent)z.push(J);return z}command(z,J,X){let Y=J,Z=X;if(typeof Y==="object"&&Y!==null)Z=Y,Y=null;Z=Z||{};let[,$,Q]=z.match(/([^ ]+) *(.*)/),G=this.createCommand($);if(Y)G.description(Y),G._executableHandler=!0;if(Z.isDefault)this._defaultCommandName=G._name;if(G._hidden=!!(Z.noHelp||Z.hidden),G._executableFile=Z.executableFile||null,Q)G.arguments(Q);if(this._registerCommand(G),G.parent=this,G.copyInheritedSettings(this),Y)return this;return G}createCommand(z){return new O(z)}createHelp(){return Object.assign(new hz,this.configureHelp())}configureHelp(z){if(z===void 0)return this._helpConfiguration;return this._helpConfiguration=z,this}configureOutput(z){if(z===void 0)return this._outputConfiguration;return this._outputConfiguration={...this._outputConfiguration,...z},this}showHelpAfterError(z=!0){if(typeof z!=="string")z=!!z;return this._showHelpAfterError=z,this}showSuggestionAfterError(z=!0){return this._showSuggestionAfterError=!!z,this}addCommand(z,J){if(!z._name)throw Error(`Command passed to .addCommand() must have a name
|
|
15
|
+
- specify the name in Command constructor or using .name()`);if(J=J||{},J.isDefault)this._defaultCommandName=z._name;if(J.noHelp||J.hidden)z._hidden=!0;return this._registerCommand(z),z.parent=this,z._checkForBrokenPassThrough(),this}createArgument(z,J){return new bz(z,J)}argument(z,J,X,Y){let Z=this.createArgument(z,J);if(typeof X==="function")Z.default(Y).argParser(X);else Z.default(X);return this.addArgument(Z),this}arguments(z){return z.trim().split(/ +/).forEach((J)=>{this.argument(J)}),this}addArgument(z){let J=this.registeredArguments.slice(-1)[0];if(J?.variadic)throw Error(`only the last argument can be variadic '${J.name()}'`);if(z.required&&z.defaultValue!==void 0&&z.parseArg===void 0)throw Error(`a default value for a required argument is never used: '${z.name()}'`);return this.registeredArguments.push(z),this}helpCommand(z,J){if(typeof z==="boolean"){if(this._addImplicitHelpCommand=z,z&&this._defaultCommandGroup)this._initCommandGroup(this._getHelpCommand());return this}let X=z??"help [command]",[,Y,Z]=X.match(/([^ ]+) *(.*)/),$=J??"display help for command",Q=this.createCommand(Y);if(Q.helpOption(!1),Z)Q.arguments(Z);if($)Q.description($);if(this._addImplicitHelpCommand=!0,this._helpCommand=Q,z||J)this._initCommandGroup(Q);return this}addHelpCommand(z,J){if(typeof z!=="object")return this.helpCommand(z,J),this;return this._addImplicitHelpCommand=!0,this._helpCommand=z,this._initCommandGroup(z),this}_getHelpCommand(){if(this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))){if(this._helpCommand===void 0)this.helpCommand(void 0,void 0);return this._helpCommand}return null}hook(z,J){let X=["preSubcommand","preAction","postAction"];if(!X.includes(z))throw Error(`Unexpected value for event passed to hook : '${z}'.
|
|
16
|
+
Expecting one of '${X.join("', '")}'`);if(this._lifeCycleHooks[z])this._lifeCycleHooks[z].push(J);else this._lifeCycleHooks[z]=[J];return this}exitOverride(z){if(z)this._exitCallback=z;else this._exitCallback=(J)=>{if(J.code!=="commander.executeSubCommandAsync")throw J};return this}_exit(z,J,X){if(this._exitCallback)this._exitCallback(new k(z,J,X));H.exit(z)}action(z){let J=(X)=>{let Y=this.registeredArguments.length,Z=X.slice(0,Y);if(this._storeOptionsAsProperties)Z[Y]=this;else Z[Y]=this.opts();return Z.push(this),z.apply(this,Z)};return this._actionHandler=J,this}createOption(z,J){return new s(z,J)}_callParseArg(z,J,X,Y){try{return z.parseArg(J,X)}catch(Z){if(Z.code==="commander.invalidArgument"){let $=`${Y} ${Z.message}`;this.error($,{exitCode:Z.exitCode,code:Z.code})}throw Z}}_registerOption(z){let J=z.short&&this._findOption(z.short)||z.long&&this._findOption(z.long);if(J){let X=z.long&&this._findOption(z.long)?z.long:z.short;throw Error(`Cannot add option '${z.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${X}'
|
|
17
|
+
- already used by option '${J.flags}'`)}this._initOptionGroup(z),this.options.push(z)}_registerCommand(z){let J=(Y)=>{return[Y.name()].concat(Y.aliases())},X=J(z).find((Y)=>this._findCommand(Y));if(X){let Y=J(this._findCommand(X)).join("|"),Z=J(z).join("|");throw Error(`cannot add command '${Z}' as already have command '${Y}'`)}this._initCommandGroup(z),this.commands.push(z)}addOption(z){this._registerOption(z);let J=z.name(),X=z.attributeName();if(z.negate){let Z=z.long.replace(/^--no-/,"--");if(!this._findOption(Z))this.setOptionValueWithSource(X,z.defaultValue===void 0?!0:z.defaultValue,"default")}else if(z.defaultValue!==void 0)this.setOptionValueWithSource(X,z.defaultValue,"default");let Y=(Z,$,Q)=>{if(Z==null&&z.presetArg!==void 0)Z=z.presetArg;let G=this.getOptionValue(X);if(Z!==null&&z.parseArg)Z=this._callParseArg(z,Z,G,$);else if(Z!==null&&z.variadic)Z=z._collectValue(Z,G);if(Z==null)if(z.negate)Z=!1;else if(z.isBoolean()||z.optional)Z=!0;else Z="";this.setOptionValueWithSource(X,Z,Q)};if(this.on("option:"+J,(Z)=>{let $=`error: option '${z.flags}' argument '${Z}' is invalid.`;Y(Z,$,"cli")}),z.envVar)this.on("optionEnv:"+J,(Z)=>{let $=`error: option '${z.flags}' value '${Z}' from env '${z.envVar}' is invalid.`;Y(Z,$,"env")});return this}_optionEx(z,J,X,Y,Z){if(typeof J==="object"&&J instanceof s)throw Error("To add an Option object use addOption() instead of option() or requiredOption()");let $=this.createOption(J,X);if($.makeOptionMandatory(!!z.mandatory),typeof Y==="function")$.default(Z).argParser(Y);else if(Y instanceof RegExp){let Q=Y;Y=(G,q)=>{let B=Q.exec(G);return B?B[0]:q},$.default(Z).argParser(Y)}else $.default(Y);return this.addOption($)}option(z,J,X,Y){return this._optionEx({},z,J,X,Y)}requiredOption(z,J,X,Y){return this._optionEx({mandatory:!0},z,J,X,Y)}combineFlagAndOptionalValue(z=!0){return this._combineFlagAndOptionalValue=!!z,this}allowUnknownOption(z=!0){return this._allowUnknownOption=!!z,this}allowExcessArguments(z=!0){return this._allowExcessArguments=!!z,this}enablePositionalOptions(z=!0){return this._enablePositionalOptions=!!z,this}passThroughOptions(z=!0){return this._passThroughOptions=!!z,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(z=!0){if(this.options.length)throw Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!z,this}getOptionValue(z){if(this._storeOptionsAsProperties)return this[z];return this._optionValues[z]}setOptionValue(z,J){return this.setOptionValueWithSource(z,J,void 0)}setOptionValueWithSource(z,J,X){if(this._storeOptionsAsProperties)this[z]=J;else this._optionValues[z]=J;return this._optionValueSources[z]=X,this}getOptionValueSource(z){return this._optionValueSources[z]}getOptionValueSourceWithGlobals(z){let J;return this._getCommandAndAncestors().forEach((X)=>{if(X.getOptionValueSource(z)!==void 0)J=X.getOptionValueSource(z)}),J}_prepareUserArgs(z,J){if(z!==void 0&&!Array.isArray(z))throw Error("first parameter to parse must be array or undefined");if(J=J||{},z===void 0&&J.from===void 0){if(H.versions?.electron)J.from="electron";let Y=H.execArgv??[];if(Y.includes("-e")||Y.includes("--eval")||Y.includes("-p")||Y.includes("--print"))J.from="eval"}if(z===void 0)z=H.argv;this.rawArgs=z.slice();let X;switch(J.from){case void 0:case"node":this._scriptPath=z[1],X=z.slice(2);break;case"electron":if(H.defaultApp)this._scriptPath=z[1],X=z.slice(2);else X=z.slice(1);break;case"user":X=z.slice(0);break;case"eval":X=z.slice(1);break;default:throw Error(`unexpected parse option { from: '${J.from}' }`)}if(!this._name&&this._scriptPath)this.nameFromFilename(this._scriptPath);return this._name=this._name||"program",X}parse(z,J){this._prepareForParse();let X=this._prepareUserArgs(z,J);return this._parseCommand([],X),this}async parseAsync(z,J){this._prepareForParse();let X=this._prepareUserArgs(z,J);return await this._parseCommand([],X),this}_prepareForParse(){if(this._savedState===null)this.saveStateBeforeParse();else this.restoreStateBeforeParse()}saveStateBeforeParse(){this._savedState={_name:this._name,_optionValues:{...this._optionValues},_optionValueSources:{...this._optionValueSources}}}restoreStateBeforeParse(){if(this._storeOptionsAsProperties)throw Error(`Can not call parse again when storeOptionsAsProperties is true.
|
|
18
18
|
- either make a new Command for each call to parse, or stop storing options as properties`);this._name=this._savedState._name,this._scriptPath=null,this.rawArgs=[],this._optionValues={...this._savedState._optionValues},this._optionValueSources={...this._savedState._optionValueSources},this.args=[],this.processedArgs=[]}_checkForMissingExecutable(z,J,X){if(N.existsSync(z))return;let Y=J?`searched for local subcommand relative to directory '${J}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",Z=`'${z}' does not exist
|
|
19
19
|
- if '${X}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
20
20
|
- if the default executable name is not suitable, use the executableFile option to supply a custom name or path
|
|
21
|
-
- ${Y}`;throw Error(Z)}_executeSubCommand(z,J){J=J.slice();let X=!1,Y=[".js",".ts",".tsx",".mjs",".cjs"];function Z(B,U){let T=K.resolve(B,U);if(N.existsSync(T))return T;if(Y.includes(K.extname(U)))return;let L=Y.find((W)=>N.existsSync(`${T}${W}`));if(L)return`${T}${L}`;return}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let $=z._executableFile||`${this._name}-${z._name}`,Q=this._executableDir||"";if(this._scriptPath){let B;try{B=N.realpathSync(this._scriptPath)}catch{B=this._scriptPath}Q=K.resolve(K.dirname(B),Q)}if(Q){let B=Z(Q,$);if(!B&&!z._executableFile&&this._scriptPath){let U=K.basename(this._scriptPath,K.extname(this._scriptPath));if(U!==this._name)B=Z(Q,`${U}-${z._name}`)}$=B||$}X=Y.includes(K.extname($));let G;if(H.platform!=="win32")if(X)J.unshift($),J=
|
|
21
|
+
- ${Y}`;throw Error(Z)}_executeSubCommand(z,J){J=J.slice();let X=!1,Y=[".js",".ts",".tsx",".mjs",".cjs"];function Z(B,U){let T=K.resolve(B,U);if(N.existsSync(T))return T;if(Y.includes(K.extname(U)))return;let L=Y.find((W)=>N.existsSync(`${T}${W}`));if(L)return`${T}${L}`;return}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let $=z._executableFile||`${this._name}-${z._name}`,Q=this._executableDir||"";if(this._scriptPath){let B;try{B=N.realpathSync(this._scriptPath)}catch{B=this._scriptPath}Q=K.resolve(K.dirname(B),Q)}if(Q){let B=Z(Q,$);if(!B&&!z._executableFile&&this._scriptPath){let U=K.basename(this._scriptPath,K.extname(this._scriptPath));if(U!==this._name)B=Z(Q,`${U}-${z._name}`)}$=B||$}X=Y.includes(K.extname($));let G;if(H.platform!=="win32")if(X)J.unshift($),J=r(H.execArgv).concat(J),G=w.spawn(H.argv[0],J,{stdio:"inherit"});else G=w.spawn($,J,{stdio:"inherit"});else this._checkForMissingExecutable($,Q,z._name),J.unshift($),J=r(H.execArgv).concat(J),G=w.spawn(H.execPath,J,{stdio:"inherit"});if(!G.killed)["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach((U)=>{H.on(U,()=>{if(G.killed===!1&&G.exitCode===null)G.kill(U)})});let q=this._exitCallback;G.on("close",(B)=>{if(B=B??1,!q)H.exit(B);else q(new k(B,"commander.executeSubCommandAsync","(close)"))}),G.on("error",(B)=>{if(B.code==="ENOENT")this._checkForMissingExecutable($,Q,z._name);else if(B.code==="EACCES")throw Error(`'${$}' not executable`);if(!q)H.exit(1);else{let U=new k(1,"commander.executeSubCommandAsync","(error)");U.nestedError=B,q(U)}}),this.runningCommand=G}_dispatchSubcommand(z,J,X){let Y=this._findCommand(z);if(!Y)this.help({error:!0});Y._prepareForParse();let Z;return Z=this._chainOrCallSubCommandHook(Z,Y,"preSubcommand"),Z=this._chainOrCall(Z,()=>{if(Y._executableHandler)this._executeSubCommand(Y,J.concat(X));else return Y._parseCommand(J,X)}),Z}_dispatchHelpCommand(z){if(!z)this.help();let J=this._findCommand(z);if(J&&!J._executableHandler)J.help();return this._dispatchSubcommand(z,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){if(this.registeredArguments.forEach((z,J)=>{if(z.required&&this.args[J]==null)this.missingArgument(z.name())}),this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)return;if(this.args.length>this.registeredArguments.length)this._excessArguments(this.args)}_processArguments(){let z=(X,Y,Z)=>{let $=Y;if(Y!==null&&X.parseArg){let Q=`error: command-argument value '${Y}' is invalid for argument '${X.name()}'.`;$=this._callParseArg(X,Y,Z,Q)}return $};this._checkNumberOfArguments();let J=[];this.registeredArguments.forEach((X,Y)=>{let Z=X.defaultValue;if(X.variadic){if(Y<this.args.length){if(Z=this.args.slice(Y),X.parseArg)Z=Z.reduce(($,Q)=>{return z(X,Q,$)},X.defaultValue)}else if(Z===void 0)Z=[]}else if(Y<this.args.length){if(Z=this.args[Y],X.parseArg)Z=z(X,Z,X.defaultValue)}J[Y]=Z}),this.processedArgs=J}_chainOrCall(z,J){if(z?.then&&typeof z.then==="function")return z.then(()=>J());return J()}_chainOrCallHooks(z,J){let X=z,Y=[];if(this._getCommandAndAncestors().reverse().filter((Z)=>Z._lifeCycleHooks[J]!==void 0).forEach((Z)=>{Z._lifeCycleHooks[J].forEach(($)=>{Y.push({hookedCommand:Z,callback:$})})}),J==="postAction")Y.reverse();return Y.forEach((Z)=>{X=this._chainOrCall(X,()=>{return Z.callback(Z.hookedCommand,this)})}),X}_chainOrCallSubCommandHook(z,J,X){let Y=z;if(this._lifeCycleHooks[X]!==void 0)this._lifeCycleHooks[X].forEach((Z)=>{Y=this._chainOrCall(Y,()=>{return Z(this,J)})});return Y}_parseCommand(z,J){let X=this.parseOptions(J);if(this._parseOptionsEnv(),this._parseOptionsImplied(),z=z.concat(X.operands),J=X.unknown,this.args=z.concat(J),z&&this._findCommand(z[0]))return this._dispatchSubcommand(z[0],z.slice(1),J);if(this._getHelpCommand()&&z[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(z[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(J),this._dispatchSubcommand(this._defaultCommandName,z,J);if(this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName)this.help({error:!0});this._outputHelpIfRequested(X.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let Y=()=>{if(X.unknown.length>0)this.unknownOption(X.unknown[0])},Z=`command:${this.name()}`;if(this._actionHandler){Y(),this._processArguments();let $;if($=this._chainOrCallHooks($,"preAction"),$=this._chainOrCall($,()=>this._actionHandler(this.processedArgs)),this.parent)$=this._chainOrCall($,()=>{this.parent.emit(Z,z,J)});return $=this._chainOrCallHooks($,"postAction"),$}if(this.parent?.listenerCount(Z))Y(),this._processArguments(),this.parent.emit(Z,z,J);else if(z.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",z,J);if(this.listenerCount("command:*"))this.emit("command:*",z,J);else if(this.commands.length)this.unknownCommand();else Y(),this._processArguments()}else if(this.commands.length)Y(),this.help({error:!0});else Y(),this._processArguments()}_findCommand(z){if(!z)return;return this.commands.find((J)=>J._name===z||J._aliases.includes(z))}_findOption(z){return this.options.find((J)=>J.is(z))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach((z)=>{z.options.forEach((J)=>{if(J.mandatory&&z.getOptionValue(J.attributeName())===void 0)z.missingMandatoryOptionValue(J)})})}_checkForConflictingLocalOptions(){let z=this.options.filter((X)=>{let Y=X.attributeName();if(this.getOptionValue(Y)===void 0)return!1;return this.getOptionValueSource(Y)!=="default"});z.filter((X)=>X.conflictsWith.length>0).forEach((X)=>{let Y=z.find((Z)=>X.conflictsWith.includes(Z.attributeName()));if(Y)this._conflictingOption(X,Y)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach((z)=>{z._checkForConflictingLocalOptions()})}parseOptions(z){let J=[],X=[],Y=J;function Z(B){return B.length>1&&B[0]==="-"}let $=(B)=>{if(!/^-(\d+|\d*\.\d+)(e[+-]?\d+)?$/.test(B))return!1;return!this._getCommandAndAncestors().some((U)=>U.options.map((T)=>T.short).some((T)=>/^-\d$/.test(T)))},Q=null,G=null,q=0;while(q<z.length||G){let B=G??z[q++];if(G=null,B==="--"){if(Y===X)Y.push(B);Y.push(...z.slice(q));break}if(Q&&(!Z(B)||$(B))){this.emit(`option:${Q.name()}`,B);continue}if(Q=null,Z(B)){let U=this._findOption(B);if(U){if(U.required){let T=z[q++];if(T===void 0)this.optionMissingArgument(U);this.emit(`option:${U.name()}`,T)}else if(U.optional){let T=null;if(q<z.length&&(!Z(z[q])||$(z[q])))T=z[q++];this.emit(`option:${U.name()}`,T)}else this.emit(`option:${U.name()}`);Q=U.variadic?U:null;continue}}if(B.length>2&&B[0]==="-"&&B[1]!=="-"){let U=this._findOption(`-${B[1]}`);if(U){if(U.required||U.optional&&this._combineFlagAndOptionalValue)this.emit(`option:${U.name()}`,B.slice(2));else this.emit(`option:${U.name()}`),G=`-${B.slice(2)}`;continue}}if(/^--[^=]+=/.test(B)){let U=B.indexOf("="),T=this._findOption(B.slice(0,U));if(T&&(T.required||T.optional)){this.emit(`option:${T.name()}`,B.slice(U+1));continue}}if(Y===J&&Z(B)&&!(this.commands.length===0&&$(B)))Y=X;if((this._enablePositionalOptions||this._passThroughOptions)&&J.length===0&&X.length===0){if(this._findCommand(B)){J.push(B),X.push(...z.slice(q));break}else if(this._getHelpCommand()&&B===this._getHelpCommand().name()){J.push(B,...z.slice(q));break}else if(this._defaultCommandName){X.push(B,...z.slice(q));break}}if(this._passThroughOptions){Y.push(B,...z.slice(q));break}Y.push(B)}return{operands:J,unknown:X}}opts(){if(this._storeOptionsAsProperties){let z={},J=this.options.length;for(let X=0;X<J;X++){let Y=this.options[X].attributeName();z[Y]=Y===this._versionOptionName?this._version:this[Y]}return z}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce((z,J)=>Object.assign(z,J.opts()),{})}error(z,J){if(this._outputConfiguration.outputError(`${z}
|
|
22
22
|
`,this._outputConfiguration.writeErr),typeof this._showHelpAfterError==="string")this._outputConfiguration.writeErr(`${this._showHelpAfterError}
|
|
23
23
|
`);else if(this._showHelpAfterError)this._outputConfiguration.writeErr(`
|
|
24
|
-
`),this.outputHelp({error:!0});let X=J||{},Y=X.exitCode||1,Z=X.code||"commander.error";this._exit(Y,Z,z)}_parseOptionsEnv(){this.options.forEach((z)=>{if(z.envVar&&z.envVar in H.env){let J=z.attributeName();if(this.getOptionValue(J)===void 0||["default","config","env"].includes(this.getOptionValueSource(J)))if(z.required||z.optional)this.emit(`optionEnv:${z.name()}`,H.env[z.envVar]);else this.emit(`optionEnv:${z.name()}`)}})}_parseOptionsImplied(){let z=new
|
|
25
|
-
`),this._exit(0,"commander.version",z)}),this}description(z,J){if(z===void 0&&J===void 0)return this._description;if(this._description=z,J)this._argsDescription=J;return this}summary(z){if(z===void 0)return this._summary;return this._summary=z,this}alias(z){if(z===void 0)return this._aliases[0];let J=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler)J=this.commands[this.commands.length-1];if(z===J._name)throw Error("Command alias can't be the same as its name");let X=this.parent?._findCommand(z);if(X){let Y=[X.name()].concat(X.aliases()).join("|");throw Error(`cannot add alias '${z}' to command '${this.name()}' as already have command '${Y}'`)}return J._aliases.push(z),this}aliases(z){if(z===void 0)return this._aliases;return z.forEach((J)=>this.alias(J)),this}usage(z){if(z===void 0){if(this._usage)return this._usage;let J=this.registeredArguments.map((X)=>{return
|
|
24
|
+
`),this.outputHelp({error:!0});let X=J||{},Y=X.exitCode||1,Z=X.code||"commander.error";this._exit(Y,Z,z)}_parseOptionsEnv(){this.options.forEach((z)=>{if(z.envVar&&z.envVar in H.env){let J=z.attributeName();if(this.getOptionValue(J)===void 0||["default","config","env"].includes(this.getOptionValueSource(J)))if(z.required||z.optional)this.emit(`optionEnv:${z.name()}`,H.env[z.envVar]);else this.emit(`optionEnv:${z.name()}`)}})}_parseOptionsImplied(){let z=new gz(this.options),J=(X)=>{return this.getOptionValue(X)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(X))};this.options.filter((X)=>X.implied!==void 0&&J(X.attributeName())&&z.valueFromOption(this.getOptionValue(X.attributeName()),X)).forEach((X)=>{Object.keys(X.implied).filter((Y)=>!J(Y)).forEach((Y)=>{this.setOptionValueWithSource(Y,X.implied[Y],"implied")})})}missingArgument(z){let J=`error: missing required argument '${z}'`;this.error(J,{code:"commander.missingArgument"})}optionMissingArgument(z){let J=`error: option '${z.flags}' argument missing`;this.error(J,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(z){let J=`error: required option '${z.flags}' not specified`;this.error(J,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(z,J){let X=($)=>{let Q=$.attributeName(),G=this.getOptionValue(Q),q=this.options.find((U)=>U.negate&&Q===U.attributeName()),B=this.options.find((U)=>!U.negate&&Q===U.attributeName());if(q&&(q.presetArg===void 0&&G===!1||q.presetArg!==void 0&&G===q.presetArg))return q;return B||$},Y=($)=>{let Q=X($),G=Q.attributeName();if(this.getOptionValueSource(G)==="env")return`environment variable '${Q.envVar}'`;return`option '${Q.flags}'`},Z=`error: ${Y(z)} cannot be used with ${Y(J)}`;this.error(Z,{code:"commander.conflictingOption"})}unknownOption(z){if(this._allowUnknownOption)return;let J="";if(z.startsWith("--")&&this._showSuggestionAfterError){let Y=[],Z=this;do{let $=Z.createHelp().visibleOptions(Z).filter((Q)=>Q.long).map((Q)=>Q.long);Y=Y.concat($),Z=Z.parent}while(Z&&!Z._enablePositionalOptions);J=i(z,Y)}let X=`error: unknown option '${z}'${J}`;this.error(X,{code:"commander.unknownOption"})}_excessArguments(z){if(this._allowExcessArguments)return;let J=this.registeredArguments.length,X=J===1?"":"s",Z=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${J} argument${X} but got ${z.length}.`;this.error(Z,{code:"commander.excessArguments"})}unknownCommand(){let z=this.args[0],J="";if(this._showSuggestionAfterError){let Y=[];this.createHelp().visibleCommands(this).forEach((Z)=>{if(Y.push(Z.name()),Z.alias())Y.push(Z.alias())}),J=i(z,Y)}let X=`error: unknown command '${z}'${J}`;this.error(X,{code:"commander.unknownCommand"})}version(z,J,X){if(z===void 0)return this._version;this._version=z,J=J||"-V, --version",X=X||"output the version number";let Y=this.createOption(J,X);return this._versionOptionName=Y.attributeName(),this._registerOption(Y),this.on("option:"+Y.name(),()=>{this._outputConfiguration.writeOut(`${z}
|
|
25
|
+
`),this._exit(0,"commander.version",z)}),this}description(z,J){if(z===void 0&&J===void 0)return this._description;if(this._description=z,J)this._argsDescription=J;return this}summary(z){if(z===void 0)return this._summary;return this._summary=z,this}alias(z){if(z===void 0)return this._aliases[0];let J=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler)J=this.commands[this.commands.length-1];if(z===J._name)throw Error("Command alias can't be the same as its name");let X=this.parent?._findCommand(z);if(X){let Y=[X.name()].concat(X.aliases()).join("|");throw Error(`cannot add alias '${z}' to command '${this.name()}' as already have command '${Y}'`)}return J._aliases.push(z),this}aliases(z){if(z===void 0)return this._aliases;return z.forEach((J)=>this.alias(J)),this}usage(z){if(z===void 0){if(this._usage)return this._usage;let J=this.registeredArguments.map((X)=>{return vz(X)});return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?J:[]).join(" ")}return this._usage=z,this}name(z){if(z===void 0)return this._name;return this._name=z,this}helpGroup(z){if(z===void 0)return this._helpGroupHeading??"";return this._helpGroupHeading=z,this}commandsGroup(z){if(z===void 0)return this._defaultCommandGroup??"";return this._defaultCommandGroup=z,this}optionsGroup(z){if(z===void 0)return this._defaultOptionGroup??"";return this._defaultOptionGroup=z,this}_initOptionGroup(z){if(this._defaultOptionGroup&&!z.helpGroupHeading)z.helpGroup(this._defaultOptionGroup)}_initCommandGroup(z){if(this._defaultCommandGroup&&!z.helpGroup())z.helpGroup(this._defaultCommandGroup)}nameFromFilename(z){return this._name=K.basename(z,K.extname(z)),this}executableDir(z){if(z===void 0)return this._executableDir;return this._executableDir=z,this}helpInformation(z){let J=this.createHelp(),X=this._getOutputContext(z);J.prepareContext({error:X.error,helpWidth:X.helpWidth,outputHasColors:X.hasColors});let Y=J.formatHelp(this,J);if(X.hasColors)return Y;return this._outputConfiguration.stripColor(Y)}_getOutputContext(z){z=z||{};let J=!!z.error,X,Y,Z;if(J)X=(Q)=>this._outputConfiguration.writeErr(Q),Y=this._outputConfiguration.getErrHasColors(),Z=this._outputConfiguration.getErrHelpWidth();else X=(Q)=>this._outputConfiguration.writeOut(Q),Y=this._outputConfiguration.getOutHasColors(),Z=this._outputConfiguration.getOutHelpWidth();return{error:J,write:(Q)=>{if(!Y)Q=this._outputConfiguration.stripColor(Q);return X(Q)},hasColors:Y,helpWidth:Z}}outputHelp(z){let J;if(typeof z==="function")J=z,z=void 0;let X=this._getOutputContext(z),Y={error:X.error,write:X.write,command:this};this._getCommandAndAncestors().reverse().forEach(($)=>$.emit("beforeAllHelp",Y)),this.emit("beforeHelp",Y);let Z=this.helpInformation({error:X.error});if(J){if(Z=J(Z),typeof Z!=="string"&&!Buffer.isBuffer(Z))throw Error("outputHelp callback must return a string or a Buffer")}if(X.write(Z),this._getHelpOption()?.long)this.emit(this._getHelpOption().long);this.emit("afterHelp",Y),this._getCommandAndAncestors().forEach(($)=>$.emit("afterAllHelp",Y))}helpOption(z,J){if(typeof z==="boolean"){if(z){if(this._helpOption===null)this._helpOption=void 0;if(this._defaultOptionGroup)this._initOptionGroup(this._getHelpOption())}else this._helpOption=null;return this}if(this._helpOption=this.createOption(z??"-h, --help",J??"display help for command"),z||J)this._initOptionGroup(this._helpOption);return this}_getHelpOption(){if(this._helpOption===void 0)this.helpOption(void 0,void 0);return this._helpOption}addHelpOption(z){return this._helpOption=z,this._initOptionGroup(z),this}help(z){this.outputHelp(z);let J=Number(H.exitCode??0);if(J===0&&z&&typeof z!=="function"&&z.error)J=1;this._exit(J,"commander.help","(outputHelp)")}addHelpText(z,J){let X=["beforeAll","before","after","afterAll"];if(!X.includes(z))throw Error(`Unexpected value for position to addHelpText.
|
|
26
26
|
Expecting one of '${X.join("', '")}'`);let Y=`${z}Help`;return this.on(Y,(Z)=>{let $;if(typeof J==="function")$=J({error:Z.error,command:Z.command});else $=J;if($)Z.write(`${$}
|
|
27
|
-
`)}),this}_outputHelpIfRequested(z){let J=this._getHelpOption();if(J&&z.find((Y)=>J.is(Y)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function
|
|
27
|
+
`)}),this}_outputHelpIfRequested(z){let J=this._getHelpOption();if(J&&z.find((Y)=>J.is(Y)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function r(z){return z.map((J)=>{if(!J.startsWith("--inspect"))return J;let X,Y="127.0.0.1",Z="9229",$;if(($=J.match(/^(--inspect(-brk)?)$/))!==null)X=$[1];else if(($=J.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null)if(X=$[1],/^\d+$/.test($[3]))Z=$[3];else Y=$[3];else if(($=J.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null)X=$[1],Y=$[3],Z=$[4];if(X&&Z!=="0")return`${X}=${Y}:${parseInt(Z)+1}`;return J})}function C(){if(H.env.NO_COLOR||H.env.FORCE_COLOR==="0"||H.env.FORCE_COLOR==="false")return!1;if(H.env.FORCE_COLOR||H.env.CLICOLOR_FORCE!==void 0)return!0;return}cz.Command=O;cz.useColor=C});var e=M((sz)=>{var{Argument:a}=S(),{Command:x}=n(),{CommanderError:dz,InvalidArgumentError:t}=P(),{Help:pz}=y(),{Option:o}=A();sz.program=new x;sz.createCommand=(z)=>new x(z);sz.createOption=(z,J)=>new o(z,J);sz.createArgument=(z,J)=>new a(z,J);sz.Command=x;sz.Option=o;sz.Argument=a;sz.Help=pz;sz.CommanderError=dz;sz.InvalidArgumentError=t;sz.InvalidOptionArgumentError=t});var zz=_z(e(),1),{program:jJ,createCommand:MJ,createArgument:RJ,createOption:PJ,CommanderError:IJ,InvalidArgumentError:VJ,InvalidOptionArgumentError:EJ,Command:Jz,Argument:SJ,Option:NJ,Help:DJ}=zz.default;import{existsSync as I,readdirSync as ZJ,rmSync as Xz,mkdirSync as $J}from"fs";import{readdir as QJ}from"fs/promises";import{basename as D,join as Yz,relative as BJ,resolve as V}from"path";var f=new Jz;f.name("build-db-migrations").description("Build TypeScript Kysely migration files into JavaScript using Bun's bundler").argument("<migrations-src>","Directory containing .ts migration source files").requiredOption("--outdir <dir>","Output directory for compiled migration .js files").requiredOption("--sql-module <path>","Path to sql.ts source module to build alongside").option("--sql-outdir <dir>","Output directory for the built sql.js module (defaults to parent of --outdir)").option("--external <pkg...>","Packages to keep external in the bundle",["@schemavaults/dbh","kysely"]).option("--debug","Enable debug logging",!1).action(async(z,J)=>{let X=J.debug,Y=V(z),Z=V(J.outdir),$=V(J.sqlModule),Q=J.sqlOutdir?V(J.sqlOutdir):V(Z,"..");if(!I(Y))console.error(`Error: Migrations source directory not found: ${Y}`),process.exit(1);if(!I($))console.error(`Error: sql.ts source module not found: ${$}`),process.exit(1);let G=ZJ(Y).filter((_)=>_.endsWith(".ts")).map((_)=>Yz(Y,_));if(G.length===0)console.error("Error: No .ts migration files found"),process.exit(1);if(console.log(`Found ${G.length} source .ts migration files to compile!`),I(Z))Xz(Z,{recursive:!0});$J(Z,{recursive:!0});let q=Yz(Q,"sql.js");if(I(q))Xz(q);let B="__sql_external__",U={name:"db-migrations-sql-import-rewriter",setup(_){_.onLoad({filter:/\.(ts|tsx|js|jsx)$/},async(j)=>{let E=await Bun.file(j.path).text(),b=E.replace(/import\s+{([^}]+)}\s+from\s+['"]@\/sql['"]/g,`import {$1} from "${B}"`).replace(/import\s+sql\s+from\s+['"]@\/sql['"]/g,`import { sql } from "${B}"`);if(X&&E!==b)console.log(`[db-migrations-sql-import-rewriter] onLoad(${j.path})`);return{contents:b,loader:"ts"}})}},T=await Bun.build({entrypoints:[...G],root:Y,outdir:Z,target:"node",sourcemap:"none",plugins:[U],external:[B,...J.external]});if(!T.success){console.error("Migration build failed:");for(let _ of T.logs)console.error(_);process.exit(1)}let L=await Bun.build({entrypoints:[$],outdir:Q,target:"node",sourcemap:"none"});if(!L.success){console.error("SQL module build failed:");for(let _ of L.logs)console.error(_);process.exit(1)}if(!I(q))console.error("Expected sql.js to exist after build operation!"),process.exit(1);let W=BJ(Z,q).replace(/\\/g,"/");for(let _ of T.outputs){let j=await Bun.file(_.path).text();if(j.includes(B)){let E=j.replace(new RegExp(`from\\s+["']${B}["']`,"g"),`from "${W}"`);if(await Bun.write(_.path,E),X)console.log(`[post-process] Rewrote ${B} => ${W} in ${D(_.path)}`)}}let Zz=await QJ(Z,{recursive:!1});for(let _ of Zz)if(!_.endsWith(".js"))throw Error("Expected all files in output migrations directory to end with .js!");console.log(""),console.log("Built migrations:");let $z=[...T.outputs].sort((_,j)=>D(_.path).localeCompare(D(j.path)));for(let _ of $z)console.log(` - ${D(_.path)} (${_.size} bytes)`);if(console.log(""),console.log(`Total: ${T.outputs.length} migration(s) built`),L.outputs.length!==1||!L.outputs[0])console.error("Expected there to be exactly one output from sql.js module write!");console.log(`Wrote supporting sql.js module to: ${L.outputs[0].path} (${L.outputs[0].size} bytes)`),console.log("[build-db-migrations] Successfully built database migrations!")});var OJ=f,GJ=process.argv[1]&&import.meta.url===`file://${process.argv[1]}`;if(GJ)f.parse();export{OJ as default};
|
package/package.json
CHANGED
package/.claude/settings.json
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: database-migrations
|
|
3
|
-
description: Authoring, building, validating, and running PostgreSQL database migrations with the @schemavaults/dbh package. Use when a project depends on @schemavaults/dbh and you are creating or editing Kysely migration files, setting up a migrations/ directory, or when the user mentions migrations, up()/down(), schema changes, or the dbh CLI's migrate / build-db-migrations / validate-migration-directory commands.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Database Migrations with @schemavaults/dbh
|
|
7
|
-
|
|
8
|
-
`@schemavaults/dbh` provides [Kysely](https://kysely.dev/) migrations for
|
|
9
|
-
PostgreSQL, applied through the `dbh` CLI. Migrations are opinionated: every file
|
|
10
|
-
is a numbered module that exports an `up()` and a `down()` function. TypeScript
|
|
11
|
-
source migrations are **built** to JavaScript first, then **applied** with the
|
|
12
|
-
CLI.
|
|
13
|
-
|
|
14
|
-
Invoke the CLI with your package runner. Use **`bunx @schemavaults/dbh`** for
|
|
15
|
-
**validating and building** migrations — `build-db-migrations` uses Bun's
|
|
16
|
-
bundler and requires Bun anyway. Use **`npx @schemavaults/dbh`** for **running /
|
|
17
|
-
applying** migrations (`migrate` and `reverse`): most PostgreSQL drivers are
|
|
18
|
-
built for Node.js rather than Bun, so apply migrations on the Node runtime.
|
|
19
|
-
|
|
20
|
-
## One-time setup (for consumers)
|
|
21
|
-
|
|
22
|
-
Migrations import the `sql` template tag from `@/sql` rather than directly from
|
|
23
|
-
the package. This indirection is required by the build step (see the note under
|
|
24
|
-
"Building migrations"), so configure it once:
|
|
25
|
-
|
|
26
|
-
1. **Create a local `sql` module** somewhere in your source tree, e.g.
|
|
27
|
-
`./src/db/sql.ts`, that re-exports the tag from the package:
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
// src/db/sql.ts
|
|
31
|
-
export { sql, sql as default } from "@schemavaults/dbh/sql";
|
|
32
|
-
export type * from "@schemavaults/dbh/sql";
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
2. **Configure the `@/sql` path alias** in your `tsconfig.json` so migration
|
|
36
|
-
sources typecheck and resolve:
|
|
37
|
-
|
|
38
|
-
```jsonc
|
|
39
|
-
{
|
|
40
|
-
"compilerOptions": {
|
|
41
|
-
"baseUrl": ".",
|
|
42
|
-
"paths": {
|
|
43
|
-
"@/sql": ["./src/db/sql.ts"]
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
3. **Create a migrations directory**, e.g. `./src/db/migrations/`, and add your
|
|
50
|
-
numbered migration files there.
|
|
51
|
-
|
|
52
|
-
## Migration file format
|
|
53
|
-
|
|
54
|
-
Each migration is a single file in your migrations directory. The rules are:
|
|
55
|
-
|
|
56
|
-
1. **The directory is non-empty.**
|
|
57
|
-
2. **Each file name is prefixed with a 5-digit migration number**, followed by a
|
|
58
|
-
short kebab-case description, e.g. `00000-template-migration.ts`,
|
|
59
|
-
`00001-create-users-table.ts`. The number defines apply order.
|
|
60
|
-
3. **Each module exports an `up(db)` and a `down(db)` function.** `up()` applies
|
|
61
|
-
the change; `down()` must reverse it exactly so migrations can be rolled back.
|
|
62
|
-
4. **Migration numbers are unique** — never reuse a number. If two branches both
|
|
63
|
-
add `00040-*.ts`, that collision must be resolved by renumbering one of them
|
|
64
|
-
before merge.
|
|
65
|
-
|
|
66
|
-
Both `up` and `down` receive a `Kysely<any>` instance and return a `Promise`.
|
|
67
|
-
Import the `Kysely` type from the package: `import type { Kysely } from "@schemavaults/dbh"`.
|
|
68
|
-
|
|
69
|
-
### Example: using the `Kysely<any>` query builder
|
|
70
|
-
|
|
71
|
-
Prefer the typed query builder for schema operations:
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
// 00001-create-users-table.ts
|
|
75
|
-
import type { Kysely } from "@schemavaults/dbh";
|
|
76
|
-
|
|
77
|
-
export async function up(db: Kysely<any>): Promise<void> {
|
|
78
|
-
await db.schema
|
|
79
|
-
.createTable("users")
|
|
80
|
-
.addColumn("user_id", "uuid", (col) => col.primaryKey())
|
|
81
|
-
.addColumn("email", "text", (col) => col.notNull().unique())
|
|
82
|
-
.addColumn("created_at", "bigint", (col) => col.notNull())
|
|
83
|
-
.execute();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export async function down(db: Kysely<any>): Promise<void> {
|
|
87
|
-
await db.schema.dropTable("users").execute();
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### Example: using the `sql` template tag
|
|
92
|
-
|
|
93
|
-
For statements the builder can't express (or raw DDL), import `sql` from
|
|
94
|
-
`@/sql` (your local module from setup, which re-exports Kysely's `sql` tag) and
|
|
95
|
-
call `.execute(db)`:
|
|
96
|
-
|
|
97
|
-
```ts
|
|
98
|
-
// 00002-create-squirrels-table.ts
|
|
99
|
-
import type { Kysely } from "@schemavaults/dbh";
|
|
100
|
-
import { sql } from "@/sql";
|
|
101
|
-
|
|
102
|
-
export async function up(db: Kysely<any>): Promise<void> {
|
|
103
|
-
await sql`
|
|
104
|
-
CREATE TABLE IF NOT EXISTS EXAMPLE_SQUIRRELS (
|
|
105
|
-
squirrel_id UUID PRIMARY KEY,
|
|
106
|
-
squirrel_name TEXT NOT NULL,
|
|
107
|
-
created_at BIGINT NOT NULL
|
|
108
|
-
);
|
|
109
|
-
`.execute(db);
|
|
110
|
-
|
|
111
|
-
// Always interpolate values via ${...}; the sql tag parameterizes them.
|
|
112
|
-
await sql`CREATE INDEX squirrels_name_idx ON EXAMPLE_SQUIRRELS (squirrel_name);`.execute(
|
|
113
|
-
db,
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export async function down(db: Kysely<any>): Promise<void> {
|
|
118
|
-
await sql`DROP TABLE IF EXISTS EXAMPLE_SQUIRRELS;`.execute(db);
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
> Important: migration files must **always** import `sql` from `@/sql`, never
|
|
123
|
-
> directly from `@schemavaults/dbh/sql`. The `build-db-migrations` step rewrites
|
|
124
|
-
> the literal `@/sql` import specifier to a relative path pointing at the built,
|
|
125
|
-
> standalone `sql.js`, so the import must be written exactly as `@/sql` for the
|
|
126
|
-
> build to work. (This is why the one-time setup configures the `@/sql` alias.)
|
|
127
|
-
|
|
128
|
-
### Empty template migration
|
|
129
|
-
|
|
130
|
-
A no-op migration is valid (useful as a starting template):
|
|
131
|
-
|
|
132
|
-
```ts
|
|
133
|
-
// 00000-template-migration.ts
|
|
134
|
-
import type { Kysely } from "@schemavaults/dbh";
|
|
135
|
-
|
|
136
|
-
export async function up(
|
|
137
|
-
db: Kysely<any>, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
138
|
-
): Promise<void> {}
|
|
139
|
-
|
|
140
|
-
export async function down(
|
|
141
|
-
db: Kysely<any>, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
142
|
-
): Promise<void> {}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Validating migrations
|
|
146
|
-
|
|
147
|
-
Before building or applying, assert your source migrations directory is
|
|
148
|
-
well-formed. The `validate-migration-directory` command checks all four rules
|
|
149
|
-
above and exits `0` when valid, non-zero otherwise (good for CI / pre-commit):
|
|
150
|
-
|
|
151
|
-
```bash
|
|
152
|
-
bunx @schemavaults/dbh validate-migration-directory ./src/db/migrations
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
It reports each problem with an `[ERROR]`/`[WARN]` prefix:
|
|
156
|
-
- empty directory,
|
|
157
|
-
- a file missing the 5-digit prefix,
|
|
158
|
-
- a module missing `up()` or `down()`,
|
|
159
|
-
- duplicate migration numbers (branch collisions).
|
|
160
|
-
|
|
161
|
-
Treat duplicate numbers as warnings (non-fatal) with `--duplicates-as-warnings`.
|
|
162
|
-
|
|
163
|
-
## Building migrations
|
|
164
|
-
|
|
165
|
-
TypeScript migrations must be compiled to JavaScript before they're applied
|
|
166
|
-
(the `migrate` step runs on Node and imports `.js`). The `build-db-migrations`
|
|
167
|
-
command uses Bun's bundler and also builds the standalone `sql` module the
|
|
168
|
-
migrations depend on. Point `--sql-module` at the local `sql.ts` you created
|
|
169
|
-
during setup:
|
|
170
|
-
|
|
171
|
-
```bash
|
|
172
|
-
bunx @schemavaults/dbh build-db-migrations ./src/db/migrations \
|
|
173
|
-
--outdir ./dist/migrations \
|
|
174
|
-
--sql-module ./src/db/sql.ts \
|
|
175
|
-
--sql-outdir ./dist
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Key options:
|
|
179
|
-
- `<migrations-src>` — directory of `.ts` migration sources (positional).
|
|
180
|
-
- `--outdir <dir>` — where compiled `.js` migrations are written (required).
|
|
181
|
-
- `--sql-module <path>` — path to your local `sql.ts` module to build alongside (required).
|
|
182
|
-
- `--sql-outdir <dir>` — where the built `sql.js` goes (defaults to the parent of `--outdir`).
|
|
183
|
-
- `--external <pkg...>` — packages to keep external (default: `@schemavaults/dbh`, `kysely`).
|
|
184
|
-
|
|
185
|
-
`build-db-migrations` requires `bun` to be installed and on the PATH.
|
|
186
|
-
|
|
187
|
-
## Running migrations
|
|
188
|
-
|
|
189
|
-
Apply built migrations with `migrate`, and roll back with `reverse`. Both take
|
|
190
|
-
the **built** migration folder and require an `--environment`; credentials come
|
|
191
|
-
from `process.env` (or an `--env-file`). Run these with **`npx`** (Node.js):
|
|
192
|
-
most PostgreSQL drivers target Node rather than Bun.
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
# Apply all pending migrations (to latest):
|
|
196
|
-
npx @schemavaults/dbh migrate ./dist/migrations --environment production --env-file ./.env.production
|
|
197
|
-
|
|
198
|
-
# Apply up to a specific version (the migration name w/o extension):
|
|
199
|
-
npx @schemavaults/dbh migrate ./dist/migrations 00001-create-users-table --environment staging
|
|
200
|
-
|
|
201
|
-
# Roll back down to a target version:
|
|
202
|
-
npx @schemavaults/dbh reverse ./dist/migrations 00000-template-migration --environment staging
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
Options for `migrate` / `reverse`:
|
|
206
|
-
- `<folder>` — path to the built migration folder (positional).
|
|
207
|
-
- `[version]` / `<version>` — target migration name; `migrate` defaults to latest, `reverse` requires it.
|
|
208
|
-
- `-e, --environment <env>` — `development | test | staging | production` (required).
|
|
209
|
-
- `--ws-proxy-url <url>` — custom Neon-compatible WebSocket proxy URL.
|
|
210
|
-
- `--env-file <path>` — load DB credentials from a `.env` file first.
|
|
211
|
-
|
|
212
|
-
Each result line prints as `[Up|Down] <migrationName>: <Success|Error|NotExecuted>`.
|
|
213
|
-
|
|
214
|
-
### Programmatic API
|
|
215
|
-
|
|
216
|
-
The same operations are available from `@schemavaults/dbh/migrate` for tests or
|
|
217
|
-
custom scripts, using the adapter's Kysely instance:
|
|
218
|
-
|
|
219
|
-
```ts
|
|
220
|
-
import { migrate, reverse } from "@schemavaults/dbh/migrate";
|
|
221
|
-
|
|
222
|
-
await migrate({ db: adapter.db, migrationFolder, version /* optional */ });
|
|
223
|
-
await reverse({ db: adapter.db, migrationFolder, version });
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
## Typical end-to-end flow
|
|
227
|
-
|
|
228
|
-
```bash
|
|
229
|
-
# 1. Validate the source migrations directory.
|
|
230
|
-
bunx @schemavaults/dbh validate-migration-directory ./src/db/migrations
|
|
231
|
-
|
|
232
|
-
# 2. Build .ts migrations (+ sql module) to .js.
|
|
233
|
-
bunx @schemavaults/dbh build-db-migrations ./src/db/migrations \
|
|
234
|
-
--outdir ./dist/migrations --sql-module ./src/db/sql.ts --sql-outdir ./dist
|
|
235
|
-
|
|
236
|
-
# 3. Apply the built migrations (npx / Node.js — pg drivers target Node).
|
|
237
|
-
npx @schemavaults/dbh migrate ./dist/migrations --environment production --env-file ./.env.production
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
## Required environment variables (for migrate/reverse)
|
|
241
|
-
|
|
242
|
-
`POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_URL`, `POSTGRES_HOST`,
|
|
243
|
-
`POSTGRES_PORT`, `POSTGRES_DATABASE` (and optional `POSTGRES_URL_NON_POOLING`).
|
|
244
|
-
Set `SCHEMAVAULTS_DBH_DEBUG=true` for verbose debug logging.
|
package/CLAUDE.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## What This Is
|
|
6
|
-
|
|
7
|
-
`@schemavaults/dbh` is an npm package that provides a Kysely-based adapter for connecting to Postgres databases through a Neon-compatible WebSocket proxy. It works with both Neon-hosted serverless Postgres and local Postgres instances (via a bundled WS proxy).
|
|
8
|
-
|
|
9
|
-
## Commands
|
|
10
|
-
|
|
11
|
-
Ensure dependencies are installed with `bun install` before attempting to run any other commands.
|
|
12
|
-
|
|
13
|
-
- **Build:** `bun run build` (runs tsc + tsc-alias, then cleans test files from dist/)
|
|
14
|
-
- **Lint:** `bun run lint` (eslint on src/)
|
|
15
|
-
- **Unit tests:** `bun run test` or `bun run test:unit`
|
|
16
|
-
- **Single test:** `bun test --test-name-pattern '<pattern>'`
|
|
17
|
-
- **E2E tests:** `cd tests && /bin/bash ./run_e2e_tests.sh` (requires Docker Compose — spins up postgres, ws-proxy, and test-runner containers)
|
|
18
|
-
- **CLI:** `bun run cli --help` locally or `bunx @schemavaults/dbh --help` remotely.
|
|
19
|
-
|
|
20
|
-
## Architecture
|
|
21
|
-
|
|
22
|
-
The core adapter is `SchemaVaultsPostgresNeonProxyAdapter<T>` (generic over Kysely table types). It wraps Kysely with a `NeonDialect` and handles credential parsing, WS proxy URL resolution, and debug logging. Consumers extend or instantiate it, passing an environment (`development|test|staging|production`), optional credentials (defaults to env vars), and an optional `wsProxyUrl` (string or generator function).
|
|
23
|
-
|
|
24
|
-
Key modules:
|
|
25
|
-
- `src/schemavaults-postgres-neon-proxy-adapter.ts` — the main adapter class
|
|
26
|
-
- `src/migrate.ts` — Kysely migration helpers (`migrate`, `reverse`), exported as a separate entrypoint (`@schemavaults/dbh/migrate`)
|
|
27
|
-
- `src/sql.ts` — re-exports Kysely's `sql` tag
|
|
28
|
-
- `src/utils/parseDatabaseCredentials.ts` — parses/validates DB credentials from an object or `process.env`
|
|
29
|
-
|
|
30
|
-
The package has two export entrypoints: `.` (adapter + sql + types), `./sql` (Kysely template tag re-export), `./migrate` (migration utilities), and `./cli` (@schemavaults/dbh command-line utility).
|
|
31
|
-
|
|
32
|
-
## Local Dev Environment
|
|
33
|
-
|
|
34
|
-
- Runtime/package manager: **Bun** (v1.3.6)
|
|
35
|
-
- TypeScript with path alias `@/*` → `src/*` (resolved by tsc-alias at build time)
|
|
36
|
-
- E2E tests run inside Docker containers (postgres:17.7 + a Go-based WS proxy on port 5433)
|
|
37
|
-
|
|
38
|
-
## Environment Variables
|
|
39
|
-
|
|
40
|
-
The adapter reads these from `process.env` when credentials aren't passed directly:
|
|
41
|
-
`POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_URL`, `POSTGRES_URL_NON_POOLING` (optional), `POSTGRES_HOST`, `POSTGRES_PORT`, `POSTGRES_DATABASE`. Debug mode via `SCHEMAVAULTS_DBH_DEBUG=true`.
|
package/eslint.config.cjs
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// @schemavaults/dbh - eslint.config.cjs
|
|
2
|
-
|
|
3
|
-
const js = require("@eslint/js");
|
|
4
|
-
const tsParser = require("@typescript-eslint/parser");
|
|
5
|
-
const tsPlugin = require("@typescript-eslint/eslint-plugin");
|
|
6
|
-
const globals = require("globals");
|
|
7
|
-
|
|
8
|
-
module.exports = [
|
|
9
|
-
// Base recommended configs
|
|
10
|
-
js.configs.recommended,
|
|
11
|
-
|
|
12
|
-
// Main config
|
|
13
|
-
{
|
|
14
|
-
files: ["src/**/*.{ts,tsx,js,jsx}"],
|
|
15
|
-
|
|
16
|
-
languageOptions: {
|
|
17
|
-
parser: tsParser,
|
|
18
|
-
parserOptions: {
|
|
19
|
-
ecmaVersion: "latest",
|
|
20
|
-
sourceType: "module",
|
|
21
|
-
ecmaFeatures: {
|
|
22
|
-
jsx: false,
|
|
23
|
-
},
|
|
24
|
-
project: "./tsconfig.json",
|
|
25
|
-
},
|
|
26
|
-
globals: {
|
|
27
|
-
...globals.browser,
|
|
28
|
-
...globals.es2021,
|
|
29
|
-
...globals.node,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
plugins: {
|
|
34
|
-
"@typescript-eslint": tsPlugin,
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
rules: {
|
|
38
|
-
// TypeScript recommended rules
|
|
39
|
-
...tsPlugin.configs.recommended.rules,
|
|
40
|
-
|
|
41
|
-
"@typescript-eslint/no-unused-vars": [
|
|
42
|
-
"warn",
|
|
43
|
-
{ argsIgnorePattern: "^_" },
|
|
44
|
-
],
|
|
45
|
-
"@typescript-eslint/no-explicit-any": "off",
|
|
46
|
-
"@typescript-eslint/no-namespace": "off",
|
|
47
|
-
"@typescript-eslint/no-empty-object-type": "off",
|
|
48
|
-
"no-redeclare": "off",
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
// Ignore patterns
|
|
53
|
-
{
|
|
54
|
-
ignores: ["dist/**", "node_modules/**", "*.config.js", "*.config.cjs"],
|
|
55
|
-
},
|
|
56
|
-
];
|