@farm.js/create-app 0.1.0-beta.6 → 0.1.0-beta.7

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 CHANGED
@@ -5,7 +5,12 @@ Create a new Farm.js application
5
5
  Farm.js is currently in beta.
6
6
 
7
7
  ```bash
8
- npm create @farm.js/app@beta
8
+ pnpm create @farm.js/app my-app
9
+ cd my-app
10
+ pnpm dev
9
11
  ```
10
12
 
13
+ The scaffolder installs React, React DOM, Farm.js, TypeScript, and the other starter dependencies
14
+ automatically. Pass `--skip-install` when you only want to generate the project files.
15
+
11
16
  See the [Farm.js repository](https://github.com/farming-labs/farm.js) for documentation, examples, and support.
@@ -11,6 +11,7 @@ program
11
11
  .argument("[project-name]", "Name of the project")
12
12
  .option("-t, --template <template>", "Template to use")
13
13
  .option("--typescript", "Use TypeScript template")
14
+ .option("--skip-install", "Skip installing dependencies")
14
15
  .action(async (projectName, options) => {
15
16
  try {
16
17
  await createApp(projectName, options);
package/dist/index.js ADDED
@@ -0,0 +1,206 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.js");
3
+ const require_utils = require("./utils.js");
4
+ let prompts = require("prompts");
5
+ prompts = require_rolldown_runtime.__toESM(prompts);
6
+ let path = require("path");
7
+ path = require_rolldown_runtime.__toESM(path);
8
+ let fs_promises = require("fs/promises");
9
+ fs_promises = require_rolldown_runtime.__toESM(fs_promises);
10
+ let node_child_process = require("node:child_process");
11
+ //#region src/index.ts
12
+ async function createApp(projectName, options = {}) {
13
+ require_utils.showBanner();
14
+ const templates = await getAvailableTemplates();
15
+ if (templates.length === 0) {
16
+ require_utils.logger.error("No templates are available in this package.");
17
+ process.exit(1);
18
+ }
19
+ if (!projectName) {
20
+ const response = await (0, prompts.default)({
21
+ type: "text",
22
+ name: "projectName",
23
+ message: "What is your project named?",
24
+ initial: "my-farm-app",
25
+ validate: validateProjectName
26
+ });
27
+ if (!response.projectName) {
28
+ require_utils.logger.error("Operation cancelled.");
29
+ process.exit(1);
30
+ }
31
+ projectName = response.projectName;
32
+ } else {
33
+ const validation = validateProjectPathArg(projectName);
34
+ if (validation !== true) {
35
+ require_utils.logger.error(validation);
36
+ process.exit(1);
37
+ }
38
+ }
39
+ let template = options.template;
40
+ if (!template) {
41
+ const response = await (0, prompts.default)({
42
+ type: "select",
43
+ name: "template",
44
+ message: "Which template would you like to use?",
45
+ choices: templates.map((name) => ({
46
+ title: prettifyTemplateName(name),
47
+ value: name,
48
+ description: name === "basic" ? "A simple Farm.js app with built-in Tailwind support" : void 0
49
+ })),
50
+ initial: 0
51
+ });
52
+ if (!response.template) {
53
+ require_utils.logger.error("Operation cancelled.");
54
+ process.exit(1);
55
+ }
56
+ template = response.template;
57
+ } else if (!templates.includes(template)) {
58
+ require_utils.logger.error(`Unknown template "${template}". Available: ${templates.map((t) => `"${t}"`).join(", ")}`);
59
+ process.exit(1);
60
+ }
61
+ let useTypeScript = options.typescript;
62
+ if (useTypeScript === void 0) {
63
+ const response = await (0, prompts.default)({
64
+ type: "confirm",
65
+ name: "typescript",
66
+ message: "Would you like to use TypeScript?",
67
+ initial: true
68
+ });
69
+ if (response.typescript === void 0) {
70
+ require_utils.logger.error("Operation cancelled.");
71
+ process.exit(1);
72
+ }
73
+ useTypeScript = response.typescript;
74
+ }
75
+ const projectPath = path.default.resolve(process.cwd(), projectName);
76
+ const packageManager = detectPackageManager();
77
+ if (await directoryHasFiles(projectPath)) {
78
+ if (!(await (0, prompts.default)({
79
+ type: "confirm",
80
+ name: "overwrite",
81
+ message: `Directory "${projectName}" is not empty. Continue and overwrite conflicting files?`,
82
+ initial: false
83
+ })).overwrite) {
84
+ require_utils.logger.error("Operation cancelled.");
85
+ process.exit(1);
86
+ }
87
+ }
88
+ require_utils.logger.info(`Creating Farm.js app in ${projectPath}`);
89
+ await fs_promises.default.mkdir(projectPath, { recursive: true });
90
+ await copyTemplate(template, projectPath, useTypeScript);
91
+ await updatePackageJson(projectPath, projectName, packageManager);
92
+ require_utils.logger.success(`🚜 Created ${projectName}`);
93
+ if (!options.skipInstall) {
94
+ require_utils.logger.info(`Installing dependencies with ${packageManager.name}...`);
95
+ await installDependencies(projectPath, packageManager);
96
+ require_utils.logger.success("Dependencies installed");
97
+ }
98
+ require_utils.logger.info("");
99
+ require_utils.logger.info("Next steps");
100
+ require_utils.logger.info(` cd ${projectName}`);
101
+ if (options.skipInstall) require_utils.logger.info(` ${packageManager.name} install`);
102
+ require_utils.logger.info(` ${getDevCommand(packageManager.name)}`);
103
+ require_utils.logger.info("");
104
+ require_utils.logger.info("Tailwind is enabled by default. You only need postcss config for custom plugins.");
105
+ }
106
+ async function copyTemplate(template, projectPath, useTypeScript) {
107
+ await copyDir(path.default.join(__dirname, "..", "templates", template), projectPath);
108
+ if (useTypeScript) {
109
+ const tsTemplatePath = path.default.join(__dirname, "..", "templates", "_typescript");
110
+ if (await dirExists(tsTemplatePath)) await copyDir(tsTemplatePath, projectPath);
111
+ }
112
+ }
113
+ async function copyDir(src, dest) {
114
+ await fs_promises.default.mkdir(dest, { recursive: true });
115
+ const entries = await fs_promises.default.readdir(src, { withFileTypes: true });
116
+ for (const entry of entries) {
117
+ const srcPath = path.default.join(src, entry.name);
118
+ const destinationName = entry.name === "gitignore" ? ".gitignore" : entry.name;
119
+ const destPath = path.default.join(dest, destinationName);
120
+ if (entry.isDirectory()) await copyDir(srcPath, destPath);
121
+ else await fs_promises.default.copyFile(srcPath, destPath);
122
+ }
123
+ }
124
+ async function dirExists(path$2) {
125
+ try {
126
+ return (await fs_promises.default.stat(path$2)).isDirectory();
127
+ } catch {
128
+ return false;
129
+ }
130
+ }
131
+ async function directoryHasFiles(dirPath) {
132
+ if (!await dirExists(dirPath)) return false;
133
+ return (await fs_promises.default.readdir(dirPath)).length > 0;
134
+ }
135
+ function validateProjectName(value) {
136
+ const trimmed = value.trim();
137
+ if (!trimmed) return "Project name is required";
138
+ if (!/^[a-z0-9._-]+$/i.test(trimmed)) return "Use letters, numbers, hyphens, underscores, or dots";
139
+ if (trimmed.startsWith(".") || trimmed.startsWith("_")) return "Project name cannot start with '.' or '_'";
140
+ return true;
141
+ }
142
+ function validateProjectPathArg(value) {
143
+ const trimmed = value.trim();
144
+ if (!trimmed) return "Project name is required";
145
+ const normalized = trimmed.replace(/[\\/]+$/, "");
146
+ const baseName = path.default.basename(normalized);
147
+ if (!baseName || baseName === "." || baseName === "..") return "Please provide a valid project directory name";
148
+ return validateProjectName(baseName);
149
+ }
150
+ function prettifyTemplateName(name) {
151
+ return name.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
152
+ }
153
+ async function getAvailableTemplates() {
154
+ const templatesRoot = path.default.join(__dirname, "..", "templates");
155
+ return (await fs_promises.default.readdir(templatesRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory() && !entry.name.startsWith("_")).map((entry) => entry.name).sort();
156
+ }
157
+ async function updatePackageJson(projectPath, projectName, packageManager) {
158
+ const packageJsonPath = path.default.join(projectPath, "package.json");
159
+ try {
160
+ const content = await fs_promises.default.readFile(packageJsonPath, "utf-8");
161
+ const packageJson = JSON.parse(content);
162
+ packageJson.name = projectName;
163
+ if (packageManager.version) packageJson.packageManager = `${packageManager.name}@${packageManager.version}`;
164
+ await fs_promises.default.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
165
+ } catch {
166
+ require_utils.logger.warn("Could not update package.json");
167
+ }
168
+ }
169
+ function detectPackageManager(userAgent = process.env.npm_config_user_agent) {
170
+ const match = userAgent?.match(/^(npm|pnpm|yarn|bun)\/([^\s]+)/);
171
+ if (!match) return { name: "pnpm" };
172
+ const [, name, version] = match;
173
+ return {
174
+ name,
175
+ version: version === "?" ? void 0 : version
176
+ };
177
+ }
178
+ function installDependencies(projectPath, packageManager) {
179
+ return new Promise((resolve, reject) => {
180
+ const command = process.platform === "win32" ? `${packageManager.name}.cmd` : packageManager.name;
181
+ const child = (0, node_child_process.spawn)(command, ["install"], {
182
+ cwd: projectPath,
183
+ env: process.env,
184
+ stdio: "inherit"
185
+ });
186
+ child.on("error", reject);
187
+ child.on("close", (code, signal) => {
188
+ if (code === 0) {
189
+ resolve();
190
+ return;
191
+ }
192
+ const reason = signal ? `signal ${signal}` : `exit code ${code ?? "unknown"}`;
193
+ reject(/* @__PURE__ */ new Error(`${packageManager.name} install failed with ${reason}.`));
194
+ });
195
+ });
196
+ }
197
+ function getDevCommand(packageManager) {
198
+ if (packageManager === "npm" || packageManager === "bun") return `${packageManager} run dev`;
199
+ return `${packageManager} dev`;
200
+ }
201
+ //#endregion
202
+ exports.createApp = createApp;
203
+ exports.detectPackageManager = detectPackageManager;
204
+ exports.installDependencies = installDependencies;
205
+
206
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["fs","path","spawn"],"sources":["../src/index.ts"],"sourcesContent":["import prompts from \"prompts\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { spawn } from \"node:child_process\";\nimport { logger, showBanner } from \"./utils\";\n\ninterface CreateAppOptions {\n template?: string;\n typescript?: boolean;\n skipInstall?: boolean;\n}\n\nexport type PackageManagerName = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport interface PackageManager {\n name: PackageManagerName;\n version?: string;\n}\n\nexport async function createApp(projectName?: string, options: CreateAppOptions = {}) {\n showBanner();\n\n const templates = await getAvailableTemplates();\n if (templates.length === 0) {\n logger.error(\"No templates are available in this package.\");\n process.exit(1);\n }\n\n // Get project name if not provided\n if (!projectName) {\n const response = await prompts({\n type: \"text\",\n name: \"projectName\",\n message: \"What is your project named?\",\n initial: \"my-farm-app\",\n validate: validateProjectName,\n });\n\n if (!response.projectName) {\n logger.error(\"Operation cancelled.\");\n process.exit(1);\n }\n\n projectName = response.projectName;\n } else {\n const validation = validateProjectPathArg(projectName);\n if (validation !== true) {\n logger.error(validation);\n process.exit(1);\n }\n }\n\n // Get template if not provided\n let template = options.template;\n if (!template) {\n const response = await prompts({\n type: \"select\",\n name: \"template\",\n message: \"Which template would you like to use?\",\n choices: templates.map((name) => ({\n title: prettifyTemplateName(name),\n value: name,\n description:\n name === \"basic\" ? \"A simple Farm.js app with built-in Tailwind support\" : undefined,\n })),\n initial: 0,\n });\n\n if (!response.template) {\n logger.error(\"Operation cancelled.\");\n process.exit(1);\n }\n template = response.template;\n } else if (!templates.includes(template)) {\n logger.error(\n `Unknown template \"${template}\". Available: ${templates.map((t) => `\"${t}\"`).join(\", \")}`,\n );\n process.exit(1);\n }\n\n // Check TypeScript preference\n let useTypeScript = options.typescript;\n if (useTypeScript === undefined) {\n const response = await prompts({\n type: \"confirm\",\n name: \"typescript\",\n message: \"Would you like to use TypeScript?\",\n initial: true,\n });\n\n if (response.typescript === undefined) {\n logger.error(\"Operation cancelled.\");\n process.exit(1);\n }\n useTypeScript = response.typescript;\n }\n\n const projectPath = path.resolve(process.cwd(), projectName!);\n const packageManager = detectPackageManager();\n const hasExistingFiles = await directoryHasFiles(projectPath);\n if (hasExistingFiles) {\n const overwriteResponse = await prompts({\n type: \"confirm\",\n name: \"overwrite\",\n message: `Directory \"${projectName}\" is not empty. Continue and overwrite conflicting files?`,\n initial: false,\n });\n\n if (!overwriteResponse.overwrite) {\n logger.error(\"Operation cancelled.\");\n process.exit(1);\n }\n }\n\n logger.info(`Creating Farm.js app in ${projectPath}`);\n\n await fs.mkdir(projectPath, { recursive: true });\n\n await copyTemplate(template!, projectPath, useTypeScript!);\n\n await updatePackageJson(projectPath, projectName!, packageManager);\n\n logger.success(`🚜 Created ${projectName}`);\n\n if (!options.skipInstall) {\n logger.info(`Installing dependencies with ${packageManager.name}...`);\n await installDependencies(projectPath, packageManager);\n logger.success(\"Dependencies installed\");\n }\n\n logger.info(\"\");\n logger.info(\"Next steps\");\n logger.info(` cd ${projectName}`);\n if (options.skipInstall) {\n logger.info(` ${packageManager.name} install`);\n }\n logger.info(` ${getDevCommand(packageManager.name)}`);\n logger.info(\"\");\n logger.info(\"Tailwind is enabled by default. You only need postcss config for custom plugins.\");\n}\n\nasync function copyTemplate(template: string, projectPath: string, useTypeScript: boolean) {\n const templatePath = path.join(__dirname, \"..\", \"templates\", template);\n\n // Copy base template files\n await copyDir(templatePath, projectPath);\n\n // If TypeScript is requested, copy TS-specific files\n if (useTypeScript) {\n const tsTemplatePath = path.join(__dirname, \"..\", \"templates\", \"_typescript\");\n if (await dirExists(tsTemplatePath)) {\n await copyDir(tsTemplatePath, projectPath);\n }\n }\n}\n\nasync function copyDir(src: string, dest: string) {\n await fs.mkdir(dest, { recursive: true });\n\n const entries = await fs.readdir(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n // npm excludes .gitignore files from published tarballs. Keep the template\n // file publishable and restore its dot when generating the application.\n const destinationName = entry.name === \"gitignore\" ? \".gitignore\" : entry.name;\n const destPath = path.join(dest, destinationName);\n\n if (entry.isDirectory()) {\n await copyDir(srcPath, destPath);\n } else {\n await fs.copyFile(srcPath, destPath);\n }\n }\n}\n\nasync function dirExists(path: string): Promise<boolean> {\n try {\n const stat = await fs.stat(path);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function directoryHasFiles(dirPath: string): Promise<boolean> {\n if (!(await dirExists(dirPath))) {\n return false;\n }\n const files = await fs.readdir(dirPath);\n return files.length > 0;\n}\n\nfunction validateProjectName(value: string): true | string {\n const trimmed = value.trim();\n if (!trimmed) {\n return \"Project name is required\";\n }\n\n // npm package-safe pattern\n if (!/^[a-z0-9._-]+$/i.test(trimmed)) {\n return \"Use letters, numbers, hyphens, underscores, or dots\";\n }\n\n if (trimmed.startsWith(\".\") || trimmed.startsWith(\"_\")) {\n return \"Project name cannot start with '.' or '_'\";\n }\n\n return true;\n}\n\nfunction validateProjectPathArg(value: string): true | string {\n const trimmed = value.trim();\n if (!trimmed) {\n return \"Project name is required\";\n }\n\n const normalized = trimmed.replace(/[\\\\/]+$/, \"\");\n const baseName = path.basename(normalized);\n if (!baseName || baseName === \".\" || baseName === \"..\") {\n return \"Please provide a valid project directory name\";\n }\n\n return validateProjectName(baseName);\n}\n\nfunction prettifyTemplateName(name: string): string {\n return name\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n\nasync function getAvailableTemplates(): Promise<string[]> {\n const templatesRoot = path.join(__dirname, \"..\", \"templates\");\n const entries = await fs.readdir(templatesRoot, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory() && !entry.name.startsWith(\"_\"))\n .map((entry) => entry.name)\n .sort();\n}\n\nasync function updatePackageJson(\n projectPath: string,\n projectName: string,\n packageManager: PackageManager,\n) {\n const packageJsonPath = path.join(projectPath, \"package.json\");\n\n try {\n const content = await fs.readFile(packageJsonPath, \"utf-8\");\n const packageJson = JSON.parse(content);\n\n packageJson.name = projectName;\n if (packageManager.version) {\n packageJson.packageManager = `${packageManager.name}@${packageManager.version}`;\n }\n\n await fs.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\\n`);\n } catch {\n logger.warn(\"Could not update package.json\");\n }\n}\n\nexport function detectPackageManager(\n userAgent = process.env.npm_config_user_agent,\n): PackageManager {\n const match = userAgent?.match(/^(npm|pnpm|yarn|bun)\\/([^\\s]+)/);\n if (!match) {\n return { name: \"pnpm\" };\n }\n\n const [, name, version] = match;\n return {\n name: name as PackageManagerName,\n version: version === \"?\" ? undefined : version,\n };\n}\n\nexport function installDependencies(\n projectPath: string,\n packageManager: PackageManager,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const command =\n process.platform === \"win32\" ? `${packageManager.name}.cmd` : packageManager.name;\n const child = spawn(command, [\"install\"], {\n cwd: projectPath,\n env: process.env,\n stdio: \"inherit\",\n });\n\n child.on(\"error\", reject);\n child.on(\"close\", (code, signal) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n const reason = signal ? `signal ${signal}` : `exit code ${code ?? \"unknown\"}`;\n reject(new Error(`${packageManager.name} install failed with ${reason}.`));\n });\n });\n}\n\nfunction getDevCommand(packageManager: PackageManagerName) {\n if (packageManager === \"npm\" || packageManager === \"bun\") {\n return `${packageManager} run dev`;\n }\n return `${packageManager} dev`;\n}\n"],"mappings":"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"}
package/dist/index.mjs ADDED
@@ -0,0 +1,199 @@
1
+ import { logger, showBanner } from "./utils.mjs";
2
+ import prompts from "prompts";
3
+ import path from "path";
4
+ import fs from "fs/promises";
5
+ import { spawn } from "node:child_process";
6
+ //#region src/index.ts
7
+ async function createApp(projectName, options = {}) {
8
+ showBanner();
9
+ const templates = await getAvailableTemplates();
10
+ if (templates.length === 0) {
11
+ logger.error("No templates are available in this package.");
12
+ process.exit(1);
13
+ }
14
+ if (!projectName) {
15
+ const response = await prompts({
16
+ type: "text",
17
+ name: "projectName",
18
+ message: "What is your project named?",
19
+ initial: "my-farm-app",
20
+ validate: validateProjectName
21
+ });
22
+ if (!response.projectName) {
23
+ logger.error("Operation cancelled.");
24
+ process.exit(1);
25
+ }
26
+ projectName = response.projectName;
27
+ } else {
28
+ const validation = validateProjectPathArg(projectName);
29
+ if (validation !== true) {
30
+ logger.error(validation);
31
+ process.exit(1);
32
+ }
33
+ }
34
+ let template = options.template;
35
+ if (!template) {
36
+ const response = await prompts({
37
+ type: "select",
38
+ name: "template",
39
+ message: "Which template would you like to use?",
40
+ choices: templates.map((name) => ({
41
+ title: prettifyTemplateName(name),
42
+ value: name,
43
+ description: name === "basic" ? "A simple Farm.js app with built-in Tailwind support" : void 0
44
+ })),
45
+ initial: 0
46
+ });
47
+ if (!response.template) {
48
+ logger.error("Operation cancelled.");
49
+ process.exit(1);
50
+ }
51
+ template = response.template;
52
+ } else if (!templates.includes(template)) {
53
+ logger.error(`Unknown template "${template}". Available: ${templates.map((t) => `"${t}"`).join(", ")}`);
54
+ process.exit(1);
55
+ }
56
+ let useTypeScript = options.typescript;
57
+ if (useTypeScript === void 0) {
58
+ const response = await prompts({
59
+ type: "confirm",
60
+ name: "typescript",
61
+ message: "Would you like to use TypeScript?",
62
+ initial: true
63
+ });
64
+ if (response.typescript === void 0) {
65
+ logger.error("Operation cancelled.");
66
+ process.exit(1);
67
+ }
68
+ useTypeScript = response.typescript;
69
+ }
70
+ const projectPath = path.resolve(process.cwd(), projectName);
71
+ const packageManager = detectPackageManager();
72
+ if (await directoryHasFiles(projectPath)) {
73
+ if (!(await prompts({
74
+ type: "confirm",
75
+ name: "overwrite",
76
+ message: `Directory "${projectName}" is not empty. Continue and overwrite conflicting files?`,
77
+ initial: false
78
+ })).overwrite) {
79
+ logger.error("Operation cancelled.");
80
+ process.exit(1);
81
+ }
82
+ }
83
+ logger.info(`Creating Farm.js app in ${projectPath}`);
84
+ await fs.mkdir(projectPath, { recursive: true });
85
+ await copyTemplate(template, projectPath, useTypeScript);
86
+ await updatePackageJson(projectPath, projectName, packageManager);
87
+ logger.success(`🚜 Created ${projectName}`);
88
+ if (!options.skipInstall) {
89
+ logger.info(`Installing dependencies with ${packageManager.name}...`);
90
+ await installDependencies(projectPath, packageManager);
91
+ logger.success("Dependencies installed");
92
+ }
93
+ logger.info("");
94
+ logger.info("Next steps");
95
+ logger.info(` cd ${projectName}`);
96
+ if (options.skipInstall) logger.info(` ${packageManager.name} install`);
97
+ logger.info(` ${getDevCommand(packageManager.name)}`);
98
+ logger.info("");
99
+ logger.info("Tailwind is enabled by default. You only need postcss config for custom plugins.");
100
+ }
101
+ async function copyTemplate(template, projectPath, useTypeScript) {
102
+ await copyDir(path.join(__dirname, "..", "templates", template), projectPath);
103
+ if (useTypeScript) {
104
+ const tsTemplatePath = path.join(__dirname, "..", "templates", "_typescript");
105
+ if (await dirExists(tsTemplatePath)) await copyDir(tsTemplatePath, projectPath);
106
+ }
107
+ }
108
+ async function copyDir(src, dest) {
109
+ await fs.mkdir(dest, { recursive: true });
110
+ const entries = await fs.readdir(src, { withFileTypes: true });
111
+ for (const entry of entries) {
112
+ const srcPath = path.join(src, entry.name);
113
+ const destinationName = entry.name === "gitignore" ? ".gitignore" : entry.name;
114
+ const destPath = path.join(dest, destinationName);
115
+ if (entry.isDirectory()) await copyDir(srcPath, destPath);
116
+ else await fs.copyFile(srcPath, destPath);
117
+ }
118
+ }
119
+ async function dirExists(path) {
120
+ try {
121
+ return (await fs.stat(path)).isDirectory();
122
+ } catch {
123
+ return false;
124
+ }
125
+ }
126
+ async function directoryHasFiles(dirPath) {
127
+ if (!await dirExists(dirPath)) return false;
128
+ return (await fs.readdir(dirPath)).length > 0;
129
+ }
130
+ function validateProjectName(value) {
131
+ const trimmed = value.trim();
132
+ if (!trimmed) return "Project name is required";
133
+ if (!/^[a-z0-9._-]+$/i.test(trimmed)) return "Use letters, numbers, hyphens, underscores, or dots";
134
+ if (trimmed.startsWith(".") || trimmed.startsWith("_")) return "Project name cannot start with '.' or '_'";
135
+ return true;
136
+ }
137
+ function validateProjectPathArg(value) {
138
+ const trimmed = value.trim();
139
+ if (!trimmed) return "Project name is required";
140
+ const normalized = trimmed.replace(/[\\/]+$/, "");
141
+ const baseName = path.basename(normalized);
142
+ if (!baseName || baseName === "." || baseName === "..") return "Please provide a valid project directory name";
143
+ return validateProjectName(baseName);
144
+ }
145
+ function prettifyTemplateName(name) {
146
+ return name.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
147
+ }
148
+ async function getAvailableTemplates() {
149
+ const templatesRoot = path.join(__dirname, "..", "templates");
150
+ return (await fs.readdir(templatesRoot, { withFileTypes: true })).filter((entry) => entry.isDirectory() && !entry.name.startsWith("_")).map((entry) => entry.name).sort();
151
+ }
152
+ async function updatePackageJson(projectPath, projectName, packageManager) {
153
+ const packageJsonPath = path.join(projectPath, "package.json");
154
+ try {
155
+ const content = await fs.readFile(packageJsonPath, "utf-8");
156
+ const packageJson = JSON.parse(content);
157
+ packageJson.name = projectName;
158
+ if (packageManager.version) packageJson.packageManager = `${packageManager.name}@${packageManager.version}`;
159
+ await fs.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
160
+ } catch {
161
+ logger.warn("Could not update package.json");
162
+ }
163
+ }
164
+ function detectPackageManager(userAgent = process.env.npm_config_user_agent) {
165
+ const match = userAgent?.match(/^(npm|pnpm|yarn|bun)\/([^\s]+)/);
166
+ if (!match) return { name: "pnpm" };
167
+ const [, name, version] = match;
168
+ return {
169
+ name,
170
+ version: version === "?" ? void 0 : version
171
+ };
172
+ }
173
+ function installDependencies(projectPath, packageManager) {
174
+ return new Promise((resolve, reject) => {
175
+ const command = process.platform === "win32" ? `${packageManager.name}.cmd` : packageManager.name;
176
+ const child = spawn(command, ["install"], {
177
+ cwd: projectPath,
178
+ env: process.env,
179
+ stdio: "inherit"
180
+ });
181
+ child.on("error", reject);
182
+ child.on("close", (code, signal) => {
183
+ if (code === 0) {
184
+ resolve();
185
+ return;
186
+ }
187
+ const reason = signal ? `signal ${signal}` : `exit code ${code ?? "unknown"}`;
188
+ reject(/* @__PURE__ */ new Error(`${packageManager.name} install failed with ${reason}.`));
189
+ });
190
+ });
191
+ }
192
+ function getDevCommand(packageManager) {
193
+ if (packageManager === "npm" || packageManager === "bun") return `${packageManager} run dev`;
194
+ return `${packageManager} dev`;
195
+ }
196
+ //#endregion
197
+ export { createApp, detectPackageManager, installDependencies };
198
+
199
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import prompts from \"prompts\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { spawn } from \"node:child_process\";\nimport { logger, showBanner } from \"./utils\";\n\ninterface CreateAppOptions {\n template?: string;\n typescript?: boolean;\n skipInstall?: boolean;\n}\n\nexport type PackageManagerName = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport interface PackageManager {\n name: PackageManagerName;\n version?: string;\n}\n\nexport async function createApp(projectName?: string, options: CreateAppOptions = {}) {\n showBanner();\n\n const templates = await getAvailableTemplates();\n if (templates.length === 0) {\n logger.error(\"No templates are available in this package.\");\n process.exit(1);\n }\n\n // Get project name if not provided\n if (!projectName) {\n const response = await prompts({\n type: \"text\",\n name: \"projectName\",\n message: \"What is your project named?\",\n initial: \"my-farm-app\",\n validate: validateProjectName,\n });\n\n if (!response.projectName) {\n logger.error(\"Operation cancelled.\");\n process.exit(1);\n }\n\n projectName = response.projectName;\n } else {\n const validation = validateProjectPathArg(projectName);\n if (validation !== true) {\n logger.error(validation);\n process.exit(1);\n }\n }\n\n // Get template if not provided\n let template = options.template;\n if (!template) {\n const response = await prompts({\n type: \"select\",\n name: \"template\",\n message: \"Which template would you like to use?\",\n choices: templates.map((name) => ({\n title: prettifyTemplateName(name),\n value: name,\n description:\n name === \"basic\" ? \"A simple Farm.js app with built-in Tailwind support\" : undefined,\n })),\n initial: 0,\n });\n\n if (!response.template) {\n logger.error(\"Operation cancelled.\");\n process.exit(1);\n }\n template = response.template;\n } else if (!templates.includes(template)) {\n logger.error(\n `Unknown template \"${template}\". Available: ${templates.map((t) => `\"${t}\"`).join(\", \")}`,\n );\n process.exit(1);\n }\n\n // Check TypeScript preference\n let useTypeScript = options.typescript;\n if (useTypeScript === undefined) {\n const response = await prompts({\n type: \"confirm\",\n name: \"typescript\",\n message: \"Would you like to use TypeScript?\",\n initial: true,\n });\n\n if (response.typescript === undefined) {\n logger.error(\"Operation cancelled.\");\n process.exit(1);\n }\n useTypeScript = response.typescript;\n }\n\n const projectPath = path.resolve(process.cwd(), projectName!);\n const packageManager = detectPackageManager();\n const hasExistingFiles = await directoryHasFiles(projectPath);\n if (hasExistingFiles) {\n const overwriteResponse = await prompts({\n type: \"confirm\",\n name: \"overwrite\",\n message: `Directory \"${projectName}\" is not empty. Continue and overwrite conflicting files?`,\n initial: false,\n });\n\n if (!overwriteResponse.overwrite) {\n logger.error(\"Operation cancelled.\");\n process.exit(1);\n }\n }\n\n logger.info(`Creating Farm.js app in ${projectPath}`);\n\n await fs.mkdir(projectPath, { recursive: true });\n\n await copyTemplate(template!, projectPath, useTypeScript!);\n\n await updatePackageJson(projectPath, projectName!, packageManager);\n\n logger.success(`🚜 Created ${projectName}`);\n\n if (!options.skipInstall) {\n logger.info(`Installing dependencies with ${packageManager.name}...`);\n await installDependencies(projectPath, packageManager);\n logger.success(\"Dependencies installed\");\n }\n\n logger.info(\"\");\n logger.info(\"Next steps\");\n logger.info(` cd ${projectName}`);\n if (options.skipInstall) {\n logger.info(` ${packageManager.name} install`);\n }\n logger.info(` ${getDevCommand(packageManager.name)}`);\n logger.info(\"\");\n logger.info(\"Tailwind is enabled by default. You only need postcss config for custom plugins.\");\n}\n\nasync function copyTemplate(template: string, projectPath: string, useTypeScript: boolean) {\n const templatePath = path.join(__dirname, \"..\", \"templates\", template);\n\n // Copy base template files\n await copyDir(templatePath, projectPath);\n\n // If TypeScript is requested, copy TS-specific files\n if (useTypeScript) {\n const tsTemplatePath = path.join(__dirname, \"..\", \"templates\", \"_typescript\");\n if (await dirExists(tsTemplatePath)) {\n await copyDir(tsTemplatePath, projectPath);\n }\n }\n}\n\nasync function copyDir(src: string, dest: string) {\n await fs.mkdir(dest, { recursive: true });\n\n const entries = await fs.readdir(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n // npm excludes .gitignore files from published tarballs. Keep the template\n // file publishable and restore its dot when generating the application.\n const destinationName = entry.name === \"gitignore\" ? \".gitignore\" : entry.name;\n const destPath = path.join(dest, destinationName);\n\n if (entry.isDirectory()) {\n await copyDir(srcPath, destPath);\n } else {\n await fs.copyFile(srcPath, destPath);\n }\n }\n}\n\nasync function dirExists(path: string): Promise<boolean> {\n try {\n const stat = await fs.stat(path);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function directoryHasFiles(dirPath: string): Promise<boolean> {\n if (!(await dirExists(dirPath))) {\n return false;\n }\n const files = await fs.readdir(dirPath);\n return files.length > 0;\n}\n\nfunction validateProjectName(value: string): true | string {\n const trimmed = value.trim();\n if (!trimmed) {\n return \"Project name is required\";\n }\n\n // npm package-safe pattern\n if (!/^[a-z0-9._-]+$/i.test(trimmed)) {\n return \"Use letters, numbers, hyphens, underscores, or dots\";\n }\n\n if (trimmed.startsWith(\".\") || trimmed.startsWith(\"_\")) {\n return \"Project name cannot start with '.' or '_'\";\n }\n\n return true;\n}\n\nfunction validateProjectPathArg(value: string): true | string {\n const trimmed = value.trim();\n if (!trimmed) {\n return \"Project name is required\";\n }\n\n const normalized = trimmed.replace(/[\\\\/]+$/, \"\");\n const baseName = path.basename(normalized);\n if (!baseName || baseName === \".\" || baseName === \"..\") {\n return \"Please provide a valid project directory name\";\n }\n\n return validateProjectName(baseName);\n}\n\nfunction prettifyTemplateName(name: string): string {\n return name\n .split(\"-\")\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n\nasync function getAvailableTemplates(): Promise<string[]> {\n const templatesRoot = path.join(__dirname, \"..\", \"templates\");\n const entries = await fs.readdir(templatesRoot, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory() && !entry.name.startsWith(\"_\"))\n .map((entry) => entry.name)\n .sort();\n}\n\nasync function updatePackageJson(\n projectPath: string,\n projectName: string,\n packageManager: PackageManager,\n) {\n const packageJsonPath = path.join(projectPath, \"package.json\");\n\n try {\n const content = await fs.readFile(packageJsonPath, \"utf-8\");\n const packageJson = JSON.parse(content);\n\n packageJson.name = projectName;\n if (packageManager.version) {\n packageJson.packageManager = `${packageManager.name}@${packageManager.version}`;\n }\n\n await fs.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\\n`);\n } catch {\n logger.warn(\"Could not update package.json\");\n }\n}\n\nexport function detectPackageManager(\n userAgent = process.env.npm_config_user_agent,\n): PackageManager {\n const match = userAgent?.match(/^(npm|pnpm|yarn|bun)\\/([^\\s]+)/);\n if (!match) {\n return { name: \"pnpm\" };\n }\n\n const [, name, version] = match;\n return {\n name: name as PackageManagerName,\n version: version === \"?\" ? undefined : version,\n };\n}\n\nexport function installDependencies(\n projectPath: string,\n packageManager: PackageManager,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const command =\n process.platform === \"win32\" ? `${packageManager.name}.cmd` : packageManager.name;\n const child = spawn(command, [\"install\"], {\n cwd: projectPath,\n env: process.env,\n stdio: \"inherit\",\n });\n\n child.on(\"error\", reject);\n child.on(\"close\", (code, signal) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n const reason = signal ? `signal ${signal}` : `exit code ${code ?? \"unknown\"}`;\n reject(new Error(`${packageManager.name} install failed with ${reason}.`));\n });\n });\n}\n\nfunction getDevCommand(packageManager: PackageManagerName) {\n if (packageManager === \"npm\" || packageManager === \"bun\") {\n return `${packageManager} run dev`;\n }\n return `${packageManager} dev`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ Object.defineProperty(exports, "__toESM", {
24
+ enumerable: true,
25
+ get: function() {
26
+ return __toESM;
27
+ }
28
+ });
package/dist/utils.js ADDED
@@ -0,0 +1,29 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.js");
3
+ let picocolors = require("picocolors");
4
+ picocolors = require_rolldown_runtime.__toESM(picocolors);
5
+ //#region src/utils.ts
6
+ const logger = {
7
+ info: (message) => console.log(`${picocolors.default.blue("ℹ")} ${message}`),
8
+ success: (message) => console.log(`${picocolors.default.green("✓")} ${message}`),
9
+ warn: (message) => console.warn(`${picocolors.default.yellow("⚠")} ${message}`),
10
+ error: (message) => console.error(`${picocolors.default.red("✗")} ${message}`)
11
+ };
12
+ function showBanner() {
13
+ const art = [
14
+ " _______ ",
15
+ "| ___ |__ _ _ __ _ __ ___ ",
16
+ "| |_ /| / _` | '__| '_ ` _ \\ ",
17
+ "| _ \\| | (_| | | | | | | | | ",
18
+ "|_| \\_\\_|\\__,_|_| |_| |_| |_|"
19
+ ];
20
+ console.log("");
21
+ for (const line of art) console.log(picocolors.default.cyan(line));
22
+ console.log(picocolors.default.bold(picocolors.default.green("Create Farm.js App")) + picocolors.default.dim(" modern React meta-framework"));
23
+ console.log("");
24
+ }
25
+ //#endregion
26
+ exports.logger = logger;
27
+ exports.showBanner = showBanner;
28
+
29
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","names":["pc"],"sources":["../src/utils.ts"],"sourcesContent":["import pc from \"picocolors\";\n\nexport const logger = {\n info: (message: string) => console.log(`${pc.blue(\"ℹ\")} ${message}`),\n success: (message: string) => console.log(`${pc.green(\"✓\")} ${message}`),\n warn: (message: string) => console.warn(`${pc.yellow(\"⚠\")} ${message}`),\n error: (message: string) => console.error(`${pc.red(\"✗\")} ${message}`),\n};\n\nexport function showBanner() {\n const art = [\n \" _______ \",\n \"| ___ |__ _ _ __ _ __ ___ \",\n \"| |_ /| / _` | '__| '_ ` _ \\\\ \",\n \"| _ \\\\| | (_| | | | | | | | | \",\n \"|_| \\\\_\\\\_|\\\\__,_|_| |_| |_| |_|\",\n ];\n\n console.log(\"\");\n for (const line of art) {\n console.log(pc.cyan(line));\n }\n console.log(pc.bold(pc.green(\"Create Farm.js App\")) + pc.dim(\" modern React meta-framework\"));\n console.log(\"\");\n}\n"],"mappings":";;;;;AAEA,MAAa,SAAS;CACpB,OAAO,YAAoB,QAAQ,IAAI,GAAGA,WAAAA,QAAG,KAAK,GAAG,EAAE,GAAG,SAAS;CACnE,UAAU,YAAoB,QAAQ,IAAI,GAAGA,WAAAA,QAAG,MAAM,GAAG,EAAE,GAAG,SAAS;CACvE,OAAO,YAAoB,QAAQ,KAAK,GAAGA,WAAAA,QAAG,OAAO,GAAG,EAAE,GAAG,SAAS;CACtE,QAAQ,YAAoB,QAAQ,MAAM,GAAGA,WAAAA,QAAG,IAAI,GAAG,EAAE,GAAG,SAAS;AACvE;AAEA,SAAgB,aAAa;CAC3B,MAAM,MAAM;EACV;EACA;EACA;EACA;EACA;CACF;CAEA,QAAQ,IAAI,EAAE;CACd,KAAK,MAAM,QAAQ,KACjB,QAAQ,IAAIA,WAAAA,QAAG,KAAK,IAAI,CAAC;CAE3B,QAAQ,IAAIA,WAAAA,QAAG,KAAKA,WAAAA,QAAG,MAAM,oBAAoB,CAAC,IAAIA,WAAAA,QAAG,IAAI,+BAA+B,CAAC;CAC7F,QAAQ,IAAI,EAAE;AAChB"}
package/dist/utils.mjs ADDED
@@ -0,0 +1,25 @@
1
+ import pc from "picocolors";
2
+ //#region src/utils.ts
3
+ const logger = {
4
+ info: (message) => console.log(`${pc.blue("ℹ")} ${message}`),
5
+ success: (message) => console.log(`${pc.green("✓")} ${message}`),
6
+ warn: (message) => console.warn(`${pc.yellow("⚠")} ${message}`),
7
+ error: (message) => console.error(`${pc.red("✗")} ${message}`)
8
+ };
9
+ function showBanner() {
10
+ const art = [
11
+ " _______ ",
12
+ "| ___ |__ _ _ __ _ __ ___ ",
13
+ "| |_ /| / _` | '__| '_ ` _ \\ ",
14
+ "| _ \\| | (_| | | | | | | | | ",
15
+ "|_| \\_\\_|\\__,_|_| |_| |_| |_|"
16
+ ];
17
+ console.log("");
18
+ for (const line of art) console.log(pc.cyan(line));
19
+ console.log(pc.bold(pc.green("Create Farm.js App")) + pc.dim(" modern React meta-framework"));
20
+ console.log("");
21
+ }
22
+ //#endregion
23
+ export { logger, showBanner };
24
+
25
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import pc from \"picocolors\";\n\nexport const logger = {\n info: (message: string) => console.log(`${pc.blue(\"ℹ\")} ${message}`),\n success: (message: string) => console.log(`${pc.green(\"✓\")} ${message}`),\n warn: (message: string) => console.warn(`${pc.yellow(\"⚠\")} ${message}`),\n error: (message: string) => console.error(`${pc.red(\"✗\")} ${message}`),\n};\n\nexport function showBanner() {\n const art = [\n \" _______ \",\n \"| ___ |__ _ _ __ _ __ ___ \",\n \"| |_ /| / _` | '__| '_ ` _ \\\\ \",\n \"| _ \\\\| | (_| | | | | | | | | \",\n \"|_| \\\\_\\\\_|\\\\__,_|_| |_| |_| |_|\",\n ];\n\n console.log(\"\");\n for (const line of art) {\n console.log(pc.cyan(line));\n }\n console.log(pc.bold(pc.green(\"Create Farm.js App\")) + pc.dim(\" modern React meta-framework\"));\n console.log(\"\");\n}\n"],"mappings":";;AAEA,MAAa,SAAS;CACpB,OAAO,YAAoB,QAAQ,IAAI,GAAG,GAAG,KAAK,GAAG,EAAE,GAAG,SAAS;CACnE,UAAU,YAAoB,QAAQ,IAAI,GAAG,GAAG,MAAM,GAAG,EAAE,GAAG,SAAS;CACvE,OAAO,YAAoB,QAAQ,KAAK,GAAG,GAAG,OAAO,GAAG,EAAE,GAAG,SAAS;CACtE,QAAQ,YAAoB,QAAQ,MAAM,GAAG,GAAG,IAAI,GAAG,EAAE,GAAG,SAAS;AACvE;AAEA,SAAgB,aAAa;CAC3B,MAAM,MAAM;EACV;EACA;EACA;EACA;EACA;CACF;CAEA,QAAQ,IAAI,EAAE;CACd,KAAK,MAAM,QAAQ,KACjB,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC;CAE3B,QAAQ,IAAI,GAAG,KAAK,GAAG,MAAM,oBAAoB,CAAC,IAAI,GAAG,IAAI,+BAA+B,CAAC;CAC7F,QAAQ,IAAI,EAAE;AAChB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farm.js/create-app",
3
- "version": "0.1.0-beta.6",
3
+ "version": "0.1.0-beta.7",
4
4
  "description": "Create a new Farm.js application",
5
5
  "keywords": [
6
6
  "@farm.js/create-app",
@@ -0,0 +1,23 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Farm and deployment output
5
+ .farm/
6
+ .output/
7
+ .vercel/
8
+ dist/
9
+
10
+ # Local environment files
11
+ .env
12
+ .env.local
13
+ .env.*.local
14
+
15
+ # Local databases
16
+ *.sqlite
17
+ *.sqlite-*
18
+ *.db
19
+ *.db-*
20
+
21
+ # Logs and TypeScript cache
22
+ *.log
23
+ *.tsbuildinfo
@@ -10,12 +10,12 @@
10
10
  "type-check": "tsc --noEmit"
11
11
  },
12
12
  "dependencies": {
13
- "@farm.js/core": "0.1.0-beta.6",
13
+ "@farm.js/core": "0.1.0-beta.7",
14
14
  "react": "^19.0.0",
15
15
  "react-dom": "^19.0.0"
16
16
  },
17
17
  "devDependencies": {
18
- "@farm.js/cli": "0.1.0-beta.6",
18
+ "@farm.js/cli": "0.1.0-beta.7",
19
19
  "@types/react": "^19.0.0",
20
20
  "@types/react-dom": "^19.0.0",
21
21
  "tailwindcss": "^4.0.0",
@@ -1,59 +0,0 @@
1
- // Generated by Farm.js. Do not edit.
2
- declare module "*.avif" {
3
- const image: import("@farm.js/core/image").StaticImageData;
4
- export const src: string;
5
- export const width: number;
6
- export const height: number;
7
- export const blurDataURL: string | undefined;
8
- export default image;
9
- }
10
-
11
- declare module "*.gif" {
12
- const image: import("@farm.js/core/image").StaticImageData;
13
- export const src: string;
14
- export const width: number;
15
- export const height: number;
16
- export const blurDataURL: string | undefined;
17
- export default image;
18
- }
19
-
20
- declare module "*.jpeg" {
21
- const image: import("@farm.js/core/image").StaticImageData;
22
- export const src: string;
23
- export const width: number;
24
- export const height: number;
25
- export const blurDataURL: string | undefined;
26
- export default image;
27
- }
28
-
29
- declare module "*.jpg" {
30
- const image: import("@farm.js/core/image").StaticImageData;
31
- export const src: string;
32
- export const width: number;
33
- export const height: number;
34
- export const blurDataURL: string | undefined;
35
- export default image;
36
- }
37
-
38
- declare module "*.png" {
39
- const image: import("@farm.js/core/image").StaticImageData;
40
- export const src: string;
41
- export const width: number;
42
- export const height: number;
43
- export const blurDataURL: string | undefined;
44
- export default image;
45
- }
46
-
47
- declare module "*.webp" {
48
- const image: import("@farm.js/core/image").StaticImageData;
49
- export const src: string;
50
- export const width: number;
51
- export const height: number;
52
- export const blurDataURL: string | undefined;
53
- export default image;
54
- }
55
-
56
- declare module "*?url" {
57
- const src: string;
58
- export default src;
59
- }