@bravostudioai/react 0.1.14 → 0.1.16
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/cli/commands/generate.js +90 -85
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/codegen/generator.js +218 -212
- package/dist/codegen/generator.js.map +1 -1
- package/dist/components/EncoreApp.js +34 -22
- package/dist/components/EncoreApp.js.map +1 -1
- package/dist/components.js +524 -537
- package/dist/components.js.map +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/packages/encore-lib/constants.js.map +1 -1
- package/dist/src/cli/commands/generate.d.ts.map +1 -1
- package/dist/src/codegen/generator.d.ts +5 -1
- package/dist/src/codegen/generator.d.ts.map +1 -1
- package/dist/src/components/EncoreApp.d.ts.map +1 -1
- package/dist/src/components.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/generate.ts +9 -1
- package/src/codegen/generator.ts +12 -1
- package/src/components/EncoreApp.tsx +9 -1
- package/src/components.tsx +11 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { promises as M, existsSync as R } from "fs";
|
|
2
|
-
import { join as
|
|
2
|
+
import { join as l, dirname as k } from "path";
|
|
3
3
|
import { m as W } from "../../_virtual/main.js";
|
|
4
4
|
import { CONST_APPS_SERVICE_URL as Y, CONST_COMPONENTS_CDN_URL as q } from "../../packages/encore-lib/constants.js";
|
|
5
5
|
import { findSlidersAndDataBindings as z, findStandaloneComponents as X, findInputGroups as Z, findForms as H, qualifyFormInputs as Q, findStandaloneSelectInputs as ee, findActionButtons as te, sanitizePropName as L } from "../../codegen/parser.js";
|
|
@@ -9,9 +9,9 @@ W.config();
|
|
|
9
9
|
const S = process.env.APPS_SERVICE_URL || process.env.VITE_APPS_SERVICE_URL || Y;
|
|
10
10
|
console.log(`Using APPS_SERVICE_URL: ${S}`);
|
|
11
11
|
const ae = q;
|
|
12
|
-
async function _(o,
|
|
12
|
+
async function _(o, a) {
|
|
13
13
|
const t = await fetch(o, {
|
|
14
|
-
headers:
|
|
14
|
+
headers: a || {}
|
|
15
15
|
});
|
|
16
16
|
if (!t.ok)
|
|
17
17
|
throw new Error(
|
|
@@ -19,46 +19,46 @@ async function _(o, n) {
|
|
|
19
19
|
);
|
|
20
20
|
return await t.text();
|
|
21
21
|
}
|
|
22
|
-
function se(o,
|
|
23
|
-
const t = L(o),
|
|
22
|
+
function se(o, a) {
|
|
23
|
+
const t = L(o), i = L(a), f = t.charAt(0).toUpperCase() + t.slice(1), p = i.charAt(0).toUpperCase() + i.slice(1);
|
|
24
24
|
return {
|
|
25
|
-
directoryPath:
|
|
25
|
+
directoryPath: l(f, p),
|
|
26
26
|
componentName: p
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
async function re(o) {
|
|
30
|
-
const
|
|
31
|
-
console.log(`Fetching app data from ${
|
|
30
|
+
const a = `${S}/devices/apps/${o}`;
|
|
31
|
+
console.log(`Fetching app data from ${a}...`);
|
|
32
32
|
try {
|
|
33
|
-
const t = await _(
|
|
34
|
-
return { pages:
|
|
33
|
+
const t = await _(a), i = JSON.parse(t);
|
|
34
|
+
return { pages: i?.app?.data?.pages || [], appData: i };
|
|
35
35
|
} catch (t) {
|
|
36
36
|
throw console.error("Failed to fetch app data:", t), t;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
async function I({
|
|
40
40
|
appId: o,
|
|
41
|
-
pageId:
|
|
41
|
+
pageId: a,
|
|
42
42
|
outputPath: t,
|
|
43
|
-
cachedAppData:
|
|
44
|
-
isProduction:
|
|
43
|
+
cachedAppData: i,
|
|
44
|
+
isProduction: f
|
|
45
45
|
}) {
|
|
46
|
-
console.log(`Generating wrapper for app: ${o}, page: ${
|
|
47
|
-
let p = t,
|
|
46
|
+
console.log(`Generating wrapper for app: ${o}, page: ${a}`);
|
|
47
|
+
let p = t, c = !1;
|
|
48
48
|
const m = t.split(".").pop()?.toLowerCase();
|
|
49
49
|
if (m !== "tsx" && m !== "ts" && m !== "jsx" && m !== "js") {
|
|
50
50
|
const { stat: e } = await import("fs/promises");
|
|
51
51
|
try {
|
|
52
|
-
(await e(t)).isDirectory() && (
|
|
52
|
+
(await e(t)).isDirectory() && (c = !0);
|
|
53
53
|
} catch {
|
|
54
|
-
(!m || t.endsWith("/")) && (
|
|
54
|
+
(!m || t.endsWith("/")) && (c = !0);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
c && console.log(
|
|
58
58
|
"Output path is a directory, will generate filename from app/page names"
|
|
59
59
|
), console.log(`Output path: ${t}`);
|
|
60
|
-
const
|
|
61
|
-
R(
|
|
60
|
+
const s = l(process.cwd(), ".temp-bravo", o, a);
|
|
61
|
+
R(s) || await T(s, { recursive: !0 });
|
|
62
62
|
const N = [
|
|
63
63
|
{
|
|
64
64
|
url: `${S}/devices/apps/${o}`,
|
|
@@ -66,126 +66,131 @@ async function I({
|
|
|
66
66
|
skipIfCached: !0
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
|
-
url: `${S}/devices/apps/${o}/node/${
|
|
69
|
+
url: `${S}/devices/apps/${o}/node/${a}`,
|
|
70
70
|
filename: "page.json"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
|
-
url: `${ae}/${o}/draft/components/${
|
|
73
|
+
url: `${ae}/${o}/draft/components/${a}.js`,
|
|
74
74
|
filename: "component.js"
|
|
75
75
|
}
|
|
76
76
|
];
|
|
77
77
|
for (const e of N) {
|
|
78
|
-
if (e.skipIfCached &&
|
|
78
|
+
if (e.skipIfCached && i) {
|
|
79
79
|
console.log(`Using cached ${e.filename} (skipping download)`);
|
|
80
|
-
const
|
|
80
|
+
const r = l(s, e.filename);
|
|
81
81
|
await C(
|
|
82
|
-
|
|
83
|
-
JSON.stringify(
|
|
82
|
+
r,
|
|
83
|
+
JSON.stringify(i, null, 2),
|
|
84
84
|
"utf-8"
|
|
85
85
|
), console.log(`✓ Saved ${e.filename} from cache`);
|
|
86
86
|
continue;
|
|
87
87
|
}
|
|
88
88
|
try {
|
|
89
89
|
console.log(`Downloading ${e.filename} from ${e.url}...`);
|
|
90
|
-
const
|
|
91
|
-
await C(
|
|
92
|
-
} catch (
|
|
93
|
-
throw console.error(`✗ Failed to download ${e.filename}:`,
|
|
90
|
+
const r = await _(e.url, e.headers), d = l(s, e.filename);
|
|
91
|
+
await C(d, r, "utf-8"), console.log(`✓ Saved ${e.filename}`);
|
|
92
|
+
} catch (r) {
|
|
93
|
+
throw console.error(`✗ Failed to download ${e.filename}:`, r), r;
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
const g =
|
|
97
|
-
let
|
|
98
|
-
if (!
|
|
96
|
+
const g = l(s, "page.json"), u = await $(g, "utf-8"), v = JSON.parse(u);
|
|
97
|
+
let n = v.data || v;
|
|
98
|
+
if (!n.body && !n.data?.body) {
|
|
99
99
|
console.log("Page data doesn't have body, trying app.json...");
|
|
100
100
|
try {
|
|
101
|
-
let e =
|
|
101
|
+
let e = i;
|
|
102
102
|
if (!e) {
|
|
103
103
|
const h = `${S}/devices/apps/${o}`, w = await _(h);
|
|
104
104
|
e = JSON.parse(w);
|
|
105
105
|
}
|
|
106
|
-
const
|
|
107
|
-
|
|
106
|
+
const d = (e?.app?.data?.pages || []).find((h) => h.id === a);
|
|
107
|
+
d && (n = d, console.log("✓ Found page data in app.json"));
|
|
108
108
|
} catch (e) {
|
|
109
109
|
console.warn("Could not load app.json:", e);
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
-
const x = z(
|
|
113
|
-
Q(
|
|
114
|
-
const U = ee(
|
|
115
|
-
let
|
|
112
|
+
const x = z(n), A = X(n), O = Z(n), y = H(n);
|
|
113
|
+
Q(y);
|
|
114
|
+
const U = ee(n, y), j = te(n);
|
|
115
|
+
let P = "Encore App", E = "Page";
|
|
116
116
|
try {
|
|
117
|
-
let e =
|
|
117
|
+
let e = i;
|
|
118
118
|
if (!e) {
|
|
119
|
-
const
|
|
120
|
-
if (R(
|
|
121
|
-
const
|
|
122
|
-
e = JSON.parse(
|
|
119
|
+
const r = l(s, "app.json");
|
|
120
|
+
if (R(r)) {
|
|
121
|
+
const d = await $(r, "utf-8");
|
|
122
|
+
e = JSON.parse(d);
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
e && (
|
|
125
|
+
e && (P = e?.app?.store?.name || P);
|
|
126
126
|
} catch {
|
|
127
127
|
}
|
|
128
|
-
|
|
129
|
-
const { directoryPath: G, componentName: D } = se(
|
|
130
|
-
if (
|
|
131
|
-
p =
|
|
128
|
+
E = n.name || n.id || E;
|
|
129
|
+
const { directoryPath: G, componentName: D } = se(P, E), F = G;
|
|
130
|
+
if (c)
|
|
131
|
+
p = l(t, F);
|
|
132
132
|
else {
|
|
133
133
|
const e = k(p);
|
|
134
|
-
p =
|
|
134
|
+
p = l(e, F);
|
|
135
135
|
}
|
|
136
136
|
const K = oe(
|
|
137
137
|
o,
|
|
138
|
-
|
|
138
|
+
a,
|
|
139
139
|
D,
|
|
140
140
|
x,
|
|
141
141
|
A,
|
|
142
142
|
O,
|
|
143
|
-
|
|
143
|
+
y,
|
|
144
144
|
U,
|
|
145
145
|
j,
|
|
146
|
-
!!
|
|
146
|
+
!!f,
|
|
147
|
+
{
|
|
148
|
+
width: n.style?.width,
|
|
149
|
+
height: n.style?.height,
|
|
150
|
+
aspectRatio: n.style?.width && n.style?.height ? n.style.width / n.style.height : void 0
|
|
151
|
+
}
|
|
147
152
|
), V = ne(
|
|
148
153
|
o,
|
|
149
|
-
|
|
154
|
+
a,
|
|
155
|
+
P,
|
|
150
156
|
E,
|
|
151
|
-
y,
|
|
152
157
|
D,
|
|
153
158
|
x,
|
|
154
159
|
A,
|
|
155
160
|
O,
|
|
156
|
-
|
|
161
|
+
y,
|
|
157
162
|
U,
|
|
158
163
|
j
|
|
159
164
|
);
|
|
160
|
-
if (R(p) || await T(p, { recursive: !0 }),
|
|
161
|
-
const e =
|
|
162
|
-
let
|
|
165
|
+
if (R(p) || await T(p, { recursive: !0 }), f) {
|
|
166
|
+
const e = l(s, "component.js");
|
|
167
|
+
let r = "";
|
|
163
168
|
try {
|
|
164
|
-
|
|
169
|
+
r = await $(e, "utf-8");
|
|
165
170
|
} catch {
|
|
166
171
|
}
|
|
167
|
-
let
|
|
168
|
-
if (!
|
|
172
|
+
let d = i;
|
|
173
|
+
if (!d)
|
|
169
174
|
try {
|
|
170
|
-
const w =
|
|
171
|
-
|
|
175
|
+
const w = l(s, "app.json"), B = await $(w, "utf-8");
|
|
176
|
+
d = JSON.parse(B);
|
|
172
177
|
} catch {
|
|
173
178
|
}
|
|
174
179
|
const h = {
|
|
175
|
-
app:
|
|
176
|
-
page:
|
|
177
|
-
componentCode:
|
|
180
|
+
app: d,
|
|
181
|
+
page: n,
|
|
182
|
+
componentCode: r
|
|
178
183
|
};
|
|
179
184
|
await C(
|
|
180
|
-
|
|
185
|
+
l(p, "data.json"),
|
|
181
186
|
JSON.stringify(h, null, 2),
|
|
182
187
|
"utf-8"
|
|
183
188
|
);
|
|
184
189
|
}
|
|
185
|
-
const J =
|
|
190
|
+
const J = l(p, "index.tsx"), b = l(p, "README.md");
|
|
186
191
|
await C(J, K, "utf-8"), await C(b, V, "utf-8"), console.log(`✓ Generated wrapper component at: ${J}`);
|
|
187
192
|
}
|
|
188
|
-
function
|
|
193
|
+
function ie() {
|
|
189
194
|
console.log(`
|
|
190
195
|
Usage: generate-wrapper.ts <appId> [pageId] <outputPath>
|
|
191
196
|
|
|
@@ -202,26 +207,26 @@ Example:
|
|
|
202
207
|
`);
|
|
203
208
|
}
|
|
204
209
|
async function ge(o) {
|
|
205
|
-
const
|
|
206
|
-
if ((t.length < 2 || t.includes("--help") || t.includes("-h")) && (
|
|
210
|
+
const a = o.includes("--production"), t = o.filter((c) => c !== "--production");
|
|
211
|
+
if ((t.length < 2 || t.includes("--help") || t.includes("-h")) && (ie(), process.exit(
|
|
207
212
|
t.includes("--help") || t.includes("-h") ? 0 : 1
|
|
208
213
|
)), t.length === 2) {
|
|
209
|
-
const [
|
|
214
|
+
const [c, m] = t;
|
|
210
215
|
try {
|
|
211
|
-
const { pages:
|
|
212
|
-
if (
|
|
216
|
+
const { pages: s, appData: N } = await re(c);
|
|
217
|
+
if (s.length === 0) {
|
|
213
218
|
console.warn("No pages found for this app.");
|
|
214
219
|
return;
|
|
215
220
|
}
|
|
216
|
-
for (const g of
|
|
221
|
+
for (const g of s)
|
|
217
222
|
if (g.id)
|
|
218
223
|
try {
|
|
219
224
|
await I({
|
|
220
|
-
appId:
|
|
225
|
+
appId: c,
|
|
221
226
|
pageId: g.id,
|
|
222
227
|
outputPath: m,
|
|
223
228
|
cachedAppData: N,
|
|
224
|
-
isProduction:
|
|
229
|
+
isProduction: a
|
|
225
230
|
});
|
|
226
231
|
} catch (u) {
|
|
227
232
|
console.warn(
|
|
@@ -229,18 +234,18 @@ async function ge(o) {
|
|
|
229
234
|
u instanceof Error ? u.message : u
|
|
230
235
|
);
|
|
231
236
|
}
|
|
232
|
-
} catch (
|
|
237
|
+
} catch (s) {
|
|
233
238
|
console.error(`
|
|
234
|
-
Error:`,
|
|
239
|
+
Error:`, s instanceof Error ? s.message : s), process.exit(1);
|
|
235
240
|
}
|
|
236
241
|
return;
|
|
237
242
|
}
|
|
238
|
-
const [
|
|
243
|
+
const [i, f, p] = t;
|
|
239
244
|
try {
|
|
240
|
-
await I({ appId:
|
|
241
|
-
} catch (
|
|
245
|
+
await I({ appId: i, pageId: f, outputPath: p, isProduction: a });
|
|
246
|
+
} catch (c) {
|
|
242
247
|
console.error(`
|
|
243
|
-
Error:`,
|
|
248
|
+
Error:`, c instanceof Error ? c.message : c), process.exit(1);
|
|
244
249
|
}
|
|
245
250
|
}
|
|
246
251
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sources":["../../../src/cli/commands/generate.ts"],"sourcesContent":["import { promises as fs } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { existsSync } from \"fs\";\nimport * as dotenv from \"dotenv\";\nimport {\n CONST_APPS_SERVICE_URL,\n CONST_COMPONENTS_CDN_URL,\n} from \"../../../constants\";\nimport {\n findSlidersAndDataBindings,\n findStandaloneComponents,\n findInputGroups,\n findForms,\n findStandaloneSelectInputs,\n findActionButtons,\n qualifyFormInputs,\n generateComponentCode,\n generateReadme,\n sanitizePropName,\n} from \"../../codegen\";\n\nconst { writeFile, mkdir, readFile } = fs;\n\ndotenv.config();\n\n// Default apps service URL (can be overridden with APPS_SERVICE_URL env var)\nconst APPS_SERVICE_URL =\n process.env.APPS_SERVICE_URL ||\n process.env.VITE_APPS_SERVICE_URL ||\n CONST_APPS_SERVICE_URL;\nconsole.log(`Using APPS_SERVICE_URL: ${APPS_SERVICE_URL}`);\nconst COMPONENTS_CDN_URL = CONST_COMPONENTS_CDN_URL;\n\nasync function downloadFile(\n url: string,\n headers?: Record<string, string>\n): Promise<string> {\n const response = await fetch(url, {\n headers: headers || {},\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to download ${url}: ${response.status} ${response.statusText}`\n );\n }\n\n return await response.text();\n}\n\nfunction generateNames(\n appName: string,\n pageName: string\n): { directoryPath: string; componentName: string } {\n const appCamel = sanitizePropName(appName);\n const pageCamel = sanitizePropName(pageName);\n // Capitalize first letter for PascalCase\n const appPascal = appCamel.charAt(0).toUpperCase() + appCamel.slice(1);\n const pagePascal = pageCamel.charAt(0).toUpperCase() + pageCamel.slice(1);\n return {\n directoryPath: join(appPascal, pagePascal),\n componentName: pagePascal,\n };\n}\n\nasync function getAppPages(\n appId: string\n): Promise<{ pages: any[]; appData: any }> {\n const url = `${APPS_SERVICE_URL}/devices/apps/${appId}`;\n console.log(`Fetching app data from ${url}...`);\n try {\n const content = await downloadFile(url);\n const appData = JSON.parse(content);\n const pages = appData?.app?.data?.pages || [];\n return { pages, appData };\n } catch (error) {\n console.error(\"Failed to fetch app data:\", error);\n throw error;\n }\n}\n\nasync function generateWrapper({\n appId,\n pageId,\n outputPath,\n cachedAppData,\n isProduction,\n}: {\n appId: string;\n pageId: string;\n outputPath: string;\n cachedAppData?: any;\n isProduction?: boolean;\n}) {\n console.log(`Generating wrapper for app: ${appId}, page: ${pageId}`);\n\n // Determine final output path - we'll update it after we get app/page names\n let finalOutputPath = outputPath;\n let needsFilenameGeneration = false;\n const pathExt = outputPath.split(\".\").pop()?.toLowerCase();\n if (\n pathExt !== \"tsx\" &&\n pathExt !== \"ts\" &&\n pathExt !== \"jsx\" &&\n pathExt !== \"js\"\n ) {\n // Path doesn't have a file extension, treat as directory\n const { stat } = await import(\"fs/promises\");\n try {\n const pathStats = await stat(outputPath);\n if (pathStats.isDirectory()) {\n needsFilenameGeneration = true;\n }\n } catch {\n // Path doesn't exist, check if it looks like a directory (no extension)\n if (!pathExt || outputPath.endsWith(\"/\")) {\n needsFilenameGeneration = true;\n }\n }\n }\n\n if (needsFilenameGeneration) {\n console.log(\n `Output path is a directory, will generate filename from app/page names`\n );\n }\n\n console.log(`Output path: ${outputPath}`);\n\n // Create temp directory for downloaded files\n const tempDir = join(process.cwd(), \".temp-bravo\", appId, pageId);\n if (!existsSync(tempDir)) {\n await mkdir(tempDir, { recursive: true });\n }\n\n // Download files (skip app.json if we have cached data)\n const files: Array<{\n url: string;\n filename: string;\n headers?: Record<string, string>;\n skipIfCached?: boolean;\n }> = [\n {\n url: `${APPS_SERVICE_URL}/devices/apps/${appId}`,\n filename: \"app.json\",\n skipIfCached: true,\n },\n {\n url: `${APPS_SERVICE_URL}/devices/apps/${appId}/node/${pageId}`,\n filename: \"page.json\",\n },\n {\n url: `${COMPONENTS_CDN_URL}/${appId}/draft/components/${pageId}.js`,\n filename: \"component.js\",\n },\n ];\n\n for (const file of files) {\n // Skip app.json if we have cached data\n if (file.skipIfCached && cachedAppData) {\n console.log(`Using cached ${file.filename} (skipping download)`);\n const filePath = join(tempDir, file.filename);\n await writeFile(\n filePath,\n JSON.stringify(cachedAppData, null, 2),\n \"utf-8\"\n );\n console.log(`✓ Saved ${file.filename} from cache`);\n continue;\n }\n\n try {\n console.log(`Downloading ${file.filename} from ${file.url}...`);\n const content = await downloadFile(file.url, file.headers);\n const filePath = join(tempDir, file.filename);\n await writeFile(filePath, content, \"utf-8\");\n console.log(`✓ Saved ${file.filename}`);\n } catch (error) {\n console.error(`✗ Failed to download ${file.filename}:`, error);\n throw error;\n }\n }\n\n // Read and parse page.json\n const pageJsonPath = join(tempDir, \"page.json\");\n const pageJsonContent = await readFile(pageJsonPath, \"utf-8\");\n const pageResponse = JSON.parse(pageJsonContent);\n\n // Extract page data - API response has it under 'data' field\n let pageData = pageResponse.data || pageResponse;\n\n // If pageData doesn't have body, try using cached app.json or downloading as fallback\n if (!pageData.body && !(pageData as any).data?.body) {\n console.log(\"Page data doesn't have body, trying app.json...\");\n try {\n let appData = cachedAppData;\n\n // If we don't have cached data, download it\n if (!appData) {\n const appUrl = `${APPS_SERVICE_URL}/devices/apps/${appId}`;\n const appContent = await downloadFile(appUrl);\n appData = JSON.parse(appContent);\n }\n\n // Find the page in app.data.pages\n const pages = appData?.app?.data?.pages || [];\n const page = pages.find((p: any) => p.id === pageId);\n if (page) {\n pageData = page;\n console.log(\"✓ Found page data in app.json\");\n }\n } catch (error) {\n console.warn(\"Could not load app.json:\", error);\n }\n }\n\n // Find components using extracted logic\n const sliders = findSlidersAndDataBindings(pageData);\n const standaloneComponents = findStandaloneComponents(pageData);\n const inputGroups = findInputGroups(pageData);\n const forms = findForms(pageData);\n\n // Qualify form input prop names\n qualifyFormInputs(forms);\n\n const selectInputs = findStandaloneSelectInputs(pageData, forms);\n const actionButtons = findActionButtons(pageData);\n\n // Extract app name and page name\n let appName = \"Encore App\";\n let pageName = \"Page\";\n\n try {\n let appDataForName = cachedAppData;\n if (!appDataForName) {\n const appJsonPath = join(tempDir, \"app.json\");\n if (existsSync(appJsonPath)) {\n const appJsonContent = await readFile(appJsonPath, \"utf-8\");\n appDataForName = JSON.parse(appJsonContent);\n }\n }\n if (appDataForName) {\n appName = appDataForName?.app?.store?.name || appName;\n }\n } catch (error) {\n // Ignore errors, use defaults\n }\n\n pageName = pageData.name || pageData.id || pageName;\n\n // Generate component name and directory name\n const { directoryPath, componentName } = generateNames(appName, pageName);\n const directoryName = directoryPath;\n\n // Update output path\n if (needsFilenameGeneration) {\n finalOutputPath = join(outputPath, directoryName);\n } else {\n const providedDir = dirname(finalOutputPath);\n finalOutputPath = join(providedDir, directoryName);\n }\n\n // Generate component code and README\n const componentCode = generateComponentCode(\n appId,\n pageId,\n componentName,\n sliders,\n standaloneComponents,\n inputGroups,\n forms,\n selectInputs,\n actionButtons,\n !!isProduction\n );\n\n const readmeContent = generateReadme(\n appId,\n pageId,\n appName,\n pageName,\n componentName,\n sliders,\n standaloneComponents,\n inputGroups,\n forms,\n selectInputs,\n actionButtons\n );\n\n // Ensure output directory exists\n if (!existsSync(finalOutputPath)) {\n await mkdir(finalOutputPath, { recursive: true });\n }\n\n // Write files\n if (isProduction) {\n const componentJsPath = join(tempDir, \"component.js\");\n let componentCodeContent = \"\";\n try {\n componentCodeContent = await readFile(componentJsPath, \"utf-8\");\n } catch (e) {}\n\n let appDataForProd = cachedAppData;\n if (!appDataForProd) {\n try {\n const appJsonPath = join(tempDir, \"app.json\");\n const appJsonContent = await readFile(appJsonPath, \"utf-8\");\n appDataForProd = JSON.parse(appJsonContent);\n } catch (e) {}\n }\n\n const productionData = {\n app: appDataForProd,\n page: pageData,\n componentCode: componentCodeContent,\n };\n await writeFile(\n join(finalOutputPath, \"data.json\"),\n JSON.stringify(productionData, null, 2),\n \"utf-8\"\n );\n }\n\n const indexPath = join(finalOutputPath, \"index.tsx\");\n const readmePath = join(finalOutputPath, \"README.md\");\n\n await writeFile(indexPath, componentCode, \"utf-8\");\n await writeFile(readmePath, readmeContent, \"utf-8\");\n\n console.log(`✓ Generated wrapper component at: ${indexPath}`);\n}\n\nfunction printUsage() {\n console.log(`\nUsage: generate-wrapper.ts <appId> [pageId] <outputPath>\n\nArguments:\n appId The Encore app ID\n pageId The Encore page ID (optional - if omitted, generates wrappers for ALL pages)\n outputPath Path where the generated TSX file(s) should be saved\n\nEnvironment variables:\n APPS_SERVICE_URL Base URL for the apps service\n\nExample:\n generate-wrapper.ts 01KA964B1T6KCKSKCNMYSTKRKZ 01KA964B2F42MN4WGCYDTG1Y70 ./src/components/MyEncoreApp.tsx\n`);\n}\n\nexport async function runGenerate(args: string[]) {\n const isProduction = args.includes(\"--production\");\n const cleanArgs = args.filter((arg) => arg !== \"--production\");\n\n if (\n cleanArgs.length < 2 ||\n cleanArgs.includes(\"--help\") ||\n cleanArgs.includes(\"-h\")\n ) {\n printUsage();\n process.exit(\n cleanArgs.includes(\"--help\") || cleanArgs.includes(\"-h\") ? 0 : 1\n );\n }\n\n if (cleanArgs.length === 2) {\n const [appId, outputPath] = cleanArgs;\n\n try {\n const { pages, appData } = await getAppPages(appId);\n if (pages.length === 0) {\n console.warn(\"No pages found for this app.\");\n return;\n }\n\n for (const page of pages) {\n if (!page.id) continue;\n try {\n await generateWrapper({\n appId,\n pageId: page.id,\n outputPath,\n cachedAppData: appData,\n isProduction,\n });\n } catch (error) {\n console.warn(\n `Error with page ${page.id}:`,\n error instanceof Error ? error.message : error\n );\n }\n }\n } catch (error) {\n console.error(\"\\nError:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n return;\n }\n\n const [appId, pageId, outputPath] = cleanArgs;\n\n try {\n await generateWrapper({ appId, pageId, outputPath, isProduction });\n } catch (error) {\n console.error(\"\\nError:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n"],"names":["writeFile","mkdir","readFile","fs","dotenv.config","APPS_SERVICE_URL","CONST_APPS_SERVICE_URL","COMPONENTS_CDN_URL","CONST_COMPONENTS_CDN_URL","downloadFile","url","headers","response","generateNames","appName","pageName","appCamel","sanitizePropName","pageCamel","appPascal","pagePascal","join","getAppPages","appId","content","appData","error","generateWrapper","pageId","outputPath","cachedAppData","isProduction","finalOutputPath","needsFilenameGeneration","pathExt","stat","tempDir","existsSync","files","file","filePath","pageJsonPath","pageJsonContent","pageResponse","pageData","appUrl","appContent","page","p","sliders","findSlidersAndDataBindings","standaloneComponents","findStandaloneComponents","inputGroups","findInputGroups","forms","findForms","qualifyFormInputs","selectInputs","findStandaloneSelectInputs","actionButtons","findActionButtons","appDataForName","appJsonPath","appJsonContent","directoryPath","componentName","directoryName","providedDir","dirname","componentCode","generateComponentCode","readmeContent","generateReadme","componentJsPath","componentCodeContent","appDataForProd","productionData","indexPath","readmePath","printUsage","runGenerate","args","cleanArgs","arg","pages"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generate.js","sources":["../../../src/cli/commands/generate.ts"],"sourcesContent":["import { promises as fs } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { existsSync } from \"fs\";\nimport * as dotenv from \"dotenv\";\nimport {\n CONST_APPS_SERVICE_URL,\n CONST_COMPONENTS_CDN_URL,\n} from \"../../../constants\";\nimport {\n findSlidersAndDataBindings,\n findStandaloneComponents,\n findInputGroups,\n findForms,\n findStandaloneSelectInputs,\n findActionButtons,\n qualifyFormInputs,\n generateComponentCode,\n generateReadme,\n sanitizePropName,\n} from \"../../codegen\";\n\nconst { writeFile, mkdir, readFile } = fs;\n\ndotenv.config();\n\n// Default apps service URL (can be overridden with APPS_SERVICE_URL env var)\nconst APPS_SERVICE_URL =\n process.env.APPS_SERVICE_URL ||\n process.env.VITE_APPS_SERVICE_URL ||\n CONST_APPS_SERVICE_URL;\nconsole.log(`Using APPS_SERVICE_URL: ${APPS_SERVICE_URL}`);\nconst COMPONENTS_CDN_URL = CONST_COMPONENTS_CDN_URL;\n\nasync function downloadFile(\n url: string,\n headers?: Record<string, string>\n): Promise<string> {\n const response = await fetch(url, {\n headers: headers || {},\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to download ${url}: ${response.status} ${response.statusText}`\n );\n }\n\n return await response.text();\n}\n\nfunction generateNames(\n appName: string,\n pageName: string\n): { directoryPath: string; componentName: string } {\n const appCamel = sanitizePropName(appName);\n const pageCamel = sanitizePropName(pageName);\n // Capitalize first letter for PascalCase\n const appPascal = appCamel.charAt(0).toUpperCase() + appCamel.slice(1);\n const pagePascal = pageCamel.charAt(0).toUpperCase() + pageCamel.slice(1);\n return {\n directoryPath: join(appPascal, pagePascal),\n componentName: pagePascal,\n };\n}\n\nasync function getAppPages(\n appId: string\n): Promise<{ pages: any[]; appData: any }> {\n const url = `${APPS_SERVICE_URL}/devices/apps/${appId}`;\n console.log(`Fetching app data from ${url}...`);\n try {\n const content = await downloadFile(url);\n const appData = JSON.parse(content);\n const pages = appData?.app?.data?.pages || [];\n return { pages, appData };\n } catch (error) {\n console.error(\"Failed to fetch app data:\", error);\n throw error;\n }\n}\n\nasync function generateWrapper({\n appId,\n pageId,\n outputPath,\n cachedAppData,\n isProduction,\n}: {\n appId: string;\n pageId: string;\n outputPath: string;\n cachedAppData?: any;\n isProduction?: boolean;\n}) {\n console.log(`Generating wrapper for app: ${appId}, page: ${pageId}`);\n\n // Determine final output path - we'll update it after we get app/page names\n let finalOutputPath = outputPath;\n let needsFilenameGeneration = false;\n const pathExt = outputPath.split(\".\").pop()?.toLowerCase();\n if (\n pathExt !== \"tsx\" &&\n pathExt !== \"ts\" &&\n pathExt !== \"jsx\" &&\n pathExt !== \"js\"\n ) {\n // Path doesn't have a file extension, treat as directory\n const { stat } = await import(\"fs/promises\");\n try {\n const pathStats = await stat(outputPath);\n if (pathStats.isDirectory()) {\n needsFilenameGeneration = true;\n }\n } catch {\n // Path doesn't exist, check if it looks like a directory (no extension)\n if (!pathExt || outputPath.endsWith(\"/\")) {\n needsFilenameGeneration = true;\n }\n }\n }\n\n if (needsFilenameGeneration) {\n console.log(\n `Output path is a directory, will generate filename from app/page names`\n );\n }\n\n console.log(`Output path: ${outputPath}`);\n\n // Create temp directory for downloaded files\n const tempDir = join(process.cwd(), \".temp-bravo\", appId, pageId);\n if (!existsSync(tempDir)) {\n await mkdir(tempDir, { recursive: true });\n }\n\n // Download files (skip app.json if we have cached data)\n const files: Array<{\n url: string;\n filename: string;\n headers?: Record<string, string>;\n skipIfCached?: boolean;\n }> = [\n {\n url: `${APPS_SERVICE_URL}/devices/apps/${appId}`,\n filename: \"app.json\",\n skipIfCached: true,\n },\n {\n url: `${APPS_SERVICE_URL}/devices/apps/${appId}/node/${pageId}`,\n filename: \"page.json\",\n },\n {\n url: `${COMPONENTS_CDN_URL}/${appId}/draft/components/${pageId}.js`,\n filename: \"component.js\",\n },\n ];\n\n for (const file of files) {\n // Skip app.json if we have cached data\n if (file.skipIfCached && cachedAppData) {\n console.log(`Using cached ${file.filename} (skipping download)`);\n const filePath = join(tempDir, file.filename);\n await writeFile(\n filePath,\n JSON.stringify(cachedAppData, null, 2),\n \"utf-8\"\n );\n console.log(`✓ Saved ${file.filename} from cache`);\n continue;\n }\n\n try {\n console.log(`Downloading ${file.filename} from ${file.url}...`);\n const content = await downloadFile(file.url, file.headers);\n const filePath = join(tempDir, file.filename);\n await writeFile(filePath, content, \"utf-8\");\n console.log(`✓ Saved ${file.filename}`);\n } catch (error) {\n console.error(`✗ Failed to download ${file.filename}:`, error);\n throw error;\n }\n }\n\n // Read and parse page.json\n const pageJsonPath = join(tempDir, \"page.json\");\n const pageJsonContent = await readFile(pageJsonPath, \"utf-8\");\n const pageResponse = JSON.parse(pageJsonContent);\n\n // Extract page data - API response has it under 'data' field\n let pageData = pageResponse.data || pageResponse;\n\n // If pageData doesn't have body, try using cached app.json or downloading as fallback\n if (!pageData.body && !(pageData as any).data?.body) {\n console.log(\"Page data doesn't have body, trying app.json...\");\n try {\n let appData = cachedAppData;\n\n // If we don't have cached data, download it\n if (!appData) {\n const appUrl = `${APPS_SERVICE_URL}/devices/apps/${appId}`;\n const appContent = await downloadFile(appUrl);\n appData = JSON.parse(appContent);\n }\n\n // Find the page in app.data.pages\n const pages = appData?.app?.data?.pages || [];\n const page = pages.find((p: any) => p.id === pageId);\n if (page) {\n pageData = page;\n console.log(\"✓ Found page data in app.json\");\n }\n } catch (error) {\n console.warn(\"Could not load app.json:\", error);\n }\n }\n\n // Find components using extracted logic\n const sliders = findSlidersAndDataBindings(pageData);\n const standaloneComponents = findStandaloneComponents(pageData);\n const inputGroups = findInputGroups(pageData);\n const forms = findForms(pageData);\n\n // Qualify form input prop names\n qualifyFormInputs(forms);\n\n const selectInputs = findStandaloneSelectInputs(pageData, forms);\n const actionButtons = findActionButtons(pageData);\n\n // Extract app name and page name\n let appName = \"Encore App\";\n let pageName = \"Page\";\n\n try {\n let appDataForName = cachedAppData;\n if (!appDataForName) {\n const appJsonPath = join(tempDir, \"app.json\");\n if (existsSync(appJsonPath)) {\n const appJsonContent = await readFile(appJsonPath, \"utf-8\");\n appDataForName = JSON.parse(appJsonContent);\n }\n }\n if (appDataForName) {\n appName = appDataForName?.app?.store?.name || appName;\n }\n } catch (error) {\n // Ignore errors, use defaults\n }\n\n pageName = pageData.name || pageData.id || pageName;\n\n // Generate component name and directory name\n const { directoryPath, componentName } = generateNames(appName, pageName);\n const directoryName = directoryPath;\n\n // Update output path\n if (needsFilenameGeneration) {\n finalOutputPath = join(outputPath, directoryName);\n } else {\n const providedDir = dirname(finalOutputPath);\n finalOutputPath = join(providedDir, directoryName);\n }\n\n // Generate component code and README\n const componentCode = generateComponentCode(\n appId,\n pageId,\n componentName,\n sliders,\n standaloneComponents,\n inputGroups,\n forms,\n selectInputs,\n actionButtons,\n !!isProduction,\n {\n width: pageData.style?.width,\n height: pageData.style?.height,\n aspectRatio:\n pageData.style?.width && pageData.style?.height\n ? pageData.style.width / pageData.style.height\n : undefined,\n }\n );\n\n const readmeContent = generateReadme(\n appId,\n pageId,\n appName,\n pageName,\n componentName,\n sliders,\n standaloneComponents,\n inputGroups,\n forms,\n selectInputs,\n actionButtons\n );\n\n // Ensure output directory exists\n if (!existsSync(finalOutputPath)) {\n await mkdir(finalOutputPath, { recursive: true });\n }\n\n // Write files\n if (isProduction) {\n const componentJsPath = join(tempDir, \"component.js\");\n let componentCodeContent = \"\";\n try {\n componentCodeContent = await readFile(componentJsPath, \"utf-8\");\n } catch (e) {}\n\n let appDataForProd = cachedAppData;\n if (!appDataForProd) {\n try {\n const appJsonPath = join(tempDir, \"app.json\");\n const appJsonContent = await readFile(appJsonPath, \"utf-8\");\n appDataForProd = JSON.parse(appJsonContent);\n } catch (e) {}\n }\n\n const productionData = {\n app: appDataForProd,\n page: pageData,\n componentCode: componentCodeContent,\n };\n await writeFile(\n join(finalOutputPath, \"data.json\"),\n JSON.stringify(productionData, null, 2),\n \"utf-8\"\n );\n }\n\n const indexPath = join(finalOutputPath, \"index.tsx\");\n const readmePath = join(finalOutputPath, \"README.md\");\n\n await writeFile(indexPath, componentCode, \"utf-8\");\n await writeFile(readmePath, readmeContent, \"utf-8\");\n\n console.log(`✓ Generated wrapper component at: ${indexPath}`);\n}\n\nfunction printUsage() {\n console.log(`\nUsage: generate-wrapper.ts <appId> [pageId] <outputPath>\n\nArguments:\n appId The Encore app ID\n pageId The Encore page ID (optional - if omitted, generates wrappers for ALL pages)\n outputPath Path where the generated TSX file(s) should be saved\n\nEnvironment variables:\n APPS_SERVICE_URL Base URL for the apps service\n\nExample:\n generate-wrapper.ts 01KA964B1T6KCKSKCNMYSTKRKZ 01KA964B2F42MN4WGCYDTG1Y70 ./src/components/MyEncoreApp.tsx\n`);\n}\n\nexport async function runGenerate(args: string[]) {\n const isProduction = args.includes(\"--production\");\n const cleanArgs = args.filter((arg) => arg !== \"--production\");\n\n if (\n cleanArgs.length < 2 ||\n cleanArgs.includes(\"--help\") ||\n cleanArgs.includes(\"-h\")\n ) {\n printUsage();\n process.exit(\n cleanArgs.includes(\"--help\") || cleanArgs.includes(\"-h\") ? 0 : 1\n );\n }\n\n if (cleanArgs.length === 2) {\n const [appId, outputPath] = cleanArgs;\n\n try {\n const { pages, appData } = await getAppPages(appId);\n if (pages.length === 0) {\n console.warn(\"No pages found for this app.\");\n return;\n }\n\n for (const page of pages) {\n if (!page.id) continue;\n try {\n await generateWrapper({\n appId,\n pageId: page.id,\n outputPath,\n cachedAppData: appData,\n isProduction,\n });\n } catch (error) {\n console.warn(\n `Error with page ${page.id}:`,\n error instanceof Error ? error.message : error\n );\n }\n }\n } catch (error) {\n console.error(\"\\nError:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n return;\n }\n\n const [appId, pageId, outputPath] = cleanArgs;\n\n try {\n await generateWrapper({ appId, pageId, outputPath, isProduction });\n } catch (error) {\n console.error(\"\\nError:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n"],"names":["writeFile","mkdir","readFile","fs","dotenv.config","APPS_SERVICE_URL","CONST_APPS_SERVICE_URL","COMPONENTS_CDN_URL","CONST_COMPONENTS_CDN_URL","downloadFile","url","headers","response","generateNames","appName","pageName","appCamel","sanitizePropName","pageCamel","appPascal","pagePascal","join","getAppPages","appId","content","appData","error","generateWrapper","pageId","outputPath","cachedAppData","isProduction","finalOutputPath","needsFilenameGeneration","pathExt","stat","tempDir","existsSync","files","file","filePath","pageJsonPath","pageJsonContent","pageResponse","pageData","appUrl","appContent","page","p","sliders","findSlidersAndDataBindings","standaloneComponents","findStandaloneComponents","inputGroups","findInputGroups","forms","findForms","qualifyFormInputs","selectInputs","findStandaloneSelectInputs","actionButtons","findActionButtons","appDataForName","appJsonPath","appJsonContent","directoryPath","componentName","directoryName","providedDir","dirname","componentCode","generateComponentCode","readmeContent","generateReadme","componentJsPath","componentCodeContent","appDataForProd","productionData","indexPath","readmePath","printUsage","runGenerate","args","cleanArgs","arg","pages"],"mappings":"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"}
|