create-fornix 0.0.6 → 0.0.8
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/index.js +106 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { defineCommand as defineCommand8 } from "citty";
|
|
|
9
9
|
// src/cli/commands/create.ts
|
|
10
10
|
import { defineCommand } from "citty";
|
|
11
11
|
import { resolve as resolve2, basename as basename2 } from "path";
|
|
12
|
-
import { mkdirSync as mkdirSync4, writeFileSync as
|
|
12
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
13
13
|
import { join as join6 } from "path";
|
|
14
14
|
import * as p2 from "@clack/prompts";
|
|
15
15
|
import pc3 from "picocolors";
|
|
@@ -305,14 +305,15 @@ ${blockImports.join("\n")}
|
|
|
305
305
|
${blockComponents.length > 0 ? blockComponents.join("\n") : ` <h1>Welcome to <span class="text-gradient">${config.projectName}</span></h1>`}
|
|
306
306
|
</main>
|
|
307
307
|
</Layout>
|
|
308
|
-
`.trim() + "
|
|
308
|
+
`.trim() + "\n";
|
|
309
309
|
files["src/pages/index.astro"] = indexAstroContent;
|
|
310
|
+
const tailwindImport = config.cssEngine === "tailwind" ? '\nimport "../../tailwind.css";' : "";
|
|
310
311
|
files["src/layouts/Layout.astro"] = `
|
|
311
312
|
---
|
|
312
313
|
interface Props {
|
|
313
314
|
title: string;
|
|
314
315
|
}
|
|
315
|
-
const { title } = Astro.props
|
|
316
|
+
const { title } = Astro.props;${tailwindImport}
|
|
316
317
|
---
|
|
317
318
|
<!doctype html>
|
|
318
319
|
<html lang="en">
|
|
@@ -403,6 +404,16 @@ function generateAstroConfig(config, blocks = []) {
|
|
|
403
404
|
configObject.integrations = configObject.integrations || [];
|
|
404
405
|
configObject.integrations.push(builders.functionCall("mdx"));
|
|
405
406
|
}
|
|
407
|
+
if (config.cssEngine === "tailwind") {
|
|
408
|
+
module.imports.$add({
|
|
409
|
+
from: "@tailwindcss/vite",
|
|
410
|
+
imported: "default",
|
|
411
|
+
local: "tailwindcss"
|
|
412
|
+
});
|
|
413
|
+
configObject.vite = {
|
|
414
|
+
plugins: [builders.functionCall("tailwindcss")]
|
|
415
|
+
};
|
|
416
|
+
}
|
|
406
417
|
const { code } = generateCode(module);
|
|
407
418
|
return ok(code);
|
|
408
419
|
} catch (error) {
|
|
@@ -427,8 +438,9 @@ function generateTailwindConfig(config) {
|
|
|
427
438
|
].join("\n");
|
|
428
439
|
const lines = [
|
|
429
440
|
'@import "tailwindcss";',
|
|
441
|
+
'@import "./src/styles/palettes/_current.css";',
|
|
430
442
|
"",
|
|
431
|
-
`@source "
|
|
443
|
+
`@source "./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}";`,
|
|
432
444
|
"",
|
|
433
445
|
themeBlock,
|
|
434
446
|
""
|
|
@@ -1491,6 +1503,7 @@ function manifest(name, overrides = {}) {
|
|
|
1491
1503
|
var FIXTURE_MANIFESTS = {
|
|
1492
1504
|
"hero-gradient": manifest("hero-gradient", {
|
|
1493
1505
|
category: "hero",
|
|
1506
|
+
conflicts: ["hero-video"],
|
|
1494
1507
|
ai: {
|
|
1495
1508
|
whenToUse: "Landing page hero with gradient background",
|
|
1496
1509
|
whenNotToUse: "Internal pages",
|
|
@@ -1885,10 +1898,13 @@ import {
|
|
|
1885
1898
|
readFileSync as readFileSync3,
|
|
1886
1899
|
readdirSync as readdirSync2,
|
|
1887
1900
|
mkdirSync as mkdirSync2,
|
|
1888
|
-
statSync as statSync2
|
|
1901
|
+
statSync as statSync2,
|
|
1902
|
+
writeFileSync as writeFileSync2,
|
|
1903
|
+
rmSync
|
|
1889
1904
|
} from "fs";
|
|
1890
1905
|
import { join as join3 } from "path";
|
|
1891
1906
|
import { homedir as homedir2 } from "os";
|
|
1907
|
+
import { createRequire } from "module";
|
|
1892
1908
|
var DEFAULT_CONFIG2 = {
|
|
1893
1909
|
repo: "kamsqe/fornix",
|
|
1894
1910
|
ref: "main",
|
|
@@ -1898,6 +1914,31 @@ var DEFAULT_CONFIG2 = {
|
|
|
1898
1914
|
maxCacheAge: 24 * 60 * 60 * 1e3
|
|
1899
1915
|
// 24 hours
|
|
1900
1916
|
};
|
|
1917
|
+
var cacheVersionChecked = false;
|
|
1918
|
+
function ensureCacheVersion(cacheDir) {
|
|
1919
|
+
if (cacheVersionChecked) return;
|
|
1920
|
+
cacheVersionChecked = true;
|
|
1921
|
+
let cliVersion = "unknown";
|
|
1922
|
+
try {
|
|
1923
|
+
const require2 = createRequire(import.meta.url);
|
|
1924
|
+
const pkg = require2("../../package.json");
|
|
1925
|
+
cliVersion = pkg.version ?? "unknown";
|
|
1926
|
+
} catch {
|
|
1927
|
+
}
|
|
1928
|
+
const versionFile = join3(cacheDir, ".version");
|
|
1929
|
+
try {
|
|
1930
|
+
if (existsSync2(versionFile)) {
|
|
1931
|
+
const cached = readFileSync3(versionFile, "utf-8").trim();
|
|
1932
|
+
if (cached === cliVersion) return;
|
|
1933
|
+
}
|
|
1934
|
+
if (existsSync2(cacheDir)) {
|
|
1935
|
+
rmSync(cacheDir, { recursive: true, force: true });
|
|
1936
|
+
}
|
|
1937
|
+
mkdirSync2(cacheDir, { recursive: true });
|
|
1938
|
+
writeFileSync2(versionFile, cliVersion);
|
|
1939
|
+
} catch {
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1901
1942
|
async function fetchBlock(blockName, config = {}) {
|
|
1902
1943
|
if (process.env.FORNIX_E2E_MOCK === "true") {
|
|
1903
1944
|
const manifest2 = FIXTURE_MANIFESTS[blockName];
|
|
@@ -1912,6 +1953,7 @@ async function fetchBlock(blockName, config = {}) {
|
|
|
1912
1953
|
return ok({ manifest: manifest2, files, fromCache: true });
|
|
1913
1954
|
}
|
|
1914
1955
|
const cfg = { ...DEFAULT_CONFIG2, ...config };
|
|
1956
|
+
ensureCacheVersion(cfg.cacheDir);
|
|
1915
1957
|
const blockCacheDir = join3(cfg.cacheDir, blockName);
|
|
1916
1958
|
if (!cfg.force && isCacheValid2(blockCacheDir, cfg.maxCacheAge)) {
|
|
1917
1959
|
return loadFromCache2(blockName, blockCacheDir);
|
|
@@ -1975,13 +2017,7 @@ function loadFromCache2(blockName, blockCacheDir) {
|
|
|
1975
2017
|
});
|
|
1976
2018
|
}
|
|
1977
2019
|
const files = {};
|
|
1978
|
-
|
|
1979
|
-
for (const entry of entries) {
|
|
1980
|
-
const fullPath = join3(blockCacheDir, entry);
|
|
1981
|
-
if (statSync2(fullPath).isFile() && entry !== "block.json") {
|
|
1982
|
-
files[entry] = readFileSync3(fullPath, "utf-8");
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
2020
|
+
readFilesRecursive(blockCacheDir, "", files);
|
|
1985
2021
|
return ok({
|
|
1986
2022
|
manifest: result.data,
|
|
1987
2023
|
files,
|
|
@@ -1996,6 +2032,18 @@ function loadFromCache2(blockName, blockCacheDir) {
|
|
|
1996
2032
|
});
|
|
1997
2033
|
}
|
|
1998
2034
|
}
|
|
2035
|
+
function readFilesRecursive(dir, prefix, files) {
|
|
2036
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
2037
|
+
for (const entry of entries) {
|
|
2038
|
+
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
2039
|
+
const fullPath = join3(dir, entry.name);
|
|
2040
|
+
if (entry.isDirectory()) {
|
|
2041
|
+
readFilesRecursive(fullPath, relativePath, files);
|
|
2042
|
+
} else if (entry.name !== "block.json") {
|
|
2043
|
+
files[relativePath] = readFileSync3(fullPath, "utf-8");
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
1999
2047
|
|
|
2000
2048
|
// src/prompts/manual-flow.ts
|
|
2001
2049
|
import * as p from "@clack/prompts";
|
|
@@ -2187,7 +2235,7 @@ function buildSummary(config, blockNames, palette) {
|
|
|
2187
2235
|
|
|
2188
2236
|
// src/scaffold/post-scaffold.ts
|
|
2189
2237
|
import { execSync } from "child_process";
|
|
2190
|
-
import { writeFileSync as
|
|
2238
|
+
import { writeFileSync as writeFileSync3 } from "fs";
|
|
2191
2239
|
import { join as join4, basename } from "path";
|
|
2192
2240
|
import pc2 from "picocolors";
|
|
2193
2241
|
function runPostScaffold(input, callbacks) {
|
|
@@ -2354,7 +2402,7 @@ function generateClaudeMd(projectDir, config, blockNames) {
|
|
|
2354
2402
|
lines.push("```");
|
|
2355
2403
|
lines.push("");
|
|
2356
2404
|
const content = lines.join("\n");
|
|
2357
|
-
|
|
2405
|
+
writeFileSync3(join4(projectDir, "CLAUDE.md"), content, "utf-8");
|
|
2358
2406
|
}
|
|
2359
2407
|
|
|
2360
2408
|
// src/ai/prompt-builder.ts
|
|
@@ -3328,7 +3376,7 @@ var RECIPES = {
|
|
|
3328
3376
|
themeSwitcher: false
|
|
3329
3377
|
},
|
|
3330
3378
|
agency: {
|
|
3331
|
-
renderMode: "
|
|
3379
|
+
renderMode: "server",
|
|
3332
3380
|
deployTarget: "cloudflare",
|
|
3333
3381
|
database: "none",
|
|
3334
3382
|
cssEngine: "tailwind",
|
|
@@ -3407,7 +3455,7 @@ var RECIPES = {
|
|
|
3407
3455
|
themeSwitcher: false
|
|
3408
3456
|
},
|
|
3409
3457
|
portfolio: {
|
|
3410
|
-
renderMode: "
|
|
3458
|
+
renderMode: "server",
|
|
3411
3459
|
deployTarget: "cloudflare",
|
|
3412
3460
|
database: "none",
|
|
3413
3461
|
cssEngine: "tailwind",
|
|
@@ -3560,6 +3608,33 @@ var createCommand = defineCommand({
|
|
|
3560
3608
|
}
|
|
3561
3609
|
},
|
|
3562
3610
|
async run({ args: args2 }) {
|
|
3611
|
+
const hasExplicitFlags = !!(args2.render || args2.deploy || args2.blocks || args2.database || args2.css || args2.locales || args2.palette || args2.recipe);
|
|
3612
|
+
let forceManual = false;
|
|
3613
|
+
if (!args2.manual && !hasExplicitFlags) {
|
|
3614
|
+
const providerName = parseProviderName(args2.provider);
|
|
3615
|
+
if (args2.provider && !providerName) {
|
|
3616
|
+
console.error(pc3.red(`\u2716 Unknown provider: ${String(args2.provider)}`));
|
|
3617
|
+
console.error(pc3.dim(` Available: ${VALID_PROVIDER_NAMES.join(", ")}`));
|
|
3618
|
+
process.exitCode = 1;
|
|
3619
|
+
return;
|
|
3620
|
+
}
|
|
3621
|
+
const legacyProvider = await resolveProvider({
|
|
3622
|
+
provider: providerName,
|
|
3623
|
+
skipOllamaDetect: false
|
|
3624
|
+
});
|
|
3625
|
+
if (!legacyProvider) {
|
|
3626
|
+
showNoProviderGuide();
|
|
3627
|
+
const fallback = await p2.confirm({
|
|
3628
|
+
message: "Would you like to continue in manual mode instead?",
|
|
3629
|
+
initialValue: true
|
|
3630
|
+
});
|
|
3631
|
+
if (p2.isCancel(fallback) || !fallback) {
|
|
3632
|
+
process.exitCode = 1;
|
|
3633
|
+
return;
|
|
3634
|
+
}
|
|
3635
|
+
forceManual = true;
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3563
3638
|
const registryResult = await fetchRegistryIndex();
|
|
3564
3639
|
if (!isOk(registryResult)) {
|
|
3565
3640
|
console.error(pc3.red(`\u2716 Failed to fetch block registry: ${registryResult.error.message}`));
|
|
@@ -3568,8 +3643,7 @@ var createCommand = defineCommand({
|
|
|
3568
3643
|
}
|
|
3569
3644
|
const manifests = registryResult.value.blocks;
|
|
3570
3645
|
const allPalettes = registryResult.value.palettes.length > 0 ? registryResult.value.palettes : loadAllPalettes();
|
|
3571
|
-
|
|
3572
|
-
if (args2.manual && !args2.yes) {
|
|
3646
|
+
if ((args2.manual || forceManual) && !args2.yes) {
|
|
3573
3647
|
const defaultProjectName = args2.dir ? basename2(resolve2(args2.dir)) : "my-project";
|
|
3574
3648
|
const config = await runManualFlow({
|
|
3575
3649
|
defaultProjectName,
|
|
@@ -3584,7 +3658,7 @@ var createCommand = defineCommand({
|
|
|
3584
3658
|
const finalConfig = { ...config, projectDir };
|
|
3585
3659
|
return runScaffold(finalConfig, manifests, allPalettes, args2["dry-run"] ?? false, args2.verbose ?? false, !(args2.install ?? true), !(args2.git ?? true));
|
|
3586
3660
|
}
|
|
3587
|
-
if (args2.manual || hasExplicitFlags) {
|
|
3661
|
+
if (args2.manual || hasExplicitFlags || forceManual) {
|
|
3588
3662
|
return runFlagDrivenMode(args2, manifests, allPalettes);
|
|
3589
3663
|
}
|
|
3590
3664
|
return runAIMode(args2, manifests, allPalettes);
|
|
@@ -3818,7 +3892,7 @@ async function runScaffold(config, manifests, allPalettes, dryRun, verbose, skip
|
|
|
3818
3892
|
const fullPath = join6(config.projectDir, relativePath);
|
|
3819
3893
|
const parentDir = join6(fullPath, "..");
|
|
3820
3894
|
mkdirSync4(parentDir, { recursive: true });
|
|
3821
|
-
|
|
3895
|
+
writeFileSync4(fullPath, content, "utf-8");
|
|
3822
3896
|
filesWritten++;
|
|
3823
3897
|
if (verbose) {
|
|
3824
3898
|
console.log(pc3.dim(` created ${relativePath}`));
|
|
@@ -3907,7 +3981,7 @@ function showNoProviderGuide() {
|
|
|
3907
3981
|
// src/cli/commands/add.ts
|
|
3908
3982
|
import { defineCommand as defineCommand2 } from "citty";
|
|
3909
3983
|
import pc4 from "picocolors";
|
|
3910
|
-
import { readFileSync as readFileSync5, writeFileSync as
|
|
3984
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync4, mkdirSync as mkdirSync5 } from "fs";
|
|
3911
3985
|
import { join as join7, dirname as dirname3 } from "path";
|
|
3912
3986
|
var addCommand = defineCommand2({
|
|
3913
3987
|
meta: {
|
|
@@ -4034,7 +4108,7 @@ var addCommand = defineCommand2({
|
|
|
4034
4108
|
}
|
|
4035
4109
|
for (const file of filesToWrite) {
|
|
4036
4110
|
mkdirSync5(dirname3(file.path), { recursive: true });
|
|
4037
|
-
|
|
4111
|
+
writeFileSync5(file.path, file.content);
|
|
4038
4112
|
if (typedArgs.verbose) {
|
|
4039
4113
|
console.log(` ${pc4.dim("\u2192")} ${file.path}`);
|
|
4040
4114
|
}
|
|
@@ -4050,7 +4124,7 @@ var addCommand = defineCommand2({
|
|
|
4050
4124
|
installedAt: now
|
|
4051
4125
|
});
|
|
4052
4126
|
}
|
|
4053
|
-
|
|
4127
|
+
writeFileSync5(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
|
|
4054
4128
|
console.log();
|
|
4055
4129
|
for (const name of blocksToAdd) {
|
|
4056
4130
|
const isDep = name !== blockName;
|
|
@@ -4091,7 +4165,7 @@ function resolveDependencies2(blockName, installedNames, manifests) {
|
|
|
4091
4165
|
// src/cli/commands/remove.ts
|
|
4092
4166
|
import { defineCommand as defineCommand3 } from "citty";
|
|
4093
4167
|
import pc5 from "picocolors";
|
|
4094
|
-
import { readFileSync as readFileSync6, writeFileSync as
|
|
4168
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync5, unlinkSync, readdirSync as readdirSync3, rmdirSync } from "fs";
|
|
4095
4169
|
import { join as join8, dirname as dirname4 } from "path";
|
|
4096
4170
|
var removeCommand = defineCommand3({
|
|
4097
4171
|
meta: {
|
|
@@ -4186,7 +4260,7 @@ var removeCommand = defineCommand3({
|
|
|
4186
4260
|
tryRemoveEmptyDir(dirname4(filePath), cwd);
|
|
4187
4261
|
}
|
|
4188
4262
|
manifest2.blocks = manifest2.blocks.filter((b) => b.name !== blockName);
|
|
4189
|
-
|
|
4263
|
+
writeFileSync6(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
|
|
4190
4264
|
console.log();
|
|
4191
4265
|
console.log(` ${pc5.red("-")} ${pc5.bold(blockName)} removed`);
|
|
4192
4266
|
if (dependents.length > 0) {
|
|
@@ -4668,7 +4742,7 @@ async function listBlocksHandler(args2) {
|
|
|
4668
4742
|
}
|
|
4669
4743
|
|
|
4670
4744
|
// src/mcp/tools/add-block.ts
|
|
4671
|
-
import { readFileSync as readFileSync9, writeFileSync as
|
|
4745
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, existsSync as existsSync8, mkdirSync as mkdirSync6 } from "fs";
|
|
4672
4746
|
import { join as join11, dirname as dirname5 } from "path";
|
|
4673
4747
|
async function addBlock2(input) {
|
|
4674
4748
|
const { name, variant = "default", projectDirectory } = input;
|
|
@@ -4734,7 +4808,7 @@ async function addBlock2(input) {
|
|
|
4734
4808
|
}
|
|
4735
4809
|
const filePath = join11(projectDirectory, file.destination);
|
|
4736
4810
|
mkdirSync6(dirname5(filePath), { recursive: true });
|
|
4737
|
-
|
|
4811
|
+
writeFileSync7(filePath, content);
|
|
4738
4812
|
filesCreated++;
|
|
4739
4813
|
}
|
|
4740
4814
|
}
|
|
@@ -4749,7 +4823,7 @@ async function addBlock2(input) {
|
|
|
4749
4823
|
installedAt: now
|
|
4750
4824
|
});
|
|
4751
4825
|
}
|
|
4752
|
-
|
|
4826
|
+
writeFileSync7(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
|
|
4753
4827
|
return ok({ addedBlocks: blocksToAdd, filesCreated });
|
|
4754
4828
|
}
|
|
4755
4829
|
function resolveDependencies3(blockName, installedNames, manifests) {
|
|
@@ -4772,7 +4846,7 @@ function resolveDependencies3(blockName, installedNames, manifests) {
|
|
|
4772
4846
|
// src/mcp/tools/remove-block.ts
|
|
4773
4847
|
import {
|
|
4774
4848
|
readFileSync as readFileSync10,
|
|
4775
|
-
writeFileSync as
|
|
4849
|
+
writeFileSync as writeFileSync8,
|
|
4776
4850
|
existsSync as existsSync9,
|
|
4777
4851
|
unlinkSync as unlinkSync2,
|
|
4778
4852
|
readdirSync as readdirSync4,
|
|
@@ -4826,7 +4900,7 @@ async function removeBlock(input) {
|
|
|
4826
4900
|
tryRemoveEmptyDirectory(dirname6(filePath), projectDirectory);
|
|
4827
4901
|
}
|
|
4828
4902
|
manifest2.blocks = manifest2.blocks.filter((block) => block.name !== name);
|
|
4829
|
-
|
|
4903
|
+
writeFileSync8(manifestPath, JSON.stringify(manifest2, null, 2) + "\n");
|
|
4830
4904
|
return ok({
|
|
4831
4905
|
removedBlock: name,
|
|
4832
4906
|
filesRemoved: filesToRemove.length,
|
|
@@ -4980,7 +5054,7 @@ function getProjectStatus(input) {
|
|
|
4980
5054
|
}
|
|
4981
5055
|
|
|
4982
5056
|
// src/mcp/tools/scaffold-project.ts
|
|
4983
|
-
import { mkdirSync as mkdirSync7, writeFileSync as
|
|
5057
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync9 } from "fs";
|
|
4984
5058
|
import { join as join14, basename as basename3 } from "path";
|
|
4985
5059
|
var DEFAULT_COLORS2 = {
|
|
4986
5060
|
primary: "#6366f1",
|
|
@@ -5055,7 +5129,7 @@ async function scaffoldProject(input) {
|
|
|
5055
5129
|
const fullPath = join14(projectDirectory, relativePath);
|
|
5056
5130
|
const parentDirectory = join14(fullPath, "..");
|
|
5057
5131
|
mkdirSync7(parentDirectory, { recursive: true });
|
|
5058
|
-
|
|
5132
|
+
writeFileSync9(fullPath, content, "utf-8");
|
|
5059
5133
|
filesCreated++;
|
|
5060
5134
|
}
|
|
5061
5135
|
return ok({
|