morphix-env 0.7.1 → 0.8.0
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 +42 -0
- package/dist/SKILL.md +11 -2
- package/dist/cli.js +565 -79
- package/dist/index.d.ts +174 -0
- package/dist/index.js +732 -0
- package/package.json +16 -3
package/dist/cli.js
CHANGED
|
@@ -831,8 +831,8 @@ var require_react_development = __commonJS({
|
|
|
831
831
|
function lazyInitializer(payload) {
|
|
832
832
|
if (-1 === payload._status) {
|
|
833
833
|
var resolveDebugValue = null, rejectDebugValue = null, ioInfo = payload._ioInfo;
|
|
834
|
-
null != ioInfo && (ioInfo.start = ioInfo.end = performance.now(), ioInfo.value = new Promise(function(
|
|
835
|
-
resolveDebugValue =
|
|
834
|
+
null != ioInfo && (ioInfo.start = ioInfo.end = performance.now(), ioInfo.value = new Promise(function(resolve7, reject) {
|
|
835
|
+
resolveDebugValue = resolve7;
|
|
836
836
|
rejectDebugValue = reject;
|
|
837
837
|
}));
|
|
838
838
|
ioInfo = payload._result;
|
|
@@ -948,21 +948,21 @@ var require_react_development = __commonJS({
|
|
|
948
948
|
);
|
|
949
949
|
actScopeDepth = prevActScopeDepth;
|
|
950
950
|
}
|
|
951
|
-
function recursivelyFlushAsyncActWork(returnValue,
|
|
951
|
+
function recursivelyFlushAsyncActWork(returnValue, resolve7, reject) {
|
|
952
952
|
var queue = ReactSharedInternals.actQueue;
|
|
953
953
|
if (null !== queue)
|
|
954
954
|
if (0 !== queue.length)
|
|
955
955
|
try {
|
|
956
956
|
flushActQueue(queue);
|
|
957
957
|
enqueueTask(function() {
|
|
958
|
-
return recursivelyFlushAsyncActWork(returnValue,
|
|
958
|
+
return recursivelyFlushAsyncActWork(returnValue, resolve7, reject);
|
|
959
959
|
});
|
|
960
960
|
return;
|
|
961
961
|
} catch (error) {
|
|
962
962
|
ReactSharedInternals.thrownErrors.push(error);
|
|
963
963
|
}
|
|
964
964
|
else ReactSharedInternals.actQueue = null;
|
|
965
|
-
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) :
|
|
965
|
+
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve7(returnValue);
|
|
966
966
|
}
|
|
967
967
|
function flushActQueue(queue) {
|
|
968
968
|
if (!isFlushing) {
|
|
@@ -1150,7 +1150,7 @@ var require_react_development = __commonJS({
|
|
|
1150
1150
|
));
|
|
1151
1151
|
});
|
|
1152
1152
|
return {
|
|
1153
|
-
then: function(
|
|
1153
|
+
then: function(resolve7, reject) {
|
|
1154
1154
|
didAwaitActCall = true;
|
|
1155
1155
|
thenable.then(
|
|
1156
1156
|
function(returnValue) {
|
|
@@ -1160,7 +1160,7 @@ var require_react_development = __commonJS({
|
|
|
1160
1160
|
flushActQueue(queue), enqueueTask(function() {
|
|
1161
1161
|
return recursivelyFlushAsyncActWork(
|
|
1162
1162
|
returnValue,
|
|
1163
|
-
|
|
1163
|
+
resolve7,
|
|
1164
1164
|
reject
|
|
1165
1165
|
);
|
|
1166
1166
|
});
|
|
@@ -1174,7 +1174,7 @@ var require_react_development = __commonJS({
|
|
|
1174
1174
|
ReactSharedInternals.thrownErrors.length = 0;
|
|
1175
1175
|
reject(_thrownError);
|
|
1176
1176
|
}
|
|
1177
|
-
} else
|
|
1177
|
+
} else resolve7(returnValue);
|
|
1178
1178
|
},
|
|
1179
1179
|
function(error) {
|
|
1180
1180
|
popActScope(prevActQueue, prevActScopeDepth);
|
|
@@ -1196,15 +1196,15 @@ var require_react_development = __commonJS({
|
|
|
1196
1196
|
if (0 < ReactSharedInternals.thrownErrors.length)
|
|
1197
1197
|
throw callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
|
|
1198
1198
|
return {
|
|
1199
|
-
then: function(
|
|
1199
|
+
then: function(resolve7, reject) {
|
|
1200
1200
|
didAwaitActCall = true;
|
|
1201
1201
|
0 === prevActScopeDepth ? (ReactSharedInternals.actQueue = queue, enqueueTask(function() {
|
|
1202
1202
|
return recursivelyFlushAsyncActWork(
|
|
1203
1203
|
returnValue$jscomp$0,
|
|
1204
|
-
|
|
1204
|
+
resolve7,
|
|
1205
1205
|
reject
|
|
1206
1206
|
);
|
|
1207
|
-
})) :
|
|
1207
|
+
})) : resolve7(returnValue$jscomp$0);
|
|
1208
1208
|
}
|
|
1209
1209
|
};
|
|
1210
1210
|
};
|
|
@@ -12991,7 +12991,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
12991
12991
|
};
|
|
12992
12992
|
}
|
|
12993
12993
|
exports2.prerender = function(children, options) {
|
|
12994
|
-
return new Promise(function(
|
|
12994
|
+
return new Promise(function(resolve7, reject) {
|
|
12995
12995
|
var onHeaders = options ? options.onHeaders : void 0, onHeadersImpl;
|
|
12996
12996
|
onHeaders && (onHeadersImpl = function(headersDescriptor) {
|
|
12997
12997
|
onHeaders(new Headers(headersDescriptor));
|
|
@@ -13035,7 +13035,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13035
13035
|
{ highWaterMark: 0 }
|
|
13036
13036
|
);
|
|
13037
13037
|
stream2 = { postponed: getPostponedState(request), prelude: stream2 };
|
|
13038
|
-
|
|
13038
|
+
resolve7(stream2);
|
|
13039
13039
|
},
|
|
13040
13040
|
void 0,
|
|
13041
13041
|
void 0,
|
|
@@ -13046,7 +13046,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13046
13046
|
});
|
|
13047
13047
|
};
|
|
13048
13048
|
exports2.prerenderToNodeStream = function(children, options) {
|
|
13049
|
-
return new Promise(function(
|
|
13049
|
+
return new Promise(function(resolve7, reject) {
|
|
13050
13050
|
var resumableState = createResumableState(
|
|
13051
13051
|
options ? options.identifierPrefix : void 0,
|
|
13052
13052
|
options ? options.unstable_externalRuntimeSrc : void 0,
|
|
@@ -13078,7 +13078,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13078
13078
|
postponed: getPostponedState(request),
|
|
13079
13079
|
prelude: readable
|
|
13080
13080
|
};
|
|
13081
|
-
|
|
13081
|
+
resolve7(readable);
|
|
13082
13082
|
},
|
|
13083
13083
|
void 0,
|
|
13084
13084
|
void 0,
|
|
@@ -13123,7 +13123,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13123
13123
|
};
|
|
13124
13124
|
};
|
|
13125
13125
|
exports2.renderToReadableStream = function(children, options) {
|
|
13126
|
-
return new Promise(function(
|
|
13126
|
+
return new Promise(function(resolve7, reject) {
|
|
13127
13127
|
var onFatalError, onAllReady, allReady = new Promise(function(res, rej) {
|
|
13128
13128
|
onAllReady = res;
|
|
13129
13129
|
onFatalError = rej;
|
|
@@ -13173,7 +13173,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13173
13173
|
{ highWaterMark: 0 }
|
|
13174
13174
|
);
|
|
13175
13175
|
stream2.allReady = allReady;
|
|
13176
|
-
|
|
13176
|
+
resolve7(stream2);
|
|
13177
13177
|
},
|
|
13178
13178
|
function(error) {
|
|
13179
13179
|
allReady.catch(function() {
|
|
@@ -13188,7 +13188,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13188
13188
|
});
|
|
13189
13189
|
};
|
|
13190
13190
|
exports2.resume = function(children, postponedState, options) {
|
|
13191
|
-
return new Promise(function(
|
|
13191
|
+
return new Promise(function(resolve7, reject) {
|
|
13192
13192
|
var onFatalError, onAllReady, allReady = new Promise(function(res, rej) {
|
|
13193
13193
|
onAllReady = res;
|
|
13194
13194
|
onFatalError = rej;
|
|
@@ -13226,7 +13226,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13226
13226
|
{ highWaterMark: 0 }
|
|
13227
13227
|
);
|
|
13228
13228
|
stream2.allReady = allReady;
|
|
13229
|
-
|
|
13229
|
+
resolve7(stream2);
|
|
13230
13230
|
},
|
|
13231
13231
|
function(error) {
|
|
13232
13232
|
allReady.catch(function() {
|
|
@@ -13240,7 +13240,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13240
13240
|
});
|
|
13241
13241
|
};
|
|
13242
13242
|
exports2.resumeAndPrerender = function(children, postponedState, options) {
|
|
13243
|
-
return new Promise(function(
|
|
13243
|
+
return new Promise(function(resolve7, reject) {
|
|
13244
13244
|
var request = resumeAndPrerenderRequest(
|
|
13245
13245
|
children,
|
|
13246
13246
|
postponedState,
|
|
@@ -13272,7 +13272,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13272
13272
|
{ highWaterMark: 0 }
|
|
13273
13273
|
);
|
|
13274
13274
|
stream2 = { postponed: getPostponedState(request), prelude: stream2 };
|
|
13275
|
-
|
|
13275
|
+
resolve7(stream2);
|
|
13276
13276
|
},
|
|
13277
13277
|
void 0,
|
|
13278
13278
|
void 0,
|
|
@@ -13283,7 +13283,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13283
13283
|
});
|
|
13284
13284
|
};
|
|
13285
13285
|
exports2.resumeAndPrerenderToNodeStream = function(children, postponedState, options) {
|
|
13286
|
-
return new Promise(function(
|
|
13286
|
+
return new Promise(function(resolve7, reject) {
|
|
13287
13287
|
var request = resumeAndPrerenderRequest(
|
|
13288
13288
|
children,
|
|
13289
13289
|
postponedState,
|
|
@@ -13304,7 +13304,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13304
13304
|
}
|
|
13305
13305
|
}), writable = createFakeWritableFromReadable(readable);
|
|
13306
13306
|
readable = { postponed: getPostponedState(request), prelude: readable };
|
|
13307
|
-
|
|
13307
|
+
resolve7(readable);
|
|
13308
13308
|
},
|
|
13309
13309
|
void 0,
|
|
13310
13310
|
void 0,
|
|
@@ -28776,7 +28776,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28776
28776
|
ensureCorrectIsomorphicReactVersion();
|
|
28777
28777
|
ensureCorrectIsomorphicReactVersion();
|
|
28778
28778
|
exports2.prerender = function(children, options) {
|
|
28779
|
-
return new Promise(function(
|
|
28779
|
+
return new Promise(function(resolve7, reject) {
|
|
28780
28780
|
var onHeaders = options ? options.onHeaders : void 0, onHeadersImpl;
|
|
28781
28781
|
onHeaders && (onHeadersImpl = function(headersDescriptor) {
|
|
28782
28782
|
onHeaders(new Headers(headersDescriptor));
|
|
@@ -28825,7 +28825,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28825
28825
|
postponed: getPostponedState(request),
|
|
28826
28826
|
prelude: stream2
|
|
28827
28827
|
};
|
|
28828
|
-
|
|
28828
|
+
resolve7(stream2);
|
|
28829
28829
|
},
|
|
28830
28830
|
void 0,
|
|
28831
28831
|
void 0,
|
|
@@ -28836,7 +28836,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28836
28836
|
});
|
|
28837
28837
|
};
|
|
28838
28838
|
exports2.prerenderToNodeStream = function(children, options) {
|
|
28839
|
-
return new Promise(function(
|
|
28839
|
+
return new Promise(function(resolve7, reject) {
|
|
28840
28840
|
var resumableState = createResumableState(
|
|
28841
28841
|
options ? options.identifierPrefix : void 0,
|
|
28842
28842
|
options ? options.unstable_externalRuntimeSrc : void 0,
|
|
@@ -28868,7 +28868,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28868
28868
|
postponed: getPostponedState(request),
|
|
28869
28869
|
prelude: readable
|
|
28870
28870
|
};
|
|
28871
|
-
|
|
28871
|
+
resolve7(readable);
|
|
28872
28872
|
},
|
|
28873
28873
|
void 0,
|
|
28874
28874
|
void 0,
|
|
@@ -28913,7 +28913,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28913
28913
|
};
|
|
28914
28914
|
};
|
|
28915
28915
|
exports2.renderToReadableStream = function(children, options) {
|
|
28916
|
-
return new Promise(function(
|
|
28916
|
+
return new Promise(function(resolve7, reject) {
|
|
28917
28917
|
var onFatalError, onAllReady, allReady = new Promise(function(res, rej) {
|
|
28918
28918
|
onAllReady = res;
|
|
28919
28919
|
onFatalError = rej;
|
|
@@ -28963,7 +28963,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28963
28963
|
{ highWaterMark: 0 }
|
|
28964
28964
|
);
|
|
28965
28965
|
stream2.allReady = allReady;
|
|
28966
|
-
|
|
28966
|
+
resolve7(stream2);
|
|
28967
28967
|
},
|
|
28968
28968
|
function(error) {
|
|
28969
28969
|
allReady.catch(function() {
|
|
@@ -28978,7 +28978,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28978
28978
|
});
|
|
28979
28979
|
};
|
|
28980
28980
|
exports2.resume = function(children, postponedState, options) {
|
|
28981
|
-
return new Promise(function(
|
|
28981
|
+
return new Promise(function(resolve7, reject) {
|
|
28982
28982
|
var onFatalError, onAllReady, allReady = new Promise(function(res, rej) {
|
|
28983
28983
|
onAllReady = res;
|
|
28984
28984
|
onFatalError = rej;
|
|
@@ -29016,7 +29016,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29016
29016
|
{ highWaterMark: 0 }
|
|
29017
29017
|
);
|
|
29018
29018
|
stream2.allReady = allReady;
|
|
29019
|
-
|
|
29019
|
+
resolve7(stream2);
|
|
29020
29020
|
},
|
|
29021
29021
|
function(error) {
|
|
29022
29022
|
allReady.catch(function() {
|
|
@@ -29030,7 +29030,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29030
29030
|
});
|
|
29031
29031
|
};
|
|
29032
29032
|
exports2.resumeAndPrerender = function(children, postponedState, options) {
|
|
29033
|
-
return new Promise(function(
|
|
29033
|
+
return new Promise(function(resolve7, reject) {
|
|
29034
29034
|
var request = resumeAndPrerenderRequest(
|
|
29035
29035
|
children,
|
|
29036
29036
|
postponedState,
|
|
@@ -29064,7 +29064,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29064
29064
|
{ highWaterMark: 0 }
|
|
29065
29065
|
);
|
|
29066
29066
|
stream2 = { postponed: getPostponedState(request), prelude: stream2 };
|
|
29067
|
-
|
|
29067
|
+
resolve7(stream2);
|
|
29068
29068
|
},
|
|
29069
29069
|
void 0,
|
|
29070
29070
|
void 0,
|
|
@@ -29075,7 +29075,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29075
29075
|
});
|
|
29076
29076
|
};
|
|
29077
29077
|
exports2.resumeAndPrerenderToNodeStream = function(children, postponedState, options) {
|
|
29078
|
-
return new Promise(function(
|
|
29078
|
+
return new Promise(function(resolve7, reject) {
|
|
29079
29079
|
var request = resumeAndPrerenderRequest(
|
|
29080
29080
|
children,
|
|
29081
29081
|
postponedState,
|
|
@@ -29099,7 +29099,7 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
29099
29099
|
postponed: getPostponedState(request),
|
|
29100
29100
|
prelude: readable
|
|
29101
29101
|
};
|
|
29102
|
-
|
|
29102
|
+
resolve7(readable);
|
|
29103
29103
|
},
|
|
29104
29104
|
void 0,
|
|
29105
29105
|
void 0,
|
|
@@ -29482,9 +29482,9 @@ var require_jsx_runtime = __commonJS({
|
|
|
29482
29482
|
|
|
29483
29483
|
// src/cli.ts
|
|
29484
29484
|
var import_cross_spawn = __toESM(require("cross-spawn"));
|
|
29485
|
-
var
|
|
29486
|
-
var
|
|
29487
|
-
var
|
|
29485
|
+
var import_fs9 = require("fs");
|
|
29486
|
+
var import_os6 = require("os");
|
|
29487
|
+
var import_path9 = require("path");
|
|
29488
29488
|
|
|
29489
29489
|
// src/audit.ts
|
|
29490
29490
|
var import_fs = require("fs");
|
|
@@ -29502,11 +29502,12 @@ function writeAudit(event, homeDir = (0, import_os.homedir)()) {
|
|
|
29502
29502
|
}
|
|
29503
29503
|
|
|
29504
29504
|
// src/composition.ts
|
|
29505
|
-
var
|
|
29505
|
+
var import_os3 = require("os");
|
|
29506
29506
|
|
|
29507
29507
|
// src/config.ts
|
|
29508
29508
|
var import_fs2 = require("fs");
|
|
29509
29509
|
var import_path2 = require("path");
|
|
29510
|
+
var import_os2 = require("os");
|
|
29510
29511
|
var CONFIG_FILE = "mx-env.config.json";
|
|
29511
29512
|
var GLOBAL_CONFIG_DIR = ".mx-env";
|
|
29512
29513
|
var GLOBAL_CONFIG_FILE = "config.json";
|
|
@@ -29534,7 +29535,7 @@ function loadConfigAt(path) {
|
|
|
29534
29535
|
}
|
|
29535
29536
|
function loadConfigLayers(options = {}) {
|
|
29536
29537
|
const cwd = options.cwd || process.cwd();
|
|
29537
|
-
const homeDir = options.homeDir || (0,
|
|
29538
|
+
const homeDir = options.homeDir || (0, import_os2.homedir)();
|
|
29538
29539
|
const globalDir = (0, import_path2.resolve)(homeDir, GLOBAL_CONFIG_DIR);
|
|
29539
29540
|
return {
|
|
29540
29541
|
global: loadConfigAt((0, import_path2.resolve)(globalDir, GLOBAL_CONFIG_FILE)),
|
|
@@ -29549,7 +29550,7 @@ function normalizeProfile(input) {
|
|
|
29549
29550
|
...input?.extends ? { extends: input.extends } : {}
|
|
29550
29551
|
};
|
|
29551
29552
|
}
|
|
29552
|
-
function expandHomePath(path, homeDir = (0,
|
|
29553
|
+
function expandHomePath(path, homeDir = (0, import_os2.homedir)()) {
|
|
29553
29554
|
if (path === "~") return homeDir;
|
|
29554
29555
|
if (path.startsWith("~/")) return (0, import_path2.resolve)(homeDir, path.slice(2));
|
|
29555
29556
|
return path;
|
|
@@ -29580,6 +29581,14 @@ function validateConfig(config, label = CONFIG_FILE) {
|
|
|
29580
29581
|
if (!source.project || !source.config) errors.push(`${label}: Doppler source "${name}" needs project and config`);
|
|
29581
29582
|
if (source.optional) errors.push(`${label}: remote source "${name}" cannot be optional`);
|
|
29582
29583
|
break;
|
|
29584
|
+
case "plugin":
|
|
29585
|
+
if (typeof source.plugin !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(source.plugin)) {
|
|
29586
|
+
errors.push(`${label}: plugin source "${name}" needs a plugin name (letters, digits, ".", "_", "-")`);
|
|
29587
|
+
}
|
|
29588
|
+
if (!Array.isArray(source.keys) || !source.keys.length || source.keys.some((key) => typeof key !== "string" || !key)) {
|
|
29589
|
+
errors.push(`${label}: plugin source "${name}" needs at least one key`);
|
|
29590
|
+
}
|
|
29591
|
+
break;
|
|
29583
29592
|
default:
|
|
29584
29593
|
errors.push(`${label}: source "${name}" has an unsupported provider`);
|
|
29585
29594
|
}
|
|
@@ -29910,6 +29919,31 @@ function resolveDoppler(entry, source, context) {
|
|
|
29910
29919
|
function parseDotenvText(text) {
|
|
29911
29920
|
return (0, import_dotenv3.parse)(text);
|
|
29912
29921
|
}
|
|
29922
|
+
var PLUGIN_TIMEOUT_MS = 3e4;
|
|
29923
|
+
function resolvePlugin(entry, source, context) {
|
|
29924
|
+
const command = `mx-env-provider-${source.plugin}`;
|
|
29925
|
+
const values = {};
|
|
29926
|
+
for (const key of source.keys) {
|
|
29927
|
+
let output;
|
|
29928
|
+
try {
|
|
29929
|
+
output = (0, import_child_process2.execFileSync)(command, [key], {
|
|
29930
|
+
encoding: "utf8",
|
|
29931
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
29932
|
+
env: { ...process.env, ...context.environment },
|
|
29933
|
+
timeout: PLUGIN_TIMEOUT_MS
|
|
29934
|
+
});
|
|
29935
|
+
} catch (error) {
|
|
29936
|
+
if (error?.code === "ENOENT") {
|
|
29937
|
+
if (source.optional) return { name: entry.name, provider: source.provider, values: {}, availability: "missing-optional" };
|
|
29938
|
+
throw new SourceError(entry.name, source.provider, `[morphix-env] plugin source "${entry.name}" needs ${command} on PATH.`);
|
|
29939
|
+
}
|
|
29940
|
+
const reason = typeof error?.code === "string" ? error.code : `exit ${error?.status ?? "unknown"}`;
|
|
29941
|
+
throw new SourceError(entry.name, source.provider, `[morphix-env] plugin source "${entry.name}" failed for key "${key}" (${reason}).`);
|
|
29942
|
+
}
|
|
29943
|
+
values[key] = output.endsWith("\r\n") ? output.slice(0, -2) : output.endsWith("\n") ? output.slice(0, -1) : output;
|
|
29944
|
+
}
|
|
29945
|
+
return { name: entry.name, provider: source.provider, values, availability: "loaded" };
|
|
29946
|
+
}
|
|
29913
29947
|
async function loadSource(entry, context) {
|
|
29914
29948
|
switch (entry.source.provider) {
|
|
29915
29949
|
case "local":
|
|
@@ -29922,6 +29956,8 @@ async function loadSource(entry, context) {
|
|
|
29922
29956
|
return resolveKeychain(entry, entry.source);
|
|
29923
29957
|
case "doppler":
|
|
29924
29958
|
return resolveDoppler(entry, entry.source, context);
|
|
29959
|
+
case "plugin":
|
|
29960
|
+
return resolvePlugin(entry, entry.source, context);
|
|
29925
29961
|
}
|
|
29926
29962
|
}
|
|
29927
29963
|
|
|
@@ -29936,6 +29972,9 @@ var CompositionError = class extends Error {
|
|
|
29936
29972
|
this.name = "CompositionError";
|
|
29937
29973
|
}
|
|
29938
29974
|
};
|
|
29975
|
+
function collectRedactionValues(environment, provenance) {
|
|
29976
|
+
return [...new Set(Object.entries(provenance).filter(([key]) => !isPublicKey(key) && Boolean(environment[key])).map(([key]) => environment[key]).filter(Boolean))];
|
|
29977
|
+
}
|
|
29939
29978
|
function declaredEntries(loaded) {
|
|
29940
29979
|
return new Map(Object.entries(loaded.config.sources || {}).map(([name, source]) => [name, {
|
|
29941
29980
|
name,
|
|
@@ -30045,7 +30084,7 @@ async function composeEnvironment(layers, options = {}) {
|
|
|
30045
30084
|
const environment = { ...options.baseEnvironment || process.env };
|
|
30046
30085
|
const owner = /* @__PURE__ */ new Map();
|
|
30047
30086
|
const sourceStatuses = [];
|
|
30048
|
-
const homeDir = options.homeDir || (0,
|
|
30087
|
+
const homeDir = options.homeDir || (0, import_os3.homedir)();
|
|
30049
30088
|
for (let precedence = 0; precedence < entries.length; precedence++) {
|
|
30050
30089
|
const entry = entries[precedence];
|
|
30051
30090
|
const loaded = await loadSource(entry, {
|
|
@@ -30078,13 +30117,14 @@ async function composeEnvironment(layers, options = {}) {
|
|
|
30078
30117
|
});
|
|
30079
30118
|
}
|
|
30080
30119
|
}
|
|
30120
|
+
const provenance = Object.fromEntries(owner);
|
|
30081
30121
|
return {
|
|
30082
30122
|
environment,
|
|
30083
30123
|
profileName,
|
|
30084
30124
|
sourceStatuses,
|
|
30085
|
-
provenance
|
|
30125
|
+
provenance,
|
|
30086
30126
|
sourceEntries: entries,
|
|
30087
|
-
redactionValues:
|
|
30127
|
+
redactionValues: collectRedactionValues(environment, provenance)
|
|
30088
30128
|
};
|
|
30089
30129
|
}
|
|
30090
30130
|
|
|
@@ -30092,7 +30132,7 @@ async function composeEnvironment(layers, options = {}) {
|
|
|
30092
30132
|
var import_child_process3 = require("child_process");
|
|
30093
30133
|
var import_http = require("http");
|
|
30094
30134
|
var import_fs6 = require("fs");
|
|
30095
|
-
var
|
|
30135
|
+
var import_os4 = require("os");
|
|
30096
30136
|
var import_path6 = require("path");
|
|
30097
30137
|
var import_crypto = require("crypto");
|
|
30098
30138
|
|
|
@@ -36909,7 +36949,7 @@ function localFile(entry, fileIndex = 0) {
|
|
|
36909
36949
|
const source = entry.source;
|
|
36910
36950
|
if (source.provider !== "local" && source.provider !== "dotenvx") throw new Error("Source does not use files");
|
|
36911
36951
|
const raw = source.files[fileIndex];
|
|
36912
|
-
const expanded = expandHomePath(raw, (0,
|
|
36952
|
+
const expanded = expandHomePath(raw, (0, import_os4.homedir)());
|
|
36913
36953
|
return (0, import_path6.isAbsolute)(expanded) ? expanded : (0, import_path6.resolve)(entry.baseDir, expanded);
|
|
36914
36954
|
}
|
|
36915
36955
|
function sourceUrl(entry) {
|
|
@@ -37061,14 +37101,14 @@ async function startEditorServer(encodedState) {
|
|
|
37061
37101
|
});
|
|
37062
37102
|
const closeTimer = setTimeout(() => server.close(), EDITOR_LIFETIME_MS);
|
|
37063
37103
|
closeTimer.unref();
|
|
37064
|
-
await new Promise((
|
|
37104
|
+
await new Promise((resolve7, reject) => {
|
|
37065
37105
|
server.once("error", reject);
|
|
37066
37106
|
server.listen(0, "127.0.0.1", () => {
|
|
37067
37107
|
const address = server.address();
|
|
37068
37108
|
if (!address || typeof address === "string") return reject(new Error("Editor did not receive a loopback port"));
|
|
37069
37109
|
process.stdout.write(`http://127.0.0.1:${address.port}${editorPath(state)}
|
|
37070
37110
|
`);
|
|
37071
|
-
|
|
37111
|
+
resolve7();
|
|
37072
37112
|
});
|
|
37073
37113
|
});
|
|
37074
37114
|
}
|
|
@@ -37089,7 +37129,7 @@ async function launchEditor(entryScript, composition, selectedSource) {
|
|
|
37089
37129
|
detached: true,
|
|
37090
37130
|
stdio: ["ignore", "pipe", "ignore"]
|
|
37091
37131
|
});
|
|
37092
|
-
const url = await new Promise((
|
|
37132
|
+
const url = await new Promise((resolve7, reject) => {
|
|
37093
37133
|
const timer = setTimeout(() => reject(new Error("[morphix-env] Timed out starting local editor.")), 5e3);
|
|
37094
37134
|
child.once("error", () => {
|
|
37095
37135
|
clearTimeout(timer);
|
|
@@ -37099,7 +37139,7 @@ async function launchEditor(entryScript, composition, selectedSource) {
|
|
|
37099
37139
|
clearTimeout(timer);
|
|
37100
37140
|
const url2 = chunk.toString("utf8").trim();
|
|
37101
37141
|
child.stdout?.destroy();
|
|
37102
|
-
|
|
37142
|
+
resolve7(url2);
|
|
37103
37143
|
});
|
|
37104
37144
|
});
|
|
37105
37145
|
child.unref();
|
|
@@ -37182,15 +37222,86 @@ var StreamingRedactor = class {
|
|
|
37182
37222
|
}
|
|
37183
37223
|
};
|
|
37184
37224
|
|
|
37225
|
+
// src/refs.ts
|
|
37226
|
+
var MX_ENV_REFERENCE_SOURCE = "mx-env:\\/\\/([A-Za-z0-9][A-Za-z0-9_-]*)\\/([A-Za-z0-9_][A-Za-z0-9_.-]*)";
|
|
37227
|
+
function referencePattern() {
|
|
37228
|
+
return new RegExp(MX_ENV_REFERENCE_SOURCE, "g");
|
|
37229
|
+
}
|
|
37230
|
+
function findMxEnvReferences(text) {
|
|
37231
|
+
const found = /* @__PURE__ */ new Map();
|
|
37232
|
+
for (const match of text.matchAll(referencePattern())) {
|
|
37233
|
+
const reference = { profile: match[1], key: match[2] };
|
|
37234
|
+
found.set(`${reference.profile}/${reference.key}`, reference);
|
|
37235
|
+
}
|
|
37236
|
+
return [...found.values()];
|
|
37237
|
+
}
|
|
37238
|
+
function hasMxEnvReference(text) {
|
|
37239
|
+
return referencePattern().test(text);
|
|
37240
|
+
}
|
|
37241
|
+
var ReferenceResolver = class {
|
|
37242
|
+
constructor(layers, composeOptions2) {
|
|
37243
|
+
this.layers = layers;
|
|
37244
|
+
this.composeOptions = composeOptions2;
|
|
37245
|
+
this.compositions = /* @__PURE__ */ new Map();
|
|
37246
|
+
}
|
|
37247
|
+
compose(profile) {
|
|
37248
|
+
let pending = this.compositions.get(profile);
|
|
37249
|
+
if (!pending) {
|
|
37250
|
+
pending = composeEnvironment(this.layers, { ...this.composeOptions, profile });
|
|
37251
|
+
this.compositions.set(profile, pending);
|
|
37252
|
+
}
|
|
37253
|
+
return pending;
|
|
37254
|
+
}
|
|
37255
|
+
/**
|
|
37256
|
+
* The value of KEY as `profile` composes it, resolving nested references.
|
|
37257
|
+
* The chain carries `profile/key` tokens of the current resolution path so
|
|
37258
|
+
* only a genuine loop (the same key re-entered) is a cycle — a nested lookup
|
|
37259
|
+
* of a different key in the same profile stays legal.
|
|
37260
|
+
*/
|
|
37261
|
+
async valueOf(profile, key, chain = []) {
|
|
37262
|
+
const token = `${profile}/${key}`;
|
|
37263
|
+
if (chain.includes(token)) return { missing: { profile, key, reason: "cycle" } };
|
|
37264
|
+
let composition;
|
|
37265
|
+
try {
|
|
37266
|
+
composition = await this.compose(profile);
|
|
37267
|
+
} catch {
|
|
37268
|
+
return { missing: { profile, key, reason: "missing" } };
|
|
37269
|
+
}
|
|
37270
|
+
const raw = composition.environment[key];
|
|
37271
|
+
if (raw === void 0 || raw === null) return { missing: { profile, key, reason: "missing" } };
|
|
37272
|
+
if (!hasMxEnvReference(raw)) return { value: raw };
|
|
37273
|
+
const resolved = await this.resolveText(raw, [...chain, token]);
|
|
37274
|
+
if (resolved.missing.length) return { missing: resolved.missing[0] };
|
|
37275
|
+
return { value: resolved.text };
|
|
37276
|
+
}
|
|
37277
|
+
/** Substitutes every resolvable reference; unresolvable ones stay literal. */
|
|
37278
|
+
async resolveText(text, chain = []) {
|
|
37279
|
+
const references = findMxEnvReferences(text);
|
|
37280
|
+
if (!references.length) return { text, missing: [] };
|
|
37281
|
+
const resolved = await Promise.all(references.map(async (reference) => ({
|
|
37282
|
+
reference,
|
|
37283
|
+
result: await this.valueOf(reference.profile, reference.key, chain)
|
|
37284
|
+
})));
|
|
37285
|
+
const values = /* @__PURE__ */ new Map();
|
|
37286
|
+
const missing = [];
|
|
37287
|
+
for (const { reference, result } of resolved) {
|
|
37288
|
+
if (result.value !== void 0) values.set(`${reference.profile}/${reference.key}`, result.value);
|
|
37289
|
+
else if (result.missing) missing.push(result.missing);
|
|
37290
|
+
}
|
|
37291
|
+
const output = text.replace(referencePattern(), (match, profile, key) => values.get(`${profile}/${key}`) ?? match);
|
|
37292
|
+
return { text: output, missing };
|
|
37293
|
+
}
|
|
37294
|
+
};
|
|
37295
|
+
|
|
37185
37296
|
// src/skill.ts
|
|
37186
37297
|
var import_fs7 = require("fs");
|
|
37187
|
-
var
|
|
37298
|
+
var import_os5 = require("os");
|
|
37188
37299
|
var import_path7 = require("path");
|
|
37189
37300
|
var SKILL_TARGETS = ["global", "project", "trellis"];
|
|
37190
37301
|
function resolveSkillPath(target) {
|
|
37191
37302
|
if (target === "project") return (0, import_path7.join)(process.cwd(), ".claude", "skills", "morphix-env", "SKILL.md");
|
|
37192
|
-
if (target === "trellis") return (0, import_path7.join)((0,
|
|
37193
|
-
return (0, import_path7.join)((0,
|
|
37303
|
+
if (target === "trellis") return (0, import_path7.join)((0, import_os5.homedir)(), ".trellis", "skills", "morphix-env", "SKILL.md");
|
|
37304
|
+
return (0, import_path7.join)((0, import_os5.homedir)(), ".claude", "skills", "morphix-env", "SKILL.md");
|
|
37194
37305
|
}
|
|
37195
37306
|
function targetHint(target) {
|
|
37196
37307
|
if (target === "project") {
|
|
@@ -37252,10 +37363,161 @@ function cmdSkill(subcommand, options) {
|
|
|
37252
37363
|
return 0;
|
|
37253
37364
|
}
|
|
37254
37365
|
|
|
37366
|
+
// src/serve.ts
|
|
37367
|
+
var import_http2 = require("http");
|
|
37368
|
+
var import_crypto2 = require("crypto");
|
|
37369
|
+
function authorized(req, token) {
|
|
37370
|
+
const header = req.headers.authorization;
|
|
37371
|
+
const presented = typeof header === "string" && header.startsWith("Bearer ") ? Buffer.from(header.slice("Bearer ".length)) : Buffer.alloc(0);
|
|
37372
|
+
return presented.length === token.length && (0, import_crypto2.timingSafeEqual)(presented, token);
|
|
37373
|
+
}
|
|
37374
|
+
async function startSecretServer(values) {
|
|
37375
|
+
const token = (0, import_crypto2.randomBytes)(24).toString("base64url");
|
|
37376
|
+
const tokenBuffer = Buffer.from(token);
|
|
37377
|
+
const server = (0, import_http2.createServer)((req, res) => {
|
|
37378
|
+
if (!authorized(req, tokenBuffer)) {
|
|
37379
|
+
res.writeHead(401, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37380
|
+
res.end("unauthorized");
|
|
37381
|
+
return;
|
|
37382
|
+
}
|
|
37383
|
+
const path = (req.url || "").split("?")[0];
|
|
37384
|
+
if (req.method !== "GET") {
|
|
37385
|
+
res.writeHead(405, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37386
|
+
res.end("method not allowed");
|
|
37387
|
+
return;
|
|
37388
|
+
}
|
|
37389
|
+
const match = /^\/key\/(.+)$/.exec(path);
|
|
37390
|
+
if (!match) {
|
|
37391
|
+
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37392
|
+
res.end("not found");
|
|
37393
|
+
return;
|
|
37394
|
+
}
|
|
37395
|
+
let key;
|
|
37396
|
+
try {
|
|
37397
|
+
key = decodeURIComponent(match[1]);
|
|
37398
|
+
} catch {
|
|
37399
|
+
res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37400
|
+
res.end("bad request");
|
|
37401
|
+
return;
|
|
37402
|
+
}
|
|
37403
|
+
if (!Object.prototype.hasOwnProperty.call(values, key)) {
|
|
37404
|
+
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37405
|
+
res.end("unknown key");
|
|
37406
|
+
return;
|
|
37407
|
+
}
|
|
37408
|
+
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
37409
|
+
res.end(values[key]);
|
|
37410
|
+
});
|
|
37411
|
+
await new Promise((resolvePromise, reject) => {
|
|
37412
|
+
server.once("error", reject);
|
|
37413
|
+
server.listen(0, "127.0.0.1", () => {
|
|
37414
|
+
server.removeListener("error", reject);
|
|
37415
|
+
server.on("error", (error) => {
|
|
37416
|
+
console.error(`[morphix-env] Secret server error: ${error instanceof Error ? error.message : "unknown"}`);
|
|
37417
|
+
});
|
|
37418
|
+
resolvePromise();
|
|
37419
|
+
});
|
|
37420
|
+
});
|
|
37421
|
+
const address = server.address();
|
|
37422
|
+
if (!address || typeof address === "string") {
|
|
37423
|
+
server.close();
|
|
37424
|
+
throw new Error("[morphix-env] Secret server did not receive a loopback port.");
|
|
37425
|
+
}
|
|
37426
|
+
let closed = false;
|
|
37427
|
+
return {
|
|
37428
|
+
endpoint: `http://127.0.0.1:${address.port}`,
|
|
37429
|
+
token,
|
|
37430
|
+
close: () => {
|
|
37431
|
+
if (closed) return;
|
|
37432
|
+
closed = true;
|
|
37433
|
+
server.close();
|
|
37434
|
+
const withConnections = server;
|
|
37435
|
+
if (typeof withConnections.closeAllConnections === "function") withConnections.closeAllConnections();
|
|
37436
|
+
}
|
|
37437
|
+
};
|
|
37438
|
+
}
|
|
37439
|
+
|
|
37440
|
+
// src/template.ts
|
|
37441
|
+
var import_child_process4 = require("child_process");
|
|
37442
|
+
var import_fs8 = require("fs");
|
|
37443
|
+
var import_path8 = require("path");
|
|
37444
|
+
function shellQuote(value) {
|
|
37445
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
37446
|
+
}
|
|
37447
|
+
function isShellIdentifier(key) {
|
|
37448
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
37449
|
+
}
|
|
37450
|
+
function findTemplateAnomalies(text) {
|
|
37451
|
+
const anomalies = [];
|
|
37452
|
+
const dollarDollar = text.indexOf("$$");
|
|
37453
|
+
if (dollarDollar >= 0) {
|
|
37454
|
+
anomalies.push(`Escaped dollar $$ at offset ${dollarDollar} is not interpolated; left literal.`);
|
|
37455
|
+
}
|
|
37456
|
+
let index2 = text.indexOf("${");
|
|
37457
|
+
while (index2 >= 0) {
|
|
37458
|
+
const rest = text.slice(index2);
|
|
37459
|
+
if (/^\$\{[A-Za-z_][A-Za-z0-9_]*\}/.test(rest)) {
|
|
37460
|
+
} else if (/^\$\{[A-Za-z_][A-Za-z0-9_]*[:+=-]/.test(rest)) {
|
|
37461
|
+
anomalies.push(`Unsupported \${...} modifier or default at offset ${index2}; only \${NAME} is substituted \u2014 left literal.`);
|
|
37462
|
+
} else {
|
|
37463
|
+
anomalies.push(`Unclosed or invalid \${ at offset ${index2}; left literal.`);
|
|
37464
|
+
}
|
|
37465
|
+
index2 = text.indexOf("${", index2 + 2);
|
|
37466
|
+
}
|
|
37467
|
+
return anomalies;
|
|
37468
|
+
}
|
|
37469
|
+
function templateVariablePattern() {
|
|
37470
|
+
return /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
37471
|
+
}
|
|
37472
|
+
function findTemplateVariables(text) {
|
|
37473
|
+
const names = /* @__PURE__ */ new Set();
|
|
37474
|
+
for (const match of text.matchAll(templateVariablePattern())) names.add(match[1]);
|
|
37475
|
+
return [...names];
|
|
37476
|
+
}
|
|
37477
|
+
function renderTemplate(text, environment) {
|
|
37478
|
+
const missing = /* @__PURE__ */ new Set();
|
|
37479
|
+
const output = text.replace(templateVariablePattern(), (match, name) => {
|
|
37480
|
+
const value = environment[name];
|
|
37481
|
+
if (value === void 0 || value === null) {
|
|
37482
|
+
missing.add(name);
|
|
37483
|
+
return match;
|
|
37484
|
+
}
|
|
37485
|
+
return value;
|
|
37486
|
+
});
|
|
37487
|
+
return { output, missing: [...missing] };
|
|
37488
|
+
}
|
|
37489
|
+
function writePrivateFile(path, content) {
|
|
37490
|
+
const absolute = (0, import_path8.resolve)(path);
|
|
37491
|
+
(0, import_fs8.mkdirSync)((0, import_path8.dirname)(absolute), { recursive: true, mode: 448 });
|
|
37492
|
+
(0, import_fs8.writeFileSync)(absolute, content, { mode: 384 });
|
|
37493
|
+
(0, import_fs8.chmodSync)(absolute, 384);
|
|
37494
|
+
}
|
|
37495
|
+
function gitOutputStatus(path) {
|
|
37496
|
+
const absolute = (0, import_path8.resolve)(path);
|
|
37497
|
+
const cwd = (0, import_path8.dirname)(absolute);
|
|
37498
|
+
const name = (0, import_path8.basename)(absolute);
|
|
37499
|
+
const inside = (0, import_child_process4.spawnSync)("git", ["rev-parse", "--is-inside-work-tree"], { cwd, encoding: "utf8" });
|
|
37500
|
+
if (inside.status !== 0) return "outside-repo";
|
|
37501
|
+
const tracked = (0, import_child_process4.spawnSync)("git", ["ls-files", "--error-unmatch", "--", name], { cwd, encoding: "utf8" });
|
|
37502
|
+
if (tracked.status === 0) return "tracked";
|
|
37503
|
+
const ignored = (0, import_child_process4.spawnSync)("git", ["check-ignore", "-q", "--", name], { cwd, encoding: "utf8" });
|
|
37504
|
+
if (ignored.status === 0) return "ignored";
|
|
37505
|
+
if (ignored.status === 1) return "untracked";
|
|
37506
|
+
return "outside-repo";
|
|
37507
|
+
}
|
|
37508
|
+
function warnOutputGitRisk(path) {
|
|
37509
|
+
const status = gitOutputStatus(path);
|
|
37510
|
+
if (status === "tracked") {
|
|
37511
|
+
console.warn(`[morphix-env] Warning: ${path} is tracked by git; a rendered value could be committed. Add it to .gitignore and untrack it.`);
|
|
37512
|
+
} else if (status === "untracked") {
|
|
37513
|
+
console.warn(`[morphix-env] Warning: ${path} is not git-ignored; add it to .gitignore before committing.`);
|
|
37514
|
+
}
|
|
37515
|
+
}
|
|
37516
|
+
|
|
37255
37517
|
// package.json
|
|
37256
37518
|
var package_default = {
|
|
37257
37519
|
name: "morphix-env",
|
|
37258
|
-
version: "0.
|
|
37520
|
+
version: "0.8.0",
|
|
37259
37521
|
description: "Secret composition CLI \u2014 Infisical, Doppler, macOS Keychain, dotenvx, and local files stay value owners; composes them into one value-safe child environment and ships a built-in Agent Skill (mx-env skill install).",
|
|
37260
37522
|
author: "MorphixAI <dev@morphixai.com>",
|
|
37261
37523
|
homepage: "https://github.com/Morphicai/morphix-env#readme",
|
|
@@ -37270,9 +37532,22 @@ var package_default = {
|
|
|
37270
37532
|
"morphix-env": "./dist/cli.js",
|
|
37271
37533
|
"mx-env": "./dist/cli.js"
|
|
37272
37534
|
},
|
|
37535
|
+
main: "./dist/index.js",
|
|
37536
|
+
types: "./dist/index.d.ts",
|
|
37537
|
+
exports: {
|
|
37538
|
+
".": {
|
|
37539
|
+
types: "./dist/index.d.ts",
|
|
37540
|
+
default: "./dist/index.js"
|
|
37541
|
+
},
|
|
37542
|
+
"./cli": {
|
|
37543
|
+
types: "./dist/cli.d.ts",
|
|
37544
|
+
default: "./dist/cli.js"
|
|
37545
|
+
},
|
|
37546
|
+
"./package.json": "./package.json"
|
|
37547
|
+
},
|
|
37273
37548
|
scripts: {
|
|
37274
|
-
build: "node scripts/build-editor-ui.mjs && tsup src/cli.ts --format cjs --dts --clean --external keytar && node scripts/copy-skill.mjs",
|
|
37275
|
-
dev: "node scripts/build-editor-ui.mjs && tsup src/cli.ts --format cjs --watch",
|
|
37549
|
+
build: "node scripts/build-editor-ui.mjs && tsup src/cli.ts src/index.ts --format cjs --dts --clean --external keytar && node scripts/copy-skill.mjs",
|
|
37550
|
+
dev: "node scripts/build-editor-ui.mjs && tsup src/cli.ts src/index.ts --format cjs --watch",
|
|
37276
37551
|
pretest: "pnpm build",
|
|
37277
37552
|
test: "vitest run",
|
|
37278
37553
|
"test:watch": "vitest",
|
|
@@ -37334,6 +37609,7 @@ function parseArgs(argv) {
|
|
|
37334
37609
|
const args = {
|
|
37335
37610
|
command: "",
|
|
37336
37611
|
subArgs: [],
|
|
37612
|
+
positionals: [],
|
|
37337
37613
|
envFiles: [],
|
|
37338
37614
|
outFile: null,
|
|
37339
37615
|
verbose: false,
|
|
@@ -37346,7 +37622,9 @@ function parseArgs(argv) {
|
|
|
37346
37622
|
printEditorUrl: false,
|
|
37347
37623
|
source: null,
|
|
37348
37624
|
target: null,
|
|
37349
|
-
force: false
|
|
37625
|
+
force: false,
|
|
37626
|
+
dryRun: false,
|
|
37627
|
+
serve: false
|
|
37350
37628
|
};
|
|
37351
37629
|
let i = 2;
|
|
37352
37630
|
const command = argv[i];
|
|
@@ -37385,28 +37663,39 @@ function parseArgs(argv) {
|
|
|
37385
37663
|
if (argv[++i]) args.target = argv[i];
|
|
37386
37664
|
} else if (arg === "--force") {
|
|
37387
37665
|
args.force = true;
|
|
37666
|
+
} else if (arg === "--dry-run") {
|
|
37667
|
+
args.dryRun = true;
|
|
37668
|
+
} else if (arg === "--serve") {
|
|
37669
|
+
args.serve = true;
|
|
37388
37670
|
} else if (args.command === "run") {
|
|
37389
37671
|
args.subArgs = argv.slice(i);
|
|
37390
37672
|
break;
|
|
37673
|
+
} else if (!arg.startsWith("-")) {
|
|
37674
|
+
args.positionals.push(arg);
|
|
37391
37675
|
}
|
|
37392
37676
|
i++;
|
|
37393
37677
|
}
|
|
37394
37678
|
return args;
|
|
37395
37679
|
}
|
|
37396
|
-
function
|
|
37397
|
-
|
|
37398
|
-
|
|
37680
|
+
function configLayers() {
|
|
37681
|
+
return loadConfigLayers({ cwd: process.cwd(), homeDir: (0, import_os6.homedir)() });
|
|
37682
|
+
}
|
|
37683
|
+
function composeOptions(args) {
|
|
37684
|
+
return {
|
|
37399
37685
|
profile: args.profile,
|
|
37400
37686
|
noGlobal: args.noGlobal,
|
|
37401
37687
|
noInfisical: args.noInfisical,
|
|
37402
37688
|
envName: args.env,
|
|
37403
37689
|
allowInsecureGlobal: args.allowInsecureGlobal,
|
|
37404
37690
|
envFiles: args.envFiles,
|
|
37405
|
-
homeDir: (0,
|
|
37406
|
-
}
|
|
37691
|
+
homeDir: (0, import_os6.homedir)()
|
|
37692
|
+
};
|
|
37693
|
+
}
|
|
37694
|
+
function resolveComposition(args) {
|
|
37695
|
+
return composeEnvironment(configLayers(), composeOptions(args));
|
|
37407
37696
|
}
|
|
37408
37697
|
function generatedOptions(args) {
|
|
37409
|
-
const config = loadConfigLayers({ cwd: process.cwd(), homeDir: (0,
|
|
37698
|
+
const config = loadConfigLayers({ cwd: process.cwd(), homeDir: (0, import_os6.homedir)() }).project.config;
|
|
37410
37699
|
return {
|
|
37411
37700
|
outFile: args.outFile || config.generate?.out || "public/__env.js",
|
|
37412
37701
|
filter: args.filter || config.generate?.filter || null
|
|
@@ -37415,12 +37704,12 @@ function generatedOptions(args) {
|
|
|
37415
37704
|
function generateClientEnv(outFile, filter, environment) {
|
|
37416
37705
|
let vars = extractPublicVars(environment);
|
|
37417
37706
|
if (filter) vars = Object.fromEntries(Object.entries(vars).filter(([key]) => key.startsWith(filter)));
|
|
37418
|
-
(0,
|
|
37419
|
-
(0,
|
|
37707
|
+
(0, import_fs9.mkdirSync)((0, import_path9.dirname)(outFile), { recursive: true });
|
|
37708
|
+
(0, import_fs9.writeFileSync)(outFile, `window.__ENV=${JSON.stringify(vars)};`);
|
|
37420
37709
|
console.log(`[morphix-env] Generated ${outFile} (${Object.keys(vars).length} client vars)`);
|
|
37421
37710
|
}
|
|
37422
37711
|
async function runChild(command, commandArgs, composition) {
|
|
37423
|
-
return new Promise((
|
|
37712
|
+
return new Promise((resolve7) => {
|
|
37424
37713
|
const child = (0, import_cross_spawn.default)(command, commandArgs, { env: composition.environment, stdio: ["inherit", "pipe", "pipe"] });
|
|
37425
37714
|
const stdout = new StreamingRedactor(composition.redactionValues);
|
|
37426
37715
|
const stderr = new StreamingRedactor(composition.redactionValues);
|
|
@@ -37428,14 +37717,14 @@ async function runChild(command, commandArgs, composition) {
|
|
|
37428
37717
|
child.stderr?.on("data", (chunk) => process.stderr.write(stderr.write(chunk)));
|
|
37429
37718
|
child.on("error", () => {
|
|
37430
37719
|
console.error(`[morphix-env] Failed to execute: ${command}`);
|
|
37431
|
-
|
|
37720
|
+
resolve7(1);
|
|
37432
37721
|
});
|
|
37433
37722
|
child.on("close", (code) => {
|
|
37434
37723
|
const stdoutFinal = stdout.flush();
|
|
37435
37724
|
const stderrFinal = stderr.flush();
|
|
37436
37725
|
if (stdoutFinal) process.stdout.write(stdoutFinal);
|
|
37437
37726
|
if (stderrFinal) process.stderr.write(stderrFinal);
|
|
37438
|
-
|
|
37727
|
+
resolve7(code ?? 1);
|
|
37439
37728
|
});
|
|
37440
37729
|
});
|
|
37441
37730
|
}
|
|
@@ -37450,6 +37739,49 @@ function writeRunAudit(composition, startedAt, outcome, exitCode) {
|
|
|
37450
37739
|
durationMs: Date.now() - startedAt
|
|
37451
37740
|
});
|
|
37452
37741
|
}
|
|
37742
|
+
async function startServeFor(composition, verbose) {
|
|
37743
|
+
const values = {};
|
|
37744
|
+
for (const key of Object.keys(composition.provenance)) {
|
|
37745
|
+
const value = composition.environment[key];
|
|
37746
|
+
if (value !== void 0) values[key] = value;
|
|
37747
|
+
}
|
|
37748
|
+
const server = await startSecretServer(values);
|
|
37749
|
+
for (const key of Object.keys(values)) {
|
|
37750
|
+
if (!isPublicKey(key)) delete composition.environment[key];
|
|
37751
|
+
}
|
|
37752
|
+
composition.environment.MXENV_ENDPOINT = server.endpoint;
|
|
37753
|
+
composition.environment.MXENV_TOKEN = server.token;
|
|
37754
|
+
composition.redactionValues = [.../* @__PURE__ */ new Set([...composition.redactionValues, server.token])];
|
|
37755
|
+
if (verbose) {
|
|
37756
|
+
console.error(`[morphix-env] Secret server listening on ${server.endpoint} (${Object.keys(values).length} keys; token is visible to the child only).`);
|
|
37757
|
+
}
|
|
37758
|
+
return server;
|
|
37759
|
+
}
|
|
37760
|
+
function warnUnresolvedReference(reference, context) {
|
|
37761
|
+
console.warn(`[morphix-env] Unresolved mx-env://${reference.profile}/${reference.key} reference ${context} (${reference.reason}); left as-is.`);
|
|
37762
|
+
}
|
|
37763
|
+
async function resolveEnvironmentReferences(composition, args) {
|
|
37764
|
+
const targets = Object.entries(composition.environment).filter((entry) => typeof entry[1] === "string" && hasMxEnvReference(entry[1]));
|
|
37765
|
+
if (!targets.length) return;
|
|
37766
|
+
const resolver = new ReferenceResolver(configLayers(), composeOptions(args));
|
|
37767
|
+
const changed = [];
|
|
37768
|
+
for (const [key, value] of targets) {
|
|
37769
|
+
const resolved = await resolver.resolveText(value);
|
|
37770
|
+
if (resolved.missing.length) {
|
|
37771
|
+
for (const reference of resolved.missing) warnUnresolvedReference(reference, `in key "${key}"`);
|
|
37772
|
+
continue;
|
|
37773
|
+
}
|
|
37774
|
+
composition.environment[key] = resolved.text;
|
|
37775
|
+
changed.push(key);
|
|
37776
|
+
}
|
|
37777
|
+
if (changed.length) {
|
|
37778
|
+
const extra = changed.map((key) => composition.environment[key]).filter((value) => Boolean(value));
|
|
37779
|
+
composition.redactionValues = [.../* @__PURE__ */ new Set([
|
|
37780
|
+
...collectRedactionValues(composition.environment, composition.provenance),
|
|
37781
|
+
...extra
|
|
37782
|
+
])];
|
|
37783
|
+
}
|
|
37784
|
+
}
|
|
37453
37785
|
async function cmdRun(args) {
|
|
37454
37786
|
if (!args.subArgs.length) {
|
|
37455
37787
|
console.error("[morphix-env] No command specified. Usage: mx-env run -- <command>");
|
|
@@ -37462,18 +37794,72 @@ async function cmdRun(args) {
|
|
|
37462
37794
|
console.log(`[morphix-env] ${source.name}: ${source.availability} (${source.keyCount} keys)`);
|
|
37463
37795
|
}
|
|
37464
37796
|
}
|
|
37797
|
+
if (args.dryRun) {
|
|
37798
|
+
console.log(`profile: ${composition.profileName}`);
|
|
37799
|
+
for (const key of Object.keys(composition.provenance).sort()) console.log(` ${key}`);
|
|
37800
|
+
return 0;
|
|
37801
|
+
}
|
|
37802
|
+
await resolveEnvironmentReferences(composition, args);
|
|
37465
37803
|
if (args.outFile || generatedOptions(args).outFile) {
|
|
37466
37804
|
const { outFile, filter } = generatedOptions(args);
|
|
37467
|
-
const configured = Boolean(args.outFile || loadConfigLayers({ cwd: process.cwd(), homeDir: (0,
|
|
37805
|
+
const configured = Boolean(args.outFile || loadConfigLayers({ cwd: process.cwd(), homeDir: (0, import_os6.homedir)() }).project.config.generate);
|
|
37468
37806
|
if (configured) generateClientEnv(outFile, filter, composition.environment);
|
|
37469
37807
|
}
|
|
37470
37808
|
const [command, ...commandArgs] = args.subArgs;
|
|
37471
|
-
const
|
|
37472
|
-
|
|
37473
|
-
|
|
37809
|
+
const secretServer = args.serve ? await startServeFor(composition, args.verbose) : null;
|
|
37810
|
+
try {
|
|
37811
|
+
const exitCode = await runChild(command, commandArgs, composition);
|
|
37812
|
+
writeRunAudit(composition, startedAt, exitCode === 0 ? "success" : "failure", exitCode);
|
|
37813
|
+
return exitCode;
|
|
37814
|
+
} finally {
|
|
37815
|
+
secretServer?.close();
|
|
37816
|
+
}
|
|
37817
|
+
}
|
|
37818
|
+
async function cmdFetch(args) {
|
|
37819
|
+
const key = args.positionals[0];
|
|
37820
|
+
if (!key) {
|
|
37821
|
+
console.error("[morphix-env] Usage: mx-env fetch <key-name>");
|
|
37822
|
+
return 1;
|
|
37823
|
+
}
|
|
37824
|
+
const endpoint = process.env.MXENV_ENDPOINT;
|
|
37825
|
+
const token = process.env.MXENV_TOKEN;
|
|
37826
|
+
if (!endpoint || !token) {
|
|
37827
|
+
console.error('[morphix-env] mx-env fetch needs MXENV_ENDPOINT and MXENV_TOKEN; run it inside "mx-env run --serve -- <command>".');
|
|
37828
|
+
return 1;
|
|
37829
|
+
}
|
|
37830
|
+
let endpointUrl;
|
|
37831
|
+
try {
|
|
37832
|
+
endpointUrl = new URL(endpoint);
|
|
37833
|
+
} catch {
|
|
37834
|
+
console.error("[morphix-env] MXENV_ENDPOINT is not a valid URL.");
|
|
37835
|
+
return 1;
|
|
37836
|
+
}
|
|
37837
|
+
if (!["127.0.0.1", "localhost", "[::1]"].includes(endpointUrl.hostname)) {
|
|
37838
|
+
console.error("[morphix-env] MXENV_ENDPOINT is not a loopback address; refusing to send the fetch token off-machine.");
|
|
37839
|
+
return 1;
|
|
37840
|
+
}
|
|
37841
|
+
try {
|
|
37842
|
+
const response = await fetch(`${endpoint}/key/${encodeURIComponent(key)}`, {
|
|
37843
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
37844
|
+
});
|
|
37845
|
+
if (response.ok) {
|
|
37846
|
+
process.stdout.write(await response.text());
|
|
37847
|
+
return 0;
|
|
37848
|
+
}
|
|
37849
|
+
if (response.status === 404) {
|
|
37850
|
+
console.error(`[morphix-env] Unknown key on the secret server: ${key}`);
|
|
37851
|
+
return 1;
|
|
37852
|
+
}
|
|
37853
|
+
console.error(`[morphix-env] Secret server rejected the request (HTTP ${response.status}).`);
|
|
37854
|
+
return 1;
|
|
37855
|
+
} catch {
|
|
37856
|
+
console.error("[morphix-env] Secret server is unreachable; the parent process may have exited.");
|
|
37857
|
+
return 1;
|
|
37858
|
+
}
|
|
37474
37859
|
}
|
|
37475
37860
|
async function cmdGenerate(args) {
|
|
37476
37861
|
const composition = await resolveComposition(args);
|
|
37862
|
+
await resolveEnvironmentReferences(composition, args);
|
|
37477
37863
|
const { outFile, filter } = generatedOptions(args);
|
|
37478
37864
|
generateClientEnv(outFile, filter, composition.environment);
|
|
37479
37865
|
if (args.verbose) {
|
|
@@ -37495,6 +37881,92 @@ async function cmdInspect(args) {
|
|
|
37495
37881
|
}
|
|
37496
37882
|
return 0;
|
|
37497
37883
|
}
|
|
37884
|
+
async function cmdExport(args) {
|
|
37885
|
+
const startedAt = Date.now();
|
|
37886
|
+
const composition = await resolveComposition(args);
|
|
37887
|
+
const keys = Object.keys(composition.provenance).sort();
|
|
37888
|
+
if (args.dryRun) {
|
|
37889
|
+
for (const key of keys) console.log(key);
|
|
37890
|
+
return 0;
|
|
37891
|
+
}
|
|
37892
|
+
await resolveEnvironmentReferences(composition, args);
|
|
37893
|
+
for (const key of keys) {
|
|
37894
|
+
if (!isShellIdentifier(key)) {
|
|
37895
|
+
console.warn(`[morphix-env] Warning: key "${key}" is not a valid shell identifier; skipped in export output.`);
|
|
37896
|
+
continue;
|
|
37897
|
+
}
|
|
37898
|
+
console.log(`export ${key}=${shellQuote(composition.environment[key] ?? "")}`);
|
|
37899
|
+
}
|
|
37900
|
+
writeRunAudit(composition, startedAt, "success", 0);
|
|
37901
|
+
return 0;
|
|
37902
|
+
}
|
|
37903
|
+
async function cmdRender(args) {
|
|
37904
|
+
const startedAt = Date.now();
|
|
37905
|
+
const [templatePath, outPath] = args.positionals;
|
|
37906
|
+
if (!templatePath || !outPath) {
|
|
37907
|
+
console.error("[morphix-env] Usage: mx-env render <template-file> <output-file> [options]");
|
|
37908
|
+
return 1;
|
|
37909
|
+
}
|
|
37910
|
+
if (!(0, import_fs9.existsSync)(templatePath)) {
|
|
37911
|
+
console.error(`[morphix-env] Template not found: ${templatePath}`);
|
|
37912
|
+
return 1;
|
|
37913
|
+
}
|
|
37914
|
+
const template = (0, import_fs9.readFileSync)(templatePath, "utf8");
|
|
37915
|
+
const composition = await resolveComposition(args);
|
|
37916
|
+
const names = findTemplateVariables(template);
|
|
37917
|
+
const missing = names.filter((name) => composition.environment[name] === void 0 || composition.environment[name] === null);
|
|
37918
|
+
if (missing.length) console.warn(`[morphix-env] Missing variables: ${missing.join(", ")} (left unresolved)`);
|
|
37919
|
+
for (const anomaly of findTemplateAnomalies(template)) console.warn(`[morphix-env] ${anomaly}`);
|
|
37920
|
+
if (args.dryRun) {
|
|
37921
|
+
for (const name of names) console.log(`${name}: ${missing.includes(name) ? "missing" : "resolved"}`);
|
|
37922
|
+
return 0;
|
|
37923
|
+
}
|
|
37924
|
+
await resolveEnvironmentReferences(composition, args);
|
|
37925
|
+
const { output } = renderTemplate(template, composition.environment);
|
|
37926
|
+
warnOutputGitRisk(outPath);
|
|
37927
|
+
writePrivateFile(outPath, output);
|
|
37928
|
+
writeRunAudit(composition, startedAt, "success", 0);
|
|
37929
|
+
console.log(`[morphix-env] Rendered ${templatePath} -> ${outPath} (${names.length} variables, ${missing.length} unresolved)`);
|
|
37930
|
+
return 0;
|
|
37931
|
+
}
|
|
37932
|
+
async function cmdInject(args) {
|
|
37933
|
+
const startedAt = Date.now();
|
|
37934
|
+
const [templatePath, outPath] = args.positionals;
|
|
37935
|
+
if (!templatePath || !outPath) {
|
|
37936
|
+
console.error("[morphix-env] Usage: mx-env inject <template-file> <output-file> [options]");
|
|
37937
|
+
return 1;
|
|
37938
|
+
}
|
|
37939
|
+
if (!(0, import_fs9.existsSync)(templatePath)) {
|
|
37940
|
+
console.error(`[morphix-env] Template not found: ${templatePath}`);
|
|
37941
|
+
return 1;
|
|
37942
|
+
}
|
|
37943
|
+
const template = (0, import_fs9.readFileSync)(templatePath, "utf8");
|
|
37944
|
+
const resolver = new ReferenceResolver(configLayers(), composeOptions(args));
|
|
37945
|
+
const references = findMxEnvReferences(template);
|
|
37946
|
+
if (args.dryRun) {
|
|
37947
|
+
for (const reference of references) {
|
|
37948
|
+
const result = await resolver.valueOf(reference.profile, reference.key);
|
|
37949
|
+
const status = result.value !== void 0 ? "resolved" : result.missing?.reason ?? "missing";
|
|
37950
|
+
console.log(`${reference.profile}/${reference.key}: ${status}`);
|
|
37951
|
+
}
|
|
37952
|
+
return 0;
|
|
37953
|
+
}
|
|
37954
|
+
const resolved = await resolver.resolveText(template);
|
|
37955
|
+
for (const reference of resolved.missing) warnUnresolvedReference(reference, `in ${templatePath}`);
|
|
37956
|
+
warnOutputGitRisk(outPath);
|
|
37957
|
+
writePrivateFile(outPath, resolved.text);
|
|
37958
|
+
writeAudit({
|
|
37959
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
37960
|
+
profile: [...new Set(references.map((reference) => reference.profile))].join(",") || "none",
|
|
37961
|
+
sources: [],
|
|
37962
|
+
keys: [...new Set(references.map((reference) => reference.key))].sort(),
|
|
37963
|
+
outcome: "success",
|
|
37964
|
+
exitCode: 0,
|
|
37965
|
+
durationMs: Date.now() - startedAt
|
|
37966
|
+
});
|
|
37967
|
+
console.log(`[morphix-env] Injected ${templatePath} -> ${outPath} (${references.length} references, ${resolved.missing.length} unresolved)`);
|
|
37968
|
+
return 0;
|
|
37969
|
+
}
|
|
37498
37970
|
async function cmdEdit(args) {
|
|
37499
37971
|
if (!args.profile && !args.source) {
|
|
37500
37972
|
console.error("[morphix-env] Specify --profile <name> or --source <name> to open the editor.");
|
|
@@ -37502,7 +37974,7 @@ async function cmdEdit(args) {
|
|
|
37502
37974
|
}
|
|
37503
37975
|
const composition = await resolveComposition(args);
|
|
37504
37976
|
if (args.source && !composition.sourceEntries.some((entry) => entry.name === args.source)) {
|
|
37505
|
-
const layers = loadConfigLayers({ cwd: process.cwd(), homeDir: (0,
|
|
37977
|
+
const layers = loadConfigLayers({ cwd: process.cwd(), homeDir: (0, import_os6.homedir)() });
|
|
37506
37978
|
const declared = layers.project.config.sources?.[args.source] ? { source: layers.project.config.sources[args.source], baseDir: layers.project.baseDir } : !args.noGlobal && layers.global.config.sources?.[args.source] ? { source: layers.global.config.sources[args.source], baseDir: layers.global.baseDir } : null;
|
|
37507
37979
|
if (!declared) {
|
|
37508
37980
|
console.error(`[morphix-env] Unknown source "${args.source}".`);
|
|
@@ -37520,7 +37992,7 @@ async function cmdEdit(args) {
|
|
|
37520
37992
|
}
|
|
37521
37993
|
async function cmdDoc(args) {
|
|
37522
37994
|
const composition = await resolveComposition(args);
|
|
37523
|
-
const outFile = args.outFile || (0,
|
|
37995
|
+
const outFile = args.outFile || (0, import_path9.join)(process.cwd(), ".agents", "skills", "morphix-env", "SKILL.md");
|
|
37524
37996
|
const keyRows = Object.entries(composition.provenance).sort(([a], [b]) => a.localeCompare(b)).map(([key, provenance]) => `| \`${key}\` | ${provenance.source} (${provenance.provider}) |`).join("\n") || "| _No resolved keys_ | \u2014 |";
|
|
37525
37997
|
const skill = `---
|
|
37526
37998
|
name: morphix-env
|
|
@@ -37554,18 +38026,18 @@ ${keyRows}
|
|
|
37554
38026
|
|
|
37555
38027
|
Secret values and value prefixes do not belong in this Skill, command output, audit records, or conversation context.
|
|
37556
38028
|
`;
|
|
37557
|
-
(0,
|
|
37558
|
-
(0,
|
|
38029
|
+
(0, import_fs9.mkdirSync)((0, import_path9.dirname)(outFile), { recursive: true });
|
|
38030
|
+
(0, import_fs9.writeFileSync)(outFile, skill, { mode: 384 });
|
|
37559
38031
|
console.log(`[morphix-env] Generated value-free workflow Skill: ${outFile}`);
|
|
37560
38032
|
return 0;
|
|
37561
38033
|
}
|
|
37562
38034
|
function cmdAudit(args) {
|
|
37563
|
-
const file = (0,
|
|
37564
|
-
if (!(0,
|
|
38035
|
+
const file = (0, import_path9.join)((0, import_os6.homedir)(), ".mx-env", "audit", `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
|
|
38036
|
+
if (!(0, import_fs9.existsSync)(file)) {
|
|
37565
38037
|
console.log("[morphix-env] No audit events for today.");
|
|
37566
38038
|
return 0;
|
|
37567
38039
|
}
|
|
37568
|
-
const lines = (0,
|
|
38040
|
+
const lines = (0, import_fs9.readFileSync)(file, "utf8").trim().split("\n").filter(Boolean);
|
|
37569
38041
|
const selected = args.subArgs[0] === "tail" ? lines.slice(-20) : lines;
|
|
37570
38042
|
for (const line of selected) console.log(line);
|
|
37571
38043
|
return 0;
|
|
@@ -37576,6 +38048,10 @@ morphix-env v${VERSION} \u2014 secret composition and environment delivery
|
|
|
37576
38048
|
|
|
37577
38049
|
Usage:
|
|
37578
38050
|
mx-env run [options] -- <command> Compose env + execute command
|
|
38051
|
+
mx-env fetch <key-name> Print one value from a run --serve secret server
|
|
38052
|
+
mx-env export [options] Print eval-able export KEY='value' lines
|
|
38053
|
+
mx-env render <template> <output> Substitute \${VAR} into a file (mode 0600)
|
|
38054
|
+
mx-env inject <template> <output> Resolve mx-env:// references into a file (mode 0600)
|
|
37579
38055
|
mx-env generate [options] Generate public __env.js
|
|
37580
38056
|
mx-env inspect [options] Print key names, sources, and status only
|
|
37581
38057
|
mx-env doc [options] Generate a value-free project Skill
|
|
@@ -37592,6 +38068,8 @@ Options:
|
|
|
37592
38068
|
-e, --env <name> Infisical environment override
|
|
37593
38069
|
-o, --out <path> Client __env.js output
|
|
37594
38070
|
--filter <prefix> Include public keys with this prefix
|
|
38071
|
+
--serve Keep composed values out of env; serve them to the child over loopback
|
|
38072
|
+
--dry-run Report key/variable names only, never values
|
|
37595
38073
|
--no-infisical Do not load Infisical sources
|
|
37596
38074
|
--no-global Ignore ~/.mx-env/.env and ~/.mx-env/config.json
|
|
37597
38075
|
--allow-insecure-global Allow a global .env with permissive file mode
|
|
@@ -37608,6 +38086,14 @@ async function main() {
|
|
|
37608
38086
|
switch (args.command) {
|
|
37609
38087
|
case "run":
|
|
37610
38088
|
return cmdRun(args);
|
|
38089
|
+
case "fetch":
|
|
38090
|
+
return cmdFetch(args);
|
|
38091
|
+
case "export":
|
|
38092
|
+
return cmdExport(args);
|
|
38093
|
+
case "render":
|
|
38094
|
+
return cmdRender(args);
|
|
38095
|
+
case "inject":
|
|
38096
|
+
return cmdInject(args);
|
|
37611
38097
|
case "generate":
|
|
37612
38098
|
case "gen":
|
|
37613
38099
|
return cmdGenerate(args);
|