@bravostudioai/react 0.1.16 → 0.1.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bravostudioai/react",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/src/index.d.ts",
@@ -85,12 +85,14 @@ async function generateWrapper({
85
85
  outputPath,
86
86
  cachedAppData,
87
87
  isProduction,
88
+ usedNames,
88
89
  }: {
89
90
  appId: string;
90
91
  pageId: string;
91
92
  outputPath: string;
92
93
  cachedAppData?: any;
93
94
  isProduction?: boolean;
95
+ usedNames?: Set<string>;
94
96
  }) {
95
97
  console.log(`Generating wrapper for app: ${appId}, page: ${pageId}`);
96
98
 
@@ -249,7 +251,27 @@ async function generateWrapper({
249
251
  pageName = pageData.name || pageData.id || pageName;
250
252
 
251
253
  // Generate component name and directory name
252
- const { directoryPath, componentName } = generateNames(appName, pageName);
254
+ let { directoryPath, componentName } = generateNames(appName, pageName);
255
+
256
+ // Ensure unique component name
257
+ if (usedNames) {
258
+ let uniqueName = componentName;
259
+ let counter = 2;
260
+ while (usedNames.has(uniqueName)) {
261
+ uniqueName = `${componentName}${counter}`;
262
+ counter++;
263
+ }
264
+ if (uniqueName !== componentName) {
265
+ componentName = uniqueName;
266
+ // Reconstitute directory path with new component name
267
+ // generateNames uses: join(appPascal, pagePascal) where pagePascal is componentName
268
+ const appCamel = sanitizePropName(appName);
269
+ const appPascal = appCamel.charAt(0).toUpperCase() + appCamel.slice(1);
270
+ directoryPath = join(appPascal, componentName);
271
+ }
272
+ usedNames.add(componentName);
273
+ }
274
+
253
275
  const directoryName = directoryPath;
254
276
 
255
277
  // Update output path
@@ -381,6 +403,7 @@ export async function runGenerate(args: string[]) {
381
403
  return;
382
404
  }
383
405
 
406
+ const usedNames = new Set<string>();
384
407
  for (const page of pages) {
385
408
  if (!page.id) continue;
386
409
  try {
@@ -390,6 +413,7 @@ export async function runGenerate(args: string[]) {
390
413
  outputPath,
391
414
  cachedAppData: appData,
392
415
  isProduction,
416
+ usedNames,
393
417
  });
394
418
  } catch (error) {
395
419
  console.warn(
@@ -408,7 +432,7 @@ export async function runGenerate(args: string[]) {
408
432
  const [appId, pageId, outputPath] = cleanArgs;
409
433
 
410
434
  try {
411
- await generateWrapper({ appId, pageId, outputPath, isProduction });
435
+ await generateWrapper({ appId, pageId, outputPath, isProduction }); // Single page generation, no collision context needed unless we wanted global uniqueness but usually used for one-off
412
436
  } catch (error) {
413
437
  console.error("\nError:", error instanceof Error ? error.message : error);
414
438
  process.exit(1);
@@ -4,104 +4,102 @@ import useEncoreState from "../stores/useEncoreState";
4
4
 
5
5
  // Get baseURL from store at runtime instead of build time
6
6
  const getAppsServiceUrl = () => {
7
- return useEncoreState.getState().baseURL;
7
+ return useEncoreState.getState().baseURL;
8
8
  };
9
9
 
10
10
  const bundledResponses: Record<string, string> = {};
11
11
 
12
12
  const fetcher = (url: string) => {
13
- // Local mode: map Encore service URLs to files in /flex-layout
14
- const forceLocal = /\buseLocal=1\b/.test(url);
15
- if (forceLocal || isLocalMode()) {
16
- const pathOnly = url.split("?")[0];
17
- const absBase = null;
18
- // /devices/apps/:appId
19
- const appMatch = pathOnly.match(/^\/devices\/apps\/([^/]+)$/);
20
- if (appMatch) {
21
- const appId = appMatch[1];
22
- const tryUrls = [
23
- `/flex-layout/${appId}/${appId}.json`,
24
- absBase
25
- ? `/@fs/${absBase}/${appId}/${appId}.json`
26
- : undefined,
27
- ].filter(Boolean) as string[];
28
- return (async () => {
29
- for (const u of tryUrls) {
30
- try {
31
- const r = await fetch(u);
32
- if (r.ok) return r.json();
33
- } catch {
34
- // try next
35
- }
36
- }
37
- throw new Error(
38
- `Local app.json not found for ${appId} (tried ${tryUrls.join(
39
- ", ",
40
- )})`,
41
- );
42
- })();
13
+ // Local mode: map Encore service URLs to files in /flex-layout
14
+ const forceLocal = /\buseLocal=1\b/.test(url);
15
+ if (forceLocal || isLocalMode()) {
16
+ const pathOnly = url.split("?")[0];
17
+ const absBase = null;
18
+ // /devices/apps/:appId
19
+ const appMatch = pathOnly.match(/^\/devices\/apps\/([^/]+)$/);
20
+ if (appMatch) {
21
+ const appId = appMatch[1];
22
+ const tryUrls = [
23
+ `/flex-layout/${appId}/${appId}.json`,
24
+ absBase ? `/@fs/${absBase}/${appId}/${appId}.json` : undefined,
25
+ ].filter(Boolean) as string[];
26
+ return (async () => {
27
+ for (const u of tryUrls) {
28
+ try {
29
+ const r = await fetch(u);
30
+ if (r.ok) return r.json();
31
+ } catch {
32
+ // try next
33
+ }
43
34
  }
44
- // /devices/apps/:appId/node/:pageId
45
- const pageMatch = pathOnly.match(
46
- /^\/devices\/apps\/([^/]+)\/node\/([^/?#]+)$/,
35
+ throw new Error(
36
+ `Local app.json not found for ${appId} (tried ${tryUrls.join(", ")})`
47
37
  );
48
- if (pageMatch) {
49
- const appId = pageMatch[1];
50
- const pageId = pageMatch[2];
51
- // Try a dedicated page JSON first (if present)
52
- const tryUrls = [
53
- `/flex-layout/${appId}/${pageId}.json`,
54
- absBase
55
- ? `/@fs/${absBase}/${appId}/${pageId}.json`
56
- : undefined,
57
- ].filter(Boolean) as string[];
58
- return fetch(tryUrls[0])
59
- .then(async (r) => {
60
- if (r.ok) return r.json();
61
- // try secondary url if defined
62
- if (tryUrls[1]) {
63
- const r2 = await fetch(tryUrls[1]).catch(() => null);
64
- if (r2 && r2.ok) return r2.json();
65
- }
66
- // Fallback: derive minimal shape from app.json
67
- const appJson =
68
- (await fetch(`/flex-layout/${appId}/${appId}.json`)
69
- .then((a) => (a.ok ? a.json() : null))
70
- .catch(() => null)) ||
71
- (absBase
72
- ? await fetch(
73
- `/@fs/${absBase}/${appId}/${appId}.json`,
74
- )
75
- .then((a) => (a.ok ? a.json() : null))
76
- .catch(() => null)
77
- : null);
78
- // Keep shape compatible with current consumers
79
- const pages =
80
- appJson?.app?.data?.pages ||
81
- appJson?.data?.pages ||
82
- [];
83
- const page = pages.find((p: any) => p?.id === pageId) || {};
84
- return { clientData: page };
85
- })
86
- .catch(async () => {
87
- // Final fallback: minimal object
88
- return { clientData: null };
89
- });
90
- }
38
+ })();
91
39
  }
92
-
93
- if (bundledResponses?.[url]) {
94
- return JSON.parse(bundledResponses?.[url]);
40
+ // /devices/apps/:appId/node/:pageId
41
+ const pageMatch = pathOnly.match(
42
+ /^\/devices\/apps\/([^/]+)\/node\/([^/?#]+)$/
43
+ );
44
+ if (pageMatch) {
45
+ const appId = pageMatch[1];
46
+ const pageId = pageMatch[2];
47
+ // Try a dedicated page JSON first (if present)
48
+ const tryUrls = [
49
+ `/flex-layout/${appId}/${pageId}.json`,
50
+ absBase ? `/@fs/${absBase}/${appId}/${pageId}.json` : undefined,
51
+ ].filter(Boolean) as string[];
52
+ return fetch(tryUrls[0])
53
+ .then(async (r) => {
54
+ if (r.ok) return r.json();
55
+ // try secondary url if defined
56
+ if (tryUrls[1]) {
57
+ const r2 = await fetch(tryUrls[1]).catch(() => null);
58
+ if (r2 && r2.ok) return r2.json();
59
+ }
60
+ // Fallback: derive minimal shape from app.json
61
+ const appJson =
62
+ (await fetch(`/flex-layout/${appId}/${appId}.json`)
63
+ .then((a) => (a.ok ? a.json() : null))
64
+ .catch(() => null)) ||
65
+ (absBase
66
+ ? await fetch(`/@fs/${absBase}/${appId}/${appId}.json`)
67
+ .then((a) => (a.ok ? a.json() : null))
68
+ .catch(() => null)
69
+ : null);
70
+ // Keep shape compatible with current consumers
71
+ const pages = appJson?.app?.data?.pages || appJson?.data?.pages || [];
72
+ const page = pages.find((p: any) => p?.id === pageId) || {};
73
+ return { clientData: page };
74
+ })
75
+ .catch(async () => {
76
+ // Final fallback: minimal object
77
+ return { clientData: null };
78
+ });
95
79
  }
80
+ }
81
+
82
+ if (bundledResponses?.[url]) {
83
+ return JSON.parse(bundledResponses?.[url]);
84
+ }
85
+
86
+ // Get baseURL at runtime from store
87
+ const appsServiceUrl = getAppsServiceUrl();
96
88
 
97
- // Get baseURL at runtime from store
98
- const appsServiceUrl = getAppsServiceUrl();
89
+ console.log(
90
+ "[Fetcher] Requesting:",
91
+ url,
92
+ "BaseURL:",
93
+ appsServiceUrl,
94
+ "Headers:",
95
+ { "x-app-clientrendered": "disabled" }
96
+ );
99
97
 
100
- return axios({
101
- baseURL: appsServiceUrl,
102
- url,
103
- headers: { "x-app-clientrendered": "true" },
104
- }).then((res) => res.data);
98
+ return axios({
99
+ baseURL: appsServiceUrl,
100
+ url,
101
+ // headers: { "x-app-clientrendered": "true" },
102
+ }).then((res) => res.data);
105
103
  };
106
104
 
107
105
  export default fetcher;