juo 0.0.1-alpha.3 → 0.0.1-alpha.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/README.md +42 -2
- package/bin/dev.js +1 -1
- package/dist/analytics-B2gwRg5Q.js +69 -0
- package/dist/commands/create.d.ts +15 -0
- package/dist/commands/create.js +465 -0
- package/dist/commands/generate.d.ts +20 -0
- package/dist/commands/generate.js +3 -0
- package/dist/commands/publish/index.d.ts +41 -13
- package/dist/commands/publish/index.js +193 -114
- package/dist/generate-D7J6nPBd.js +252 -0
- package/dist/hooks/postrun.d.ts +6 -0
- package/dist/hooks/postrun.js +62 -0
- package/dist/hooks/prerun.d.ts +6 -0
- package/dist/hooks/prerun.js +15 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/oclif.manifest.json +89 -1
- package/package.json +12 -3
- package/templates/.storybook/preview-head.html.liquid +11 -0
- package/templates/block/preact/index.ts.liquid +40 -0
- package/templates/block/preact/{{block.clsName}}.tsx.liquid +200 -0
- package/templates/block/react/index.ts.liquid +41 -0
- package/templates/block/react/state.ts.liquid +105 -0
- package/templates/block/react/{{block.clsName}}.tsx.liquid +91 -0
- package/templates/configFiles/.env.liquid +0 -0
- package/templates/configFiles/.gitignore.liquid +6 -0
- package/templates/configFiles/.prettierignore.liquid +45 -0
- package/templates/configFiles/.prettierrc.liquid +1 -0
- package/templates/configFiles/vite-env.d.ts.liquid +2 -0
- package/templates/css/styles.css +71 -0
- package/templates/stories/{{block.clsName}}.stories.tsx.liquid +24 -0
- package/templates/tailwind/src/tailwind.css.liquid +1 -0
- package/templates/tailwind/vite.config.ts.liquid +23 -0
- package/dist/base-command.d.ts +0 -23
- package/dist/base-command.js +0 -119
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ npm install -g juo
|
|
|
20
20
|
$ juo COMMAND
|
|
21
21
|
running command...
|
|
22
22
|
$ juo (--version)
|
|
23
|
-
juo/0.0.1-alpha.
|
|
23
|
+
juo/0.0.1-alpha.4 darwin-arm64 node-v22.13.1
|
|
24
24
|
$ juo --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ juo COMMAND
|
|
@@ -31,9 +31,49 @@ USAGE
|
|
|
31
31
|
# Commands
|
|
32
32
|
|
|
33
33
|
<!-- commands -->
|
|
34
|
+
* [`juo create`](#juo-create)
|
|
35
|
+
* [`juo generate`](#juo-generate)
|
|
34
36
|
* [`juo help [COMMAND]`](#juo-help-command)
|
|
35
37
|
* [`juo publish`](#juo-publish)
|
|
36
38
|
|
|
39
|
+
## `juo create`
|
|
40
|
+
|
|
41
|
+
Generate a new Juo project
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
USAGE
|
|
45
|
+
$ juo create [-q] [-v]
|
|
46
|
+
|
|
47
|
+
FLAGS
|
|
48
|
+
-q, --quickstart
|
|
49
|
+
-v, --verbose
|
|
50
|
+
|
|
51
|
+
DESCRIPTION
|
|
52
|
+
Generate a new Juo project
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## `juo generate`
|
|
56
|
+
|
|
57
|
+
Generate blocks for your project
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
USAGE
|
|
61
|
+
$ juo generate [-n <value>] [--type block] [-t] [-v]
|
|
62
|
+
|
|
63
|
+
FLAGS
|
|
64
|
+
-n, --name=<value> The name of the component
|
|
65
|
+
-t, --[no-]tailwind
|
|
66
|
+
-v, --[no-]verbose
|
|
67
|
+
--type=<option> [default: block] The type of the component
|
|
68
|
+
<options: block>
|
|
69
|
+
|
|
70
|
+
DESCRIPTION
|
|
71
|
+
Generate blocks for your project
|
|
72
|
+
|
|
73
|
+
EXAMPLES
|
|
74
|
+
$ juo generate
|
|
75
|
+
```
|
|
76
|
+
|
|
37
77
|
## `juo help [COMMAND]`
|
|
38
78
|
|
|
39
79
|
Display help for juo.
|
|
@@ -43,7 +83,7 @@ USAGE
|
|
|
43
83
|
$ juo help [COMMAND...] [-n]
|
|
44
84
|
|
|
45
85
|
ARGUMENTS
|
|
46
|
-
COMMAND... Command to show help for.
|
|
86
|
+
[COMMAND...] Command to show help for.
|
|
47
87
|
|
|
48
88
|
FLAGS
|
|
49
89
|
-n, --nested-commands Include all nested commands in the output.
|
package/bin/dev.js
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import debug from "debug";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/config.ts
|
|
4
|
+
const MIXPANEL_TOKEN = "919dd811a5e2137983cc8fc304b8584b";
|
|
5
|
+
const MIXPANEL_API_URL = "https://api-eu.mixpanel.com";
|
|
6
|
+
const CUSTOMERIO_BETA_FORM_URL = "https://track-cio.juo.io/api/v1/forms/3c02106b-9746-4ebe-a116-553e47494eb4/submit";
|
|
7
|
+
const CUSTOMERIO_SITE_ID = "60da89062ce61084fc27";
|
|
8
|
+
const CUSTOMERIO_API_KEY = "1d54688e66cddda9ea72";
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/utils/analytics.ts
|
|
12
|
+
const log = debug("juo:analytics");
|
|
13
|
+
let userId = null;
|
|
14
|
+
function getUserId() {
|
|
15
|
+
if (!userId) userId = `cli_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
16
|
+
return userId;
|
|
17
|
+
}
|
|
18
|
+
async function sendToMixpanel(event) {
|
|
19
|
+
if (!MIXPANEL_TOKEN) return;
|
|
20
|
+
try {
|
|
21
|
+
const data = {
|
|
22
|
+
event: event.event,
|
|
23
|
+
properties: {
|
|
24
|
+
...event.properties,
|
|
25
|
+
token: MIXPANEL_TOKEN,
|
|
26
|
+
distinct_id: getUserId(),
|
|
27
|
+
time: Math.floor(Date.now() / 1e3)
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const encodedData = Buffer.from(JSON.stringify(data)).toString("base64");
|
|
31
|
+
await fetch(`${MIXPANEL_API_URL}/track?data=${encodedData}`, {
|
|
32
|
+
method: "GET",
|
|
33
|
+
headers: { "Content-Type": "application/json" }
|
|
34
|
+
}).catch((error) => {
|
|
35
|
+
log("Failed to send analytics event to Mixpanel: %O", error);
|
|
36
|
+
});
|
|
37
|
+
} catch (error) {
|
|
38
|
+
log("Error sending analytics event: %O", error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function trackEvent(eventName, properties = {}) {
|
|
42
|
+
sendToMixpanel({
|
|
43
|
+
event: eventName,
|
|
44
|
+
properties
|
|
45
|
+
}).catch((error) => {
|
|
46
|
+
log("Failed to track event %s: %O", eventName, error);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function trackCommandStarted(commandName, flags = {}) {
|
|
50
|
+
trackEvent("cli.command.started", {
|
|
51
|
+
command: commandName,
|
|
52
|
+
...flags
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function trackCommandCompleted(commandName, success = true) {
|
|
56
|
+
trackEvent("cli.command.completed", {
|
|
57
|
+
command: commandName,
|
|
58
|
+
success
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function trackBetaSignup(email, commandContext) {
|
|
62
|
+
trackEvent("cli.beta.signup", {
|
|
63
|
+
email,
|
|
64
|
+
command: commandContext
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { CUSTOMERIO_BETA_FORM_URL as a, CUSTOMERIO_API_KEY as i, trackCommandCompleted as n, CUSTOMERIO_SITE_ID as o, trackCommandStarted as r, trackBetaSignup as t };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
import * as _oclif_core_interfaces1 from "@oclif/core/interfaces";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/create.d.ts
|
|
5
|
+
declare class Create extends Command {
|
|
6
|
+
static description: string;
|
|
7
|
+
static flags: {
|
|
8
|
+
quickstart: _oclif_core_interfaces1.BooleanFlag<boolean>;
|
|
9
|
+
verbose: _oclif_core_interfaces1.BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
private getProjectConfig;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { Create as default };
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
import { n as BaseTemplateGenerator, t as Generate } from "../generate-D7J6nPBd.js";
|
|
2
|
+
import { Command, Flags } from "@oclif/core";
|
|
3
|
+
import { isCancel, outro, select, spinner, text } from "@clack/prompts";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { definePackageJSON, defineTSConfig, sortPackage, writePackageJSON, writeTSConfig } from "pkg-types";
|
|
7
|
+
import { execSync, spawn } from "node:child_process";
|
|
8
|
+
import { readdir, rm, stat, unlink } from "node:fs/promises";
|
|
9
|
+
|
|
10
|
+
//#region src/utils/packageGenerator.ts
|
|
11
|
+
const FRAMEWORK_CONFIGS = {
|
|
12
|
+
react: {
|
|
13
|
+
dependencies: {
|
|
14
|
+
"@juo/orion-core": "^0.4.0-rc.1",
|
|
15
|
+
"@mantine/core": "7.5.3",
|
|
16
|
+
"@mantine/hooks": "7.5.3",
|
|
17
|
+
react: "^18.2.0",
|
|
18
|
+
"react-dom": "^18.2.0"
|
|
19
|
+
},
|
|
20
|
+
devDependencies: {
|
|
21
|
+
"@storybook/react-vite": "^10.0.7",
|
|
22
|
+
"@types/react": "^18.2.55",
|
|
23
|
+
"@types/react-dom": "^18.2.19",
|
|
24
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
25
|
+
"vite-plugin-svgr": "^4.5.0"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
preact: {
|
|
29
|
+
dependencies: { preact: "^10.26.8" },
|
|
30
|
+
devDependencies: {
|
|
31
|
+
"@storybook/react-vite": "^10.0.7",
|
|
32
|
+
"json-schema-to-ts": "^3.1.1",
|
|
33
|
+
"@preact/preset-vite": "^2.10.2",
|
|
34
|
+
"vite-plugin-svgr": "^4.5.0"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var PackageGenerator = class {
|
|
39
|
+
static async generate(destDir, options) {
|
|
40
|
+
if (!existsSync(destDir)) mkdirSync(destDir, { recursive: true });
|
|
41
|
+
const packageJsonPath = path.join(destDir, "package.json");
|
|
42
|
+
const packageJson = this.buildPackageJson(options);
|
|
43
|
+
try {
|
|
44
|
+
await writePackageJSON(packageJsonPath, packageJson);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
throw new Error(`Failed to write package.json to ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
static sort(packageJson) {
|
|
50
|
+
return sortPackage(packageJson);
|
|
51
|
+
}
|
|
52
|
+
static readPackageManagerVersion(packageManager) {
|
|
53
|
+
try {
|
|
54
|
+
return execSync(`${packageManager} --version`, {
|
|
55
|
+
encoding: "utf-8",
|
|
56
|
+
stdio: [
|
|
57
|
+
"pipe",
|
|
58
|
+
"pipe",
|
|
59
|
+
"ignore"
|
|
60
|
+
]
|
|
61
|
+
}).trim();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.warn(`Failed to read ${packageManager} version, using fallback`);
|
|
64
|
+
return "latest";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
static buildPackageJson(options) {
|
|
68
|
+
const pmVersion = this.readPackageManagerVersion(options.packageManager);
|
|
69
|
+
const baseConfig = definePackageJSON({
|
|
70
|
+
name: options.name,
|
|
71
|
+
private: true,
|
|
72
|
+
version: "0.0.0",
|
|
73
|
+
type: "module",
|
|
74
|
+
scripts: {
|
|
75
|
+
dev: "vite build -w & vite preview --port 5174",
|
|
76
|
+
build: "tsc && vite build",
|
|
77
|
+
preview: "vite preview",
|
|
78
|
+
storybook: "storybook dev -p 6006",
|
|
79
|
+
"build-storybook": "storybook build"
|
|
80
|
+
},
|
|
81
|
+
engines: {
|
|
82
|
+
node: ">=20.0.0",
|
|
83
|
+
pnpm: ">=7.0.0"
|
|
84
|
+
},
|
|
85
|
+
packageManager: `${options.packageManager}@${pmVersion}`,
|
|
86
|
+
devDependencies: {
|
|
87
|
+
"@testing-library/dom": "^10.4.0",
|
|
88
|
+
"@types/node": "^22.15.29",
|
|
89
|
+
"json-schema-to-ts": "^3.1.1",
|
|
90
|
+
postcss: "^8.5.3",
|
|
91
|
+
"postcss-prefix-selector": "^2.1.1",
|
|
92
|
+
prettier: "^3.5.3",
|
|
93
|
+
...options.tailwind ? {
|
|
94
|
+
tailwindcss: "^4.1.17",
|
|
95
|
+
"@tailwindcss/vite": "^4.1.17"
|
|
96
|
+
} : {},
|
|
97
|
+
storybook: "^10.0.7",
|
|
98
|
+
typebox: "^1.0.51",
|
|
99
|
+
typescript: "~5.7.2",
|
|
100
|
+
vite: "^6.3.1"
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
if (options.framework === "react") {
|
|
104
|
+
baseConfig.devDependencies = {
|
|
105
|
+
...baseConfig.devDependencies,
|
|
106
|
+
...FRAMEWORK_CONFIGS.react.devDependencies
|
|
107
|
+
};
|
|
108
|
+
baseConfig.dependencies = {
|
|
109
|
+
...baseConfig.dependencies,
|
|
110
|
+
...FRAMEWORK_CONFIGS.react.dependencies
|
|
111
|
+
};
|
|
112
|
+
} else if (options.framework === "preact") {
|
|
113
|
+
baseConfig.dependencies = {
|
|
114
|
+
...baseConfig.dependencies,
|
|
115
|
+
...FRAMEWORK_CONFIGS.preact.dependencies
|
|
116
|
+
};
|
|
117
|
+
baseConfig.devDependencies = {
|
|
118
|
+
...baseConfig.devDependencies,
|
|
119
|
+
...FRAMEWORK_CONFIGS.preact.devDependencies
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return this.sort(baseConfig);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/utils/storybookGenerator.ts
|
|
128
|
+
const COMMAND_CONFIG = {
|
|
129
|
+
npm: "npx",
|
|
130
|
+
yarn: "yarn dlx",
|
|
131
|
+
pnpm: "pnpx"
|
|
132
|
+
};
|
|
133
|
+
var StorybookGenerator = class extends BaseTemplateGenerator {
|
|
134
|
+
async generate(destDir, options) {
|
|
135
|
+
const args = [
|
|
136
|
+
"storybook@latest",
|
|
137
|
+
"init",
|
|
138
|
+
"--skip-install",
|
|
139
|
+
"--package-manager",
|
|
140
|
+
options.packageManager,
|
|
141
|
+
"--builder",
|
|
142
|
+
"vite",
|
|
143
|
+
"--type",
|
|
144
|
+
"react",
|
|
145
|
+
"--no-dev",
|
|
146
|
+
"--features",
|
|
147
|
+
"docs",
|
|
148
|
+
"--disable-telemetry",
|
|
149
|
+
"--yes"
|
|
150
|
+
];
|
|
151
|
+
const command = COMMAND_CONFIG[options.packageManager];
|
|
152
|
+
if (!options.verbose) options.logger?.("Initializing Storybook...");
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
const child = spawn(command, args, {
|
|
155
|
+
cwd: destDir,
|
|
156
|
+
stdio: options.verbose ? "inherit" : [
|
|
157
|
+
"ignore",
|
|
158
|
+
"ignore",
|
|
159
|
+
"ignore"
|
|
160
|
+
],
|
|
161
|
+
shell: true
|
|
162
|
+
});
|
|
163
|
+
child.on("close", async (code) => {
|
|
164
|
+
if (code === 0) try {
|
|
165
|
+
await this.postGenerate(destDir);
|
|
166
|
+
resolve();
|
|
167
|
+
} catch (error) {
|
|
168
|
+
reject(error);
|
|
169
|
+
}
|
|
170
|
+
else reject(/* @__PURE__ */ new Error(`Storybook init failed with exit code ${code}`));
|
|
171
|
+
});
|
|
172
|
+
child.on("error", (error) => {
|
|
173
|
+
reject(/* @__PURE__ */ new Error(`Error initializing storybook: ${error.message}`));
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
async cleanUp(destDir) {
|
|
178
|
+
try {
|
|
179
|
+
const items = await readdir(destDir);
|
|
180
|
+
const itemsToSkip = ["assets", "Configure.mdx"];
|
|
181
|
+
for (const item of items) {
|
|
182
|
+
const itemPath = path.join(destDir, item);
|
|
183
|
+
const stats = await stat(itemPath);
|
|
184
|
+
if (itemsToSkip.includes(item)) continue;
|
|
185
|
+
if (stats.isDirectory()) await rm(itemPath, {
|
|
186
|
+
recursive: true,
|
|
187
|
+
force: true
|
|
188
|
+
});
|
|
189
|
+
else await unlink(itemPath);
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
throw new Error(`Error cleaning up storybook: ${error}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async appendPreviewHead(destDir) {
|
|
196
|
+
const storybookDir = path.join(destDir, ".storybook");
|
|
197
|
+
this.renderTemplate(".storybook", storybookDir, {});
|
|
198
|
+
}
|
|
199
|
+
async postGenerate(destDir) {
|
|
200
|
+
const storiesDir = path.join(destDir, "stories");
|
|
201
|
+
try {
|
|
202
|
+
if (!existsSync(storiesDir)) mkdirSync(storiesDir, { recursive: true });
|
|
203
|
+
await this.cleanUp(storiesDir);
|
|
204
|
+
await this.appendPreviewHead(destDir);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
throw new Error(`Error post-generating storybook: ${error}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async appendStylesToPreview(destDir) {
|
|
210
|
+
const storybookDir = path.join(destDir, ".storybook");
|
|
211
|
+
const previewJsPath = path.join(storybookDir, "preview.js");
|
|
212
|
+
const previewTsPath = path.join(storybookDir, "preview.ts");
|
|
213
|
+
const importStatement = "import \"../src/styles.css\";\n";
|
|
214
|
+
try {
|
|
215
|
+
const previewJsExists = existsSync(previewJsPath);
|
|
216
|
+
const previewTsExists = existsSync(previewTsPath);
|
|
217
|
+
let targetPath;
|
|
218
|
+
if (previewTsExists) targetPath = previewTsPath;
|
|
219
|
+
else if (previewJsExists) targetPath = previewJsPath;
|
|
220
|
+
else {
|
|
221
|
+
targetPath = previewTsPath;
|
|
222
|
+
mkdirSync(storybookDir, { recursive: true });
|
|
223
|
+
writeFileSync(targetPath, importStatement);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const existingContent = readFileSync(targetPath, "utf-8");
|
|
227
|
+
if (!existingContent.includes("import \"../src/styles.css\"")) writeFileSync(targetPath, importStatement + existingContent);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
throw new Error(`Error appending styles to preview: ${error}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/utils/tsconfigGenerator.ts
|
|
236
|
+
const baseTSConfig = {
|
|
237
|
+
compilerOptions: {
|
|
238
|
+
target: "ES2022",
|
|
239
|
+
module: "ESNext",
|
|
240
|
+
moduleResolution: "bundler",
|
|
241
|
+
jsx: "react-jsx",
|
|
242
|
+
strict: true,
|
|
243
|
+
esModuleInterop: true,
|
|
244
|
+
allowSyntheticDefaultImports: true,
|
|
245
|
+
skipLibCheck: true,
|
|
246
|
+
resolveJsonModule: true,
|
|
247
|
+
allowImportingTsExtensions: true,
|
|
248
|
+
isolatedModules: true,
|
|
249
|
+
noEmit: true,
|
|
250
|
+
forceConsistentCasingInFileNames: true,
|
|
251
|
+
types: ["vitest/globals", "node"]
|
|
252
|
+
},
|
|
253
|
+
include: [
|
|
254
|
+
"src/**/*",
|
|
255
|
+
"vitest.config.ts",
|
|
256
|
+
"vitest.shims.d.ts",
|
|
257
|
+
"vite-env.d.ts"
|
|
258
|
+
],
|
|
259
|
+
exclude: ["node_modules", "dist"]
|
|
260
|
+
};
|
|
261
|
+
const preactTSConfig = {
|
|
262
|
+
...baseTSConfig,
|
|
263
|
+
compilerOptions: {
|
|
264
|
+
...baseTSConfig.compilerOptions,
|
|
265
|
+
paths: {
|
|
266
|
+
react: ["./node_modules/preact/compat/"],
|
|
267
|
+
"react-dom": ["./node_modules/preact/compat/"]
|
|
268
|
+
},
|
|
269
|
+
jsxImportSource: "preact"
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
const configs = {
|
|
273
|
+
react: {
|
|
274
|
+
...baseTSConfig,
|
|
275
|
+
compilerOptions: { ...baseTSConfig.compilerOptions }
|
|
276
|
+
},
|
|
277
|
+
preact: preactTSConfig
|
|
278
|
+
};
|
|
279
|
+
var TsconfigGenerator = class {
|
|
280
|
+
static async generate(destDir, options) {
|
|
281
|
+
try {
|
|
282
|
+
const tsconfigPath = path.join(destDir, "tsconfig.json");
|
|
283
|
+
if (!existsSync(tsconfigPath)) mkdirSync(path.dirname(tsconfigPath), { recursive: true });
|
|
284
|
+
await writeTSConfig(tsconfigPath, defineTSConfig(configs[options.framework] ?? baseTSConfig));
|
|
285
|
+
} catch (error) {
|
|
286
|
+
throw new Error(`Error generating TypeScript configuration: ${error}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region src/utils/tailwindGenerator.ts
|
|
293
|
+
var TailwindGenerator = class extends BaseTemplateGenerator {
|
|
294
|
+
async generate(destDir, options) {
|
|
295
|
+
this.renderTemplate("tailwind", destDir, { framework: options.framework });
|
|
296
|
+
await this.appendStorybookPreview(destDir);
|
|
297
|
+
}
|
|
298
|
+
async appendStorybookPreview(destDir) {
|
|
299
|
+
const storybookDir = path.join(destDir, ".storybook");
|
|
300
|
+
const previewJsPath = path.join(storybookDir, "preview.js");
|
|
301
|
+
const previewTsPath = path.join(storybookDir, "preview.ts");
|
|
302
|
+
const importStatement = "import \"../src/tailwind.css\";\n";
|
|
303
|
+
const previewJsExists = existsSync(previewJsPath);
|
|
304
|
+
const previewTsExists = existsSync(previewTsPath);
|
|
305
|
+
let targetPath;
|
|
306
|
+
if (previewTsExists) targetPath = previewTsPath;
|
|
307
|
+
else if (previewJsExists) targetPath = previewJsPath;
|
|
308
|
+
else {
|
|
309
|
+
targetPath = previewTsPath;
|
|
310
|
+
try {
|
|
311
|
+
mkdirSync(storybookDir, { recursive: true });
|
|
312
|
+
writeFileSync(targetPath, importStatement);
|
|
313
|
+
return;
|
|
314
|
+
} catch (error) {
|
|
315
|
+
throw new Error(`Error appending Storybook preview: ${error}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const existingContent = readFileSync(targetPath, "utf-8");
|
|
320
|
+
if (!existingContent.includes("import \"../src/tailwind.css\"")) writeFileSync(targetPath, importStatement + existingContent);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
throw new Error(`Error appending Storybook preview: ${error}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
//#endregion
|
|
328
|
+
//#region src/utils/configFilesGenerator.ts
|
|
329
|
+
var ConfigFilesGenerator = class extends BaseTemplateGenerator {
|
|
330
|
+
async generate(destDir, options) {
|
|
331
|
+
this.renderTemplate("configFiles", destDir, { framework: options.framework });
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
//#endregion
|
|
336
|
+
//#region src/commands/create.ts
|
|
337
|
+
var Create = class Create extends Command {
|
|
338
|
+
static description = "Generate a new Juo project";
|
|
339
|
+
static flags = {
|
|
340
|
+
quickstart: Flags.boolean({ char: "q" }),
|
|
341
|
+
verbose: Flags.boolean({ char: "v" })
|
|
342
|
+
};
|
|
343
|
+
async run() {
|
|
344
|
+
const { flags } = await this.parse(Create);
|
|
345
|
+
const { packageName, packageManager, framework, tailwind } = await this.getProjectConfig(flags.quickstart);
|
|
346
|
+
const storybookGenerator = new StorybookGenerator();
|
|
347
|
+
const projectDir = path.resolve("./", packageName);
|
|
348
|
+
const packageJsonSpinner = spinner();
|
|
349
|
+
packageJsonSpinner.start();
|
|
350
|
+
packageJsonSpinner.message("Generating package.json file");
|
|
351
|
+
await PackageGenerator.generate(projectDir, {
|
|
352
|
+
name: packageName,
|
|
353
|
+
packageManager,
|
|
354
|
+
framework,
|
|
355
|
+
tailwind
|
|
356
|
+
});
|
|
357
|
+
packageJsonSpinner.stop("Generated package.json");
|
|
358
|
+
await new ConfigFilesGenerator().generate(projectDir, { framework });
|
|
359
|
+
const storybookSpinner = spinner();
|
|
360
|
+
storybookSpinner.start();
|
|
361
|
+
storybookSpinner.message("Generating Storybook configuration");
|
|
362
|
+
await storybookGenerator.generate(projectDir, {
|
|
363
|
+
packageManager,
|
|
364
|
+
framework,
|
|
365
|
+
logger: (msg) => storybookSpinner.message(msg),
|
|
366
|
+
verbose: flags.verbose
|
|
367
|
+
});
|
|
368
|
+
storybookSpinner.stop("Generated Storybook configuration");
|
|
369
|
+
const tsconfigSpinner = spinner();
|
|
370
|
+
tsconfigSpinner.start();
|
|
371
|
+
tsconfigSpinner.message("Generating TypeScript configuration");
|
|
372
|
+
await TsconfigGenerator.generate(projectDir, { framework });
|
|
373
|
+
tsconfigSpinner.stop("Generated TypeScript configuration");
|
|
374
|
+
if (tailwind) {
|
|
375
|
+
const tailwindSpinner = spinner();
|
|
376
|
+
tailwindSpinner.start();
|
|
377
|
+
tailwindSpinner.message("Generating Tailwind CSS configuration");
|
|
378
|
+
await new TailwindGenerator().generate(projectDir, { framework });
|
|
379
|
+
tailwindSpinner.stop("Generated Tailwind CSS configuration");
|
|
380
|
+
} else await storybookGenerator.appendStylesToPreview(projectDir);
|
|
381
|
+
const originalCwd = process.cwd();
|
|
382
|
+
try {
|
|
383
|
+
process.chdir(projectDir);
|
|
384
|
+
await new Generate([
|
|
385
|
+
"--name",
|
|
386
|
+
"Starter Block",
|
|
387
|
+
"--no-verbose"
|
|
388
|
+
], this.config).run();
|
|
389
|
+
} finally {
|
|
390
|
+
process.chdir(originalCwd);
|
|
391
|
+
}
|
|
392
|
+
outro(`Run \`cd ${packageName}\` to start developing your project.`);
|
|
393
|
+
process.exit(0);
|
|
394
|
+
}
|
|
395
|
+
async getProjectConfig(quickstart) {
|
|
396
|
+
if (quickstart) return {
|
|
397
|
+
packageName: "juo-theme",
|
|
398
|
+
packageManager: "npm",
|
|
399
|
+
framework: "react",
|
|
400
|
+
tailwind: true
|
|
401
|
+
};
|
|
402
|
+
const packageName = await text({
|
|
403
|
+
message: "What is the name of the package?",
|
|
404
|
+
placeholder: "juo-theme",
|
|
405
|
+
initialValue: "juo-theme",
|
|
406
|
+
validate(value) {
|
|
407
|
+
if (value.length === 0) return `Value is required!`;
|
|
408
|
+
if (!/^[a-z0-9-]+$/.test(value)) return `Invalid package name`;
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
if (isCancel(packageName)) process.exit(0);
|
|
412
|
+
const packageManager = await select({
|
|
413
|
+
message: "What package manager to use?",
|
|
414
|
+
options: [
|
|
415
|
+
{
|
|
416
|
+
value: "npm",
|
|
417
|
+
label: "npm"
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
value: "pnpm",
|
|
421
|
+
label: "pnpm"
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
value: "yarn",
|
|
425
|
+
label: "yarn"
|
|
426
|
+
}
|
|
427
|
+
],
|
|
428
|
+
initialValue: "npm"
|
|
429
|
+
});
|
|
430
|
+
if (isCancel(packageManager)) process.exit(0);
|
|
431
|
+
const framework = await select({
|
|
432
|
+
message: "What framework to use?",
|
|
433
|
+
options: [{
|
|
434
|
+
value: "react",
|
|
435
|
+
label: "React"
|
|
436
|
+
}, {
|
|
437
|
+
value: "preact",
|
|
438
|
+
label: "Preact"
|
|
439
|
+
}],
|
|
440
|
+
initialValue: "react"
|
|
441
|
+
});
|
|
442
|
+
if (isCancel(framework)) process.exit(0);
|
|
443
|
+
const tailwind = await select({
|
|
444
|
+
message: "Do you want to use Tailwind CSS?",
|
|
445
|
+
options: [{
|
|
446
|
+
value: true,
|
|
447
|
+
label: "Yes"
|
|
448
|
+
}, {
|
|
449
|
+
value: false,
|
|
450
|
+
label: "No"
|
|
451
|
+
}],
|
|
452
|
+
initialValue: true
|
|
453
|
+
});
|
|
454
|
+
if (isCancel(tailwind)) process.exit(0);
|
|
455
|
+
return {
|
|
456
|
+
packageName,
|
|
457
|
+
packageManager,
|
|
458
|
+
framework,
|
|
459
|
+
tailwind
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
//#endregion
|
|
465
|
+
export { Create as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
import * as _oclif_core_interfaces3 from "@oclif/core/interfaces";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/generate.d.ts
|
|
5
|
+
declare class Generate extends Command {
|
|
6
|
+
static id: string;
|
|
7
|
+
static description: string;
|
|
8
|
+
static flags: {
|
|
9
|
+
name: _oclif_core_interfaces3.OptionFlag<string | undefined, _oclif_core_interfaces3.CustomOptions>;
|
|
10
|
+
type: _oclif_core_interfaces3.OptionFlag<string, _oclif_core_interfaces3.CustomOptions>;
|
|
11
|
+
tailwind: _oclif_core_interfaces3.BooleanFlag<boolean>;
|
|
12
|
+
verbose: _oclif_core_interfaces3.BooleanFlag<boolean>;
|
|
13
|
+
};
|
|
14
|
+
static examples: string[];
|
|
15
|
+
private resolvePackageJsonPath;
|
|
16
|
+
private resolveCSSFramework;
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { Generate as default };
|
|
@@ -1,14 +1,42 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
getAllFiles(dirPath: string, basePath: string): string[];
|
|
10
|
-
run(): Promise<void>;
|
|
11
|
-
private getAwsConnectionInfo;
|
|
12
|
-
private uploadFile;
|
|
13
|
-
private uploadFiles;
|
|
1
|
+
import { Command, Interfaces } from "@oclif/core";
|
|
2
|
+
import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
|
|
3
|
+
|
|
4
|
+
//#region src/base-command.d.ts
|
|
5
|
+
interface OrionConfig {
|
|
6
|
+
JUO_API_KEY: string;
|
|
7
|
+
JUO_API_URL: string;
|
|
14
8
|
}
|
|
9
|
+
type Flags$1<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
|
|
10
|
+
type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
|
|
11
|
+
declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
12
|
+
static baseFlags: {
|
|
13
|
+
reconfigure: Interfaces.BooleanFlag<boolean>;
|
|
14
|
+
};
|
|
15
|
+
protected args: Args<T>;
|
|
16
|
+
protected flags: Flags$1<T>;
|
|
17
|
+
protected get configFileName(): string;
|
|
18
|
+
protected get configFilePath(): string;
|
|
19
|
+
protected configExists(): boolean;
|
|
20
|
+
protected ensureConfig(reconfigure?: boolean): Promise<OrionConfig>;
|
|
21
|
+
init(): Promise<void>;
|
|
22
|
+
protected loadConfig(): Partial<OrionConfig>;
|
|
23
|
+
protected saveConfig(config: Partial<OrionConfig>): void;
|
|
24
|
+
protected validateConfig(config: Partial<OrionConfig>): config is OrionConfig;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/commands/publish/index.d.ts
|
|
28
|
+
declare class Publish extends BaseCommand<typeof Publish> {
|
|
29
|
+
static args: {};
|
|
30
|
+
static description: string;
|
|
31
|
+
static examples: string[];
|
|
32
|
+
static flags: {
|
|
33
|
+
theme: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
|
|
34
|
+
};
|
|
35
|
+
getAllFiles(dirPath: string, basePath: string): string[];
|
|
36
|
+
run(): Promise<void>;
|
|
37
|
+
private getAwsConnectionInfo;
|
|
38
|
+
private uploadFile;
|
|
39
|
+
private uploadFiles;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { Publish as default };
|