@yoamigo.com/cli 0.1.0
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/LICENSE +11 -0
- package/README.md +85 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +363 -0
- package/package.json +58 -0
- package/templates/starter/index.html +12 -0
- package/templates/starter/package.json +25 -0
- package/templates/starter/postcss.config.cjs +5 -0
- package/templates/starter/public/favicon.svg +4 -0
- package/templates/starter/src/App.tsx +81 -0
- package/templates/starter/src/content.json +8 -0
- package/templates/starter/src/main.tsx +17 -0
- package/templates/starter/src/styles/globals.css +7 -0
- package/templates/starter/tsconfig.json +20 -0
- package/templates/starter/vite.config.ts +6 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright (c) 2025 YoAmigo. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
This software and associated documentation files (the "Software") are the
|
|
4
|
+
proprietary property of YoAmigo. Unauthorized copying, modification,
|
|
5
|
+
distribution, or use of this Software, via any medium, is strictly prohibited.
|
|
6
|
+
|
|
7
|
+
The Software is provided for use solely in connection with the YoAmigo platform
|
|
8
|
+
and template development program. Any other use requires explicit written
|
|
9
|
+
permission from YoAmigo.
|
|
10
|
+
|
|
11
|
+
For licensing inquiries, contact: support@yoamigo.com
|
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @yoamigo/cli
|
|
2
|
+
|
|
3
|
+
CLI for creating and managing YoAmigo templates.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @yoamigo/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 1. Login with your API key (get one at yoamigo.com/dev/dashboard)
|
|
15
|
+
yoamigo login
|
|
16
|
+
|
|
17
|
+
# 2. Create a new template
|
|
18
|
+
yoamigo init my-template
|
|
19
|
+
|
|
20
|
+
# 3. Start development
|
|
21
|
+
cd my-template
|
|
22
|
+
yoamigo dev
|
|
23
|
+
|
|
24
|
+
# 4. Preview in the builder
|
|
25
|
+
yoamigo preview
|
|
26
|
+
|
|
27
|
+
# 5. Submit for review
|
|
28
|
+
yoamigo deploy --submit
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Commands
|
|
32
|
+
|
|
33
|
+
### `yoamigo login`
|
|
34
|
+
|
|
35
|
+
Authenticate with your YoAmigo API key. Keys can be created at [yoamigo.com/dev/dashboard](https://yoamigo.com/dev/dashboard).
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
yoamigo login
|
|
39
|
+
# or
|
|
40
|
+
yoamigo login --key ya_dev_xxxxx
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### `yoamigo init <name>`
|
|
44
|
+
|
|
45
|
+
Create a new template project from the starter template.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
yoamigo init my-template
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### `yoamigo dev`
|
|
52
|
+
|
|
53
|
+
Start the Vite development server for local development.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
yoamigo dev
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### `yoamigo preview`
|
|
60
|
+
|
|
61
|
+
Upload your template to YoAmigo for preview in the builder. Does not submit for review.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
yoamigo preview
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### `yoamigo deploy`
|
|
68
|
+
|
|
69
|
+
Deploy your template. Use `--submit` to submit for review.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Deploy without submitting
|
|
73
|
+
yoamigo deploy
|
|
74
|
+
|
|
75
|
+
# Deploy and submit for review
|
|
76
|
+
yoamigo deploy --submit
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Documentation
|
|
80
|
+
|
|
81
|
+
For full documentation, visit [yoamigo.com/developers](https://yoamigo.com/developers).
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
Proprietary - All Rights Reserved. See LICENSE file for details.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command as Command5 } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/commands/login.ts
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import chalk from "chalk";
|
|
9
|
+
import ora from "ora";
|
|
10
|
+
import fs from "fs-extra";
|
|
11
|
+
import path from "path";
|
|
12
|
+
import os from "os";
|
|
13
|
+
import { input } from "@inquirer/prompts";
|
|
14
|
+
|
|
15
|
+
// src/config.ts
|
|
16
|
+
var API_URLS = {
|
|
17
|
+
production: "https://api.yoamigo.com",
|
|
18
|
+
staging: "https://api-staging.yoamigo.com"
|
|
19
|
+
};
|
|
20
|
+
var APP_URLS = {
|
|
21
|
+
production: "https://dev.yoamigo.com",
|
|
22
|
+
staging: "https://dev-staging.yoamigo.com"
|
|
23
|
+
};
|
|
24
|
+
function isStaging() {
|
|
25
|
+
return process.env.YOAMIGO_ENVIRONMENT === "staging";
|
|
26
|
+
}
|
|
27
|
+
function getApiBaseUrl() {
|
|
28
|
+
if (process.env.YOAMIGO_API_URL) {
|
|
29
|
+
return process.env.YOAMIGO_API_URL;
|
|
30
|
+
}
|
|
31
|
+
return isStaging() ? API_URLS.staging : API_URLS.production;
|
|
32
|
+
}
|
|
33
|
+
function getAppBaseUrl() {
|
|
34
|
+
return isStaging() ? APP_URLS.staging : APP_URLS.production;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/commands/login.ts
|
|
38
|
+
var CREDENTIALS_DIR = path.join(os.homedir(), ".yoamigo");
|
|
39
|
+
var CREDENTIALS_FILE = path.join(CREDENTIALS_DIR, "credentials.json");
|
|
40
|
+
var API_BASE_URL = getApiBaseUrl();
|
|
41
|
+
async function getCredentials() {
|
|
42
|
+
try {
|
|
43
|
+
if (await fs.pathExists(CREDENTIALS_FILE)) {
|
|
44
|
+
return await fs.readJson(CREDENTIALS_FILE);
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
async function saveCredentials(credentials) {
|
|
51
|
+
await fs.ensureDir(CREDENTIALS_DIR);
|
|
52
|
+
await fs.writeJson(CREDENTIALS_FILE, credentials, { spaces: 2 });
|
|
53
|
+
}
|
|
54
|
+
var loginCommand = new Command("login").description("Authenticate with your API key").option("-k, --key <apiKey>", "API key (or enter interactively)").action(async (options) => {
|
|
55
|
+
let apiKey = options.key;
|
|
56
|
+
if (!apiKey) {
|
|
57
|
+
apiKey = await input({
|
|
58
|
+
message: "Enter your API key:",
|
|
59
|
+
validate: (value) => {
|
|
60
|
+
if (!value || value.trim().length === 0) {
|
|
61
|
+
return "API key is required";
|
|
62
|
+
}
|
|
63
|
+
if (!value.startsWith("ya_dev_")) {
|
|
64
|
+
return "Invalid API key format. Keys should start with ya_dev_";
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const spinner = ora("Authenticating...").start();
|
|
71
|
+
try {
|
|
72
|
+
const response = await fetch(`${API_BASE_URL}/trpc/developer.validateApiKey?input=${encodeURIComponent(JSON.stringify({ apiKey }))}`, {
|
|
73
|
+
method: "GET",
|
|
74
|
+
headers: {
|
|
75
|
+
"Content-Type": "application/json"
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw new Error("Invalid API key");
|
|
80
|
+
}
|
|
81
|
+
const data = await response.json();
|
|
82
|
+
const result = data.result?.data;
|
|
83
|
+
if (!result?.valid) {
|
|
84
|
+
throw new Error("Invalid API key");
|
|
85
|
+
}
|
|
86
|
+
await saveCredentials({
|
|
87
|
+
apiKey,
|
|
88
|
+
email: result.email,
|
|
89
|
+
expiresAt: result.expiresAt
|
|
90
|
+
});
|
|
91
|
+
spinner.succeed("Authenticated successfully!");
|
|
92
|
+
console.log();
|
|
93
|
+
console.log(chalk.green(`Welcome, ${result.email}!`));
|
|
94
|
+
console.log(chalk.dim(`Credentials saved to ${CREDENTIALS_FILE}`));
|
|
95
|
+
} catch (error) {
|
|
96
|
+
spinner.fail("Authentication failed");
|
|
97
|
+
console.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// src/commands/init.ts
|
|
103
|
+
import { Command as Command2 } from "commander";
|
|
104
|
+
import chalk2 from "chalk";
|
|
105
|
+
import ora2 from "ora";
|
|
106
|
+
import fs2 from "fs-extra";
|
|
107
|
+
import path2 from "path";
|
|
108
|
+
import { fileURLToPath } from "url";
|
|
109
|
+
import { input as input2 } from "@inquirer/prompts";
|
|
110
|
+
import { spawn } from "child_process";
|
|
111
|
+
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
112
|
+
var TEMPLATES_DIR = path2.resolve(__dirname, "../../templates");
|
|
113
|
+
var initCommand = new Command2("init").description("Create a new template project").argument("[name]", "Project name").option("-t, --template <template>", "Template to use", "starter").action(async (name, options) => {
|
|
114
|
+
let projectName = name;
|
|
115
|
+
if (!projectName) {
|
|
116
|
+
projectName = await input2({
|
|
117
|
+
message: "Project name:",
|
|
118
|
+
default: "my-template",
|
|
119
|
+
validate: (value) => {
|
|
120
|
+
if (!value || value.trim().length === 0) {
|
|
121
|
+
return "Project name is required";
|
|
122
|
+
}
|
|
123
|
+
if (!/^[a-z0-9-]+$/.test(value)) {
|
|
124
|
+
return "Project name must be lowercase letters, numbers, and hyphens only";
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const targetDir = path2.resolve(process.cwd(), projectName);
|
|
131
|
+
const templateDir = path2.join(TEMPLATES_DIR, options.template);
|
|
132
|
+
if (await fs2.pathExists(targetDir)) {
|
|
133
|
+
console.error(chalk2.red(`Error: Directory ${projectName} already exists`));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
if (!await fs2.pathExists(templateDir)) {
|
|
137
|
+
console.error(chalk2.red(`Error: Template "${options.template}" not found`));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
const spinner = ora2(`Creating ${projectName}...`).start();
|
|
141
|
+
try {
|
|
142
|
+
await fs2.copy(templateDir, targetDir);
|
|
143
|
+
const packageJsonPath = path2.join(targetDir, "package.json");
|
|
144
|
+
if (await fs2.pathExists(packageJsonPath)) {
|
|
145
|
+
const packageJson = await fs2.readJson(packageJsonPath);
|
|
146
|
+
packageJson.name = projectName;
|
|
147
|
+
await fs2.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
148
|
+
}
|
|
149
|
+
spinner.succeed(`Created ${projectName}`);
|
|
150
|
+
console.log();
|
|
151
|
+
const installSpinner = ora2("Installing dependencies...").start();
|
|
152
|
+
await new Promise((resolve, reject) => {
|
|
153
|
+
const child = spawn("npm", ["install"], {
|
|
154
|
+
cwd: targetDir,
|
|
155
|
+
stdio: "pipe"
|
|
156
|
+
});
|
|
157
|
+
child.on("error", reject);
|
|
158
|
+
child.on("close", (code) => {
|
|
159
|
+
if (code === 0) {
|
|
160
|
+
resolve();
|
|
161
|
+
} else {
|
|
162
|
+
reject(new Error(`npm install failed with code ${code}`));
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
installSpinner.succeed("Installed dependencies");
|
|
167
|
+
console.log();
|
|
168
|
+
console.log(chalk2.green("Success!") + ` Created ${projectName} at ${targetDir}`);
|
|
169
|
+
console.log();
|
|
170
|
+
console.log("Next steps:");
|
|
171
|
+
console.log(chalk2.cyan(` cd ${projectName}`));
|
|
172
|
+
console.log(chalk2.cyan(" yoamigo dev # Start development server"));
|
|
173
|
+
console.log(chalk2.cyan(" yoamigo preview # Preview in builder"));
|
|
174
|
+
console.log();
|
|
175
|
+
} catch (error) {
|
|
176
|
+
spinner.fail("Failed to create project");
|
|
177
|
+
console.error(chalk2.red(error instanceof Error ? error.message : "Unknown error"));
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// src/commands/dev.ts
|
|
183
|
+
import { Command as Command3 } from "commander";
|
|
184
|
+
import chalk3 from "chalk";
|
|
185
|
+
import { spawn as spawn2 } from "child_process";
|
|
186
|
+
import fs3 from "fs-extra";
|
|
187
|
+
import path3 from "path";
|
|
188
|
+
var devCommand = new Command3("dev").description("Start development server").option("-p, --port <port>", "Port to run on", "5173").option("--edit", "Enable edit mode").action(async (options) => {
|
|
189
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
190
|
+
if (!await fs3.pathExists(packageJsonPath)) {
|
|
191
|
+
console.error(chalk3.red("Error: No package.json found. Are you in a template project?"));
|
|
192
|
+
console.log(chalk3.dim("Run `yoamigo init` to create a new template project."));
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
const viteConfigPath = path3.join(process.cwd(), "vite.config.ts");
|
|
196
|
+
if (!await fs3.pathExists(viteConfigPath)) {
|
|
197
|
+
console.error(chalk3.red("Error: No vite.config.ts found. Are you in a template project?"));
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
console.log(chalk3.cyan("Starting development server..."));
|
|
201
|
+
console.log();
|
|
202
|
+
const packageManager = await detectPackageManager();
|
|
203
|
+
const env = {
|
|
204
|
+
...process.env,
|
|
205
|
+
...options.edit ? { YA_EDIT_MODE: "true" } : {}
|
|
206
|
+
};
|
|
207
|
+
const args = packageManager === "npm" ? ["run", "dev"] : ["dev"];
|
|
208
|
+
const child = spawn2(packageManager, args, {
|
|
209
|
+
cwd: process.cwd(),
|
|
210
|
+
stdio: "inherit",
|
|
211
|
+
env
|
|
212
|
+
});
|
|
213
|
+
child.on("error", (error) => {
|
|
214
|
+
console.error(chalk3.red(`Failed to start dev server: ${error.message}`));
|
|
215
|
+
process.exit(1);
|
|
216
|
+
});
|
|
217
|
+
child.on("close", (code) => {
|
|
218
|
+
process.exit(code ?? 0);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
async function detectPackageManager() {
|
|
222
|
+
if (await fs3.pathExists(path3.join(process.cwd(), "pnpm-lock.yaml"))) {
|
|
223
|
+
return "pnpm";
|
|
224
|
+
}
|
|
225
|
+
if (await fs3.pathExists(path3.join(process.cwd(), "yarn.lock"))) {
|
|
226
|
+
return "yarn";
|
|
227
|
+
}
|
|
228
|
+
return "npm";
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// src/commands/deploy.ts
|
|
232
|
+
import { Command as Command4 } from "commander";
|
|
233
|
+
import chalk4 from "chalk";
|
|
234
|
+
import ora3 from "ora";
|
|
235
|
+
import fs4 from "fs-extra";
|
|
236
|
+
import path4 from "path";
|
|
237
|
+
var API_BASE_URL2 = getApiBaseUrl();
|
|
238
|
+
var APP_BASE_URL = getAppBaseUrl();
|
|
239
|
+
var EXCLUDE_PATTERNS = ["node_modules", "dist", ".git", "vite.config.ts", "tsconfig.json", "*.log"];
|
|
240
|
+
var deployCommand = new Command4("deploy").description("Upload template to YoAmigo").requiredOption("--version <semver>", "Template version (e.g., 1.0.0)").action(async (options) => {
|
|
241
|
+
const credentials = await getCredentials();
|
|
242
|
+
if (!credentials) {
|
|
243
|
+
console.error(chalk4.red("Error: Not logged in. Run `yoamigo login` first."));
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
const versionRegex = /^\d+\.\d+\.\d+$/;
|
|
247
|
+
if (!versionRegex.test(options.version)) {
|
|
248
|
+
console.error(chalk4.red("Error: Version must be in semver format (e.g., 1.0.0)"));
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
const packageJsonPath = path4.join(process.cwd(), "package.json");
|
|
252
|
+
if (!await fs4.pathExists(packageJsonPath)) {
|
|
253
|
+
console.error(chalk4.red("Error: No package.json found. Are you in a template project?"));
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
const packageJson = await fs4.readJson(packageJsonPath);
|
|
257
|
+
const templateName = packageJson.name || "unnamed-template";
|
|
258
|
+
const spinner = ora3("Deploying template...").start();
|
|
259
|
+
try {
|
|
260
|
+
spinner.text = "Collecting files...";
|
|
261
|
+
const files = await collectFiles(process.cwd());
|
|
262
|
+
if (files.length === 0) {
|
|
263
|
+
throw new Error("No files found to upload");
|
|
264
|
+
}
|
|
265
|
+
spinner.text = `Uploading ${files.length} files...`;
|
|
266
|
+
const templateResponse = await fetch(`${API_BASE_URL2}/trpc/developer.createOrUpdateTemplate`, {
|
|
267
|
+
method: "POST",
|
|
268
|
+
headers: {
|
|
269
|
+
"Content-Type": "application/json",
|
|
270
|
+
"X-API-Key": credentials.apiKey
|
|
271
|
+
},
|
|
272
|
+
body: JSON.stringify({
|
|
273
|
+
name: templateName,
|
|
274
|
+
version: options.version,
|
|
275
|
+
description: packageJson.description || ""
|
|
276
|
+
})
|
|
277
|
+
});
|
|
278
|
+
if (!templateResponse.ok) {
|
|
279
|
+
const error = await templateResponse.json();
|
|
280
|
+
const errorMessage = error.error?.message || error.message || "Failed to create template";
|
|
281
|
+
throw new Error(errorMessage);
|
|
282
|
+
}
|
|
283
|
+
const templateData = await templateResponse.json();
|
|
284
|
+
const templateId = templateData.result?.data?.id;
|
|
285
|
+
if (!templateId) {
|
|
286
|
+
throw new Error("Failed to get template ID");
|
|
287
|
+
}
|
|
288
|
+
for (const file of files) {
|
|
289
|
+
const relativePath = path4.relative(process.cwd(), file);
|
|
290
|
+
const content = await fs4.readFile(file, "utf-8");
|
|
291
|
+
const uploadResponse = await fetch(`${API_BASE_URL2}/trpc/developer.uploadTemplateFile`, {
|
|
292
|
+
method: "POST",
|
|
293
|
+
headers: {
|
|
294
|
+
"Content-Type": "application/json",
|
|
295
|
+
"X-API-Key": credentials.apiKey
|
|
296
|
+
},
|
|
297
|
+
body: JSON.stringify({
|
|
298
|
+
templateId,
|
|
299
|
+
path: relativePath,
|
|
300
|
+
content
|
|
301
|
+
})
|
|
302
|
+
});
|
|
303
|
+
if (!uploadResponse.ok) {
|
|
304
|
+
console.warn(chalk4.yellow(`Warning: Failed to upload ${relativePath}`));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
spinner.succeed(`Template v${options.version} deployed successfully!`);
|
|
308
|
+
console.log();
|
|
309
|
+
console.log(chalk4.green("Preview URL:"));
|
|
310
|
+
console.log(chalk4.cyan(` ${APP_BASE_URL}/preview/${templateId}`));
|
|
311
|
+
console.log();
|
|
312
|
+
console.log(chalk4.dim("To submit for review, visit your dashboard:"));
|
|
313
|
+
console.log(chalk4.dim(` ${APP_BASE_URL}/dashboard`));
|
|
314
|
+
} catch (error) {
|
|
315
|
+
spinner.fail("Failed to deploy template");
|
|
316
|
+
console.error(chalk4.red(error instanceof Error ? error.message : "Unknown error"));
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
async function collectFiles(dir) {
|
|
321
|
+
const files = [];
|
|
322
|
+
const srcDir = path4.join(dir, "src");
|
|
323
|
+
const publicDir = path4.join(dir, "public");
|
|
324
|
+
const packageJsonPath = path4.join(dir, "package.json");
|
|
325
|
+
if (await fs4.pathExists(srcDir)) {
|
|
326
|
+
const srcFiles = await collectFilesRecursive(srcDir);
|
|
327
|
+
files.push(...srcFiles);
|
|
328
|
+
}
|
|
329
|
+
if (await fs4.pathExists(publicDir)) {
|
|
330
|
+
const publicFiles = await collectFilesRecursive(publicDir);
|
|
331
|
+
files.push(...publicFiles);
|
|
332
|
+
}
|
|
333
|
+
if (await fs4.pathExists(packageJsonPath)) {
|
|
334
|
+
files.push(packageJsonPath);
|
|
335
|
+
}
|
|
336
|
+
return files;
|
|
337
|
+
}
|
|
338
|
+
async function collectFilesRecursive(dir) {
|
|
339
|
+
const files = [];
|
|
340
|
+
const entries = await fs4.readdir(dir, { withFileTypes: true });
|
|
341
|
+
for (const entry of entries) {
|
|
342
|
+
const fullPath = path4.join(dir, entry.name);
|
|
343
|
+
if (EXCLUDE_PATTERNS.some((pattern) => entry.name.includes(pattern))) {
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
if (entry.isDirectory()) {
|
|
347
|
+
const subFiles = await collectFilesRecursive(fullPath);
|
|
348
|
+
files.push(...subFiles);
|
|
349
|
+
} else {
|
|
350
|
+
files.push(fullPath);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return files;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// src/index.ts
|
|
357
|
+
var program = new Command5();
|
|
358
|
+
program.name("yoamigo").description("CLI for creating and managing YoAmigo templates").version("1.0.0");
|
|
359
|
+
program.addCommand(loginCommand);
|
|
360
|
+
program.addCommand(initCommand);
|
|
361
|
+
program.addCommand(devCommand);
|
|
362
|
+
program.addCommand(deployCommand);
|
|
363
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yoamigo.com/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for creating and managing YoAmigo templates",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
7
|
+
"bin": {
|
|
8
|
+
"yoamigo": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"templates",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/yoamigo/sdk.git",
|
|
24
|
+
"directory": "packages/yoamigo-cli"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://yoamigo.com/developers",
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/yoamigo/sdk/issues"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"yoamigo",
|
|
32
|
+
"cli",
|
|
33
|
+
"template",
|
|
34
|
+
"vite",
|
|
35
|
+
"website-builder",
|
|
36
|
+
"scaffold"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup src/index.ts --format esm --dts",
|
|
40
|
+
"dev": "tsup src/index.ts --format esm --watch",
|
|
41
|
+
"typecheck": "tsc --noEmit",
|
|
42
|
+
"lint": "eslint src --ext .ts",
|
|
43
|
+
"lint:check": "eslint src --ext .ts"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"commander": "^14.0.2",
|
|
47
|
+
"chalk": "^5.6.2",
|
|
48
|
+
"ora": "^9.0.0",
|
|
49
|
+
"@inquirer/prompts": "^8.1.0",
|
|
50
|
+
"fs-extra": "^11.3.2"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/fs-extra": "^12.0.1",
|
|
54
|
+
"@types/node": "^22.10.5",
|
|
55
|
+
"tsup": "^9.1.0",
|
|
56
|
+
"typescript": "^5.9.3"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>YoAmigo Template</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-yoamigo-template",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"dev:edit": "YA_EDIT_MODE=true vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@yoamigo/core": "^0.1.0",
|
|
13
|
+
"react": "^19.2.1",
|
|
14
|
+
"react-dom": "^19.2.1"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/react": "^19.2.1",
|
|
18
|
+
"@types/react-dom": "^19.2.1",
|
|
19
|
+
"typescript": "^5.9.3",
|
|
20
|
+
"vite": "^7.2.4",
|
|
21
|
+
"tailwindcss": "^4.1.17",
|
|
22
|
+
"@tailwindcss/postcss": "^4.1.17",
|
|
23
|
+
"postcss": "^8.4.49"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { YaText, YaImage, YaLink } from '@yoamigo/core'
|
|
2
|
+
import { Router } from '@yoamigo/core/router'
|
|
3
|
+
|
|
4
|
+
function HomePage() {
|
|
5
|
+
return (
|
|
6
|
+
<div className="min-h-screen bg-gradient-to-b from-gray-900 to-gray-800 text-white">
|
|
7
|
+
{/* Hero Section */}
|
|
8
|
+
<section className="container mx-auto px-4 py-20">
|
|
9
|
+
<div className="text-center max-w-3xl mx-auto">
|
|
10
|
+
<h1 className="text-5xl font-bold mb-6">
|
|
11
|
+
<YaText fieldId="hero.title" as="span">
|
|
12
|
+
Welcome to YoAmigo
|
|
13
|
+
</YaText>
|
|
14
|
+
</h1>
|
|
15
|
+
<p className="text-xl text-gray-300 mb-8">
|
|
16
|
+
<YaText fieldId="hero.subtitle" as="span">
|
|
17
|
+
Build beautiful websites with our template system.
|
|
18
|
+
Click any text to edit it in the builder.
|
|
19
|
+
</YaText>
|
|
20
|
+
</p>
|
|
21
|
+
<div className="flex gap-4 justify-center">
|
|
22
|
+
<YaLink fieldId="hero.cta1" href="#about" className="px-6 py-3 bg-blue-600 hover:bg-blue-700 rounded-lg font-medium transition-colors">
|
|
23
|
+
Learn More
|
|
24
|
+
</YaLink>
|
|
25
|
+
<YaLink fieldId="hero.cta2" href="#contact" className="px-6 py-3 bg-gray-700 hover:bg-gray-600 rounded-lg font-medium transition-colors">
|
|
26
|
+
Contact
|
|
27
|
+
</YaLink>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</section>
|
|
31
|
+
|
|
32
|
+
{/* About Section */}
|
|
33
|
+
<section id="about" className="container mx-auto px-4 py-20">
|
|
34
|
+
<div className="max-w-3xl mx-auto">
|
|
35
|
+
<h2 className="text-3xl font-bold mb-6 text-center">
|
|
36
|
+
<YaText fieldId="about.title" as="span">
|
|
37
|
+
About Us
|
|
38
|
+
</YaText>
|
|
39
|
+
</h2>
|
|
40
|
+
<p className="text-gray-300 text-center">
|
|
41
|
+
<YaText fieldId="about.description" as="span">
|
|
42
|
+
We create beautiful, responsive templates for modern websites.
|
|
43
|
+
Our templates are designed to be easy to customize and deploy.
|
|
44
|
+
</YaText>
|
|
45
|
+
</p>
|
|
46
|
+
</div>
|
|
47
|
+
</section>
|
|
48
|
+
|
|
49
|
+
{/* Contact Section */}
|
|
50
|
+
<section id="contact" className="container mx-auto px-4 py-20">
|
|
51
|
+
<div className="max-w-3xl mx-auto text-center">
|
|
52
|
+
<h2 className="text-3xl font-bold mb-6">
|
|
53
|
+
<YaText fieldId="contact.title" as="span">
|
|
54
|
+
Get in Touch
|
|
55
|
+
</YaText>
|
|
56
|
+
</h2>
|
|
57
|
+
<p className="text-gray-300 mb-8">
|
|
58
|
+
<YaText fieldId="contact.description" as="span">
|
|
59
|
+
Have questions? We'd love to hear from you.
|
|
60
|
+
</YaText>
|
|
61
|
+
</p>
|
|
62
|
+
</div>
|
|
63
|
+
</section>
|
|
64
|
+
|
|
65
|
+
{/* Footer */}
|
|
66
|
+
<footer className="border-t border-gray-800 py-8">
|
|
67
|
+
<div className="container mx-auto px-4 text-center text-gray-400">
|
|
68
|
+
<p>Built with YoAmigo</p>
|
|
69
|
+
</div>
|
|
70
|
+
</footer>
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default function App() {
|
|
76
|
+
return (
|
|
77
|
+
<Router>
|
|
78
|
+
<HomePage />
|
|
79
|
+
</Router>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hero.title": "Welcome to YoAmigo",
|
|
3
|
+
"hero.subtitle": "Build beautiful websites with our template system. Click any text to edit it in the builder.",
|
|
4
|
+
"about.title": "About Us",
|
|
5
|
+
"about.description": "We create beautiful, responsive templates for modern websites. Our templates are designed to be easy to customize and deploy.",
|
|
6
|
+
"contact.title": "Get in Touch",
|
|
7
|
+
"contact.description": "Have questions? We'd love to hear from you."
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StrictMode } from 'react'
|
|
2
|
+
import { createRoot } from 'react-dom/client'
|
|
3
|
+
import { ContentStoreProvider, registerContent } from '@yoamigo/core'
|
|
4
|
+
import App from './App'
|
|
5
|
+
import content from './content.json'
|
|
6
|
+
import './styles/globals.css'
|
|
7
|
+
|
|
8
|
+
// Register content for the content store
|
|
9
|
+
registerContent(content)
|
|
10
|
+
|
|
11
|
+
createRoot(document.getElementById('root')!).render(
|
|
12
|
+
<StrictMode>
|
|
13
|
+
<ContentStoreProvider initialContent={content}>
|
|
14
|
+
<App />
|
|
15
|
+
</ContentStoreProvider>
|
|
16
|
+
</StrictMode>
|
|
17
|
+
)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"noEmit": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"baseUrl": ".",
|
|
14
|
+
"paths": {
|
|
15
|
+
"@/*": ["src/*"]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*"],
|
|
19
|
+
"exclude": ["node_modules", "dist"]
|
|
20
|
+
}
|