juo 0.0.1-alpha.4 → 0.0.2-pre.1
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 +6 -5
- package/dist/{analytics-B2gwRg5Q.js → analytics-CyANz2YH.js} +12 -12
- package/dist/commands/create.d.ts +4 -3
- package/dist/commands/create.js +155 -260
- package/dist/commands/generate.d.ts +10 -9
- package/dist/commands/generate.js +2 -1
- package/dist/commands/publish/index.d.ts +7 -7
- package/dist/commands/publish/index.js +4 -3
- package/dist/generate-Be3Ctuvv.js +118 -0
- package/dist/hooks/postrun.js +10 -10
- package/dist/hooks/prerun.js +1 -1
- package/dist/juoTemplateGenerator-C0le5FdK.js +130 -0
- package/dist/lib/index.d.ts +69 -0
- package/dist/lib/index.js +4 -0
- package/dist/packageGenerator-8E_-V5CL.js +117 -0
- package/oclif.manifest.json +12 -7
- package/package.json +10 -2
- package/templates/block/preact/index.ts.liquid +4 -5
- package/templates/block/preact/{{block.clsName}}.tsx.liquid +1 -2
- package/templates/block/react/index.ts.liquid +3 -6
- package/templates/block/react/{{block.clsName}}.tsx.liquid +2 -3
- package/templates/tailwind/vite.config.ts.liquid +11 -1
- package/dist/generate-D7J6nPBd.js +0 -252
- package/templates/block/react/state.ts.liquid +0 -105
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { Command } from "@oclif/core";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
|
|
3
3
|
|
|
4
4
|
//#region src/commands/generate.d.ts
|
|
5
5
|
declare class Generate extends Command {
|
|
6
|
-
static id: string;
|
|
7
6
|
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
8
|
static flags: {
|
|
9
|
-
name:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
verbose:
|
|
9
|
+
name: _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
10
|
+
tailwind: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
11
|
+
type: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
|
|
12
|
+
verbose: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
13
13
|
};
|
|
14
|
-
static
|
|
15
|
-
private resolvePackageJsonPath;
|
|
16
|
-
private resolveCSSFramework;
|
|
14
|
+
static id: string;
|
|
17
15
|
run(): Promise<void>;
|
|
16
|
+
private detectStorybook;
|
|
17
|
+
private resolveCSSFramework;
|
|
18
|
+
private resolvePackageJsonPath;
|
|
18
19
|
}
|
|
19
20
|
//#endregion
|
|
20
21
|
export { Generate as default };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Command, Interfaces } from "@oclif/core";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _oclif_core_interfaces8 from "@oclif/core/interfaces";
|
|
3
3
|
|
|
4
4
|
//#region src/base-command.d.ts
|
|
5
|
-
interface
|
|
5
|
+
interface BaseConfig {
|
|
6
6
|
JUO_API_KEY: string;
|
|
7
7
|
JUO_API_URL: string;
|
|
8
8
|
}
|
|
@@ -17,11 +17,11 @@ declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
|
17
17
|
protected get configFileName(): string;
|
|
18
18
|
protected get configFilePath(): string;
|
|
19
19
|
protected configExists(): boolean;
|
|
20
|
-
protected ensureConfig(reconfigure?: boolean): Promise<
|
|
20
|
+
protected ensureConfig(reconfigure?: boolean): Promise<BaseConfig>;
|
|
21
21
|
init(): Promise<void>;
|
|
22
|
-
protected loadConfig(): Partial<
|
|
23
|
-
protected saveConfig(config: Partial<
|
|
24
|
-
protected validateConfig(config: Partial<
|
|
22
|
+
protected loadConfig(): Partial<BaseConfig>;
|
|
23
|
+
protected saveConfig(config: Partial<BaseConfig>): void;
|
|
24
|
+
protected validateConfig(config: Partial<BaseConfig>): config is BaseConfig;
|
|
25
25
|
}
|
|
26
26
|
//#endregion
|
|
27
27
|
//#region src/commands/publish/index.d.ts
|
|
@@ -30,7 +30,7 @@ declare class Publish extends BaseCommand<typeof Publish> {
|
|
|
30
30
|
static description: string;
|
|
31
31
|
static examples: string[];
|
|
32
32
|
static flags: {
|
|
33
|
-
theme:
|
|
33
|
+
theme: _oclif_core_interfaces8.OptionFlag<string, _oclif_core_interfaces8.CustomOptions>;
|
|
34
34
|
};
|
|
35
35
|
getAllFiles(dirPath: string, basePath: string): string[];
|
|
36
36
|
run(): Promise<void>;
|
|
@@ -91,7 +91,7 @@ var BaseCommand = class extends Command {
|
|
|
91
91
|
fs.writeFileSync(this.configFilePath, JSON.stringify(config, null, 2), { encoding: "utf8" });
|
|
92
92
|
}
|
|
93
93
|
validateConfig(config) {
|
|
94
|
-
return Boolean(config.JUO_API_KEY && config.JUO_API_KEY.length > 0 && config.JUO_API_URL && config.JUO_API_URL.length > 0);
|
|
94
|
+
return Boolean(config.JUO_API_KEY && config.JUO_API_KEY.trim().length > 0 && config.JUO_API_URL && config.JUO_API_URL.trim().length > 0);
|
|
95
95
|
}
|
|
96
96
|
};
|
|
97
97
|
|
|
@@ -121,10 +121,11 @@ Reconfigure settings and publish.
|
|
|
121
121
|
const items = fs.readdirSync(dirPath);
|
|
122
122
|
for (const item of items) {
|
|
123
123
|
const fullPath = path.join(dirPath, item);
|
|
124
|
-
|
|
124
|
+
const stat = fs.statSync(fullPath);
|
|
125
|
+
if (stat.isFile()) {
|
|
125
126
|
const relativePath = path.relative(basePath, fullPath);
|
|
126
127
|
files.push(relativePath);
|
|
127
|
-
}
|
|
128
|
+
} else if (stat.isDirectory()) files.push(...this.getAllFiles(fullPath, basePath));
|
|
128
129
|
}
|
|
129
130
|
return files;
|
|
130
131
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { t as JuoTemplateGenerator } from "./juoTemplateGenerator-C0le5FdK.js";
|
|
2
|
+
import { Command, Flags } from "@oclif/core";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { readPackageJSON } from "pkg-types";
|
|
6
|
+
import { isCancel, log, spinner, text } from "@clack/prompts";
|
|
7
|
+
import { detectPackageManager } from "nypm";
|
|
8
|
+
|
|
9
|
+
//#region src/utils/resolveFramework.ts
|
|
10
|
+
async function resolveFramework() {
|
|
11
|
+
try {
|
|
12
|
+
const packageJson = await readPackageJSON();
|
|
13
|
+
if (!packageJson) throw new Error("Could not find package.json");
|
|
14
|
+
if (packageJson.dependencies == null) throw new Error("Could not find dependencies in package.json");
|
|
15
|
+
if ("preact" in packageJson.dependencies) return "preact";
|
|
16
|
+
return "react";
|
|
17
|
+
} catch (error) {
|
|
18
|
+
throw new Error(`Error resolving framework: ${error}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/commands/generate.ts
|
|
24
|
+
var Generate = class Generate extends Command {
|
|
25
|
+
static description = "Generate blocks for your project";
|
|
26
|
+
static examples = ["<%= config.bin %> <%= command.id %>"];
|
|
27
|
+
static flags = {
|
|
28
|
+
name: Flags.string({
|
|
29
|
+
char: "n",
|
|
30
|
+
description: "The name of the component"
|
|
31
|
+
}),
|
|
32
|
+
tailwind: Flags.boolean({
|
|
33
|
+
allowNo: true,
|
|
34
|
+
char: "t",
|
|
35
|
+
default: void 0
|
|
36
|
+
}),
|
|
37
|
+
type: Flags.string({
|
|
38
|
+
default: "block",
|
|
39
|
+
description: "The type of the component",
|
|
40
|
+
options: ["block"]
|
|
41
|
+
}),
|
|
42
|
+
verbose: Flags.boolean({
|
|
43
|
+
allowNo: true,
|
|
44
|
+
char: "v",
|
|
45
|
+
default: true
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
static id = "generate";
|
|
49
|
+
async run() {
|
|
50
|
+
const { flags } = await this.parse(Generate);
|
|
51
|
+
let rootDir;
|
|
52
|
+
const templateGenerator = new JuoTemplateGenerator();
|
|
53
|
+
try {
|
|
54
|
+
rootDir = this.resolvePackageJsonPath();
|
|
55
|
+
} catch (error) {
|
|
56
|
+
throw new Error(`Error resolving package JSON path: ${error}`);
|
|
57
|
+
}
|
|
58
|
+
const tailwind = flags.tailwind ?? await this.resolveCSSFramework(rootDir);
|
|
59
|
+
const generateSpinner = flags.verbose ? spinner() : null;
|
|
60
|
+
const blocksDir = path.join(rootDir, "src/blocks");
|
|
61
|
+
const name = flags.name ?? await text({
|
|
62
|
+
initialValue: "Starter Block",
|
|
63
|
+
message: "What is the name of the component?",
|
|
64
|
+
validate(value) {
|
|
65
|
+
if (value.length === 0) return `Value is required!`;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
if (isCancel(name)) this.exit(0);
|
|
69
|
+
const framework = await resolveFramework();
|
|
70
|
+
generateSpinner?.start();
|
|
71
|
+
generateSpinner?.message("Detecting package manager");
|
|
72
|
+
const packageManager = await detectPackageManager(rootDir);
|
|
73
|
+
if (!packageManager) throw new Error("Could not detect package manager");
|
|
74
|
+
if (flags.verbose) log.info("Package manager detected: " + packageManager.name);
|
|
75
|
+
generateSpinner?.message("Generating block");
|
|
76
|
+
const hasStorybook = await this.detectStorybook(rootDir);
|
|
77
|
+
await templateGenerator.generate(blocksDir, {
|
|
78
|
+
framework,
|
|
79
|
+
logger: (msg) => generateSpinner?.message(msg),
|
|
80
|
+
name,
|
|
81
|
+
story: hasStorybook,
|
|
82
|
+
tailwind,
|
|
83
|
+
type: "block"
|
|
84
|
+
});
|
|
85
|
+
templateGenerator.appendStylesheet(rootDir);
|
|
86
|
+
generateSpinner?.stop("Generated block");
|
|
87
|
+
}
|
|
88
|
+
async detectStorybook(rootDir) {
|
|
89
|
+
if (existsSync(path.join(rootDir, ".storybook"))) return true;
|
|
90
|
+
try {
|
|
91
|
+
const packageJson = await readPackageJSON(path.join(rootDir, "package.json"));
|
|
92
|
+
return Boolean(packageJson?.devDependencies?.storybook || packageJson?.dependencies?.storybook);
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async resolveCSSFramework(dir) {
|
|
98
|
+
try {
|
|
99
|
+
const packageJson = await readPackageJSON(path.join(dir, "package.json"));
|
|
100
|
+
if (packageJson?.dependencies?.tailwindcss || packageJson?.devDependencies?.tailwindcss) return "tailwind";
|
|
101
|
+
return false;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
throw new Error(`Error resolving CSS framework: ${error}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
resolvePackageJsonPath() {
|
|
107
|
+
let currentPath = path.resolve("./");
|
|
108
|
+
while (!existsSync(path.join(currentPath, "package.json"))) {
|
|
109
|
+
const parentDir = path.dirname(currentPath);
|
|
110
|
+
if (parentDir === currentPath) throw new Error("Could not find 'package.json' in the project");
|
|
111
|
+
currentPath = parentDir;
|
|
112
|
+
}
|
|
113
|
+
return currentPath;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
//#endregion
|
|
118
|
+
export { Generate as t };
|
package/dist/hooks/postrun.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as CUSTOMERIO_BETA_FORM_URL, i as CUSTOMERIO_API_KEY, n as trackCommandCompleted, o as CUSTOMERIO_SITE_ID, t as trackBetaSignup } from "../analytics-
|
|
1
|
+
import { a as CUSTOMERIO_BETA_FORM_URL, i as CUSTOMERIO_API_KEY, n as trackCommandCompleted, o as CUSTOMERIO_SITE_ID, t as trackBetaSignup } from "../analytics-CyANz2YH.js";
|
|
2
2
|
import { confirm, isCancel, text } from "@clack/prompts";
|
|
3
3
|
import debug from "debug";
|
|
4
4
|
|
|
@@ -9,15 +9,15 @@ async function sendToCustomerIO(email) {
|
|
|
9
9
|
try {
|
|
10
10
|
const basicAuth = Buffer.from(`${CUSTOMERIO_SITE_ID}:${CUSTOMERIO_API_KEY}`).toString("base64");
|
|
11
11
|
await fetch(CUSTOMERIO_BETA_FORM_URL, {
|
|
12
|
-
method: "POST",
|
|
13
|
-
headers: {
|
|
14
|
-
"Content-Type": "application/json",
|
|
15
|
-
Authorization: `Basic ${basicAuth}`
|
|
16
|
-
},
|
|
17
12
|
body: JSON.stringify({ data: {
|
|
18
13
|
email,
|
|
19
14
|
source: "cli"
|
|
20
|
-
} })
|
|
15
|
+
} }),
|
|
16
|
+
headers: {
|
|
17
|
+
Authorization: `Basic ${basicAuth}`,
|
|
18
|
+
"Content-Type": "application/json"
|
|
19
|
+
},
|
|
20
|
+
method: "POST"
|
|
21
21
|
}).catch((error) => {
|
|
22
22
|
log$1("Failed to send beta signup to CustomerIO: %O", error);
|
|
23
23
|
});
|
|
@@ -28,8 +28,8 @@ async function sendToCustomerIO(email) {
|
|
|
28
28
|
async function promptBetaSignup(commandContext) {
|
|
29
29
|
try {
|
|
30
30
|
const shouldSignup = await confirm({
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
initialValue: true,
|
|
32
|
+
message: "Would you like to request access to the private beta?"
|
|
33
33
|
});
|
|
34
34
|
if (isCancel(shouldSignup) || !shouldSignup) return;
|
|
35
35
|
const email = await text({
|
|
@@ -54,7 +54,7 @@ async function promptBetaSignup(commandContext) {
|
|
|
54
54
|
//#region src/hooks/postrun.ts
|
|
55
55
|
const hook = async function(options) {
|
|
56
56
|
if (options.Command) trackCommandCompleted(options.Command.id || options.Command.name || "unknown", true);
|
|
57
|
-
if (options.Command) await promptBetaSignup(options.Command.id || options.Command.name || "unknown");
|
|
57
|
+
if (options.Command && process.stdout.isTTY) await promptBetaSignup(options.Command.id || options.Command.name || "unknown");
|
|
58
58
|
};
|
|
59
59
|
var postrun_default = hook;
|
|
60
60
|
|
package/dist/hooks/prerun.js
CHANGED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Liquid } from "liquidjs";
|
|
2
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import slugify from "slugify";
|
|
6
|
+
|
|
7
|
+
//#region src/utils/baseTemplateGenerator.ts
|
|
8
|
+
var BaseTemplateGenerator = class {
|
|
9
|
+
getTemplateDir(name) {
|
|
10
|
+
const packageRoot = this.resolvePackageRoot();
|
|
11
|
+
return path.join(packageRoot, "templates", name);
|
|
12
|
+
}
|
|
13
|
+
getTemplateFiles(name) {
|
|
14
|
+
function scan(dirpath, baseDir) {
|
|
15
|
+
return readdirSync(dirpath).flatMap((filename) => {
|
|
16
|
+
const filepath = path.join(dirpath, filename);
|
|
17
|
+
if (statSync(filepath).isDirectory()) return scan(filepath, baseDir);
|
|
18
|
+
return [path.relative(baseDir, filepath)];
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const templateDir = this.getTemplateDir(name);
|
|
22
|
+
return scan(templateDir, templateDir);
|
|
23
|
+
}
|
|
24
|
+
renderTemplate(templateName, destDir, scope, fileFilter) {
|
|
25
|
+
try {
|
|
26
|
+
const templateDir = this.getTemplateDir(templateName);
|
|
27
|
+
const engine = new Liquid();
|
|
28
|
+
const files = this.getTemplateFiles(templateName);
|
|
29
|
+
const filteredFiles = fileFilter ? files.filter((filename) => fileFilter(filename)) : files;
|
|
30
|
+
for (const file of filteredFiles) {
|
|
31
|
+
const filename = engine.parseAndRenderSync(file, scope).replace(/\.liquid$/, "");
|
|
32
|
+
const tplPath = path.join(templateDir, file);
|
|
33
|
+
const destPath = path.join(destDir, filename);
|
|
34
|
+
mkdirSync(path.dirname(destPath), { recursive: true });
|
|
35
|
+
writeFileSync(destPath, engine.parseAndRenderSync(readFileSync(tplPath, "utf8"), scope));
|
|
36
|
+
}
|
|
37
|
+
} catch (error) {
|
|
38
|
+
throw new Error(`Error rendering template ${templateName}: ${error}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
resolvePackageRoot() {
|
|
42
|
+
let currentPath = path.dirname(fileURLToPath(import.meta.url));
|
|
43
|
+
while (!existsSync(path.join(currentPath, "package.json"))) {
|
|
44
|
+
const parentDir = path.dirname(currentPath);
|
|
45
|
+
if (parentDir === currentPath) throw new Error("Could not find package root");
|
|
46
|
+
currentPath = parentDir;
|
|
47
|
+
}
|
|
48
|
+
return currentPath;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/utils/storyGenerator.ts
|
|
54
|
+
var StoryGenerator = class extends BaseTemplateGenerator {
|
|
55
|
+
async generate(destDir, options) {
|
|
56
|
+
await (options.type === "block" ? this.generateBlockTemplate(destDir, options) : this.generateThemeTemplate(destDir, options));
|
|
57
|
+
}
|
|
58
|
+
async generateBlockTemplate(destDir, options) {
|
|
59
|
+
const scope = { block: {
|
|
60
|
+
clsName: slugify(options.name, { lower: true }).split("-").map((item) => `${item[0].toUpperCase()}${item.slice(1)}`).join(""),
|
|
61
|
+
framework: options.framework,
|
|
62
|
+
name: options.name,
|
|
63
|
+
slug: slugify(options.name, { lower: true })
|
|
64
|
+
} };
|
|
65
|
+
if (["react", "preact"].includes(scope.block.framework)) {
|
|
66
|
+
if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true });
|
|
67
|
+
this.renderTemplate("stories", destDir, scope);
|
|
68
|
+
} else options.logger?.("Story generation skipped");
|
|
69
|
+
}
|
|
70
|
+
async generateThemeTemplate(destDir, options) {
|
|
71
|
+
const themeScope = { theme: {
|
|
72
|
+
clsName: slugify(options.name, { lower: true }).split("-").map((item) => `${item[0].toUpperCase()}${item.slice(1)}`).join(""),
|
|
73
|
+
framework: options.framework,
|
|
74
|
+
name: options.name,
|
|
75
|
+
slug: slugify(options.name, { lower: true })
|
|
76
|
+
} };
|
|
77
|
+
if (options.framework === "react") this.renderTemplate("theme/react", destDir, themeScope, (filename) => filename.includes(".stories.tsx.liquid"));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/utils/juoTemplateGenerator.ts
|
|
83
|
+
var JuoTemplateGenerator = class extends BaseTemplateGenerator {
|
|
84
|
+
storyGenerator;
|
|
85
|
+
constructor() {
|
|
86
|
+
super();
|
|
87
|
+
this.storyGenerator = new StoryGenerator();
|
|
88
|
+
}
|
|
89
|
+
appendStylesheet(destDir) {
|
|
90
|
+
this.renderTemplate("css", path.join(destDir, "src"), {});
|
|
91
|
+
}
|
|
92
|
+
async generate(destDir, options) {
|
|
93
|
+
await this.generateBlockTemplate(destDir, options);
|
|
94
|
+
}
|
|
95
|
+
async generateBlockTemplate(destDir, options) {
|
|
96
|
+
const scope = { block: {
|
|
97
|
+
clsName: slugify(options.name, { lower: true }).split("-").map((item) => `${item[0].toUpperCase()}${item.slice(1)}`).join(""),
|
|
98
|
+
framework: options.framework,
|
|
99
|
+
name: options.name,
|
|
100
|
+
slug: slugify(options.name, { lower: true }),
|
|
101
|
+
tailwind: options.tailwind
|
|
102
|
+
} };
|
|
103
|
+
this.renderTemplate(`${options.type}/${options.framework}`, path.join(destDir, scope.block.slug), scope);
|
|
104
|
+
options.logger?.("Adding block to theme");
|
|
105
|
+
try {
|
|
106
|
+
appendFileSync(path.join(destDir, "index.ts"), `export { ${scope.block.clsName}Block } from "./${scope.block.slug}";\n`);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
options.logger?.("Error adding block to theme: " + error);
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
if (options.story) {
|
|
112
|
+
const projectRoot = path.dirname(path.dirname(destDir));
|
|
113
|
+
const storiesDir = path.join(projectRoot, "stories");
|
|
114
|
+
try {
|
|
115
|
+
await this.storyGenerator.generate(storiesDir, {
|
|
116
|
+
framework: options.framework,
|
|
117
|
+
name: scope.block.name,
|
|
118
|
+
tailwind: options.tailwind,
|
|
119
|
+
type: "block"
|
|
120
|
+
});
|
|
121
|
+
} catch (error) {
|
|
122
|
+
options.logger?.("Error generating story: " + error);
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
} else options.logger?.(`Story generation skipped (options.story = ${options.story})`);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
//#endregion
|
|
130
|
+
export { StoryGenerator as n, BaseTemplateGenerator as r, JuoTemplateGenerator as t };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//#region src/utils/baseTemplateGenerator.d.ts
|
|
2
|
+
interface TemplateScope {
|
|
3
|
+
block?: {
|
|
4
|
+
clsName: string;
|
|
5
|
+
framework: string;
|
|
6
|
+
name: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
tailwind?: boolean;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
declare abstract class BaseTemplateGenerator {
|
|
12
|
+
protected getTemplateDir(name: string): string;
|
|
13
|
+
protected getTemplateFiles(name: string): string[];
|
|
14
|
+
protected renderTemplate(templateName: string, destDir: string, scope: TemplateScope, fileFilter?: (filename: string) => boolean): void;
|
|
15
|
+
protected resolvePackageRoot(): string;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/utils/juoTemplateGenerator.d.ts
|
|
19
|
+
type Logger$1 = (message?: string) => void;
|
|
20
|
+
interface JuoTemplateGeneratorOptionsBase {
|
|
21
|
+
framework: 'preact' | 'react';
|
|
22
|
+
story?: boolean;
|
|
23
|
+
tailwind: boolean;
|
|
24
|
+
type: 'block' | 'theme';
|
|
25
|
+
}
|
|
26
|
+
interface JuoBlockTemplateGeneratorOptions extends JuoTemplateGeneratorOptionsBase {
|
|
27
|
+
logger?: Logger$1;
|
|
28
|
+
name: string;
|
|
29
|
+
}
|
|
30
|
+
declare class JuoTemplateGenerator extends BaseTemplateGenerator {
|
|
31
|
+
private storyGenerator;
|
|
32
|
+
constructor();
|
|
33
|
+
appendStylesheet(destDir: string): void;
|
|
34
|
+
generate(destDir: string, options: JuoBlockTemplateGeneratorOptions): Promise<void>;
|
|
35
|
+
private generateBlockTemplate;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/utils/packageGenerator.d.ts
|
|
39
|
+
interface PackageGeneratorOptions {
|
|
40
|
+
framework: 'preact' | 'react';
|
|
41
|
+
name: string;
|
|
42
|
+
packageManager: 'npm' | 'pnpm' | 'yarn';
|
|
43
|
+
storybook?: boolean;
|
|
44
|
+
tailwind?: boolean;
|
|
45
|
+
version?: string;
|
|
46
|
+
}
|
|
47
|
+
declare class PackageGenerator {
|
|
48
|
+
static generate(destDir: string, options: PackageGeneratorOptions): Promise<void>;
|
|
49
|
+
private static buildPackageJson;
|
|
50
|
+
private static readPackageManagerVersion;
|
|
51
|
+
private static sort;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/utils/storyGenerator.d.ts
|
|
55
|
+
type Logger = (message?: string) => void;
|
|
56
|
+
interface StoryGeneratorOptions {
|
|
57
|
+
framework: 'preact' | 'react';
|
|
58
|
+
logger?: Logger;
|
|
59
|
+
name: string;
|
|
60
|
+
tailwind: boolean;
|
|
61
|
+
type: 'block' | 'theme';
|
|
62
|
+
}
|
|
63
|
+
declare class StoryGenerator extends BaseTemplateGenerator {
|
|
64
|
+
generate(destDir: string, options: StoryGeneratorOptions): Promise<void>;
|
|
65
|
+
private generateBlockTemplate;
|
|
66
|
+
private generateThemeTemplate;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { BaseTemplateGenerator, type JuoBlockTemplateGeneratorOptions, JuoTemplateGenerator, type JuoTemplateGeneratorOptionsBase, PackageGenerator, type PackageGeneratorOptions, StoryGenerator, type StoryGeneratorOptions, type TemplateScope };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { n as StoryGenerator, r as BaseTemplateGenerator, t as JuoTemplateGenerator } from "../juoTemplateGenerator-C0le5FdK.js";
|
|
2
|
+
import { t as PackageGenerator } from "../packageGenerator-8E_-V5CL.js";
|
|
3
|
+
|
|
4
|
+
export { BaseTemplateGenerator, JuoTemplateGenerator, PackageGenerator, StoryGenerator };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { definePackageJSON, sortPackage, writePackageJSON } from "pkg-types";
|
|
5
|
+
|
|
6
|
+
//#region src/utils/packageGenerator.ts
|
|
7
|
+
const FRAMEWORK_CONFIGS = {
|
|
8
|
+
preact: {
|
|
9
|
+
dependencies: { preact: "^10.26.8" },
|
|
10
|
+
devDependencies: {
|
|
11
|
+
"@preact/preset-vite": "^2.10.2",
|
|
12
|
+
"json-schema-to-ts": "^3.1.1",
|
|
13
|
+
"vite-plugin-svgr": "^4.5.0"
|
|
14
|
+
},
|
|
15
|
+
storybookDevDependencies: { "@storybook/react-vite": "^10.0.7" }
|
|
16
|
+
},
|
|
17
|
+
react: {
|
|
18
|
+
dependencies: {
|
|
19
|
+
"@juo/blocks": "^1.0.0",
|
|
20
|
+
"@mantine/core": "7.5.3",
|
|
21
|
+
"@mantine/hooks": "7.5.3",
|
|
22
|
+
react: "^18.2.0",
|
|
23
|
+
"react-dom": "^18.2.0"
|
|
24
|
+
},
|
|
25
|
+
devDependencies: {
|
|
26
|
+
"@types/react": "^18.2.55",
|
|
27
|
+
"@types/react-dom": "^18.2.19",
|
|
28
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
29
|
+
"vite-plugin-svgr": "^4.5.0"
|
|
30
|
+
},
|
|
31
|
+
storybookDevDependencies: { "@storybook/react-vite": "^10.0.7" }
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var PackageGenerator = class {
|
|
35
|
+
static async generate(destDir, options) {
|
|
36
|
+
if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true });
|
|
37
|
+
const packageJsonPath = path.join(destDir, "package.json");
|
|
38
|
+
const packageJson = this.buildPackageJson(options);
|
|
39
|
+
try {
|
|
40
|
+
await writePackageJSON(packageJsonPath, packageJson);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
throw new Error(`Failed to write package.json to ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
static buildPackageJson(options) {
|
|
46
|
+
const pmVersion = this.readPackageManagerVersion(options.packageManager);
|
|
47
|
+
const baseConfig = definePackageJSON({
|
|
48
|
+
devDependencies: {
|
|
49
|
+
"@testing-library/dom": "^10.4.0",
|
|
50
|
+
"@types/node": "^22.15.29",
|
|
51
|
+
"json-schema-to-ts": "^3.1.1",
|
|
52
|
+
postcss: "^8.5.3",
|
|
53
|
+
"postcss-prefix-selector": "^2.1.1",
|
|
54
|
+
prettier: "^3.5.3",
|
|
55
|
+
...options.tailwind ? {
|
|
56
|
+
"@tailwindcss/vite": "^4.1.17",
|
|
57
|
+
tailwindcss: "^4.1.17"
|
|
58
|
+
} : {},
|
|
59
|
+
...options.storybook ? { storybook: "^10.0.7" } : {},
|
|
60
|
+
typebox: "^1.0.51",
|
|
61
|
+
typescript: "~5.7.2",
|
|
62
|
+
vite: "^6.3.1"
|
|
63
|
+
},
|
|
64
|
+
engines: {
|
|
65
|
+
node: ">=20.0.0",
|
|
66
|
+
pnpm: ">=7.0.0"
|
|
67
|
+
},
|
|
68
|
+
name: options.name,
|
|
69
|
+
packageManager: `${options.packageManager}@${pmVersion}`,
|
|
70
|
+
private: true,
|
|
71
|
+
scripts: {
|
|
72
|
+
build: "vite build",
|
|
73
|
+
"typecheck": "tsc --noEmit",
|
|
74
|
+
...options.storybook ? {
|
|
75
|
+
"build-storybook": "storybook build",
|
|
76
|
+
storybook: "storybook dev -p 6006"
|
|
77
|
+
} : {},
|
|
78
|
+
dev: "vite build -w & vite preview --port 5174",
|
|
79
|
+
preview: "vite preview"
|
|
80
|
+
},
|
|
81
|
+
type: "module",
|
|
82
|
+
version: "0.0.0"
|
|
83
|
+
});
|
|
84
|
+
const frameworkConfig = FRAMEWORK_CONFIGS[options.framework];
|
|
85
|
+
baseConfig.dependencies = {
|
|
86
|
+
...baseConfig.dependencies,
|
|
87
|
+
...frameworkConfig.dependencies
|
|
88
|
+
};
|
|
89
|
+
baseConfig.devDependencies = {
|
|
90
|
+
...baseConfig.devDependencies,
|
|
91
|
+
...frameworkConfig.devDependencies,
|
|
92
|
+
...options.storybook ? frameworkConfig.storybookDevDependencies : {}
|
|
93
|
+
};
|
|
94
|
+
return this.sort(baseConfig);
|
|
95
|
+
}
|
|
96
|
+
static readPackageManagerVersion(packageManager) {
|
|
97
|
+
try {
|
|
98
|
+
return execSync(`${packageManager} --version`, {
|
|
99
|
+
encoding: "utf8",
|
|
100
|
+
stdio: [
|
|
101
|
+
"pipe",
|
|
102
|
+
"pipe",
|
|
103
|
+
"ignore"
|
|
104
|
+
]
|
|
105
|
+
}).trim();
|
|
106
|
+
} catch {
|
|
107
|
+
console.warn(`Failed to read ${packageManager} version, using fallback`);
|
|
108
|
+
return "latest";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
static sort(packageJson) {
|
|
112
|
+
return sortPackage(packageJson);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
//#endregion
|
|
117
|
+
export { PackageGenerator as t };
|
package/oclif.manifest.json
CHANGED
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"allowNo": false,
|
|
12
12
|
"type": "boolean"
|
|
13
13
|
},
|
|
14
|
+
"storybook": {
|
|
15
|
+
"name": "storybook",
|
|
16
|
+
"allowNo": true,
|
|
17
|
+
"type": "boolean"
|
|
18
|
+
},
|
|
14
19
|
"verbose": {
|
|
15
20
|
"char": "v",
|
|
16
21
|
"name": "verbose",
|
|
@@ -49,6 +54,12 @@
|
|
|
49
54
|
"multiple": false,
|
|
50
55
|
"type": "option"
|
|
51
56
|
},
|
|
57
|
+
"tailwind": {
|
|
58
|
+
"char": "t",
|
|
59
|
+
"name": "tailwind",
|
|
60
|
+
"allowNo": true,
|
|
61
|
+
"type": "boolean"
|
|
62
|
+
},
|
|
52
63
|
"type": {
|
|
53
64
|
"description": "The type of the component",
|
|
54
65
|
"name": "type",
|
|
@@ -60,12 +71,6 @@
|
|
|
60
71
|
],
|
|
61
72
|
"type": "option"
|
|
62
73
|
},
|
|
63
|
-
"tailwind": {
|
|
64
|
-
"char": "t",
|
|
65
|
-
"name": "tailwind",
|
|
66
|
-
"allowNo": true,
|
|
67
|
-
"type": "boolean"
|
|
68
|
-
},
|
|
69
74
|
"verbose": {
|
|
70
75
|
"char": "v",
|
|
71
76
|
"name": "verbose",
|
|
@@ -132,5 +137,5 @@
|
|
|
132
137
|
]
|
|
133
138
|
}
|
|
134
139
|
},
|
|
135
|
-
"version": "0.0.
|
|
140
|
+
"version": "0.0.2-pre.1"
|
|
136
141
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "juo",
|
|
3
3
|
"description": "A CLI tool for the Juo platform",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.2-pre.1",
|
|
5
5
|
"author": "Juo (https://juo.io)",
|
|
6
6
|
"bin": {
|
|
7
7
|
"juo": "./bin/run.js"
|
|
@@ -56,6 +56,10 @@
|
|
|
56
56
|
],
|
|
57
57
|
"license": "MIT",
|
|
58
58
|
"main": "dist/index.js",
|
|
59
|
+
"exports": {
|
|
60
|
+
".": "./dist/index.js",
|
|
61
|
+
"./lib": "./dist/lib/index.js"
|
|
62
|
+
},
|
|
59
63
|
"type": "module",
|
|
60
64
|
"oclif": {
|
|
61
65
|
"bin": "juo",
|
|
@@ -64,6 +68,10 @@
|
|
|
64
68
|
"plugins": [
|
|
65
69
|
"@oclif/plugin-help"
|
|
66
70
|
],
|
|
71
|
+
"hooks": {
|
|
72
|
+
"prerun": "./dist/hooks/prerun.js",
|
|
73
|
+
"postrun": "./dist/hooks/postrun.js"
|
|
74
|
+
},
|
|
67
75
|
"topicSeparator": " ",
|
|
68
76
|
"topics": {
|
|
69
77
|
"publish": {
|
|
@@ -76,7 +84,7 @@
|
|
|
76
84
|
"build": "tsdown",
|
|
77
85
|
"lint": "eslint",
|
|
78
86
|
"posttest": "pnpm run lint",
|
|
79
|
-
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
|
|
87
|
+
"test": "TS_NODE_PROJECT=./tsconfig.test.json mocha --forbid-only \"test/**/*.test.ts\"",
|
|
80
88
|
"version": "oclif readme && git add README.md"
|
|
81
89
|
}
|
|
82
90
|
}
|