@memberjunction/react-runtime 2.92.0 â 2.94.0
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/.turbo/turbo-build.log +14 -16
- package/CHANGELOG.md +31 -0
- package/README.md +180 -2
- package/dist/compiler/babel-config.js.map +1 -1
- package/dist/compiler/component-compiler.d.ts.map +1 -1
- package/dist/compiler/component-compiler.js +206 -57
- package/dist/compiler/component-compiler.js.map +1 -1
- package/dist/compiler/index.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -5
- package/dist/index.js.map +1 -1
- package/dist/registry/component-registry-service.d.ts +37 -0
- package/dist/registry/component-registry-service.d.ts.map +1 -0
- package/dist/registry/component-registry-service.js +319 -0
- package/dist/registry/component-registry-service.js.map +1 -0
- package/dist/registry/component-registry.d.ts +4 -3
- package/dist/registry/component-registry.d.ts.map +1 -1
- package/dist/registry/component-registry.js.map +1 -1
- package/dist/registry/component-resolver.d.ts +12 -2
- package/dist/registry/component-resolver.d.ts.map +1 -1
- package/dist/registry/component-resolver.js +96 -12
- package/dist/registry/component-resolver.js.map +1 -1
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +3 -1
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/registry-provider.d.ts +54 -0
- package/dist/registry/registry-provider.d.ts.map +1 -0
- package/dist/registry/registry-provider.js +3 -0
- package/dist/registry/registry-provider.js.map +1 -0
- package/dist/runtime/component-hierarchy.d.ts.map +1 -1
- package/dist/runtime/component-hierarchy.js +8 -2
- package/dist/runtime/component-hierarchy.js.map +1 -1
- package/dist/runtime/error-boundary.js.map +1 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/prop-builder.d.ts +2 -2
- package/dist/runtime/prop-builder.d.ts.map +1 -1
- package/dist/runtime/prop-builder.js +32 -14
- package/dist/runtime/prop-builder.js.map +1 -1
- package/dist/runtime/react-root-manager.js.map +1 -1
- package/dist/runtime.umd.js +1 -1
- package/dist/types/dependency-types.d.ts +62 -0
- package/dist/types/dependency-types.d.ts.map +1 -0
- package/dist/types/dependency-types.js +3 -0
- package/dist/types/dependency-types.js.map +1 -0
- package/dist/types/index.d.ts +8 -10
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/library-config.js.map +1 -1
- package/dist/utilities/cache-manager.js.map +1 -1
- package/dist/utilities/component-error-analyzer.js.map +1 -1
- package/dist/utilities/component-styles.js.map +1 -1
- package/dist/utilities/core-libraries.js.map +1 -1
- package/dist/utilities/index.d.ts +1 -0
- package/dist/utilities/index.d.ts.map +1 -1
- package/dist/utilities/index.js +1 -0
- package/dist/utilities/index.js.map +1 -1
- package/dist/utilities/library-dependency-resolver.d.ts +19 -0
- package/dist/utilities/library-dependency-resolver.d.ts.map +1 -0
- package/dist/utilities/library-dependency-resolver.js +410 -0
- package/dist/utilities/library-dependency-resolver.js.map +1 -0
- package/dist/utilities/library-loader.d.ts +9 -0
- package/dist/utilities/library-loader.d.ts.map +1 -1
- package/dist/utilities/library-loader.js +143 -0
- package/dist/utilities/library-loader.js.map +1 -1
- package/dist/utilities/library-registry.js.map +1 -1
- package/dist/utilities/resource-manager.js.map +1 -1
- package/dist/utilities/standard-libraries.js.map +1 -1
- package/package.json +5 -6
- package/src/compiler/component-compiler.ts +227 -77
- package/src/index.ts +21 -5
- package/src/registry/component-registry-service.ts +578 -0
- package/src/registry/component-registry.ts +8 -7
- package/src/registry/component-resolver.ts +146 -16
- package/src/registry/index.ts +9 -0
- package/src/registry/registry-provider.ts +119 -0
- package/src/runtime/component-hierarchy.ts +13 -5
- package/src/runtime/prop-builder.ts +38 -18
- package/src/types/dependency-types.ts +110 -0
- package/src/types/index.ts +17 -21
- package/src/utilities/index.ts +1 -0
- package/src/utilities/library-dependency-resolver.ts +603 -0
- package/src/utilities/library-loader.ts +252 -0
- package/tsconfig.json +2 -1
- package/tsconfig.tsbuildinfo +0 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
|
|
2
|
-
> @memberjunction/react-runtime@2.
|
|
2
|
+
> @memberjunction/react-runtime@2.94.0 build
|
|
3
3
|
> npm run build:node && npm run build:umd
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @memberjunction/react-runtime@2.
|
|
6
|
+
> @memberjunction/react-runtime@2.94.0 build:node
|
|
7
7
|
> tsc
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
> @memberjunction/react-runtime@2.
|
|
10
|
+
> @memberjunction/react-runtime@2.94.0 build:umd
|
|
11
11
|
> webpack --config webpack.umd.config.js
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Why you should do it regularly: https://github.com/browserslist/update-db#readme
|
|
16
|
-
asset runtime.umd.js 694 KiB [emitted] [minimized] [big] (name: main) 1 related asset
|
|
13
|
+
[BABEL] Note: The code generator has deoptimised the styling of /home/runner/work/MJ/MJ/packages/MJCoreEntities/dist/generated/entity_subclasses.js as it exceeds the max of 500KB.
|
|
14
|
+
asset runtime.umd.js 1.91 MiB [emitted] [minimized] [big] (name: main) 1 related asset
|
|
17
15
|
runtime modules 344 bytes 2 modules
|
|
18
|
-
modules by path ../../../node_modules/
|
|
16
|
+
modules by path ../../../node_modules/ 1.01 MiB 237 modules
|
|
19
17
|
modules by path ../../MJGlobal/ 174 KiB
|
|
20
18
|
modules by path ../../MJGlobal/node_modules/uuid/dist/commonjs-browser/*.js 35 KiB 21 modules
|
|
21
19
|
modules by path ../../MJGlobal/dist/ 139 KiB 14 modules
|
|
22
|
-
modules by path ../../MJCore/ 643 KiB
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
modules by path
|
|
20
|
+
modules by path ../../MJCore/ 643 KiB 31 modules
|
|
21
|
+
modules by path ./dist/ 336 KiB 25 modules
|
|
22
|
+
modules by path ../../MJCoreEntities/dist/ 2.04 MiB
|
|
23
|
+
modules by path ../../MJCoreEntities/dist/custom/*.js 241 KiB 15 modules
|
|
24
|
+
modules by path ../../MJCoreEntities/dist/custom/ResourcePermissions/*.js 46.9 KiB 3 modules
|
|
25
|
+
+ 3 modules
|
|
27
26
|
modules by path ../../InteractiveComponents/dist/*.js 36.8 KiB
|
|
28
27
|
../../InteractiveComponents/dist/index.js 1.21 KiB [built] [code generated]
|
|
29
28
|
../../InteractiveComponents/dist/data-requirements.js 79 bytes [built] [code generated]
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
webpack 5.92.1 compiled successfully in 65451 ms
|
|
29
|
+
+ 8 modules
|
|
30
|
+
webpack 5.92.1 compiled successfully in 109563 ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @memberjunction/react-runtime
|
|
2
2
|
|
|
3
|
+
## 2.94.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 455654e: migration (unrelated) to bump to minor
|
|
8
|
+
- 7c27b04: migration
|
|
9
|
+
- 98afc80: migrations
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [eed16e0]
|
|
14
|
+
- @memberjunction/interactive-component-types@2.94.0
|
|
15
|
+
- @memberjunction/core-entities@2.94.0
|
|
16
|
+
- @memberjunction/core@2.94.0
|
|
17
|
+
- @memberjunction/global@2.94.0
|
|
18
|
+
|
|
19
|
+
## 2.93.0
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- bfcd737: Refactoring and new AI functionality
|
|
24
|
+
- Updated dependencies [f8757aa]
|
|
25
|
+
- Updated dependencies [bfcd737]
|
|
26
|
+
- Updated dependencies [103e4a9]
|
|
27
|
+
- Updated dependencies [7f465b5]
|
|
28
|
+
- Updated dependencies [1461a44]
|
|
29
|
+
- @memberjunction/core@2.93.0
|
|
30
|
+
- @memberjunction/interactive-component-types@2.93.0
|
|
31
|
+
- @memberjunction/core-entities@2.93.0
|
|
32
|
+
- @memberjunction/global@2.93.0
|
|
33
|
+
|
|
3
34
|
## 2.92.0
|
|
4
35
|
|
|
5
36
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -165,20 +165,198 @@ const context = {
|
|
|
165
165
|
const MyComponent = runtime.registry.get('MyComponent', 'MyNamespace');
|
|
166
166
|
|
|
167
167
|
// Execute the component factory
|
|
168
|
-
const
|
|
168
|
+
const componentObject = MyComponent(context);
|
|
169
|
+
|
|
170
|
+
// The componentObject contains the React component and method accessors
|
|
171
|
+
const { component, print, refresh, getCurrentDataState, isDirty } = componentObject;
|
|
169
172
|
|
|
170
173
|
// Render with props
|
|
171
174
|
const props = {
|
|
172
175
|
data: { name: 'World' },
|
|
173
176
|
userState: {},
|
|
174
177
|
callbacks: {
|
|
175
|
-
|
|
178
|
+
OpenEntityRecord: (entityName, key) => console.log('Open entity:', entityName),
|
|
179
|
+
RegisterMethod: (methodName, handler) => {
|
|
180
|
+
// Component will register its methods here
|
|
181
|
+
}
|
|
176
182
|
}
|
|
177
183
|
};
|
|
178
184
|
|
|
179
185
|
React.createElement(component, props);
|
|
180
186
|
```
|
|
181
187
|
|
|
188
|
+
## Component Methods System
|
|
189
|
+
|
|
190
|
+
### Overview
|
|
191
|
+
|
|
192
|
+
Components can expose methods that allow containers to interact with them beyond just passing props. This enables scenarios like:
|
|
193
|
+
- AI agents introspecting component state
|
|
194
|
+
- Containers checking if components have unsaved changes
|
|
195
|
+
- Programmatic validation and reset operations
|
|
196
|
+
- Custom business logic exposed by components
|
|
197
|
+
|
|
198
|
+
### How Components Register Methods
|
|
199
|
+
|
|
200
|
+
Components register their methods during initialization using the `RegisterMethod` callback:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
function MyComponent({ callbacks, data, userState }) {
|
|
204
|
+
const [currentData, setCurrentData] = React.useState(data);
|
|
205
|
+
const [isDirty, setIsDirty] = React.useState(false);
|
|
206
|
+
|
|
207
|
+
// Register methods on mount
|
|
208
|
+
React.useEffect(() => {
|
|
209
|
+
if (callbacks?.RegisterMethod) {
|
|
210
|
+
// Register standard methods
|
|
211
|
+
callbacks.RegisterMethod('getCurrentDataState', () => {
|
|
212
|
+
return currentData;
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
callbacks.RegisterMethod('isDirty', () => {
|
|
216
|
+
return isDirty;
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
callbacks.RegisterMethod('reset', () => {
|
|
220
|
+
setCurrentData(data);
|
|
221
|
+
setIsDirty(false);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
callbacks.RegisterMethod('validate', () => {
|
|
225
|
+
// Custom validation logic
|
|
226
|
+
if (!currentData.name) {
|
|
227
|
+
return { valid: false, errors: ['Name is required'] };
|
|
228
|
+
}
|
|
229
|
+
return true;
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Register custom methods
|
|
233
|
+
callbacks.RegisterMethod('exportToCSV', () => {
|
|
234
|
+
// Custom export logic
|
|
235
|
+
return convertToCSV(currentData);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}, [callbacks, currentData, isDirty]);
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<div>
|
|
242
|
+
{/* Component UI */}
|
|
243
|
+
</div>
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Standard Methods
|
|
249
|
+
|
|
250
|
+
The ComponentObject interface defines standard methods that components can optionally implement:
|
|
251
|
+
|
|
252
|
+
- **`getCurrentDataState()`**: Returns the current data being displayed
|
|
253
|
+
- **`getDataStateHistory()`**: Returns an array of timestamped state changes
|
|
254
|
+
- **`validate()`**: Validates the component state
|
|
255
|
+
- **`isDirty()`**: Checks if there are unsaved changes
|
|
256
|
+
- **`reset()`**: Resets the component to initial state
|
|
257
|
+
- **`scrollTo(target)`**: Scrolls to a specific element
|
|
258
|
+
- **`focus(target)`**: Sets focus to an element
|
|
259
|
+
- **`print()`**: Prints the component content
|
|
260
|
+
- **`refresh()`**: Refreshes the component data
|
|
261
|
+
|
|
262
|
+
### Using Component Methods
|
|
263
|
+
|
|
264
|
+
After compilation, the ComponentObject provides typed access to standard methods:
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
// Compile the component
|
|
268
|
+
const result = await compiler.compile({
|
|
269
|
+
componentName: 'MyComponent',
|
|
270
|
+
componentCode: componentCode
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Get the component object
|
|
274
|
+
const componentObject = result.component.component(context);
|
|
275
|
+
|
|
276
|
+
// Call standard methods directly (type-safe)
|
|
277
|
+
const currentData = componentObject.getCurrentDataState();
|
|
278
|
+
const isDirty = componentObject.isDirty();
|
|
279
|
+
const validationResult = componentObject.validate();
|
|
280
|
+
|
|
281
|
+
if (isDirty) {
|
|
282
|
+
componentObject.reset();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Call custom methods via invokeMethod
|
|
286
|
+
if (componentObject.hasMethod('exportToCSV')) {
|
|
287
|
+
const csvData = componentObject.invokeMethod('exportToCSV');
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Method Availability
|
|
292
|
+
|
|
293
|
+
All methods are optional. The runtime provides sensible defaults when methods aren't registered:
|
|
294
|
+
|
|
295
|
+
- `getCurrentDataState()` returns `undefined`
|
|
296
|
+
- `getDataStateHistory()` returns `[]`
|
|
297
|
+
- `isDirty()` returns `false`
|
|
298
|
+
- `validate()` returns `true`
|
|
299
|
+
- Other methods perform no operation if not implemented
|
|
300
|
+
|
|
301
|
+
### Integration with Angular
|
|
302
|
+
|
|
303
|
+
The Angular wrapper (`@memberjunction/ng-react`) provides strongly-typed access to all standard methods:
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
export class MyDashboard {
|
|
307
|
+
@ViewChild(MJReactComponent) reactComponent!: MJReactComponent;
|
|
308
|
+
|
|
309
|
+
checkComponentState() {
|
|
310
|
+
// Standard methods have full TypeScript support
|
|
311
|
+
if (this.reactComponent.isDirty()) {
|
|
312
|
+
const data = this.reactComponent.getCurrentDataState();
|
|
313
|
+
console.log('Component has unsaved changes:', data);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Validate before saving
|
|
317
|
+
const validation = this.reactComponent.validate();
|
|
318
|
+
if (validation === true || validation.valid) {
|
|
319
|
+
// Save data...
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Custom methods
|
|
323
|
+
if (this.reactComponent.hasMethod('generateReport')) {
|
|
324
|
+
const report = this.reactComponent.invokeMethod('generateReport', options);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Method Declaration in Component Spec
|
|
331
|
+
|
|
332
|
+
Components can declare their supported methods in the ComponentSpec for discovery:
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
const componentSpec = {
|
|
336
|
+
name: 'MyComponent',
|
|
337
|
+
code: '...',
|
|
338
|
+
methods: [
|
|
339
|
+
{
|
|
340
|
+
name: 'getCurrentDataState',
|
|
341
|
+
category: 'standard',
|
|
342
|
+
description: 'Returns current component data',
|
|
343
|
+
returnType: 'DataState | undefined'
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
name: 'exportToExcel',
|
|
347
|
+
category: 'custom',
|
|
348
|
+
description: 'Exports data to Excel format',
|
|
349
|
+
parameters: [{
|
|
350
|
+
name: 'options',
|
|
351
|
+
type: '{includeHeaders?: boolean, sheetName?: string}',
|
|
352
|
+
required: false
|
|
353
|
+
}],
|
|
354
|
+
returnType: 'Promise<Blob>'
|
|
355
|
+
}
|
|
356
|
+
]
|
|
357
|
+
};
|
|
358
|
+
```
|
|
359
|
+
|
|
182
360
|
## Advanced Features
|
|
183
361
|
|
|
184
362
|
### Component Hierarchies
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"babel-config.js","sourceRoot":"","sources":["../../src/compiler/babel-config.ts"],"names":[],"mappings":";;;AASa,QAAA,eAAe,GAAG;IAC7B,OAAO;CACR,CAAC;AAKW,QAAA,eAAe,GAAa,EAGxC,CAAC;AAKW,QAAA,iBAAiB,GAAG;IAC/B,OAAO,EAAE,uBAAe;IACxB,OAAO,EAAE;QACP,GAAG,uBAAe;KAEnB;IACD,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;CAChB,CAAC;AAKW,QAAA,kBAAkB,GAAG;IAChC,OAAO,EAAE,uBAAe;IACxB,OAAO,EAAE;QACP,GAAG,uBAAe;KAEnB;IACD,UAAU,EAAE,QAAQ;IACpB,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,IAAI;CACf,CAAC;AAOF,SAAgB,cAAc,CAAC,aAAsB,KAAK;IACxD,OAAO,UAAU,CAAC,CAAC,CAAC,yBAAiB,CAAC,CAAC,CAAC,0BAAkB,CAAC;AAC7D,CAAC;AAFD,wCAEC;AAOD,SAAgB,oBAAoB,CAAC,KAAU;IAC7C,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,OAAO,OAAO,IAAI,KAAK,CAAC,gBAAgB,CAAC;AAC3C,CAAC;AAPD,oDAOC;AAKY,QAAA,WAAW,GAAG;IACzB,OAAO,EAAE;QACP,MAAM,EAAE,qBAAqB;QAC7B,UAAU,EAAE,gBAAgB;KAC7B;IACD,SAAS,EAAE;QACT,OAAO,EAAE,WAAW;QACpB,YAAY,EAAE,OAAO;KACtB;CACF,CAAC;AAOF,SAAgB,YAAY,CAAC,YAAqB;IAEhD,IAAI,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/D,OAAO,mBAAW,CAAC,SAAS,CAAC;IAC/B,CAAC;IACD,OAAO,mBAAW,CAAC,OAAO,CAAC;AAC7B,CAAC;AAND,oCAMC"}
|
|
1
|
+
{"version":3,"file":"babel-config.js","sourceRoot":"","sources":["../../src/compiler/babel-config.ts"],"names":[],"mappings":";;;AASa,QAAA,eAAe,GAAG;IAC7B,OAAO;CACR,CAAC;AAKW,QAAA,eAAe,GAAa,EAGxC,CAAC;AAKW,QAAA,iBAAiB,GAAG;IAC/B,OAAO,EAAE,uBAAe;IACxB,OAAO,EAAE;QACP,GAAG,uBAAe;KAEnB;IACD,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAK;CAChB,CAAC;AAKW,QAAA,kBAAkB,GAAG;IAChC,OAAO,EAAE,uBAAe;IACxB,OAAO,EAAE;QACP,GAAG,uBAAe;KAEnB;IACD,UAAU,EAAE,QAAQ;IACpB,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,IAAI;CACf,CAAC;AAOF,SAAgB,cAAc,CAAC,aAAsB,KAAK;IACxD,OAAO,UAAU,CAAC,CAAC,CAAC,yBAAiB,CAAC,CAAC,CAAC,0BAAkB,CAAC;AAC7D,CAAC;AAFD,wCAEC;AAOD,SAAgB,oBAAoB,CAAC,KAAU;IAC7C,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,OAAO,OAAO,IAAI,KAAK,CAAC,gBAAgB,CAAC;AAC3C,CAAC;AAPD,oDAOC;AAKY,QAAA,WAAW,GAAG;IACzB,OAAO,EAAE;QACP,MAAM,EAAE,qBAAqB;QAC7B,UAAU,EAAE,gBAAgB;KAC7B;IACD,SAAS,EAAE;QACT,OAAO,EAAE,WAAW;QACpB,YAAY,EAAE,OAAO;KACtB;CACF,CAAC;AAOF,SAAgB,YAAY,CAAC,YAAqB;IAEhD,IAAI,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/D,OAAO,mBAAW,CAAC,SAAS,CAAC;IAC/B,CAAC;IACD,OAAO,mBAAW,CAAC,OAAO,CAAC;AAC7B,CAAC;AAND,oCAMC","sourcesContent":["/**\n * @fileoverview Babel configuration for React component compilation.\n * Provides default presets and plugins for transforming JSX and modern JavaScript.\n * @module @memberjunction/react-runtime/compiler\n */\n\n/**\n * Default Babel presets for React compilation\n */\nexport const DEFAULT_PRESETS = [\n 'react', // Transforms JSX\n];\n\n/**\n * Default Babel plugins for enhanced functionality\n */\nexport const DEFAULT_PLUGINS: string[] = [\n // Add plugins as needed for specific transformations\n // e.g., 'transform-class-properties', 'transform-optional-chaining'\n];\n\n/**\n * Production-specific Babel configuration\n */\nexport const PRODUCTION_CONFIG = {\n presets: DEFAULT_PRESETS,\n plugins: [\n ...DEFAULT_PLUGINS,\n // Production optimizations could go here\n ],\n minified: true,\n comments: false\n};\n\n/**\n * Development-specific Babel configuration\n */\nexport const DEVELOPMENT_CONFIG = {\n presets: DEFAULT_PRESETS,\n plugins: [\n ...DEFAULT_PLUGINS,\n // Development helpers could go here\n ],\n sourceMaps: 'inline',\n minified: false,\n comments: true\n};\n\n/**\n * Get Babel configuration based on environment\n * @param production - Whether to use production configuration\n * @returns Babel configuration object\n */\nexport function getBabelConfig(production: boolean = false) {\n return production ? PRODUCTION_CONFIG : DEVELOPMENT_CONFIG;\n}\n\n/**\n * Validates that required Babel presets are available\n * @param babel - Babel instance to check\n * @returns true if all required presets are available\n */\nexport function validateBabelPresets(babel: any): boolean {\n if (!babel || !babel.availablePresets) {\n return false;\n }\n\n // Check that React preset is available\n return 'react' in babel.availablePresets;\n}\n\n/**\n * Common JSX pragma options for different React versions\n */\nexport const JSX_PRAGMAS = {\n classic: {\n pragma: 'React.createElement',\n pragmaFrag: 'React.Fragment'\n },\n automatic: {\n runtime: 'automatic',\n importSource: 'react'\n }\n};\n\n/**\n * Get appropriate JSX configuration based on React version\n * @param reactVersion - React version (e.g., \"18.2.0\")\n * @returns JSX configuration options\n */\nexport function getJSXConfig(reactVersion?: string) {\n // React 17+ supports the new JSX transform\n if (reactVersion && parseInt(reactVersion.split('.')[0]) >= 17) {\n return JSX_PRAGMAS.automatic;\n }\n return JSX_PRAGMAS.classic;\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-compiler.d.ts","sourceRoot":"","sources":["../../src/compiler/component-compiler.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,cAAc,EAEd,iBAAiB,EACjB,cAAc,EAGf,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"component-compiler.d.ts","sourceRoot":"","sources":["../../src/compiler/component-compiler.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,cAAc,EAEd,iBAAiB,EACjB,cAAc,EAGf,MAAM,UAAU,CAAC;AAyBlB,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,gBAAgB,CAAW;IACnC,OAAO,CAAC,aAAa,CAAM;gBAMf,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAS5C,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAS5B,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyElE,OAAO,CAAC,kBAAkB;IAkC1B,OAAO,CAAC,iBAAiB;YA6KX,qBAAqB;YA2HrB,UAAU;IA+BxB,OAAO,CAAC,UAAU;IAyElB,OAAO,CAAC,sBAAsB;IA0E9B,OAAO,CAAC,sBAAsB;IAiE9B,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,sBAAsB;IAa9B,UAAU,IAAI,IAAI;IAQlB,YAAY,IAAI,MAAM;IAQtB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;CAGpD"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ComponentCompiler = void 0;
|
|
4
4
|
const library_registry_1 = require("../utilities/library-registry");
|
|
5
|
+
const library_loader_1 = require("../utilities/library-loader");
|
|
5
6
|
const DEFAULT_COMPILER_CONFIG = {
|
|
6
7
|
babel: {
|
|
7
8
|
presets: ['react'],
|
|
@@ -10,7 +11,8 @@ const DEFAULT_COMPILER_CONFIG = {
|
|
|
10
11
|
minify: false,
|
|
11
12
|
sourceMaps: false,
|
|
12
13
|
cache: true,
|
|
13
|
-
maxCacheSize: 100
|
|
14
|
+
maxCacheSize: 100,
|
|
15
|
+
debug: false
|
|
14
16
|
};
|
|
15
17
|
class ComponentCompiler {
|
|
16
18
|
constructor(config) {
|
|
@@ -38,7 +40,7 @@ class ComponentCompiler {
|
|
|
38
40
|
const transpiledCode = this.transpileComponent(options.componentCode, options.componentName, options);
|
|
39
41
|
const componentFactory = this.createComponentFactory(transpiledCode, options.componentName, loadedLibraries);
|
|
40
42
|
const compiledComponent = {
|
|
41
|
-
|
|
43
|
+
factory: componentFactory,
|
|
42
44
|
id: this.generateComponentId(options.componentName),
|
|
43
45
|
name: options.componentName,
|
|
44
46
|
compiledAt: new Date(),
|
|
@@ -99,6 +101,7 @@ class ComponentCompiler {
|
|
|
99
101
|
useState, useEffect, useCallback, useMemo, useRef, useContext, useReducer, useLayoutEffect,
|
|
100
102
|
libraries, styles, console, components
|
|
101
103
|
) {
|
|
104
|
+
// Parse the component code once to get the component definition
|
|
102
105
|
${libraryDeclarations ? libraryDeclarations + '\n ' : ''}${componentDeclarations ? componentDeclarations + '\n ' : ''}${componentCode}
|
|
103
106
|
|
|
104
107
|
// Ensure the component exists
|
|
@@ -106,16 +109,137 @@ class ComponentCompiler {
|
|
|
106
109
|
throw new Error('Component "${componentName}" is not defined in the provided code');
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
//
|
|
112
|
+
// Store the component in a variable so we don't lose it
|
|
113
|
+
const UserComponent = ${componentName};
|
|
114
|
+
|
|
115
|
+
// Debug logging to understand what we're getting
|
|
116
|
+
console.log('Component ${componentName} type:', typeof UserComponent);
|
|
117
|
+
if (typeof UserComponent === 'object' && UserComponent !== null) {
|
|
118
|
+
console.log('Component ${componentName} keys:', Object.keys(UserComponent));
|
|
119
|
+
console.log('Component ${componentName} has .component:', 'component' in UserComponent);
|
|
120
|
+
if ('component' in UserComponent) {
|
|
121
|
+
console.log('Component ${componentName}.component type:', typeof UserComponent.component);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Check if the component is already a ComponentObject (has a .component property)
|
|
126
|
+
// If so, extract the actual React component
|
|
127
|
+
const ActualComponent = (typeof UserComponent === 'object' && UserComponent !== null && 'component' in UserComponent)
|
|
128
|
+
? UserComponent.component
|
|
129
|
+
: UserComponent;
|
|
130
|
+
|
|
131
|
+
// Validate that we have a function (React component)
|
|
132
|
+
if (typeof ActualComponent !== 'function') {
|
|
133
|
+
console.error('Invalid component type for ${componentName}:', typeof ActualComponent);
|
|
134
|
+
console.error('ActualComponent value:', ActualComponent);
|
|
135
|
+
console.error('Original UserComponent value:', UserComponent);
|
|
136
|
+
throw new Error('Component "${componentName}" must be a function (React component) or an object with a .component property that is a function. Got: ' + typeof ActualComponent);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Create a fresh method registry for each factory call
|
|
140
|
+
const methodRegistry = new Map();
|
|
141
|
+
|
|
142
|
+
// Create a wrapper component that provides RegisterMethod in callbacks
|
|
143
|
+
const ComponentWithMethodRegistry = React.forwardRef((props, ref) => {
|
|
144
|
+
// Register methods on mount
|
|
145
|
+
React.useEffect(() => {
|
|
146
|
+
// Clear previous methods
|
|
147
|
+
methodRegistry.clear();
|
|
148
|
+
|
|
149
|
+
// Provide RegisterMethod callback if callbacks exist
|
|
150
|
+
if (props.callbacks && typeof props.callbacks.RegisterMethod === 'function') {
|
|
151
|
+
// Component can now register its methods
|
|
152
|
+
// This will be called from within the component
|
|
153
|
+
}
|
|
154
|
+
}, [props.callbacks]);
|
|
155
|
+
|
|
156
|
+
// Create enhanced callbacks with RegisterMethod
|
|
157
|
+
const enhancedCallbacks = React.useMemo(() => {
|
|
158
|
+
if (!props.callbacks) return {};
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
...props.callbacks,
|
|
162
|
+
RegisterMethod: (methodName, handler) => {
|
|
163
|
+
if (methodName && handler) {
|
|
164
|
+
methodRegistry.set(methodName, handler);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}, [props.callbacks]);
|
|
169
|
+
|
|
170
|
+
// Render the original component with enhanced callbacks
|
|
171
|
+
return React.createElement(ActualComponent, {
|
|
172
|
+
...props,
|
|
173
|
+
callbacks: enhancedCallbacks
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
ComponentWithMethodRegistry.displayName = '${componentName}WithMethods';
|
|
178
|
+
|
|
179
|
+
// Return the component object with method access
|
|
110
180
|
return {
|
|
111
|
-
component:
|
|
181
|
+
component: ComponentWithMethodRegistry,
|
|
182
|
+
|
|
183
|
+
// Legacy methods for backward compatibility
|
|
112
184
|
print: function() {
|
|
113
|
-
|
|
185
|
+
const printMethod = methodRegistry.get('print');
|
|
186
|
+
if (printMethod) {
|
|
187
|
+
printMethod();
|
|
188
|
+
} else if (typeof window !== 'undefined' && window.print) {
|
|
114
189
|
window.print();
|
|
115
190
|
}
|
|
116
191
|
},
|
|
117
192
|
refresh: function(data) {
|
|
193
|
+
const refreshMethod = methodRegistry.get('refresh');
|
|
194
|
+
if (refreshMethod) {
|
|
195
|
+
refreshMethod(data);
|
|
196
|
+
}
|
|
118
197
|
// Refresh functionality is handled by the host environment
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
// Standard method accessors with type safety
|
|
201
|
+
getCurrentDataState: function() {
|
|
202
|
+
const method = methodRegistry.get('getCurrentDataState');
|
|
203
|
+
return method ? method() : undefined;
|
|
204
|
+
},
|
|
205
|
+
getDataStateHistory: function() {
|
|
206
|
+
const method = methodRegistry.get('getDataStateHistory');
|
|
207
|
+
return method ? method() : [];
|
|
208
|
+
},
|
|
209
|
+
validate: function() {
|
|
210
|
+
const method = methodRegistry.get('validate');
|
|
211
|
+
return method ? method() : true;
|
|
212
|
+
},
|
|
213
|
+
isDirty: function() {
|
|
214
|
+
const method = methodRegistry.get('isDirty');
|
|
215
|
+
return method ? method() : false;
|
|
216
|
+
},
|
|
217
|
+
reset: function() {
|
|
218
|
+
const method = methodRegistry.get('reset');
|
|
219
|
+
if (method) method();
|
|
220
|
+
},
|
|
221
|
+
scrollTo: function(target) {
|
|
222
|
+
const method = methodRegistry.get('scrollTo');
|
|
223
|
+
if (method) method(target);
|
|
224
|
+
},
|
|
225
|
+
focus: function(target) {
|
|
226
|
+
const method = methodRegistry.get('focus');
|
|
227
|
+
if (method) method(target);
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
// Generic method invoker for custom methods
|
|
231
|
+
invokeMethod: function(methodName, ...args) {
|
|
232
|
+
const method = methodRegistry.get(methodName);
|
|
233
|
+
if (method) {
|
|
234
|
+
return method(...args);
|
|
235
|
+
}
|
|
236
|
+
console.warn(\`Method '\${methodName}' is not registered on component ${componentName}\`);
|
|
237
|
+
return undefined;
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
// Check if a method exists
|
|
241
|
+
hasMethod: function(methodName) {
|
|
242
|
+
return methodRegistry.has(methodName);
|
|
119
243
|
}
|
|
120
244
|
};
|
|
121
245
|
}
|
|
@@ -123,12 +247,16 @@ class ComponentCompiler {
|
|
|
123
247
|
}
|
|
124
248
|
async loadRequiredLibraries(libraries, componentLibraries) {
|
|
125
249
|
const loadedLibraries = new Map();
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
250
|
+
if (this.config.debug) {
|
|
251
|
+
console.log('đ loadRequiredLibraries called with:', {
|
|
252
|
+
librariesCount: libraries?.length || 0,
|
|
253
|
+
libraries: libraries?.map(l => ({ name: l.name, version: l.version, globalVariable: l.globalVariable }))
|
|
254
|
+
});
|
|
255
|
+
}
|
|
130
256
|
if (!libraries || libraries.length === 0) {
|
|
131
|
-
|
|
257
|
+
if (this.config.debug) {
|
|
258
|
+
console.log('đ No libraries to load, returning empty map');
|
|
259
|
+
}
|
|
132
260
|
return loadedLibraries;
|
|
133
261
|
}
|
|
134
262
|
if (typeof window === 'undefined') {
|
|
@@ -141,53 +269,69 @@ class ComponentCompiler {
|
|
|
141
269
|
else {
|
|
142
270
|
console.warn('â ī¸ No componentLibraries provided for LibraryRegistry initialization');
|
|
143
271
|
}
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
272
|
+
const libraryNames = libraries.map(lib => lib.name);
|
|
273
|
+
if (this.config.debug) {
|
|
274
|
+
console.log('đĻ Using dependency-aware loading for libraries:', libraryNames);
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
const loadedLibraryMap = await library_loader_1.LibraryLoader.loadLibrariesWithDependencies(libraryNames, componentLibraries, 'component-compiler', { debug: this.config.debug });
|
|
278
|
+
for (const lib of libraries) {
|
|
279
|
+
const isApproved = library_registry_1.LibraryRegistry.isApproved(lib.name);
|
|
280
|
+
if (!isApproved) {
|
|
281
|
+
console.error(`â Library '${lib.name}' is not approved`);
|
|
282
|
+
throw new Error(`Library '${lib.name}' is not approved. Only approved libraries can be used.`);
|
|
283
|
+
}
|
|
284
|
+
const loadedValue = loadedLibraryMap.get(lib.name);
|
|
285
|
+
if (loadedValue) {
|
|
286
|
+
loadedLibraries.set(lib.globalVariable, loadedValue);
|
|
287
|
+
if (this.config.debug) {
|
|
288
|
+
console.log(`â
Mapped ${lib.name} to global variable ${lib.globalVariable}`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
const globalValue = window[lib.globalVariable];
|
|
293
|
+
if (globalValue) {
|
|
294
|
+
loadedLibraries.set(lib.globalVariable, globalValue);
|
|
295
|
+
if (this.config.debug) {
|
|
296
|
+
console.log(`â
Found ${lib.name} already loaded as ${lib.globalVariable}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
console.error(`â Library '${lib.name}' failed to load`);
|
|
301
|
+
throw new Error(`Library '${lib.name}' failed to load or did not expose '${lib.globalVariable}'`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
174
304
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
loadedLibraries.set(lib.globalVariable, libraryValue);
|
|
181
|
-
console.log(` â
Added ${lib.name} to loaded libraries map`);
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
console.error('Failed to load libraries with dependencies:', error);
|
|
308
|
+
if (this.config.debug) {
|
|
309
|
+
console.warn('â ī¸ Falling back to non-dependency-aware loading due to error');
|
|
182
310
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
311
|
+
for (const lib of libraries) {
|
|
312
|
+
if (window[lib.globalVariable]) {
|
|
313
|
+
loadedLibraries.set(lib.globalVariable, window[lib.globalVariable]);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
const libraryDef = library_registry_1.LibraryRegistry.getLibrary(lib.name);
|
|
317
|
+
if (libraryDef) {
|
|
318
|
+
const resolvedVersion = library_registry_1.LibraryRegistry.resolveVersion(lib.name, lib.version);
|
|
319
|
+
const cdnUrl = library_registry_1.LibraryRegistry.getCdnUrl(lib.name, resolvedVersion);
|
|
320
|
+
if (cdnUrl) {
|
|
321
|
+
await this.loadScript(cdnUrl, lib.globalVariable);
|
|
322
|
+
const libraryValue = window[lib.globalVariable];
|
|
323
|
+
if (libraryValue) {
|
|
324
|
+
loadedLibraries.set(lib.globalVariable, libraryValue);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
186
329
|
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
330
|
+
}
|
|
331
|
+
if (this.config.debug) {
|
|
332
|
+
console.log(`â
All libraries loaded successfully. Total: ${loadedLibraries.size}`);
|
|
333
|
+
console.log('đ Loaded libraries map:', Array.from(loadedLibraries.keys()));
|
|
334
|
+
}
|
|
191
335
|
return loadedLibraries;
|
|
192
336
|
}
|
|
193
337
|
async loadStyles(urls) {
|
|
@@ -237,12 +381,17 @@ class ComponentCompiler {
|
|
|
237
381
|
const checkInterval = 100;
|
|
238
382
|
const checkGlobal = () => {
|
|
239
383
|
if (window[globalName]) {
|
|
240
|
-
|
|
384
|
+
if (this.config.debug) {
|
|
385
|
+
console.log(` â Global variable ${globalName} found after ${attempts * checkInterval}ms`);
|
|
386
|
+
}
|
|
241
387
|
resolve();
|
|
242
388
|
}
|
|
243
389
|
else if (attempts >= maxAttempts) {
|
|
244
|
-
|
|
245
|
-
|
|
390
|
+
if (this.config.debug) {
|
|
391
|
+
console.error(` â ${globalName} not found after ${attempts * checkInterval}ms`);
|
|
392
|
+
const matchingKeys = Object.keys(window).filter(k => k.toLowerCase().includes(globalName.toLowerCase()));
|
|
393
|
+
console.log(` âšī¸ Matching window properties: ${matchingKeys.join(', ') || 'none'}`);
|
|
394
|
+
}
|
|
246
395
|
reject(new Error(`${globalName} not found after loading script from ${url}`));
|
|
247
396
|
}
|
|
248
397
|
else {
|