@bravostudioai/react 0.1.31 → 0.1.34

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.
Files changed (83) hide show
  1. package/dist/cli/commands/download.js +22 -39
  2. package/dist/cli/commands/download.js.map +1 -1
  3. package/dist/cli/commands/generate.js +130 -147
  4. package/dist/cli/commands/generate.js.map +1 -1
  5. package/dist/cli.js +21 -24
  6. package/dist/cli.js.map +1 -1
  7. package/dist/codegen/generator.js +126 -125
  8. package/dist/codegen/generator.js.map +1 -1
  9. package/dist/codegen/parser.js +256 -593
  10. package/dist/codegen/parser.js.map +1 -1
  11. package/dist/codegen/propQualification.js +117 -0
  12. package/dist/codegen/propQualification.js.map +1 -0
  13. package/dist/components/DynamicComponent.js.map +1 -1
  14. package/dist/components/EncoreApp.js +156 -265
  15. package/dist/components/EncoreApp.js.map +1 -1
  16. package/dist/components/EncoreContextProviders.js +24 -0
  17. package/dist/components/EncoreContextProviders.js.map +1 -0
  18. package/dist/components.js +179 -174
  19. package/dist/components.js.map +1 -1
  20. package/dist/hooks/useFontLoader.js +41 -0
  21. package/dist/hooks/useFontLoader.js.map +1 -0
  22. package/dist/hooks/usePusherUpdates.js +41 -45
  23. package/dist/hooks/usePusherUpdates.js.map +1 -1
  24. package/dist/hooks/useRepeatingContainers.js +79 -0
  25. package/dist/hooks/useRepeatingContainers.js.map +1 -0
  26. package/dist/index.js +13 -14
  27. package/dist/index.js.map +1 -1
  28. package/dist/lib/dataPatching.js +24 -0
  29. package/dist/lib/dataPatching.js.map +1 -0
  30. package/dist/lib/dynamicModules.js +44 -45
  31. package/dist/lib/dynamicModules.js.map +1 -1
  32. package/dist/lib/fetcher.js +6 -13
  33. package/dist/lib/fetcher.js.map +1 -1
  34. package/dist/lib/logger.js +35 -0
  35. package/dist/lib/logger.js.map +1 -0
  36. package/dist/lib/moduleRegistry.js +9 -8
  37. package/dist/lib/moduleRegistry.js.map +1 -1
  38. package/dist/src/cli/commands/download.d.ts +1 -1
  39. package/dist/src/cli/commands/download.d.ts.map +1 -1
  40. package/dist/src/cli/commands/generate.d.ts +1 -1
  41. package/dist/src/cli/commands/generate.d.ts.map +1 -1
  42. package/dist/src/codegen/generator.d.ts +75 -1
  43. package/dist/src/codegen/generator.d.ts.map +1 -1
  44. package/dist/src/codegen/parser.d.ts +39 -0
  45. package/dist/src/codegen/parser.d.ts.map +1 -1
  46. package/dist/src/codegen/propQualification.d.ts +42 -0
  47. package/dist/src/codegen/propQualification.d.ts.map +1 -0
  48. package/dist/src/components/DynamicComponent.d.ts +1 -1
  49. package/dist/src/components/DynamicComponent.d.ts.map +1 -1
  50. package/dist/src/components/EncoreApp.d.ts +58 -3
  51. package/dist/src/components/EncoreApp.d.ts.map +1 -1
  52. package/dist/src/components/EncoreContextProviders.d.ts +34 -0
  53. package/dist/src/components/EncoreContextProviders.d.ts.map +1 -0
  54. package/dist/src/components.d.ts.map +1 -1
  55. package/dist/src/hooks/useFontLoader.d.ts +17 -0
  56. package/dist/src/hooks/useFontLoader.d.ts.map +1 -0
  57. package/dist/src/hooks/usePusherUpdates.d.ts.map +1 -1
  58. package/dist/src/hooks/useRepeatingContainers.d.ts +31 -0
  59. package/dist/src/hooks/useRepeatingContainers.d.ts.map +1 -0
  60. package/dist/src/index.d.ts +2 -0
  61. package/dist/src/index.d.ts.map +1 -1
  62. package/dist/src/lib/dataPatching.d.ts +18 -0
  63. package/dist/src/lib/dataPatching.d.ts.map +1 -0
  64. package/dist/src/lib/dynamicModules.d.ts.map +1 -1
  65. package/dist/src/lib/fetcher.d.ts.map +1 -1
  66. package/dist/src/lib/logger.d.ts +33 -0
  67. package/dist/src/lib/logger.d.ts.map +1 -0
  68. package/dist/src/lib/moduleRegistry.d.ts.map +1 -1
  69. package/dist/src/stores/useEncoreState.d.ts +43 -1
  70. package/dist/src/stores/useEncoreState.d.ts.map +1 -1
  71. package/dist/src/version.d.ts +1 -1
  72. package/dist/stores/useEncoreState.js.map +1 -1
  73. package/dist/version.js +1 -1
  74. package/dist/version.js.map +1 -1
  75. package/package.json +2 -1
  76. package/src/cli/commands/download.ts +8 -28
  77. package/src/cli/commands/generate.ts +44 -45
  78. package/src/cli/index.ts +49 -32
  79. package/src/codegen/generator.ts +6 -3
  80. package/src/components/DynamicComponent.tsx +1 -1
  81. package/src/components/EncoreApp.tsx +111 -21
  82. package/src/hooks/useRepeatingContainers.ts +1 -1
  83. package/src/version.ts +1 -1
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Data patching utilities for fixing layout and component issues
3
+ *
4
+ * Applies heuristic-based fixes to page data to correct common layout problems
5
+ * that occur during the Figma-to-Encore conversion process.
6
+ */
7
+ /**
8
+ * Recursively patches page data to fix layout issues
9
+ *
10
+ * Current heuristics:
11
+ * 1. Horizontal layout detection - If children widths sum to ~100% or ~375px,
12
+ * force HORIZONTAL layout mode to prevent vertical stacking
13
+ *
14
+ * @param clientData - The client data object from page definition
15
+ * @returns Patched client data (mutates in place)
16
+ */
17
+ export declare function patchPageData(clientData: any): any;
18
+ //# sourceMappingURL=dataPatching.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataPatching.d.ts","sourceRoot":"","sources":["../../../src/lib/dataPatching.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,GAAG,GAAG,GAAG,CA0DlD"}
@@ -1 +1 @@
1
- {"version":3,"file":"dynamicModules.d.ts","sourceRoot":"","sources":["../../../src/lib/dynamicModules.ts"],"names":[],"mappings":"AAUA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,gBAyGvD;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,gBAoE1C;AAOD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"dynamicModules.d.ts","sourceRoot":"","sources":["../../../src/lib/dynamicModules.ts"],"names":[],"mappings":"AAWA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,gBAuGvD;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,gBAoE1C;AAOD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../../src/lib/fetcher.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,iBAAiB,cAEtB,CAAC;AAIF,QAAA,MAAM,OAAO,GAAI,KAAK,MAAM,QA2F3B,CAAC;AAEF,eAAe,OAAO,CAAC;AACvB,OAAO,EAAE,iBAAiB,IAAI,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../../src/lib/fetcher.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,iBAAiB,cAEtB,CAAC;AAIF,QAAA,MAAM,OAAO,GAAI,KAAK,MAAM,QAmF3B,CAAC;AAEF,eAAe,OAAO,CAAC;AACvB,OAAO,EAAE,iBAAiB,IAAI,cAAc,EAAE,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Centralized logging utility for encore-lib
3
+ *
4
+ * Provides conditional logging based on environment.
5
+ * Debug logs only appear in development mode.
6
+ */
7
+ /**
8
+ * Logger instance with environment-aware methods
9
+ */
10
+ export declare const logger: {
11
+ /**
12
+ * Debug-level logging (only in development)
13
+ * Use for detailed diagnostic information
14
+ */
15
+ debug: (...args: any[]) => void;
16
+ /**
17
+ * Info-level logging (only in development)
18
+ * Use for general informational messages
19
+ */
20
+ info: (...args: any[]) => void;
21
+ /**
22
+ * Warning-level logging (always shown)
23
+ * Use for recoverable issues that need attention
24
+ */
25
+ warn: (...args: any[]) => void;
26
+ /**
27
+ * Error-level logging (always shown)
28
+ * Use for errors and exceptions
29
+ */
30
+ error: (...args: any[]) => void;
31
+ };
32
+ export default logger;
33
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;GAEG;AACH,eAAO,MAAM,MAAM;IACjB;;;OAGG;qBACc,GAAG,EAAE;IAMtB;;;OAGG;oBACa,GAAG,EAAE;IAMrB;;;OAGG;oBACa,GAAG,EAAE;IAIrB;;;OAGG;qBACc,GAAG,EAAE;CAGvB,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"moduleRegistry.d.ts","sourceRoot":"","sources":["../../../src/lib/moduleRegistry.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAEvD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,OAE5C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKnD"}
1
+ {"version":3,"file":"moduleRegistry.d.ts","sourceRoot":"","sources":["../../../src/lib/moduleRegistry.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAEvD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,OAE5C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKnD"}
@@ -1,33 +1,75 @@
1
- type EncoreState = {
1
+ /**
2
+ * Global state for the Encore runtime
3
+ *
4
+ * Manages app data, form inputs, authentication, and UI state across
5
+ * all Encore components in the application.
6
+ */
7
+ export type EncoreState = {
8
+ /** Current app definition loaded from Encore service */
2
9
  app: any;
10
+ /** Base URL for Encore service API requests */
3
11
  baseURL: string;
12
+ /** Authentication token with expiration and refresh capability */
4
13
  accessToken?: {
5
14
  expireAt: number;
6
15
  token: string;
7
16
  refreshToken: string;
8
17
  params: string;
9
18
  };
19
+ /** Currently loaded app ID */
10
20
  appId?: string;
21
+ /** Form input values organized by page ID, then by component ID */
11
22
  formInputs: Record<string, Record<string, any>>;
23
+ /** Currently loaded page ID */
12
24
  pageId?: string;
25
+ /** Component variant selections for stateful sets */
13
26
  statefulSetVariants: Record<string, string>;
27
+ /** Input group selections - maps group name to active element name */
14
28
  inputGroups: Record<string, string>;
29
+ /** Asset lookup by ID (images, videos, etc.) */
15
30
  assetsById: Record<string, any>;
31
+ /** Font family names by font ID */
16
32
  fontsById: Record<string, string>;
33
+ /** Full font metadata by font ID */
17
34
  fontsByIdFull: Record<string, {
18
35
  family: string;
19
36
  postScriptName?: string;
20
37
  }>;
38
+ /** Clear all form inputs across all pages */
21
39
  resetFormInputs: () => void;
40
+ /** Set authentication token */
22
41
  setAccessToken: (accessToken: EncoreState["accessToken"]) => void;
42
+ /** Set app definition and extract assets/fonts */
23
43
  setApp: (app: any) => void;
44
+ /** Set current app ID */
24
45
  setAppId: (appId: string) => void;
46
+ /** Set form input value for current page */
25
47
  setFormInputValue: (nodeId: string, value: any) => void;
48
+ /** Set current page ID */
26
49
  setPageId: (pageId: string) => void;
50
+ /** Set active variant for a stateful set component */
27
51
  setStatefulSetVariant: (statefulSetId: string, variant: string) => void;
52
+ /** Set active element for an input group */
28
53
  setInputGroupValue: (groupName: string, elementName: string) => void;
54
+ /** Set base URL for Encore service */
29
55
  setBaseURL: (baseURL: string) => void;
30
56
  };
31
57
  declare const useEncoreState: import("zustand").UseBoundStore<import("zustand").StoreApi<EncoreState>>;
58
+ /**
59
+ * Global Zustand store for Encore runtime state
60
+ *
61
+ * Provides centralized state management for app data, form inputs,
62
+ * authentication, and UI state across all Encore components.
63
+ *
64
+ * @example
65
+ * // Access state in a component
66
+ * const app = useEncoreState((state) => state.app);
67
+ * const setFormValue = useEncoreState((state) => state.setFormInputValue);
68
+ *
69
+ * @example
70
+ * // Access state outside React components
71
+ * const currentApp = useEncoreState.getState().app;
72
+ * useEncoreState.getState().setAppId('01ABC123');
73
+ */
32
74
  export default useEncoreState;
33
75
  //# sourceMappingURL=useEncoreState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEncoreState.d.ts","sourceRoot":"","sources":["../../../src/stores/useEncoreState.ts"],"names":[],"mappings":"AAKA,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,GAAG,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE3E,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,cAAc,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IAClE,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACxD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,QAAA,MAAM,cAAc,0EA4FjB,CAAC;AAEJ,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"useEncoreState.d.ts","sourceRoot":"","sources":["../../../src/stores/useEncoreState.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,wDAAwD;IACxD,GAAG,EAAE,GAAG,CAAC;IAET,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAEhB,kEAAkE;IAClE,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IAEF,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAEhD,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,qDAAqD;IACrD,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE5C,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEpC,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEhC,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAElC,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE3E,6CAA6C;IAC7C,eAAe,EAAE,MAAM,IAAI,CAAC;IAE5B,+BAA+B;IAC/B,cAAc,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IAElE,kDAAkD;IAClD,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAE3B,yBAAyB;IACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,4CAA4C;IAC5C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAExD,0BAA0B;IAC1B,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAEpC,sDAAsD;IACtD,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAExE,4CAA4C;IAC5C,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAErE,sCAAsC;IACtC,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,QAAA,MAAM,cAAc,0EA4FjB,CAAC;AAEJ;;;;;;;;;;;;;;;GAeG;AACH,eAAe,cAAc,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const PACKAGE_VERSION = "0.1.28";
1
+ export declare const PACKAGE_VERSION = "0.1.34";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEncoreState.js","sources":["../../src/stores/useEncoreState.ts"],"sourcesContent":["\"use client\";\nimport { create } from \"zustand\";\n\nimport { CONST_APPS_SERVICE_URL } from \"../../constants\";\n\ntype EncoreState = {\n app: any;\n baseURL: string;\n accessToken?: {\n expireAt: number;\n token: string;\n refreshToken: string;\n params: string;\n };\n appId?: string;\n formInputs: Record<string, Record<string, any>>;\n pageId?: string;\n statefulSetVariants: Record<string, string>;\n inputGroups: Record<string, string>; // Maps group name to active element name\n assetsById: Record<string, any>;\n fontsById: Record<string, string>;\n fontsByIdFull: Record<string, { family: string; postScriptName?: string }>;\n\n resetFormInputs: () => void;\n setAccessToken: (accessToken: EncoreState[\"accessToken\"]) => void;\n setApp: (app: any) => void;\n setAppId: (appId: string) => void;\n setFormInputValue: (nodeId: string, value: any) => void;\n setPageId: (pageId: string) => void;\n setStatefulSetVariant: (statefulSetId: string, variant: string) => void;\n setInputGroupValue: (groupName: string, elementName: string) => void;\n setBaseURL: (baseURL: string) => void;\n};\n\nconst useEncoreState = create<EncoreState>((set) => ({\n app: undefined,\n baseURL:\n (typeof import.meta !== \"undefined\" &&\n (import.meta as any).env &&\n (import.meta as any).env.VITE_APPS_SERVICE_URL) ||\n CONST_APPS_SERVICE_URL,\n\n accessToken: undefined,\n appId: undefined,\n formInputs: {},\n pageId: undefined,\n statefulSetVariants: {},\n inputGroups: {},\n assetsById: {},\n fontsById: {},\n fontsByIdFull: {},\n\n resetFormInputs: () => set((state) => ({ ...state, formInputs: {} })),\n\n setAccessToken: (accessToken) => set((state) => ({ ...state, accessToken })),\n\n setApp: (app: any) =>\n set((state) => ({\n ...state,\n app,\n assetsById:\n app.app?.assets?.reduce?.(\n (acc: Record<string, any>, asset: any) => ({\n ...acc,\n [asset.id]: asset,\n }),\n {}\n ) ?? {},\n fontsById:\n app.app?.fonts?.reduce?.(\n (acc: Record<string, string>, font: any) => ({\n ...acc,\n [font.id]:\n font.fontName?.postScriptName ||\n font.fontName?.family ||\n \"sans-serif\",\n }),\n {}\n ) ?? {},\n fontsByIdFull:\n app.app?.fonts?.reduce?.(\n (\n acc: Record<string, { family: string; postScriptName?: string }>,\n font: any\n ) => ({\n ...acc,\n [font.id]: {\n family: font.fontName?.family || \"sans-serif\",\n postScriptName: font.fontName?.postScriptName,\n },\n }),\n {}\n ) ?? {},\n })),\n\n setAppId: (appId) => set((state) => ({ ...state, appId })),\n\n setFormInputValue: (nodeId, value) =>\n set((state) => {\n const oldPageInputs = state.formInputs[state.pageId!] || {};\n const newPageInputs = { ...oldPageInputs, [nodeId]: value };\n const newInputs = { ...state.formInputs, [state.pageId!]: newPageInputs };\n return { ...state, formInputs: newInputs };\n }),\n\n setPageId: (pageId) => set((state) => ({ ...state, pageId })),\n\n setStatefulSetVariant: (statefulSetId, variant) =>\n set((state) => ({\n ...state,\n statefulSetVariants: {\n ...state.statefulSetVariants,\n [statefulSetId]: variant,\n },\n })),\n\n setInputGroupValue: (groupName, elementName) =>\n set((state) => ({\n ...state,\n inputGroups: {\n ...state.inputGroups,\n [groupName]: elementName,\n },\n })),\n\n setBaseURL: (baseURL) => set((state) => ({ ...state, baseURL })),\n}));\n\nexport default useEncoreState;\n"],"names":["useEncoreState","create","set","CONST_APPS_SERVICE_URL","state","accessToken","app","acc","asset","font","appId","nodeId","value","newPageInputs","newInputs","pageId","statefulSetId","variant","groupName","elementName","baseURL"],"mappings":";;AAkCA,MAAMA,IAAiBC,EAAoB,CAACC,OAAS;AAAA,EACnD,KAAK;AAAA,EACL,SAIEC;AAAA,EAEF,aAAa;AAAA,EACb,OAAO;AAAA,EACP,YAAY,CAAA;AAAA,EACZ,QAAQ;AAAA,EACR,qBAAqB,CAAA;AAAA,EACrB,aAAa,CAAA;AAAA,EACb,YAAY,CAAA;AAAA,EACZ,WAAW,CAAA;AAAA,EACX,eAAe,CAAA;AAAA,EAEf,iBAAiB,MAAMD,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,YAAY,CAAA,EAAC,EAAI;AAAA,EAEpE,gBAAgB,CAACC,MAAgBH,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,aAAAC,EAAA,EAAc;AAAA,EAE3E,QAAQ,CAACC,MACPJ,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,KAAAE;AAAA,IACA,YACEA,EAAI,KAAK,QAAQ;AAAA,MACf,CAACC,GAA0BC,OAAgB;AAAA,QACzC,GAAGD;AAAA,QACH,CAACC,EAAM,EAAE,GAAGA;AAAA,MAAA;AAAA,MAEd,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,IACP,WACEF,EAAI,KAAK,OAAO;AAAA,MACd,CAACC,GAA6BE,OAAe;AAAA,QAC3C,GAAGF;AAAA,QACH,CAACE,EAAK,EAAE,GACNA,EAAK,UAAU,kBACfA,EAAK,UAAU,UACf;AAAA,MAAA;AAAA,MAEJ,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,IACP,eACEH,EAAI,KAAK,OAAO;AAAA,MACd,CACEC,GACAE,OACI;AAAA,QACJ,GAAGF;AAAA,QACH,CAACE,EAAK,EAAE,GAAG;AAAA,UACT,QAAQA,EAAK,UAAU,UAAU;AAAA,UACjC,gBAAgBA,EAAK,UAAU;AAAA,QAAA;AAAA,MACjC;AAAA,MAEF,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,EAAC,EACR;AAAA,EAEJ,UAAU,CAACC,MAAUR,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,OAAAM,EAAA,EAAQ;AAAA,EAEzD,mBAAmB,CAACC,GAAQC,MAC1BV,EAAI,CAACE,MAAU;AAEb,UAAMS,IAAgB,EAAE,GADFT,EAAM,WAAWA,EAAM,MAAO,KAAK,CAAA,GACf,CAACO,CAAM,GAAGC,EAAA,GAC9CE,IAAY,EAAE,GAAGV,EAAM,YAAY,CAACA,EAAM,MAAO,GAAGS,EAAA;AAC1D,WAAO,EAAE,GAAGT,GAAO,YAAYU,EAAA;AAAA,EACjC,CAAC;AAAA,EAEH,WAAW,CAACC,MAAWb,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,QAAAW,EAAA,EAAS;AAAA,EAE5D,uBAAuB,CAACC,GAAeC,MACrCf,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,qBAAqB;AAAA,MACnB,GAAGA,EAAM;AAAA,MACT,CAACY,CAAa,GAAGC;AAAA,IAAA;AAAA,EACnB,EACA;AAAA,EAEJ,oBAAoB,CAACC,GAAWC,MAC9BjB,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,aAAa;AAAA,MACX,GAAGA,EAAM;AAAA,MACT,CAACc,CAAS,GAAGC;AAAA,IAAA;AAAA,EACf,EACA;AAAA,EAEJ,YAAY,CAACC,MAAYlB,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,SAAAgB,IAAU;AACjE,EAAE;"}
1
+ {"version":3,"file":"useEncoreState.js","sources":["../../src/stores/useEncoreState.ts"],"sourcesContent":["\"use client\";\nimport { create } from \"zustand\";\n\nimport { CONST_APPS_SERVICE_URL } from \"../../constants\";\n\n/**\n * Global state for the Encore runtime\n *\n * Manages app data, form inputs, authentication, and UI state across\n * all Encore components in the application.\n */\nexport type EncoreState = {\n /** Current app definition loaded from Encore service */\n app: any;\n\n /** Base URL for Encore service API requests */\n baseURL: string;\n\n /** Authentication token with expiration and refresh capability */\n accessToken?: {\n expireAt: number;\n token: string;\n refreshToken: string;\n params: string;\n };\n\n /** Currently loaded app ID */\n appId?: string;\n\n /** Form input values organized by page ID, then by component ID */\n formInputs: Record<string, Record<string, any>>;\n\n /** Currently loaded page ID */\n pageId?: string;\n\n /** Component variant selections for stateful sets */\n statefulSetVariants: Record<string, string>;\n\n /** Input group selections - maps group name to active element name */\n inputGroups: Record<string, string>;\n\n /** Asset lookup by ID (images, videos, etc.) */\n assetsById: Record<string, any>;\n\n /** Font family names by font ID */\n fontsById: Record<string, string>;\n\n /** Full font metadata by font ID */\n fontsByIdFull: Record<string, { family: string; postScriptName?: string }>;\n\n /** Clear all form inputs across all pages */\n resetFormInputs: () => void;\n\n /** Set authentication token */\n setAccessToken: (accessToken: EncoreState[\"accessToken\"]) => void;\n\n /** Set app definition and extract assets/fonts */\n setApp: (app: any) => void;\n\n /** Set current app ID */\n setAppId: (appId: string) => void;\n\n /** Set form input value for current page */\n setFormInputValue: (nodeId: string, value: any) => void;\n\n /** Set current page ID */\n setPageId: (pageId: string) => void;\n\n /** Set active variant for a stateful set component */\n setStatefulSetVariant: (statefulSetId: string, variant: string) => void;\n\n /** Set active element for an input group */\n setInputGroupValue: (groupName: string, elementName: string) => void;\n\n /** Set base URL for Encore service */\n setBaseURL: (baseURL: string) => void;\n};\n\nconst useEncoreState = create<EncoreState>((set) => ({\n app: undefined,\n baseURL:\n (typeof import.meta !== \"undefined\" &&\n (import.meta as any).env &&\n (import.meta as any).env.VITE_APPS_SERVICE_URL) ||\n CONST_APPS_SERVICE_URL,\n\n accessToken: undefined,\n appId: undefined,\n formInputs: {},\n pageId: undefined,\n statefulSetVariants: {},\n inputGroups: {},\n assetsById: {},\n fontsById: {},\n fontsByIdFull: {},\n\n resetFormInputs: () => set((state) => ({ ...state, formInputs: {} })),\n\n setAccessToken: (accessToken) => set((state) => ({ ...state, accessToken })),\n\n setApp: (app: any) =>\n set((state) => ({\n ...state,\n app,\n assetsById:\n app.app?.assets?.reduce?.(\n (acc: Record<string, any>, asset: any) => ({\n ...acc,\n [asset.id]: asset,\n }),\n {}\n ) ?? {},\n fontsById:\n app.app?.fonts?.reduce?.(\n (acc: Record<string, string>, font: any) => ({\n ...acc,\n [font.id]:\n font.fontName?.postScriptName ||\n font.fontName?.family ||\n \"sans-serif\",\n }),\n {}\n ) ?? {},\n fontsByIdFull:\n app.app?.fonts?.reduce?.(\n (\n acc: Record<string, { family: string; postScriptName?: string }>,\n font: any\n ) => ({\n ...acc,\n [font.id]: {\n family: font.fontName?.family || \"sans-serif\",\n postScriptName: font.fontName?.postScriptName,\n },\n }),\n {}\n ) ?? {},\n })),\n\n setAppId: (appId) => set((state) => ({ ...state, appId })),\n\n setFormInputValue: (nodeId, value) =>\n set((state) => {\n const oldPageInputs = state.formInputs[state.pageId!] || {};\n const newPageInputs = { ...oldPageInputs, [nodeId]: value };\n const newInputs = { ...state.formInputs, [state.pageId!]: newPageInputs };\n return { ...state, formInputs: newInputs };\n }),\n\n setPageId: (pageId) => set((state) => ({ ...state, pageId })),\n\n setStatefulSetVariant: (statefulSetId, variant) =>\n set((state) => ({\n ...state,\n statefulSetVariants: {\n ...state.statefulSetVariants,\n [statefulSetId]: variant,\n },\n })),\n\n setInputGroupValue: (groupName, elementName) =>\n set((state) => ({\n ...state,\n inputGroups: {\n ...state.inputGroups,\n [groupName]: elementName,\n },\n })),\n\n setBaseURL: (baseURL) => set((state) => ({ ...state, baseURL })),\n}));\n\n/**\n * Global Zustand store for Encore runtime state\n *\n * Provides centralized state management for app data, form inputs,\n * authentication, and UI state across all Encore components.\n *\n * @example\n * // Access state in a component\n * const app = useEncoreState((state) => state.app);\n * const setFormValue = useEncoreState((state) => state.setFormInputValue);\n *\n * @example\n * // Access state outside React components\n * const currentApp = useEncoreState.getState().app;\n * useEncoreState.getState().setAppId('01ABC123');\n */\nexport default useEncoreState;\n"],"names":["useEncoreState","create","set","CONST_APPS_SERVICE_URL","state","accessToken","app","acc","asset","font","appId","nodeId","value","newPageInputs","newInputs","pageId","statefulSetId","variant","groupName","elementName","baseURL"],"mappings":";;AA8EA,MAAMA,IAAiBC,EAAoB,CAACC,OAAS;AAAA,EACnD,KAAK;AAAA,EACL,SAIEC;AAAA,EAEF,aAAa;AAAA,EACb,OAAO;AAAA,EACP,YAAY,CAAA;AAAA,EACZ,QAAQ;AAAA,EACR,qBAAqB,CAAA;AAAA,EACrB,aAAa,CAAA;AAAA,EACb,YAAY,CAAA;AAAA,EACZ,WAAW,CAAA;AAAA,EACX,eAAe,CAAA;AAAA,EAEf,iBAAiB,MAAMD,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,YAAY,CAAA,EAAC,EAAI;AAAA,EAEpE,gBAAgB,CAACC,MAAgBH,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,aAAAC,EAAA,EAAc;AAAA,EAE3E,QAAQ,CAACC,MACPJ,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,KAAAE;AAAA,IACA,YACEA,EAAI,KAAK,QAAQ;AAAA,MACf,CAACC,GAA0BC,OAAgB;AAAA,QACzC,GAAGD;AAAA,QACH,CAACC,EAAM,EAAE,GAAGA;AAAA,MAAA;AAAA,MAEd,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,IACP,WACEF,EAAI,KAAK,OAAO;AAAA,MACd,CAACC,GAA6BE,OAAe;AAAA,QAC3C,GAAGF;AAAA,QACH,CAACE,EAAK,EAAE,GACNA,EAAK,UAAU,kBACfA,EAAK,UAAU,UACf;AAAA,MAAA;AAAA,MAEJ,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,IACP,eACEH,EAAI,KAAK,OAAO;AAAA,MACd,CACEC,GACAE,OACI;AAAA,QACJ,GAAGF;AAAA,QACH,CAACE,EAAK,EAAE,GAAG;AAAA,UACT,QAAQA,EAAK,UAAU,UAAU;AAAA,UACjC,gBAAgBA,EAAK,UAAU;AAAA,QAAA;AAAA,MACjC;AAAA,MAEF,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,EAAC,EACR;AAAA,EAEJ,UAAU,CAACC,MAAUR,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,OAAAM,EAAA,EAAQ;AAAA,EAEzD,mBAAmB,CAACC,GAAQC,MAC1BV,EAAI,CAACE,MAAU;AAEb,UAAMS,IAAgB,EAAE,GADFT,EAAM,WAAWA,EAAM,MAAO,KAAK,CAAA,GACf,CAACO,CAAM,GAAGC,EAAA,GAC9CE,IAAY,EAAE,GAAGV,EAAM,YAAY,CAACA,EAAM,MAAO,GAAGS,EAAA;AAC1D,WAAO,EAAE,GAAGT,GAAO,YAAYU,EAAA;AAAA,EACjC,CAAC;AAAA,EAEH,WAAW,CAACC,MAAWb,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,QAAAW,EAAA,EAAS;AAAA,EAE5D,uBAAuB,CAACC,GAAeC,MACrCf,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,qBAAqB;AAAA,MACnB,GAAGA,EAAM;AAAA,MACT,CAACY,CAAa,GAAGC;AAAA,IAAA;AAAA,EACnB,EACA;AAAA,EAEJ,oBAAoB,CAACC,GAAWC,MAC9BjB,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,aAAa;AAAA,MACX,GAAGA,EAAM;AAAA,MACT,CAACc,CAAS,GAAGC;AAAA,IAAA;AAAA,EACf,EACA;AAAA,EAEJ,YAAY,CAACC,MAAYlB,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,SAAAgB,IAAU;AACjE,EAAE;"}
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const o = "0.1.28";
1
+ const o = "0.1.34";
2
2
  export {
3
3
  o as PACKAGE_VERSION
4
4
  };
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = \"0.1.28\";\n"],"names":["PACKAGE_VERSION"],"mappings":"AAAO,MAAMA,IAAkB;"}
1
+ {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = \"0.1.34\";\n"],"names":["PACKAGE_VERSION"],"mappings":"AAAO,MAAMA,IAAkB;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bravostudioai/react",
3
- "version": "0.1.31",
3
+ "version": "0.1.34",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/src/index.d.ts",
@@ -39,6 +39,7 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "axios": "^1.13.0",
42
+ "commander": "^14.0.2",
42
43
  "dotenv": "^16.0.0",
43
44
  "pusher-js": "^8.4.0",
44
45
  "swr": "^2.3.6",
@@ -88,35 +88,15 @@ async function downloadEncoreFiles({
88
88
  console.log("\n✓ All files downloaded successfully!");
89
89
  }
90
90
 
91
- function printUsage() {
92
- console.log(`
93
- Usage: download-bravo.ts <appId> <pageId> <targetPath>
94
-
95
- Arguments:
96
- appId The Encore app ID
97
- pageId The Encore page ID
98
- targetPath Path where files should be saved
99
-
100
- Environment variables:
101
- APPS_SERVICE_URL Base URL for the apps service
102
-
103
- Example:
104
- download-bravo.ts my-app-id my-page-id ./bravo-files
105
- APPS_SERVICE_URL=https://api.example.com download-bravo.ts my-app-id my-page-id ./bravo-files
106
- `);
107
- }
108
-
109
- export async function runDownload(args: string[]) {
110
- if (args.length < 3 || args.includes("--help") || args.includes("-h")) {
111
- printUsage();
112
- process.exit(args.includes("--help") || args.includes("-h") ? 0 : 1);
113
- }
114
-
115
- const [appId, pageId, targetPath] = args;
116
-
91
+ export async function runDownload(
92
+ appId: string,
93
+ pageId: string,
94
+ targetPath: string
95
+ ) {
117
96
  if (!appId || !pageId || !targetPath) {
118
- console.error("Error: Missing required arguments");
119
- printUsage();
97
+ console.error(
98
+ "Error: Missing required arguments. Usage: download <appId> <pageId> <targetPath>"
99
+ );
120
100
  process.exit(1);
121
101
  }
122
102
 
@@ -84,17 +84,19 @@ async function generateWrapper({
84
84
  pageId,
85
85
  outputPath,
86
86
  cachedAppData,
87
- isProduction,
87
+ mode = "dynamic",
88
88
  usedNames,
89
89
  }: {
90
90
  appId: string;
91
91
  pageId: string;
92
92
  outputPath: string;
93
93
  cachedAppData?: any;
94
- isProduction?: boolean;
94
+ mode?: string;
95
95
  usedNames?: Set<string>;
96
96
  }) {
97
- console.log(`Generating wrapper for app: ${appId}, page: ${pageId}`);
97
+ console.log(
98
+ `Generating wrapper for app: ${appId}, page: ${pageId}, mode: ${mode}`
99
+ );
98
100
 
99
101
  // Determine final output path - we'll update it after we get app/page names
100
102
  let finalOutputPath = outputPath;
@@ -283,6 +285,7 @@ async function generateWrapper({
283
285
  }
284
286
 
285
287
  // Generate component code and README
288
+ const shouldBundleData = mode === "production" || mode === "optimistic";
286
289
  const componentCode = generateComponentCode(
287
290
  appId,
288
291
  pageId,
@@ -293,7 +296,7 @@ async function generateWrapper({
293
296
  forms,
294
297
  selectInputs,
295
298
  actionButtons,
296
- !!isProduction,
299
+ mode,
297
300
  {
298
301
  width: pageData.style?.width,
299
302
  height: pageData.style?.height,
@@ -324,7 +327,7 @@ async function generateWrapper({
324
327
  }
325
328
 
326
329
  // Write files
327
- if (isProduction) {
330
+ if (shouldBundleData) {
328
331
  const componentJsPath = join(tempDir, "component.js");
329
332
  let componentCodeContent = "";
330
333
  try {
@@ -361,46 +364,43 @@ async function generateWrapper({
361
364
  console.log(`✓ Generated wrapper component at: ${indexPath}`);
362
365
  }
363
366
 
364
- function printUsage() {
365
- console.log(`
366
- Usage: generate-wrapper.ts <appId> [pageId] <outputPath>
367
-
368
- Arguments:
369
- appId The Encore app ID
370
- pageId The Encore page ID (optional - if omitted, generates wrappers for ALL pages)
371
- outputPath Path where the generated TSX file(s) should be saved
372
- --production Generate for production (bundles data)
373
- --preseed Alias for --production (bundles data)
374
-
375
- Environment variables:
376
- APPS_SERVICE_URL Base URL for the apps service
377
-
378
- Example:
379
- generate-wrapper.ts 01KA964B1T6KCKSKCNMYSTKRKZ 01KA964B2F42MN4WGCYDTG1Y70 ./src/components/MyEncoreApp.tsx
380
- `);
381
- }
382
-
383
- export async function runGenerate(args: string[]) {
384
- const isProduction =
385
- args.includes("--production") || args.includes("--preseed");
386
- const cleanArgs = args.filter(
387
- (arg) => arg !== "--production" && arg !== "--preseed"
388
- );
389
-
390
- if (
391
- cleanArgs.length < 2 ||
392
- cleanArgs.includes("--help") ||
393
- cleanArgs.includes("-h")
394
- ) {
395
- printUsage();
396
- process.exit(
397
- cleanArgs.includes("--help") || cleanArgs.includes("-h") ? 0 : 1
367
+ export async function runGenerate(
368
+ appId: string,
369
+ pageId: string | undefined,
370
+ outputPath: string | undefined,
371
+ mode: string
372
+ ) {
373
+ if (!appId || (!pageId && !outputPath)) {
374
+ console.error(
375
+ "Error: Missing required arguments. Usage: generate <appId> [pageId] <outputPath>"
398
376
  );
377
+ process.exit(1);
399
378
  }
400
379
 
401
- if (cleanArgs.length === 2) {
402
- const [appId, outputPath] = cleanArgs;
380
+ // If outputPath is missing but we have 2 args logic from caller, handle it.
381
+ // actually caller logic:
382
+ // if 2 args (appId, pageId/output), caller puts output in output and pageId=undefined.
383
+ // so if we are here, we have appId and outputPath. pageId might be undefined.
384
+
385
+ // Wait, if I changed the caller to pass (appId, undefined, outputPath), I need to be sure.
386
+ // arguments: appId, pageId, outputPath.
387
+ // If user ran: generate app out
388
+ // caller: appId=app, pageId=out, output=undefined.
389
+ // caller logic: if (pageId && !output) -> output=pageId, pageId=undefined.
390
+ // caller calls: runGenerate(app, undefined, out, prod).
391
+
392
+ // If user ran: generate app page out
393
+ // caller: appId=app, pageId=page, output=out.
394
+ // caller calls: runGenerate(app, page, out, prod).
395
+
396
+ // So outputPath MUST be defined here effectively if the CLI usage was correct.
397
+ if (!outputPath) {
398
+ console.error("Error: Missing output path.");
399
+ process.exit(1);
400
+ }
403
401
 
402
+ // Default mode: Generate all pages
403
+ if (!pageId) {
404
404
  try {
405
405
  const { pages, appData } = await getAppPages(appId);
406
406
  if (pages.length === 0) {
@@ -417,7 +417,7 @@ export async function runGenerate(args: string[]) {
417
417
  pageId: page.id,
418
418
  outputPath,
419
419
  cachedAppData: appData,
420
- isProduction,
420
+ mode,
421
421
  usedNames,
422
422
  });
423
423
  } catch (error) {
@@ -434,10 +434,9 @@ export async function runGenerate(args: string[]) {
434
434
  return;
435
435
  }
436
436
 
437
- const [appId, pageId, outputPath] = cleanArgs;
438
-
437
+ // Single page generation
439
438
  try {
440
- await generateWrapper({ appId, pageId, outputPath, isProduction }); // Single page generation, no collision context needed unless we wanted global uniqueness but usually used for one-off
439
+ await generateWrapper({ appId, pageId, outputPath, mode });
441
440
  } catch (error) {
442
441
  console.error("\nError:", error instanceof Error ? error.message : error);
443
442
  process.exit(1);
package/src/cli/index.ts CHANGED
@@ -1,35 +1,52 @@
1
-
1
+ import { Command } from "commander";
2
2
  import { runDownload } from "./commands/download";
3
3
  import { runGenerate } from "./commands/generate";
4
4
 
5
- async function main() {
6
- const args = process.argv.slice(2);
7
-
8
- if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
9
- console.log(`
10
- Usage: encore-lib <command> [options]
11
-
12
- Commands:
13
- download <appId> <pageId> <targetPath> Download Encore page data
14
- generate <appId> [pageId] <outputPath> Generate React wrapper components
15
- `);
16
- process.exit(0);
17
- }
18
-
19
- const command = args[0];
20
- const commandArgs = args.slice(1);
21
-
22
- switch (command) {
23
- case "download":
24
- await runDownload(commandArgs);
25
- break;
26
- case "generate":
27
- await runGenerate(commandArgs);
28
- break;
29
- default:
30
- console.error(`Unknown command: ${command}`);
31
- process.exit(1);
32
- }
33
- }
34
-
35
- main();
5
+ const program = new Command();
6
+
7
+ program
8
+ .name("encore-lib")
9
+ .description("Encore CLI tools")
10
+ // We'll read version from package.json in build or hardcode for now to avoid async import issues in simple CLI
11
+ .version("0.1.32");
12
+
13
+ program
14
+ .command("download")
15
+ .description("Download Encore page data")
16
+ .argument("<appId>", "The Encore app ID")
17
+ .argument("<pageId>", "The Encore page ID")
18
+ .argument("<targetPath>", "Path where files should be saved")
19
+ .action(async (appId, pageId, targetPath) => {
20
+ await runDownload(appId, pageId, targetPath);
21
+ });
22
+
23
+ program
24
+ .command("generate")
25
+ .description("Generate React wrapper components")
26
+ .argument("<appId>", "The Encore app ID")
27
+ .argument("[pageId]", "The Encore page ID (optional)")
28
+ .argument(
29
+ "[outputPath]",
30
+ "Path where the generated TSX file(s) should be saved"
31
+ )
32
+ .option(
33
+ "--mode <mode>",
34
+ "Deployment mode: dynamic (default), optimistic, or production"
35
+ )
36
+ .action(async (appId, pageId, outputPath, options) => {
37
+ // Handle overload: generate <appId> <outputPath> vs generate <appId> <pageId> <outputPath>
38
+ let finalPageId = pageId;
39
+ let finalOutputPath = outputPath;
40
+
41
+ // If only 2 arguments provided (appId and pageId/outputPath), the second one is outputPath
42
+ if (pageId && !outputPath) {
43
+ finalOutputPath = pageId;
44
+ finalPageId = undefined;
45
+ }
46
+
47
+ const mode = options.mode || "dynamic";
48
+
49
+ await runGenerate(appId, finalPageId, finalOutputPath, mode);
50
+ });
51
+
52
+ program.parse();
@@ -67,7 +67,7 @@ export function generateComponentCode(
67
67
  forms: FormInfo[],
68
68
  selectInputs: SelectInputInfo[],
69
69
  actionButtons: ActionButtonInfo[],
70
- isProduction: boolean = false,
70
+ mode: string = "dynamic",
71
71
  pageMeta?: {
72
72
  width?: number;
73
73
  height?: number;
@@ -448,6 +448,8 @@ ${inputGroupMapping.join("\n")}
448
448
  const propsParameter = hasProps ? `props: ${componentName}Props` : "";
449
449
  const propsInterfaceSection = propsInterface ? `${propsInterface}\n\n` : "";
450
450
 
451
+ const shouldBundleData = mode === "production" || mode === "optimistic";
452
+
451
453
  return `/**
452
454
  * ${componentName}
453
455
  *
@@ -458,7 +460,7 @@ ${inputGroupMapping.join("\n")}
458
460
  import { EncoreApp${
459
461
  forms.length > 0 ? ", useEncoreState" : ""
460
462
  } } from "@bravostudioai/react";
461
- ${isProduction ? `import productionData from "./data.json";` : ""}
463
+ ${shouldBundleData ? `import productionData from "./data.json";` : ""}
462
464
 
463
465
  ${itemTypes ? `${itemTypes}\n\n` : ""}${
464
466
  formDataTypes ? `${formDataTypes}\n\n` : ""
@@ -468,8 +470,9 @@ ${inputGroupHandlers.length > 0 ? inputGroupHandlers.join("\n") : ""}
468
470
  <EncoreApp
469
471
  appId="${appId}"
470
472
  pageId="${pageId}"
473
+ mode="${mode}"
471
474
  ${
472
- isProduction
475
+ shouldBundleData
473
476
  ? `appDefinition={productionData.app}
474
477
  pageDefinition={productionData.page}
475
478
  componentCode={productionData.componentCode}`
@@ -3,7 +3,7 @@ import React, { useMemo, Suspense } from "react";
3
3
 
4
4
  type Props = {
5
5
  name: string;
6
- children: unknown;
6
+ children?: React.ReactNode;
7
7
  componentId?: string;
8
8
  fallback?: React.ReactNode;
9
9
  reloadKey?: string | number;