@solid-stack/mason 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +184 -9
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +184 -9
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/commands/import.d.ts +12 -2
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/index.cjs +184 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +184 -9
- package/dist/index.js.map +1 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/registry.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -147,7 +147,7 @@ function getEffectiveMode(projectRoot, flags) {
|
|
|
147
147
|
if (flags?.registry) return "registry";
|
|
148
148
|
const config = loadMasonConfig(projectRoot);
|
|
149
149
|
if (config?.mode) return config.mode;
|
|
150
|
-
if (fs4.existsSync(path2.join(projectRoot, "index.json")) && (fs4.existsSync(path2.join(projectRoot, "features")) || fs4.existsSync(path2.join(projectRoot, "shared")))
|
|
150
|
+
if (fs4.existsSync(path2.join(projectRoot, "index.json")) && (fs4.existsSync(path2.join(projectRoot, "features")) || fs4.existsSync(path2.join(projectRoot, "shared")) || fs4.existsSync(path2.join(projectRoot, "src/features")) || fs4.existsSync(path2.join(projectRoot, "src/shared")))) {
|
|
151
151
|
return "registry";
|
|
152
152
|
}
|
|
153
153
|
return "app";
|
|
@@ -161,6 +161,9 @@ function getConfiguredFeaturesDir(projectRoot, flags) {
|
|
|
161
161
|
}
|
|
162
162
|
const mode = getEffectiveMode(projectRoot, flags);
|
|
163
163
|
if (mode === "registry") {
|
|
164
|
+
if (fs4.existsSync(path2.join(projectRoot, "src/features"))) {
|
|
165
|
+
return path2.join(projectRoot, "src/features");
|
|
166
|
+
}
|
|
164
167
|
return path2.join(projectRoot, "features");
|
|
165
168
|
}
|
|
166
169
|
if (fs4.existsSync(path2.join(projectRoot, "src/features"))) {
|
|
@@ -177,6 +180,9 @@ function getConfiguredSharedDir(projectRoot, flags) {
|
|
|
177
180
|
}
|
|
178
181
|
const mode = getEffectiveMode(projectRoot, flags);
|
|
179
182
|
if (mode === "registry") {
|
|
183
|
+
if (fs4.existsSync(path2.join(projectRoot, "src/shared"))) {
|
|
184
|
+
return path2.join(projectRoot, "src/shared");
|
|
185
|
+
}
|
|
180
186
|
return path2.join(projectRoot, "shared");
|
|
181
187
|
}
|
|
182
188
|
if (fs4.existsSync(path2.join(projectRoot, "src/shared"))) {
|
|
@@ -483,7 +489,14 @@ async function fetchRegistryFile(registryBase, relPath) {
|
|
|
483
489
|
if (token) {
|
|
484
490
|
headers["Authorization"] = `Bearer ${token}`;
|
|
485
491
|
}
|
|
486
|
-
|
|
492
|
+
let res = await fetch(url, { headers });
|
|
493
|
+
if (!res.ok && res.status === 404 && !cleanRelPath.startsWith("src/")) {
|
|
494
|
+
const srcUrl = `${registryBase.replace(/\/+$/, "")}/src/${cleanRelPath}`;
|
|
495
|
+
const srcRes = await fetch(srcUrl, { headers });
|
|
496
|
+
if (srcRes.ok) {
|
|
497
|
+
res = srcRes;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
487
500
|
if (!res.ok) {
|
|
488
501
|
let extraHint = "";
|
|
489
502
|
if (res.status === 404) {
|
|
@@ -503,9 +516,14 @@ async function fetchRegistryFile(registryBase, relPath) {
|
|
|
503
516
|
if (baseDir.startsWith("file://")) {
|
|
504
517
|
baseDir = fileURLToPath(baseDir);
|
|
505
518
|
}
|
|
506
|
-
|
|
519
|
+
let filePath = path2.resolve(baseDir, cleanRelPath);
|
|
507
520
|
if (!fs4.existsSync(filePath)) {
|
|
508
|
-
|
|
521
|
+
const inSrcPath = path2.resolve(baseDir, "src", cleanRelPath);
|
|
522
|
+
if (fs4.existsSync(inSrcPath)) {
|
|
523
|
+
filePath = inSrcPath;
|
|
524
|
+
} else {
|
|
525
|
+
throw new Error(`Registry file not found at ${filePath}`);
|
|
526
|
+
}
|
|
509
527
|
}
|
|
510
528
|
return fs4.promises.readFile(filePath, "utf-8");
|
|
511
529
|
}
|
|
@@ -3600,11 +3618,18 @@ function rewriteImports(content, aliasMap) {
|
|
|
3600
3618
|
return rewritten;
|
|
3601
3619
|
}
|
|
3602
3620
|
function getModuleBaseDir(projectRoot, modType) {
|
|
3621
|
+
const mode = getEffectiveMode(projectRoot);
|
|
3622
|
+
if (mode === "registry") {
|
|
3623
|
+
return modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
3624
|
+
}
|
|
3603
3625
|
const folder = modType === "shared" ? "shared" : "features";
|
|
3604
3626
|
return path2.join(projectRoot, "src", folder);
|
|
3605
3627
|
}
|
|
3606
3628
|
function getExistingModuleDir(projectRoot, modType, modName) {
|
|
3607
3629
|
const folder = modType === "shared" ? "shared" : "features";
|
|
3630
|
+
const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
3631
|
+
const inConfigured = path2.join(configuredDir, modName);
|
|
3632
|
+
if (fs4.existsSync(inConfigured)) return inConfigured;
|
|
3608
3633
|
const inSrc = path2.join(projectRoot, "src", folder, modName);
|
|
3609
3634
|
if (fs4.existsSync(inSrc)) return inSrc;
|
|
3610
3635
|
const inRoot = path2.join(projectRoot, folder, modName);
|
|
@@ -3614,6 +3639,50 @@ function getExistingModuleDir(projectRoot, modType, modName) {
|
|
|
3614
3639
|
function checkModuleExists(projectRoot, modType, modName) {
|
|
3615
3640
|
return getExistingModuleDir(projectRoot, modType, modName) !== null;
|
|
3616
3641
|
}
|
|
3642
|
+
function getAvailableLocalModules(projectRoot, modType) {
|
|
3643
|
+
const folder = modType === "shared" ? "shared" : "features";
|
|
3644
|
+
const configuredDir = modType === "shared" ? getConfiguredSharedDir(projectRoot) : getConfiguredFeaturesDir(projectRoot);
|
|
3645
|
+
const dirs = [
|
|
3646
|
+
configuredDir,
|
|
3647
|
+
path2.join(projectRoot, "src", folder),
|
|
3648
|
+
path2.join(projectRoot, folder)
|
|
3649
|
+
];
|
|
3650
|
+
const set = /* @__PURE__ */ new Set();
|
|
3651
|
+
for (const dir of dirs) {
|
|
3652
|
+
if (fs4.existsSync(dir)) {
|
|
3653
|
+
try {
|
|
3654
|
+
const entries = fs4.readdirSync(dir, { withFileTypes: true });
|
|
3655
|
+
for (const e of entries) {
|
|
3656
|
+
if (e.isDirectory() && !e.name.startsWith(".")) {
|
|
3657
|
+
set.add(e.name);
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
} catch {
|
|
3661
|
+
}
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3664
|
+
return Array.from(set).sort();
|
|
3665
|
+
}
|
|
3666
|
+
function parseMappingFlags(raw) {
|
|
3667
|
+
if (!raw) return {};
|
|
3668
|
+
if (typeof raw === "object" && !Array.isArray(raw)) return raw;
|
|
3669
|
+
const result = {};
|
|
3670
|
+
const entries = Array.isArray(raw) ? raw : [raw];
|
|
3671
|
+
for (const entry of entries) {
|
|
3672
|
+
if (typeof entry === "string") {
|
|
3673
|
+
const idx = entry.indexOf(":");
|
|
3674
|
+
if (idx !== -1) {
|
|
3675
|
+
let key = entry.slice(0, idx).trim();
|
|
3676
|
+
let val = entry.slice(idx + 1).trim();
|
|
3677
|
+
val = val.replace(/^@\/(shared|features)\//, "").replace(/^(src\/)?(shared|features)\//, "").replace(/^\/+|\/+$/g, "").trim();
|
|
3678
|
+
if (key && val) {
|
|
3679
|
+
result[key] = val;
|
|
3680
|
+
}
|
|
3681
|
+
}
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3684
|
+
return result;
|
|
3685
|
+
}
|
|
3617
3686
|
async function handleImport(typeArg, nameArg, flags = {}) {
|
|
3618
3687
|
const projectRoot = findProjectRoot();
|
|
3619
3688
|
let type = typeArg?.trim().toLowerCase();
|
|
@@ -3734,7 +3803,8 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
3734
3803
|
const { type: modType, name: registryName, manifest } = node;
|
|
3735
3804
|
const folder = modType === "shared" ? "shared" : "features";
|
|
3736
3805
|
if (key === rootKey) {
|
|
3737
|
-
const
|
|
3806
|
+
const aliasMap2 = parseMappingFlags(flags.alias);
|
|
3807
|
+
const programmaticAlias2 = aliasMap2[registryName] || aliasMap2[`${modType}/${registryName}`];
|
|
3738
3808
|
const targetName = programmaticAlias2 || registryName;
|
|
3739
3809
|
if (targetName !== registryName) {
|
|
3740
3810
|
globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${targetName}/`);
|
|
@@ -3749,7 +3819,36 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
3749
3819
|
});
|
|
3750
3820
|
continue;
|
|
3751
3821
|
}
|
|
3752
|
-
const
|
|
3822
|
+
const aliasMap = parseMappingFlags(flags.alias);
|
|
3823
|
+
const pointToMap = {
|
|
3824
|
+
...parseMappingFlags(flags.pointTo),
|
|
3825
|
+
...parseMappingFlags(flags["point-to"]),
|
|
3826
|
+
...parseMappingFlags(flags.useExisting),
|
|
3827
|
+
...parseMappingFlags(flags["use-existing"])
|
|
3828
|
+
};
|
|
3829
|
+
const programmaticPointTo = pointToMap[registryName] || pointToMap[`${modType}/${registryName}`];
|
|
3830
|
+
if (programmaticPointTo) {
|
|
3831
|
+
if (!checkModuleExists(projectRoot, modType, programmaticPointTo)) {
|
|
3832
|
+
p14.log.error(
|
|
3833
|
+
pc14.red(
|
|
3834
|
+
`Module '${programmaticPointTo}' specified in --point-to does not exist in ${folder}.`
|
|
3835
|
+
)
|
|
3836
|
+
);
|
|
3837
|
+
process.exit(1);
|
|
3838
|
+
}
|
|
3839
|
+
globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${programmaticPointTo}/`);
|
|
3840
|
+
globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${programmaticPointTo}`);
|
|
3841
|
+
p14.log.step(`Pointing '${modType}/${registryName}' to existing '${folder}/${programmaticPointTo}'`);
|
|
3842
|
+
resolutions.set(key, {
|
|
3843
|
+
type: modType,
|
|
3844
|
+
registryName,
|
|
3845
|
+
targetName: programmaticPointTo,
|
|
3846
|
+
action: "reuse",
|
|
3847
|
+
manifest
|
|
3848
|
+
});
|
|
3849
|
+
continue;
|
|
3850
|
+
}
|
|
3851
|
+
const programmaticAlias = aliasMap[registryName] || aliasMap[`${modType}/${registryName}`];
|
|
3753
3852
|
if (programmaticAlias) {
|
|
3754
3853
|
globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${programmaticAlias}/`);
|
|
3755
3854
|
globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${programmaticAlias}`);
|
|
@@ -3823,6 +3922,10 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
3823
3922
|
value: "keep_existing",
|
|
3824
3923
|
label: `Keep existing local version (Recommended)`
|
|
3825
3924
|
},
|
|
3925
|
+
{
|
|
3926
|
+
value: "point_existing",
|
|
3927
|
+
label: `Point to another existing ${modType} module`
|
|
3928
|
+
},
|
|
3826
3929
|
{
|
|
3827
3930
|
value: "rename",
|
|
3828
3931
|
label: "Import fresh copy under a new name (alias)"
|
|
@@ -3845,6 +3948,78 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
3845
3948
|
});
|
|
3846
3949
|
continue;
|
|
3847
3950
|
}
|
|
3951
|
+
if (choice === "point_existing" || choice === "point_to_existing") {
|
|
3952
|
+
const candidates = getAvailableLocalModules(projectRoot, modType).filter(
|
|
3953
|
+
(m) => m !== registryName
|
|
3954
|
+
);
|
|
3955
|
+
let chosenName;
|
|
3956
|
+
if (candidates.length > 0) {
|
|
3957
|
+
const selection = handleCancel(
|
|
3958
|
+
await importPrompts.select({
|
|
3959
|
+
message: `Select an existing ${modType} module to point to:`,
|
|
3960
|
+
options: [
|
|
3961
|
+
...candidates.map((m) => ({
|
|
3962
|
+
value: m,
|
|
3963
|
+
label: m
|
|
3964
|
+
})),
|
|
3965
|
+
{
|
|
3966
|
+
value: "__custom__",
|
|
3967
|
+
label: "Enter name manually..."
|
|
3968
|
+
}
|
|
3969
|
+
]
|
|
3970
|
+
})
|
|
3971
|
+
);
|
|
3972
|
+
if (selection === "__custom__") {
|
|
3973
|
+
chosenName = handleCancel(
|
|
3974
|
+
await importPrompts.text({
|
|
3975
|
+
message: `Enter the name of the existing ${modType} module:`,
|
|
3976
|
+
placeholder: `my${registryName}`,
|
|
3977
|
+
validate(val) {
|
|
3978
|
+
const v = val?.trim();
|
|
3979
|
+
if (!v) return "Name cannot be empty";
|
|
3980
|
+
if (v === registryName) {
|
|
3981
|
+
return `Name must be different from '${registryName}' (or select 'Keep existing local version')`;
|
|
3982
|
+
}
|
|
3983
|
+
if (!checkModuleExists(projectRoot, modType, v)) {
|
|
3984
|
+
return `'${v}' does not exist in ${folder}`;
|
|
3985
|
+
}
|
|
3986
|
+
}
|
|
3987
|
+
})
|
|
3988
|
+
).trim();
|
|
3989
|
+
} else {
|
|
3990
|
+
chosenName = selection;
|
|
3991
|
+
}
|
|
3992
|
+
} else {
|
|
3993
|
+
chosenName = handleCancel(
|
|
3994
|
+
await importPrompts.text({
|
|
3995
|
+
message: `Enter the name of the existing ${modType} module:`,
|
|
3996
|
+
placeholder: `my${registryName}`,
|
|
3997
|
+
validate(val) {
|
|
3998
|
+
const v = val?.trim();
|
|
3999
|
+
if (!v) return "Name cannot be empty";
|
|
4000
|
+
if (v === registryName) {
|
|
4001
|
+
return `Name must be different from '${registryName}' (or select 'Keep existing local version')`;
|
|
4002
|
+
}
|
|
4003
|
+
if (!checkModuleExists(projectRoot, modType, v)) {
|
|
4004
|
+
return `'${v}' does not exist in ${folder}`;
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
})
|
|
4008
|
+
).trim();
|
|
4009
|
+
}
|
|
4010
|
+
chosenName = chosenName.replace(/^@\/(shared|features)\//, "").replace(/^(src\/)?(shared|features)\//, "").replace(/^\/+|\/+$/g, "").trim();
|
|
4011
|
+
globalAliasMap.set(`@/${folder}/${registryName}/`, `@/${folder}/${chosenName}/`);
|
|
4012
|
+
globalAliasMap.set(`@/${folder}/${registryName}`, `@/${folder}/${chosenName}`);
|
|
4013
|
+
p14.log.step(`Pointing '${modType}/${registryName}' to existing '${folder}/${chosenName}'`);
|
|
4014
|
+
resolutions.set(key, {
|
|
4015
|
+
type: modType,
|
|
4016
|
+
registryName,
|
|
4017
|
+
targetName: chosenName,
|
|
4018
|
+
action: "reuse",
|
|
4019
|
+
manifest
|
|
4020
|
+
});
|
|
4021
|
+
continue;
|
|
4022
|
+
}
|
|
3848
4023
|
if (choice === "rename") {
|
|
3849
4024
|
const newName = handleCancel(
|
|
3850
4025
|
await importPrompts.text({
|
|
@@ -3972,7 +4147,7 @@ async function handleImport(typeArg, nameArg, flags = {}) {
|
|
|
3972
4147
|
// src/cli.ts
|
|
3973
4148
|
function createCli() {
|
|
3974
4149
|
const cli = cac("mason");
|
|
3975
|
-
cli.command("[...args]", "Interactive scaffolding and import wizard").option("-d, --dry-run", "Preview changes without writing to disk").option("-o, --overwrite", "Overwrite existing files").option("-y, --yes", "Accept defaults and skip interactive prompts").option("--registry", "Run in registry mode").action(async (args, flags) => {
|
|
4150
|
+
cli.command("[...args]", "Interactive scaffolding and import wizard").option("-d, --dry-run", "Preview changes without writing to disk").option("-o, --overwrite", "Overwrite existing files").option("-y, --yes", "Accept defaults and skip interactive prompts").option("--registry", "Run in registry mode").option("--point-to <mapping>", "Point a dependency to an existing local module (e.g. --point-to time:mytime)").option("--alias <mapping>", "Import a dependency fresh under an alias name (e.g. --alias time:time-mason)").action(async (args, flags) => {
|
|
3976
4151
|
if (args && args.length > 0) {
|
|
3977
4152
|
p14.log.error(
|
|
3978
4153
|
pc14.red(
|
|
@@ -4067,7 +4242,7 @@ function createCli() {
|
|
|
4067
4242
|
cli.command(
|
|
4068
4243
|
"import [type] [name]",
|
|
4069
4244
|
"Import pre-built shared modules or features from the Solid Stack Registry"
|
|
4070
|
-
).option("-o, --overwrite", "Overwrite existing files").option("-d, --dry-run", "Preview changes without writing to disk").option("-y, --yes", "Accept defaults and skip interactive prompts").option("--registry <url>", "Registry base URL or local directory").option("--skip-install", "Skip automatic package manager dependency installation").example("mason import shared hasher").example("mason import feature authn").example("mason import shared").example("mason import feature").action(async (type, name, flags = {}) => {
|
|
4245
|
+
).option("-o, --overwrite", "Overwrite existing files").option("-d, --dry-run", "Preview changes without writing to disk").option("-y, --yes", "Accept defaults and skip interactive prompts").option("--registry <url>", "Registry base URL or local directory").option("--skip-install", "Skip automatic package manager dependency installation").option("--point-to <mapping>", "Point a dependency to an existing local module (e.g. --point-to time:mytime)").option("--alias <mapping>", "Import a dependency fresh under an alias name (e.g. --alias time:time-mason)").example("mason import shared hasher").example("mason import feature authn").example("mason import shared").example("mason import feature").action(async (type, name, flags = {}) => {
|
|
4071
4246
|
try {
|
|
4072
4247
|
await handleImport(type, name, flags);
|
|
4073
4248
|
} catch (err) {
|
|
@@ -4097,7 +4272,7 @@ function createCli() {
|
|
|
4097
4272
|
});
|
|
4098
4273
|
}
|
|
4099
4274
|
cli.help();
|
|
4100
|
-
cli.version("1.0.
|
|
4275
|
+
cli.version("1.0.18");
|
|
4101
4276
|
return cli;
|
|
4102
4277
|
}
|
|
4103
4278
|
function handleCliError(err) {
|