fimo 0.3.4-staging.26 → 0.3.4
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/cli/bundle.json +2 -2
- package/dist/cli/index.js +155 -54
- package/package.json +1 -1
- package/release.json +2 -2
- package/templates/react-router/package.json +1 -1
package/dist/cli/bundle.json
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -45923,13 +45923,22 @@ var init_local_project_files = __esm({
|
|
|
45923
45923
|
}
|
|
45924
45924
|
});
|
|
45925
45925
|
|
|
45926
|
+
// src/cli/utils/slug.ts
|
|
45927
|
+
function slugifyName(input) {
|
|
45928
|
+
return input.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
45929
|
+
}
|
|
45930
|
+
var init_slug = __esm({
|
|
45931
|
+
"src/cli/utils/slug.ts"() {
|
|
45932
|
+
__name(slugifyName, "slugifyName");
|
|
45933
|
+
}
|
|
45934
|
+
});
|
|
45935
|
+
|
|
45926
45936
|
// src/cli/commands/clone.ts
|
|
45927
45937
|
import fs18 from "node:fs";
|
|
45928
45938
|
import path22 from "node:path";
|
|
45929
45939
|
function defaultDirectoryName(project) {
|
|
45930
45940
|
const source = project.displayName?.trim() || project.name || project.id;
|
|
45931
|
-
|
|
45932
|
-
return cleaned || project.id;
|
|
45941
|
+
return slugifyName(source) || project.id;
|
|
45933
45942
|
}
|
|
45934
45943
|
function explainCloneRemoteError(error45) {
|
|
45935
45944
|
if (error45 instanceof ApiRequestError && error45.status === 403) {
|
|
@@ -46079,7 +46088,12 @@ async function cloneProject(args) {
|
|
|
46079
46088
|
}
|
|
46080
46089
|
const targetDir = path22.resolve(dir ?? defaultDirectoryName(project));
|
|
46081
46090
|
if (fs18.existsSync(targetDir) && fs18.readdirSync(targetDir).length > 0) {
|
|
46082
|
-
|
|
46091
|
+
const name = path22.basename(targetDir);
|
|
46092
|
+
throw new CloneError(
|
|
46093
|
+
"DIRECTORY_NOT_EMPTY",
|
|
46094
|
+
`The folder "${name}" already exists and isn't empty.`,
|
|
46095
|
+
`Pick a different directory (e.g. \`fimo clone ${projectId} <dir>\`), or empty "${name}" first.`
|
|
46096
|
+
);
|
|
46083
46097
|
}
|
|
46084
46098
|
const relativeTarget = path22.relative(process.cwd(), targetDir) || ".";
|
|
46085
46099
|
if (!await remoteHasBranch(remote.url, remote.branch)) {
|
|
@@ -46174,6 +46188,7 @@ var init_clone = __esm({
|
|
|
46174
46188
|
init_git();
|
|
46175
46189
|
init_interactive();
|
|
46176
46190
|
init_local_project_files();
|
|
46191
|
+
init_slug();
|
|
46177
46192
|
CloneError = class extends Error {
|
|
46178
46193
|
static {
|
|
46179
46194
|
__name(this, "CloneError");
|
|
@@ -48440,12 +48455,15 @@ function explainCreateProjectError(error45) {
|
|
|
48440
48455
|
return error45 instanceof Error ? error45.message : String(error45);
|
|
48441
48456
|
}
|
|
48442
48457
|
async function scaffoldNewProject(args) {
|
|
48443
|
-
const { api, cfg, targetDir, options } = args;
|
|
48458
|
+
const { api, cfg, targetDir, displayName, options } = args;
|
|
48444
48459
|
const organizationId = await resolveOrganization(api, options.org);
|
|
48445
48460
|
const createSpinner = spinner("Creating Fimo project");
|
|
48446
48461
|
let project;
|
|
48447
48462
|
try {
|
|
48448
|
-
project = await api.createProject({
|
|
48463
|
+
project = await api.createProject({
|
|
48464
|
+
organizationId,
|
|
48465
|
+
displayName: displayName ?? path34.basename(targetDir)
|
|
48466
|
+
});
|
|
48449
48467
|
} catch (error45) {
|
|
48450
48468
|
createSpinner.fail("Project creation failed");
|
|
48451
48469
|
throw new ScaffoldError("PROJECT_CREATE_FAILED", explainCreateProjectError(error45));
|
|
@@ -48687,7 +48705,17 @@ async function initCommand(dirArg, options) {
|
|
|
48687
48705
|
const api = new FimoApiClient(cfg);
|
|
48688
48706
|
const creds = readCredentials(cfg);
|
|
48689
48707
|
const useExisting = await resolveUseExisting(options);
|
|
48690
|
-
const
|
|
48708
|
+
const plan = await planInit({ api, creds, useExisting, dirArg, options });
|
|
48709
|
+
if (!plan) {
|
|
48710
|
+
return;
|
|
48711
|
+
}
|
|
48712
|
+
const result = useExisting ? await runExisting({ api, cfg, projectId: plan.projectId, dirArg, options: plan.options }) : await runNew({
|
|
48713
|
+
api,
|
|
48714
|
+
cfg,
|
|
48715
|
+
targetDir: plan.targetDir,
|
|
48716
|
+
displayName: plan.displayName,
|
|
48717
|
+
options: plan.options
|
|
48718
|
+
});
|
|
48691
48719
|
if (!result) {
|
|
48692
48720
|
return;
|
|
48693
48721
|
}
|
|
@@ -48695,8 +48723,8 @@ async function initCommand(dirArg, options) {
|
|
|
48695
48723
|
const scaffoldSummary = result.summary;
|
|
48696
48724
|
const scaffoldedAgents = result.selectedAgents;
|
|
48697
48725
|
const pushedInitial = result.pushedInitial;
|
|
48698
|
-
const depResult = await maybeInstallDependencies(checkout.targetDir,
|
|
48699
|
-
const skills2 = await maybeInstallSkills(checkout.targetDir, options, scaffoldedAgents);
|
|
48726
|
+
const depResult = await maybeInstallDependencies(checkout.targetDir, plan.packageManager);
|
|
48727
|
+
const skills2 = await maybeInstallSkills(checkout.targetDir, plan.options, scaffoldedAgents);
|
|
48700
48728
|
const warnings = [];
|
|
48701
48729
|
if (!pushedInitial) {
|
|
48702
48730
|
warnings.push(
|
|
@@ -48835,19 +48863,73 @@ async function resolveUseExisting(options) {
|
|
|
48835
48863
|
}
|
|
48836
48864
|
return choice === "existing";
|
|
48837
48865
|
}
|
|
48838
|
-
async function
|
|
48839
|
-
const { api,
|
|
48840
|
-
|
|
48841
|
-
|
|
48842
|
-
|
|
48843
|
-
|
|
48844
|
-
|
|
48845
|
-
|
|
48846
|
-
|
|
48847
|
-
|
|
48866
|
+
async function planInit(args) {
|
|
48867
|
+
const { api, creds, useExisting, dirArg, options } = args;
|
|
48868
|
+
let projectId;
|
|
48869
|
+
let targetDir;
|
|
48870
|
+
let displayName;
|
|
48871
|
+
if (useExisting) {
|
|
48872
|
+
projectId = options.projectId ?? await selectProjectId({
|
|
48873
|
+
api,
|
|
48874
|
+
activeOrganizationId: creds?.activeOrganization?.id ?? null,
|
|
48875
|
+
command: "init",
|
|
48876
|
+
message: "Select a project to link"
|
|
48877
|
+
}) ?? void 0;
|
|
48878
|
+
if (!projectId) {
|
|
48879
|
+
return null;
|
|
48880
|
+
}
|
|
48881
|
+
} else {
|
|
48882
|
+
const resolved = await resolveTargetDir(dirArg, nonInteractive(options));
|
|
48883
|
+
if (!resolved) {
|
|
48884
|
+
return null;
|
|
48885
|
+
}
|
|
48886
|
+
targetDir = resolved.targetDir;
|
|
48887
|
+
displayName = resolved.displayName;
|
|
48888
|
+
if (fs33.existsSync(targetDir) && fs33.readdirSync(targetDir).length > 0) {
|
|
48889
|
+
const name = path35.basename(targetDir);
|
|
48890
|
+
ui.error({
|
|
48891
|
+
command: "init",
|
|
48892
|
+
code: "DIRECTORY_NOT_EMPTY",
|
|
48893
|
+
message: `The folder "${name}" already exists and isn't empty.`,
|
|
48894
|
+
hint: `Pick a different directory (e.g. \`fimo init <dir>\`), or empty "${name}" first.`
|
|
48895
|
+
});
|
|
48896
|
+
return null;
|
|
48897
|
+
}
|
|
48848
48898
|
}
|
|
48899
|
+
const derived = { ...options };
|
|
48900
|
+
const gatherAgents = !nonInteractive(options) && (!useExisting || options.skills !== false);
|
|
48901
|
+
if (gatherAgents) {
|
|
48902
|
+
let agents;
|
|
48903
|
+
try {
|
|
48904
|
+
agents = await selectAgents(options, {
|
|
48905
|
+
promptMessage: "Which agents do you want to set up?",
|
|
48906
|
+
detectFn: detectAgentsWithFimoSkills
|
|
48907
|
+
});
|
|
48908
|
+
} catch (err) {
|
|
48909
|
+
ui.error({
|
|
48910
|
+
command: "init",
|
|
48911
|
+
code: "AGENT_SELECTION_FAILED",
|
|
48912
|
+
message: err instanceof Error ? err.message : String(err)
|
|
48913
|
+
});
|
|
48914
|
+
return null;
|
|
48915
|
+
}
|
|
48916
|
+
derived.agents = agents.length > 0 ? agents.join(",") : "none";
|
|
48917
|
+
} else if (useExisting && options.skills === false && !derived.agents) {
|
|
48918
|
+
derived.agents = "none";
|
|
48919
|
+
}
|
|
48920
|
+
const packageManager = options.install === false ? null : await resolvePackageManager(derived);
|
|
48921
|
+
return { projectId, targetDir, displayName, packageManager, options: derived };
|
|
48922
|
+
}
|
|
48923
|
+
async function runExisting(args) {
|
|
48924
|
+
const { api, cfg, projectId, dirArg, options } = args;
|
|
48849
48925
|
try {
|
|
48850
|
-
const result = await cloneProject({
|
|
48926
|
+
const result = await cloneProject({
|
|
48927
|
+
api,
|
|
48928
|
+
cfg,
|
|
48929
|
+
projectId,
|
|
48930
|
+
dir: dirArg,
|
|
48931
|
+
env: options.env
|
|
48932
|
+
});
|
|
48851
48933
|
return {
|
|
48852
48934
|
checkout: {
|
|
48853
48935
|
projectId: result.project.id,
|
|
@@ -48864,7 +48946,12 @@ async function runExisting(args) {
|
|
|
48864
48946
|
return adoptEmptyRemote({ api, cfg, ctx: error45.emptyRemote, options });
|
|
48865
48947
|
}
|
|
48866
48948
|
if (error45 instanceof CloneError) {
|
|
48867
|
-
ui.error({
|
|
48949
|
+
ui.error({
|
|
48950
|
+
command: "init",
|
|
48951
|
+
code: error45.code,
|
|
48952
|
+
message: error45.message,
|
|
48953
|
+
hint: error45.hint
|
|
48954
|
+
});
|
|
48868
48955
|
return null;
|
|
48869
48956
|
}
|
|
48870
48957
|
throw error45;
|
|
@@ -48876,7 +48963,13 @@ async function adoptEmptyRemote(args) {
|
|
|
48876
48963
|
O2.step("This project has no content yet \u2014 scaffolding a starter site and pushing the first commit.");
|
|
48877
48964
|
}
|
|
48878
48965
|
try {
|
|
48879
|
-
const result = await scaffoldIntoProject({
|
|
48966
|
+
const result = await scaffoldIntoProject({
|
|
48967
|
+
project: ctx.project,
|
|
48968
|
+
api,
|
|
48969
|
+
cfg,
|
|
48970
|
+
targetDir: ctx.targetDir,
|
|
48971
|
+
options
|
|
48972
|
+
});
|
|
48880
48973
|
return {
|
|
48881
48974
|
checkout: {
|
|
48882
48975
|
projectId: result.project.id,
|
|
@@ -48890,28 +48983,21 @@ async function adoptEmptyRemote(args) {
|
|
|
48890
48983
|
};
|
|
48891
48984
|
} catch (error45) {
|
|
48892
48985
|
if (error45 instanceof ScaffoldError) {
|
|
48893
|
-
ui.error({
|
|
48986
|
+
ui.error({
|
|
48987
|
+
command: "init",
|
|
48988
|
+
code: error45.code,
|
|
48989
|
+
message: error45.message,
|
|
48990
|
+
hint: error45.hint
|
|
48991
|
+
});
|
|
48894
48992
|
return null;
|
|
48895
48993
|
}
|
|
48896
48994
|
throw error45;
|
|
48897
48995
|
}
|
|
48898
48996
|
}
|
|
48899
48997
|
async function runNew(args) {
|
|
48900
|
-
const { api, cfg,
|
|
48901
|
-
const targetDir = await resolveTargetDir(dirArg, nonInteractive(options));
|
|
48902
|
-
if (!targetDir) {
|
|
48903
|
-
return null;
|
|
48904
|
-
}
|
|
48905
|
-
if (fs33.existsSync(targetDir) && fs33.readdirSync(targetDir).length > 0) {
|
|
48906
|
-
ui.error({
|
|
48907
|
-
command: "init",
|
|
48908
|
-
code: "DIRECTORY_NOT_EMPTY",
|
|
48909
|
-
message: `Refusing to scaffold into non-empty directory: ${targetDir}`
|
|
48910
|
-
});
|
|
48911
|
-
return null;
|
|
48912
|
-
}
|
|
48998
|
+
const { api, cfg, targetDir, displayName, options } = args;
|
|
48913
48999
|
try {
|
|
48914
|
-
const result = await scaffoldNewProject({ api, cfg, targetDir, options });
|
|
49000
|
+
const result = await scaffoldNewProject({ api, cfg, targetDir, displayName, options });
|
|
48915
49001
|
return {
|
|
48916
49002
|
checkout: {
|
|
48917
49003
|
projectId: result.project.id,
|
|
@@ -48925,7 +49011,12 @@ async function runNew(args) {
|
|
|
48925
49011
|
};
|
|
48926
49012
|
} catch (error45) {
|
|
48927
49013
|
if (error45 instanceof ScaffoldError) {
|
|
48928
|
-
ui.error({
|
|
49014
|
+
ui.error({
|
|
49015
|
+
command: "init",
|
|
49016
|
+
code: error45.code,
|
|
49017
|
+
message: error45.message,
|
|
49018
|
+
hint: error45.hint
|
|
49019
|
+
});
|
|
48929
49020
|
return null;
|
|
48930
49021
|
}
|
|
48931
49022
|
throw error45;
|
|
@@ -48933,7 +49024,7 @@ async function runNew(args) {
|
|
|
48933
49024
|
}
|
|
48934
49025
|
async function resolveTargetDir(dirArg, noPrompt) {
|
|
48935
49026
|
if (dirArg) {
|
|
48936
|
-
return path35.resolve(dirArg);
|
|
49027
|
+
return { targetDir: path35.resolve(dirArg) };
|
|
48937
49028
|
}
|
|
48938
49029
|
if (noPrompt) {
|
|
48939
49030
|
ui.error({
|
|
@@ -48945,21 +49036,19 @@ async function resolveTargetDir(dirArg, noPrompt) {
|
|
|
48945
49036
|
return null;
|
|
48946
49037
|
}
|
|
48947
49038
|
const input = await Ot({
|
|
48948
|
-
message: "Project
|
|
48949
|
-
placeholder: "
|
|
48950
|
-
validate: /* @__PURE__ */ __name((value) => value && value.trim().length > 0 ? void 0 : "
|
|
49039
|
+
message: "Project name",
|
|
49040
|
+
placeholder: "My Fimo Site",
|
|
49041
|
+
validate: /* @__PURE__ */ __name((value) => value && value.trim().length > 0 ? void 0 : "project name required", "validate")
|
|
48951
49042
|
});
|
|
48952
49043
|
if (q(input)) {
|
|
48953
49044
|
ui.info({ command: "init", message: "Cancelled." });
|
|
48954
49045
|
return null;
|
|
48955
49046
|
}
|
|
48956
|
-
|
|
49047
|
+
const displayName = String(input).trim();
|
|
49048
|
+
const folder = slugifyName(displayName) || "fimo-project";
|
|
49049
|
+
return { targetDir: path35.resolve(folder), displayName };
|
|
48957
49050
|
}
|
|
48958
|
-
async function maybeInstallDependencies(targetDir,
|
|
48959
|
-
if (options.install === false) {
|
|
48960
|
-
return { installed: false, packageManager: null, error: null };
|
|
48961
|
-
}
|
|
48962
|
-
const packageManager = await resolvePackageManager(options);
|
|
49051
|
+
async function maybeInstallDependencies(targetDir, packageManager) {
|
|
48963
49052
|
if (!packageManager) {
|
|
48964
49053
|
return { installed: false, packageManager: null, error: null };
|
|
48965
49054
|
}
|
|
@@ -48977,9 +49066,12 @@ async function resolvePackageManager(options) {
|
|
|
48977
49066
|
const selected = await _t({
|
|
48978
49067
|
message: "Install dependencies with which package manager?",
|
|
48979
49068
|
initialValue: detected,
|
|
48980
|
-
options:
|
|
49069
|
+
options: [
|
|
49070
|
+
...PACKAGE_MANAGERS.map((pm) => ({ value: pm, label: pm })),
|
|
49071
|
+
{ value: MANUAL_INSTALL, label: "Manual \u2014 I'll install dependencies myself" }
|
|
49072
|
+
]
|
|
48981
49073
|
});
|
|
48982
|
-
if (q(selected)) {
|
|
49074
|
+
if (q(selected) || selected === MANUAL_INSTALL) {
|
|
48983
49075
|
return null;
|
|
48984
49076
|
}
|
|
48985
49077
|
return selected;
|
|
@@ -49000,7 +49092,6 @@ async function maybeInstallSkills(targetDir, options, scaffoldedAgents) {
|
|
|
49000
49092
|
} else if (nonInteractive(options) && !agentsFlag) {
|
|
49001
49093
|
return { setUp: false, error: null };
|
|
49002
49094
|
}
|
|
49003
|
-
const noPrompt = nonInteractive(options);
|
|
49004
49095
|
const prevCwd = process.cwd();
|
|
49005
49096
|
let outcome;
|
|
49006
49097
|
try {
|
|
@@ -49008,21 +49099,27 @@ async function maybeInstallSkills(targetDir, options, scaffoldedAgents) {
|
|
|
49008
49099
|
outcome = await runSkillsInstall({
|
|
49009
49100
|
agents: agentsFlag,
|
|
49010
49101
|
agent: scaffoldedAgents !== null ? void 0 : options.agent,
|
|
49011
|
-
mode:
|
|
49012
|
-
yes:
|
|
49102
|
+
mode: options.mode ?? "symlink",
|
|
49103
|
+
yes: true
|
|
49013
49104
|
});
|
|
49014
49105
|
} finally {
|
|
49015
49106
|
process.chdir(prevCwd);
|
|
49016
49107
|
}
|
|
49108
|
+
if (outcome.status === "error" && outcome.code === "NO_AGENTS_SELECTED") {
|
|
49109
|
+
return { setUp: false, error: null };
|
|
49110
|
+
}
|
|
49017
49111
|
if (outcome.status === "ok") {
|
|
49018
|
-
return {
|
|
49112
|
+
return {
|
|
49113
|
+
setUp: true,
|
|
49114
|
+
error: outcome.data.ok ? null : "Some skills failed to install."
|
|
49115
|
+
};
|
|
49019
49116
|
}
|
|
49020
49117
|
if (outcome.status === "cancelled") {
|
|
49021
49118
|
return { setUp: false, error: null };
|
|
49022
49119
|
}
|
|
49023
49120
|
return { setUp: false, error: outcome.message };
|
|
49024
49121
|
}
|
|
49025
|
-
var PACKAGE_MANAGERS;
|
|
49122
|
+
var PACKAGE_MANAGERS, MANUAL_INSTALL;
|
|
49026
49123
|
var init_init = __esm({
|
|
49027
49124
|
"src/cli/commands/init.ts"() {
|
|
49028
49125
|
init_dist6();
|
|
@@ -49030,13 +49127,16 @@ var init_init = __esm({
|
|
|
49030
49127
|
init_api();
|
|
49031
49128
|
init_auth();
|
|
49032
49129
|
init_config2();
|
|
49130
|
+
init_agents();
|
|
49033
49131
|
init_color();
|
|
49034
49132
|
init_interactive();
|
|
49133
|
+
init_slug();
|
|
49035
49134
|
init_clone();
|
|
49036
49135
|
init_login();
|
|
49037
49136
|
init_scaffold_project();
|
|
49038
49137
|
init_skills();
|
|
49039
49138
|
PACKAGE_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
|
|
49139
|
+
MANUAL_INSTALL = "manual";
|
|
49040
49140
|
__name(isPretty, "isPretty");
|
|
49041
49141
|
__name(nonInteractive, "nonInteractive");
|
|
49042
49142
|
__name(initCommand, "initCommand");
|
|
@@ -49044,6 +49144,7 @@ var init_init = __esm({
|
|
|
49044
49144
|
__name(renderInitPushFailed, "renderInitPushFailed");
|
|
49045
49145
|
__name(ensureAuthenticated, "ensureAuthenticated");
|
|
49046
49146
|
__name(resolveUseExisting, "resolveUseExisting");
|
|
49147
|
+
__name(planInit, "planInit");
|
|
49047
49148
|
__name(runExisting, "runExisting");
|
|
49048
49149
|
__name(adoptEmptyRemote, "adoptEmptyRemote");
|
|
49049
49150
|
__name(runNew, "runNew");
|
package/package.json
CHANGED
package/release.json
CHANGED