craft-native 0.0.37 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/android/src/index.js +268 -0
- package/dist/android/src/index.js.map +10 -0
- package/dist/android/templates/AndroidManifest.xml.template +69 -0
- package/dist/android/templates/CraftBridge.kt.template +3748 -0
- package/dist/android/templates/CraftBridgeExtensions.kt.template +383 -0
- package/dist/android/templates/CraftWidgetProvider.kt.template +246 -0
- package/dist/android/templates/MainActivity.kt.template +109 -0
- package/dist/android/templates/build.gradle.kts.app.template +80 -0
- package/dist/android/templates/build.gradle.kts.project.template +5 -0
- package/dist/android/templates/fastlane/Appfile +25 -0
- package/dist/android/templates/fastlane/Fastfile +192 -0
- package/dist/android/templates/fastlane/Gemfile +7 -0
- package/dist/android/templates/github-workflow-android.yml +248 -0
- package/dist/android/templates/github-workflow-test.yml +329 -0
- package/dist/android/templates/settings.gradle.kts.template +18 -0
- package/dist/android/templates/test-bridges.html +1463 -0
- package/dist/api/window.d.ts +18 -0
- package/dist/api/window.d.ts.map +1 -1
- package/dist/assets/index.d.ts.map +1 -1
- package/dist/bridge/core.d.ts +2 -0
- package/dist/bridge/core.d.ts.map +1 -1
- package/dist/cli.js +4168 -0
- package/dist/components/sidebar.d.ts +5 -1
- package/dist/components/sidebar.d.ts.map +1 -1
- package/dist/dev/devtools.d.ts +1 -1
- package/dist/dev/devtools.d.ts.map +1 -1
- package/dist/dev/hot-reload.d.ts +12 -3
- package/dist/dev/hot-reload.d.ts.map +1 -1
- package/dist/index.cjs +573 -208
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +585 -216
- package/dist/index.js.map +45 -0
- package/dist/ios/src/index.js +186 -0
- package/dist/ios/src/index.js.map +10 -0
- package/dist/ios/templates/CraftApp.swift +4241 -0
- package/dist/ios/templates/CraftAppExtensions.swift +361 -0
- package/dist/ios/templates/CraftWidget.swift +247 -0
- package/dist/ios/templates/Info.plist.template +65 -0
- package/dist/ios/templates/fastlane/Appfile +45 -0
- package/dist/ios/templates/fastlane/Fastfile +189 -0
- package/dist/ios/templates/fastlane/Gemfile +7 -0
- package/dist/ios/templates/fastlane/Matchfile +58 -0
- package/dist/ios/templates/github-workflow-ios.yml +192 -0
- package/dist/ios/templates/github-workflow-release.yml +175 -0
- package/dist/ios/templates/github-workflow-test.yml +272 -0
- package/dist/ios/templates/project.yml.template +25 -0
- package/dist/ios/templates/test-bridges.html +1463 -0
- package/dist/package.d.ts +106 -2
- package/dist/package.d.ts.map +1 -1
- package/dist/package.test.d.ts +2 -0
- package/dist/package.test.d.ts.map +1 -0
- package/dist/styles/sidebar-templates.d.ts.map +1 -1
- package/dist/styles/sidebars.d.ts +12 -8
- package/dist/styles/sidebars.d.ts.map +1 -1
- package/dist/templates/projects/blank/craft.config.ts +19 -0
- package/dist/templates/projects/blank/index.html +27 -0
- package/dist/templates/projects/blank/package.json +19 -0
- package/dist/templates/projects/blank/src/main.ts +26 -0
- package/dist/templates/projects/dashboard/craft.config.ts +42 -0
- package/dist/templates/projects/dashboard/index.html +13 -0
- package/dist/templates/projects/dashboard/package.json +20 -0
- package/dist/templates/projects/dashboard/src/main.ts +163 -0
- package/dist/templates/projects/dashboard/src/styles.css +280 -0
- package/dist/templates/projects/drawer/craft.config.ts +47 -0
- package/dist/templates/projects/drawer/index.html +13 -0
- package/dist/templates/projects/drawer/package.json +21 -0
- package/dist/templates/projects/drawer/src/main.ts +406 -0
- package/dist/templates/projects/drawer/src/styles.css +468 -0
- package/dist/templates/projects/ecommerce/craft.config.ts +32 -0
- package/dist/templates/projects/ecommerce/index.html +13 -0
- package/dist/templates/projects/ecommerce/package.json +19 -0
- package/dist/templates/projects/ecommerce/src/main.ts +194 -0
- package/dist/templates/projects/ecommerce/src/styles.css +169 -0
- package/dist/templates/projects/social/craft.config.ts +32 -0
- package/dist/templates/projects/social/index.html +13 -0
- package/dist/templates/projects/social/package.json +19 -0
- package/dist/templates/projects/social/src/main.ts +270 -0
- package/dist/templates/projects/social/src/styles.css +216 -0
- package/dist/templates/projects/tabs/craft.config.ts +47 -0
- package/dist/templates/projects/tabs/index.html +13 -0
- package/dist/templates/projects/tabs/package.json +21 -0
- package/dist/templates/projects/tabs/src/main.ts +177 -0
- package/dist/templates/projects/tabs/src/styles.css +163 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/updater/index.d.ts +1 -0
- package/dist/updater/index.d.ts.map +1 -1
- package/package.json +5 -12
- package/bin/cli.ts +0 -937
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// ../ios/src/index.ts
|
|
3
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from "fs";
|
|
4
|
+
import { join, dirname } from "path";
|
|
5
|
+
var {$ } = globalThis.Bun;
|
|
6
|
+
var TEMPLATES_DIR = join(dirname(import.meta.dir), "templates");
|
|
7
|
+
async function init(options) {
|
|
8
|
+
const { name, bundleId, teamId, output } = options;
|
|
9
|
+
console.log(`
|
|
10
|
+
\u26A1 Initializing Craft iOS project: ${name}`);
|
|
11
|
+
console.log(` Output: ${output}
|
|
12
|
+
`);
|
|
13
|
+
const dirs = [output, join(output, "Sources"), join(output, "dist")];
|
|
14
|
+
for (const dir of dirs) {
|
|
15
|
+
if (!existsSync(dir)) {
|
|
16
|
+
mkdirSync(dir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const finalBundleId = bundleId || `com.craft.${name.toLowerCase().replace(/[^a-z0-9]/g, "")}`;
|
|
20
|
+
const bundleIdPrefix = finalBundleId.split(".").slice(0, -1).join(".");
|
|
21
|
+
const config = {
|
|
22
|
+
appName: name,
|
|
23
|
+
bundleId: finalBundleId,
|
|
24
|
+
version: "1.0.0",
|
|
25
|
+
buildNumber: "1",
|
|
26
|
+
darkMode: true,
|
|
27
|
+
backgroundColor: "#1a1a2e",
|
|
28
|
+
enableSpeechRecognition: true,
|
|
29
|
+
enableHaptics: true,
|
|
30
|
+
enableShare: true,
|
|
31
|
+
iosVersion: "15.0",
|
|
32
|
+
teamId: teamId || ""
|
|
33
|
+
};
|
|
34
|
+
writeFileSync(join(output, "craft.config.json"), JSON.stringify(config, null, 2));
|
|
35
|
+
const swiftTemplate = readFileSync(join(TEMPLATES_DIR, "CraftApp.swift"), "utf-8");
|
|
36
|
+
writeFileSync(join(output, "Sources", `${name}App.swift`), swiftTemplate.replace(/CraftApp/g, `${name}App`));
|
|
37
|
+
const infoPlistTemplate = readFileSync(join(TEMPLATES_DIR, "Info.plist.template"), "utf-8");
|
|
38
|
+
const infoPlist = infoPlistTemplate.replace(/\{\{APP_NAME\}\}/g, name).replace(/\{\{BUNDLE_ID\}\}/g, finalBundleId).replace(/\{\{VERSION\}\}/g, config.version || "1.0.0").replace(/\{\{BUILD_NUMBER\}\}/g, config.buildNumber || "1").replace(/\{\{UI_STYLE\}\}/g, config.darkMode ? "Dark" : "Light");
|
|
39
|
+
writeFileSync(join(output, "Info.plist"), infoPlist);
|
|
40
|
+
const projectYmlTemplate = readFileSync(join(TEMPLATES_DIR, "project.yml.template"), "utf-8");
|
|
41
|
+
const projectYml = projectYmlTemplate.replace(/\{\{APP_NAME\}\}/g, name).replace(/\{\{BUNDLE_ID\}\}/g, finalBundleId).replace(/\{\{BUNDLE_ID_PREFIX\}\}/g, bundleIdPrefix).replace(/\{\{VERSION\}\}/g, config.version || "1.0.0").replace(/\{\{BUILD_NUMBER\}\}/g, config.buildNumber || "1").replace(/\{\{IOS_VERSION\}\}/g, config.iosVersion || "15.0").replace(/\{\{TEAM_ID\}\}/g, teamId || "");
|
|
42
|
+
writeFileSync(join(output, "project.yml"), projectYml);
|
|
43
|
+
const placeholderHtml = `<!DOCTYPE html>
|
|
44
|
+
<html>
|
|
45
|
+
<head>
|
|
46
|
+
<meta charset="UTF-8">
|
|
47
|
+
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
48
|
+
<title>${name}</title>
|
|
49
|
+
<style>
|
|
50
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
51
|
+
body {
|
|
52
|
+
font-family: -apple-system, system-ui, sans-serif;
|
|
53
|
+
background: ${config.backgroundColor};
|
|
54
|
+
color: white;
|
|
55
|
+
min-height: 100vh;
|
|
56
|
+
display: flex;
|
|
57
|
+
justify-content: center;
|
|
58
|
+
align-items: center;
|
|
59
|
+
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
|
|
60
|
+
}
|
|
61
|
+
.container { text-align: center; padding: 2rem; }
|
|
62
|
+
h1 { font-size: 2.5rem; margin-bottom: 1rem; }
|
|
63
|
+
p { opacity: 0.7; }
|
|
64
|
+
.ready { color: #4ade80; font-size: 0.9rem; margin-top: 2rem; }
|
|
65
|
+
</style>
|
|
66
|
+
</head>
|
|
67
|
+
<body>
|
|
68
|
+
<div class="container">
|
|
69
|
+
<h1>\u26A1 ${name}</h1>
|
|
70
|
+
<p>Built with Craft iOS</p>
|
|
71
|
+
<p class="ready" id="status">Waiting for Craft bridge...</p>
|
|
72
|
+
</div>
|
|
73
|
+
<script>
|
|
74
|
+
window.addEventListener('craftReady', (e) => {
|
|
75
|
+
document.getElementById('status').textContent = \`\u2713 Craft bridge ready (platform: \${e.detail.platform})\`;
|
|
76
|
+
console.log('Craft capabilities:', e.detail.capabilities);
|
|
77
|
+
});
|
|
78
|
+
</script>
|
|
79
|
+
</body>
|
|
80
|
+
</html>`;
|
|
81
|
+
writeFileSync(join(output, "dist", "index.html"), placeholderHtml);
|
|
82
|
+
console.log("\u2705 Project initialized");
|
|
83
|
+
console.log("");
|
|
84
|
+
console.log("Next steps:");
|
|
85
|
+
console.log(` 1. cd ${output}`);
|
|
86
|
+
console.log(" 2. Add your web content to dist/index.html");
|
|
87
|
+
console.log(" 3. Run: craft ios build");
|
|
88
|
+
console.log(" 4. Run: craft ios open");
|
|
89
|
+
console.log("");
|
|
90
|
+
}
|
|
91
|
+
async function build(options) {
|
|
92
|
+
const { htmlPath, devServer, output } = options;
|
|
93
|
+
console.log(`
|
|
94
|
+
\uD83D\uDCE6 Building Craft iOS project...`);
|
|
95
|
+
const configPath = join(output, "craft.config.json");
|
|
96
|
+
if (!existsSync(configPath)) {
|
|
97
|
+
throw new Error(`No craft.config.json found in ${output}. Run 'craft ios init' first.`);
|
|
98
|
+
}
|
|
99
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
100
|
+
if (devServer) {
|
|
101
|
+
config.devServerURL = devServer;
|
|
102
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
103
|
+
console.log(` Dev server: ${devServer}`);
|
|
104
|
+
}
|
|
105
|
+
if (htmlPath) {
|
|
106
|
+
const distDir = join(output, "dist");
|
|
107
|
+
if (!existsSync(distDir)) {
|
|
108
|
+
mkdirSync(distDir, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
if (existsSync(htmlPath)) {
|
|
111
|
+
const stat = await Bun.file(htmlPath).exists();
|
|
112
|
+
if (stat) {
|
|
113
|
+
const html = readFileSync(htmlPath, "utf-8");
|
|
114
|
+
writeFileSync(join(distDir, "index.html"), html);
|
|
115
|
+
console.log(` Copied: ${htmlPath} \u2192 dist/index.html`);
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
throw new Error(`HTML path not found: ${htmlPath}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const result = await $`which xcodegen`.quiet();
|
|
123
|
+
if (result.exitCode === 0) {
|
|
124
|
+
console.log(" Running xcodegen...");
|
|
125
|
+
await $`cd ${output} && xcodegen generate`.quiet();
|
|
126
|
+
console.log(`\u2705 Xcode project created: ${config.appName}.xcodeproj`);
|
|
127
|
+
} else {
|
|
128
|
+
throw new Error("xcodegen not found");
|
|
129
|
+
}
|
|
130
|
+
} catch {
|
|
131
|
+
console.log("\u26A0\uFE0F xcodegen not found. Install with: brew install xcodegen");
|
|
132
|
+
console.log(" Then run: craft ios build");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
console.log("");
|
|
136
|
+
}
|
|
137
|
+
async function open(options) {
|
|
138
|
+
const { output } = options;
|
|
139
|
+
const files = readdirSync(output);
|
|
140
|
+
const xcodeproj = files.find((f) => f.endsWith(".xcodeproj"));
|
|
141
|
+
if (!xcodeproj) {
|
|
142
|
+
throw new Error(`No Xcode project found in ${output}. Run 'craft ios build' first.`);
|
|
143
|
+
}
|
|
144
|
+
const projectPath = join(output, xcodeproj);
|
|
145
|
+
console.log(`\uD83D\uDE80 Opening ${xcodeproj}...`);
|
|
146
|
+
await $`open ${projectPath}`;
|
|
147
|
+
}
|
|
148
|
+
async function run(options) {
|
|
149
|
+
const { simulator, output } = options;
|
|
150
|
+
await build({ output });
|
|
151
|
+
const files = readdirSync(output);
|
|
152
|
+
const xcodeproj = files.find((f) => f.endsWith(".xcodeproj"));
|
|
153
|
+
if (!xcodeproj) {
|
|
154
|
+
throw new Error(`No Xcode project found in ${output}`);
|
|
155
|
+
}
|
|
156
|
+
const projectPath = join(output, xcodeproj);
|
|
157
|
+
const appName = xcodeproj.replace(".xcodeproj", "");
|
|
158
|
+
if (simulator) {
|
|
159
|
+
console.log("\uD83D\uDCF1 Building and running on simulator...");
|
|
160
|
+
try {
|
|
161
|
+
await $`xcodebuild -project ${projectPath} -scheme ${appName} -destination 'platform=iOS Simulator,name=iPhone 15' build`;
|
|
162
|
+
await $`xcrun simctl boot "iPhone 15"`.quiet().nothrow();
|
|
163
|
+
await $`open -a Simulator`;
|
|
164
|
+
console.log("\u2705 App deployed to simulator");
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error("Build failed. Open in Xcode for details:", projectPath);
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
console.log("\uD83D\uDCF1 Opening Xcode for device deployment...");
|
|
170
|
+
await $`open ${projectPath}`;
|
|
171
|
+
console.log("");
|
|
172
|
+
console.log("In Xcode:");
|
|
173
|
+
console.log(" 1. Select your Team in Signing & Capabilities");
|
|
174
|
+
console.log(" 2. Connect your iPhone");
|
|
175
|
+
console.log(" 3. Select your device");
|
|
176
|
+
console.log(" 4. Click Run (\u25B6\uFE0F)");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
export {
|
|
180
|
+
run,
|
|
181
|
+
open,
|
|
182
|
+
init,
|
|
183
|
+
build
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
//# debugId=357E4FC7A8DD0D6264756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../ios/src/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Craft iOS Builder\n *\n * Generates native iOS apps from web content using WKWebView.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync, cpSync, readdirSync } from 'node:fs'\nimport { join, dirname, basename } from 'node:path'\nimport { $ } from 'bun'\n\nconst TEMPLATES_DIR = join(dirname(import.meta.dir), 'templates')\n\nexport interface CraftConfig {\n appName: string\n bundleId: string\n version?: string\n buildNumber?: string\n darkMode?: boolean\n backgroundColor?: string\n enableSpeechRecognition?: boolean\n enableHaptics?: boolean\n enableShare?: boolean\n devServerURL?: string\n iosVersion?: string\n teamId?: string\n}\n\nexport interface InitOptions {\n name: string\n bundleId?: string\n teamId?: string\n output: string\n}\n\nexport interface BuildOptions {\n htmlPath?: string\n devServer?: string\n output: string\n}\n\nexport interface OpenOptions {\n output: string\n}\n\nexport interface RunOptions {\n simulator: boolean\n output: string\n}\n\n/**\n * Initialize a new iOS project\n */\nexport async function init(options: InitOptions): Promise<void> {\n const { name, bundleId, teamId, output } = options\n\n console.log(`\\n⚡ Initializing Craft iOS project: ${name}`)\n console.log(` Output: ${output}\\n`)\n\n // Create directory structure\n const dirs = [output, join(output, 'Sources'), join(output, 'dist')]\n for (const dir of dirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n }\n\n // Generate bundle ID from name if not provided\n const finalBundleId = bundleId || `com.craft.${name.toLowerCase().replace(/[^a-z0-9]/g, '')}`\n const bundleIdPrefix = finalBundleId.split('.').slice(0, -1).join('.')\n\n // Create craft.config.json\n const config: CraftConfig = {\n appName: name,\n bundleId: finalBundleId,\n version: '1.0.0',\n buildNumber: '1',\n darkMode: true,\n backgroundColor: '#1a1a2e',\n enableSpeechRecognition: true,\n enableHaptics: true,\n enableShare: true,\n iosVersion: '15.0',\n teamId: teamId || '',\n }\n\n writeFileSync(join(output, 'craft.config.json'), JSON.stringify(config, null, 2))\n\n // Copy and customize Swift template\n const swiftTemplate = readFileSync(join(TEMPLATES_DIR, 'CraftApp.swift'), 'utf-8')\n writeFileSync(join(output, 'Sources', `${name}App.swift`), swiftTemplate.replace(/CraftApp/g, `${name}App`))\n\n // Generate Info.plist\n const infoPlistTemplate = readFileSync(join(TEMPLATES_DIR, 'Info.plist.template'), 'utf-8')\n const infoPlist = infoPlistTemplate\n .replace(/\\{\\{APP_NAME\\}\\}/g, name)\n .replace(/\\{\\{BUNDLE_ID\\}\\}/g, finalBundleId)\n .replace(/\\{\\{VERSION\\}\\}/g, config.version || '1.0.0')\n .replace(/\\{\\{BUILD_NUMBER\\}\\}/g, config.buildNumber || '1')\n .replace(/\\{\\{UI_STYLE\\}\\}/g, config.darkMode ? 'Dark' : 'Light')\n\n writeFileSync(join(output, 'Info.plist'), infoPlist)\n\n // Generate project.yml for xcodegen\n const projectYmlTemplate = readFileSync(join(TEMPLATES_DIR, 'project.yml.template'), 'utf-8')\n const projectYml = projectYmlTemplate\n .replace(/\\{\\{APP_NAME\\}\\}/g, name)\n .replace(/\\{\\{BUNDLE_ID\\}\\}/g, finalBundleId)\n .replace(/\\{\\{BUNDLE_ID_PREFIX\\}\\}/g, bundleIdPrefix)\n .replace(/\\{\\{VERSION\\}\\}/g, config.version || '1.0.0')\n .replace(/\\{\\{BUILD_NUMBER\\}\\}/g, config.buildNumber || '1')\n .replace(/\\{\\{IOS_VERSION\\}\\}/g, config.iosVersion || '15.0')\n .replace(/\\{\\{TEAM_ID\\}\\}/g, teamId || '')\n\n writeFileSync(join(output, 'project.yml'), projectYml)\n\n // Create placeholder index.html\n const placeholderHtml = `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"viewport-fit=cover, width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n <title>${name}</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, system-ui, sans-serif;\n background: ${config.backgroundColor};\n color: white;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);\n }\n .container { text-align: center; padding: 2rem; }\n h1 { font-size: 2.5rem; margin-bottom: 1rem; }\n p { opacity: 0.7; }\n .ready { color: #4ade80; font-size: 0.9rem; margin-top: 2rem; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <h1>⚡ ${name}</h1>\n <p>Built with Craft iOS</p>\n <p class=\"ready\" id=\"status\">Waiting for Craft bridge...</p>\n </div>\n <script>\n window.addEventListener('craftReady', (e) => {\n document.getElementById('status').textContent = \\`✓ Craft bridge ready (platform: \\${e.detail.platform})\\`;\n console.log('Craft capabilities:', e.detail.capabilities);\n });\n </script>\n</body>\n</html>`\n\n writeFileSync(join(output, 'dist', 'index.html'), placeholderHtml)\n\n console.log('✅ Project initialized')\n console.log('')\n console.log('Next steps:')\n console.log(` 1. cd ${output}`)\n console.log(' 2. Add your web content to dist/index.html')\n console.log(' 3. Run: craft ios build')\n console.log(' 4. Run: craft ios open')\n console.log('')\n}\n\n/**\n * Build web assets and generate Xcode project\n */\nexport async function build(options: BuildOptions): Promise<void> {\n const { htmlPath, devServer, output } = options\n\n console.log('\\n📦 Building Craft iOS project...')\n\n // Load config\n const configPath = join(output, 'craft.config.json')\n if (!existsSync(configPath)) {\n throw new Error(`No craft.config.json found in ${output}. Run 'craft ios init' first.`)\n }\n\n const config: CraftConfig = JSON.parse(readFileSync(configPath, 'utf-8'))\n\n // Update dev server URL if provided\n if (devServer) {\n config.devServerURL = devServer\n writeFileSync(configPath, JSON.stringify(config, null, 2))\n console.log(` Dev server: ${devServer}`)\n }\n\n // Copy HTML if provided\n if (htmlPath) {\n const distDir = join(output, 'dist')\n if (!existsSync(distDir)) {\n mkdirSync(distDir, { recursive: true })\n }\n\n if (existsSync(htmlPath)) {\n const stat = await Bun.file(htmlPath).exists()\n if (stat) {\n // Single file\n const html = readFileSync(htmlPath, 'utf-8')\n writeFileSync(join(distDir, 'index.html'), html)\n console.log(` Copied: ${htmlPath} → dist/index.html`)\n }\n }\nelse {\n throw new Error(`HTML path not found: ${htmlPath}`)\n }\n }\n\n // Generate Xcode project using xcodegen\n try {\n const result = await $`which xcodegen`.quiet()\n if (result.exitCode === 0) {\n console.log(' Running xcodegen...')\n await $`cd ${output} && xcodegen generate`.quiet()\n console.log(`✅ Xcode project created: ${config.appName}.xcodeproj`)\n }\nelse {\n throw new Error('xcodegen not found')\n }\n }\ncatch {\n console.log('⚠️ xcodegen not found. Install with: brew install xcodegen')\n console.log(' Then run: craft ios build')\n return\n }\n\n console.log('')\n}\n\n/**\n * Open Xcode project\n */\nexport async function open(options: OpenOptions): Promise<void> {\n const { output } = options\n\n // Find .xcodeproj\n const files = readdirSync(output)\n const xcodeproj = files.find(f => f.endsWith('.xcodeproj'))\n\n if (!xcodeproj) {\n throw new Error(`No Xcode project found in ${output}. Run 'craft ios build' first.`)\n }\n\n const projectPath = join(output, xcodeproj)\n console.log(`🚀 Opening ${xcodeproj}...`)\n await $`open ${projectPath}`\n}\n\n/**\n * Build and run on simulator or device\n */\nexport async function run(options: RunOptions): Promise<void> {\n const { simulator, output } = options\n\n // First build\n await build({ output })\n\n // Find .xcodeproj\n const files = readdirSync(output)\n const xcodeproj = files.find(f => f.endsWith('.xcodeproj'))\n\n if (!xcodeproj) {\n throw new Error(`No Xcode project found in ${output}`)\n }\n\n const projectPath = join(output, xcodeproj)\n const appName = xcodeproj.replace('.xcodeproj', '')\n\n if (simulator) {\n console.log('📱 Building and running on simulator...')\n try {\n // Build for simulator\n await $`xcodebuild -project ${projectPath} -scheme ${appName} -destination 'platform=iOS Simulator,name=iPhone 15' build`\n\n // Boot simulator if needed\n await $`xcrun simctl boot \"iPhone 15\"`.quiet().nothrow()\n\n // Open simulator\n await $`open -a Simulator`\n\n console.log('✅ App deployed to simulator')\n }\ncatch (error) {\n console.error('Build failed. Open in Xcode for details:', projectPath)\n }\n }\nelse {\n // Open in Xcode for device deployment\n console.log('📱 Opening Xcode for device deployment...')\n await $`open ${projectPath}`\n console.log('')\n console.log('In Xcode:')\n console.log(' 1. Select your Team in Signing & Capabilities')\n console.log(' 2. Connect your iPhone')\n console.log(' 3. Select your device')\n console.log(' 4. Click Run (▶️)')\n }\n}\n\n// Re-export types\nexport type { CraftConfig }\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "357E4FC7A8DD0D6264756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|