@jfdevelops/react-layout 1.1.0 → 1.3.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.
Files changed (63) hide show
  1. package/dist/create-config/create-defined-resource-layout.cjs +40 -4
  2. package/dist/create-config/create-defined-resource-layout.cjs.map +1 -1
  3. package/dist/create-config/create-defined-resource-layout.d.cts +33 -13
  4. package/dist/create-config/create-defined-resource-layout.d.cts.map +1 -1
  5. package/dist/create-config/create-defined-resource-layout.d.mts +33 -13
  6. package/dist/create-config/create-defined-resource-layout.d.mts.map +1 -1
  7. package/dist/create-config/create-defined-resource-layout.mjs +40 -4
  8. package/dist/create-config/create-defined-resource-layout.mjs.map +1 -1
  9. package/dist/create-config/define-layout.cjs +149 -30
  10. package/dist/create-config/define-layout.cjs.map +1 -1
  11. package/dist/create-config/define-layout.d.cts +46 -15
  12. package/dist/create-config/define-layout.d.cts.map +1 -1
  13. package/dist/create-config/define-layout.d.mts +46 -15
  14. package/dist/create-config/define-layout.d.mts.map +1 -1
  15. package/dist/create-config/define-layout.mjs +149 -30
  16. package/dist/create-config/define-layout.mjs.map +1 -1
  17. package/dist/create-config/for-resource.cjs.map +1 -1
  18. package/dist/create-config/for-resource.d.cts +2 -1
  19. package/dist/create-config/for-resource.d.cts.map +1 -1
  20. package/dist/create-config/for-resource.d.mts +2 -1
  21. package/dist/create-config/for-resource.d.mts.map +1 -1
  22. package/dist/create-config/for-resource.mjs.map +1 -1
  23. package/dist/create-config/index.d.cts +1 -1
  24. package/dist/create-config/index.d.mts +1 -1
  25. package/dist/create-config/inspection.cjs +65 -0
  26. package/dist/create-config/inspection.cjs.map +1 -0
  27. package/dist/create-config/inspection.mjs +64 -0
  28. package/dist/create-config/inspection.mjs.map +1 -0
  29. package/dist/create-config/layout-name.cjs +21 -0
  30. package/dist/create-config/layout-name.cjs.map +1 -0
  31. package/dist/create-config/layout-name.d.cts +49 -0
  32. package/dist/create-config/layout-name.d.cts.map +1 -0
  33. package/dist/create-config/layout-name.d.mts +49 -0
  34. package/dist/create-config/layout-name.d.mts.map +1 -0
  35. package/dist/create-config/layout-name.mjs +20 -0
  36. package/dist/create-config/layout-name.mjs.map +1 -0
  37. package/dist/create-config/merge-layout-props.cjs +20 -0
  38. package/dist/create-config/merge-layout-props.cjs.map +1 -0
  39. package/dist/create-config/merge-layout-props.mjs +19 -0
  40. package/dist/create-config/merge-layout-props.mjs.map +1 -0
  41. package/dist/create-config/render-state.cjs +80 -5
  42. package/dist/create-config/render-state.cjs.map +1 -1
  43. package/dist/create-config/render-state.d.cts +72 -17
  44. package/dist/create-config/render-state.d.cts.map +1 -1
  45. package/dist/create-config/render-state.d.mts +72 -17
  46. package/dist/create-config/render-state.d.mts.map +1 -1
  47. package/dist/create-config/render-state.mjs +81 -6
  48. package/dist/create-config/render-state.mjs.map +1 -1
  49. package/dist/create-config/state-composable.cjs +9 -1
  50. package/dist/create-config/state-composable.cjs.map +1 -1
  51. package/dist/create-config/state-composable.d.cts.map +1 -1
  52. package/dist/create-config/state-composable.d.mts.map +1 -1
  53. package/dist/create-config/state-composable.mjs +8 -2
  54. package/dist/create-config/state-composable.mjs.map +1 -1
  55. package/dist/index.cjs +2 -0
  56. package/dist/index.d.cts +3 -2
  57. package/dist/index.d.mts +3 -2
  58. package/dist/index.mjs +2 -1
  59. package/dist/utils/capitalize.d.cts +6 -0
  60. package/dist/utils/capitalize.d.cts.map +1 -0
  61. package/dist/utils/capitalize.d.mts +6 -0
  62. package/dist/utils/capitalize.d.mts.map +1 -0
  63. package/package.json +5 -4
@@ -2,19 +2,22 @@ import { InvalidConfigError } from "../errors/invalid-config.mjs";
2
2
  import { MissingResourceProviderError } from "../errors/missing-resource-provider.mjs";
3
3
  import { LayoutConfigurationError } from "../errors/layout-configuration-error.mjs";
4
4
  import { ResourceModuleLoadError, ResourceRenderError } from "../errors/resource-state-error.mjs";
5
+ import { capitalize } from "../utils/capitalize.mjs";
6
+ import { StateComposableContext, createStateReferences, stateReferenceSource } from "./state-composable.mjs";
7
+ import { mergeLayoutProps } from "./merge-layout-props.mjs";
8
+ import { inspectDefinition, trackComposable } from "./inspection.mjs";
5
9
  import { createIsValidResourceFn, normalizeResourceDefinitions, normalizeResources, toResourceEnum } from "../resource.mjs";
6
10
  import { functionalUpdate, pick } from "../utils.mjs";
7
- import { capitalize } from "../utils/capitalize.mjs";
8
11
  import { isResourceConfigComponentKey } from "./component-keys.mjs";
9
12
  import { createResourceConfig } from "./get-component.mjs";
10
13
  import { createResourceLinksFn } from "./create-resource-links.mjs";
11
14
  import { createForResource } from "./for-resource.mjs";
12
15
  import { createForResources } from "./for-resources/create-for-resources.mjs";
13
16
  import { ResourceLayoutShellPublisherContext, useResourceLayoutShellPublisher } from "./shell-context.mjs";
14
- import { StateComposableContext, createStateReferences } from "./state-composable.mjs";
15
17
  import { deferredRenderStateSymbol, definedResourceLayoutComponentSymbol, findDefinedRenderState, isDeferredRenderState, isLazyRenderState, lazyRenderStateSymbol } from "./render-state.mjs";
16
18
  import { LayoutComposablePresetProvider, collectComposablePresetEntries, makeComposable, resolveLayoutComposables } from "@jfdevelops/react-layout-composables";
17
19
  import { Component, Suspense, createContext, lazy, useCallback, useContext, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
20
+ import { inspectionId } from "@jfdevelops/react-layout-devtools-core";
18
21
  import { attachComponentPropDefinitions, createPrimitivePropBuilder, createProp, resolvePropDefinitionValues, validateProps } from "@jfdevelops/react-layout-validator";
19
22
  import { Fragment, jsx } from "react/jsx-runtime";
20
23
 
@@ -138,9 +141,21 @@ function assertUnreservedResourceSlugs(resources, owner) {
138
141
  if (typeof resource !== "string") assertUnreservedResourceSlugs(resource.subResources, slug);
139
142
  }
140
143
  }
141
- function defineResourceLayoutImpl(options, inheritedStateScope) {
144
+ function defineResourceLayoutImpl(options, inheritedStateScope, inheritedInspection) {
142
145
  const { options: inProps = {}, resources, layout, namespace: defaultNamespace = false } = options;
143
146
  const shellId = options.shellId;
147
+ const inspection = inheritedInspection ? void 0 : inspectDefinition(resources);
148
+ if (inspection) inspection.store.node({
149
+ id: inspection.definition,
150
+ kind: "definition",
151
+ label: "Layout definition",
152
+ details: {
153
+ props: layout.props,
154
+ propSchemas: typeof inProps === "function" ? void 0 : inProps,
155
+ options: typeof inProps === "function" ? "Resource-specific schemas" : Object.keys(inProps),
156
+ states: typeof layout.render === "function" ? ["default"] : Object.keys(layout.render)
157
+ }
158
+ });
144
159
  assertUnreservedResourceSlugs(resources);
145
160
  const resourcesAccessor = createLayoutResourcesAccessor(resources);
146
161
  const ResourceContext = createContext(void 0);
@@ -158,19 +173,70 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
158
173
  const normalizedResources = normalizeResources(resources);
159
174
  const resourcesEnum = createPrimitivePropBuilder("string").enum(toResourceEnum(normalizedResources));
160
175
  const definedResourceLayout = ((layoutOptions) => {
161
- const { name, props: instancePropDefinitions, namespace = defaultNamespace, ...layoutOptionProps } = layoutOptions;
176
+ const { name: suppliedName, props: instancePropDefinitions, namespace = defaultNamespace, ...layoutOptionProps } = layoutOptions;
177
+ const naming = suppliedName ?? options.name;
178
+ const name = typeof naming === "function" ? naming({
179
+ resource: layoutOptions.resource,
180
+ states: typeof layout.render === "function" ? ["default"] : Object.keys(layout.render),
181
+ capitalize
182
+ }) : naming;
183
+ if (name !== void 0 && (typeof name !== "string" || !name)) throw new LayoutConfigurationError("A non-empty layout name is required");
162
184
  const createComposableLayout = makeComposable();
163
185
  const nameProp = createProp.string().literal(name);
186
+ const rawResolvedOptions = typeof inProps === "function" ? inProps({
187
+ resource: resourcesEnum,
188
+ name: nameProp
189
+ }) : inProps;
164
190
  const { resolvedInProps, splitInProps } = splitLayoutInProps({
165
- ...typeof inProps === "function" ? inProps({
166
- resource: resourcesEnum,
167
- name: nameProp
168
- }) : inProps,
191
+ ...rawResolvedOptions,
169
192
  ...instancePropDefinitions,
170
193
  ...layoutOptionProps
171
194
  });
172
195
  const { composables, props: legacyLayoutProps } = layout;
173
196
  const renderStates = typeof layout.render === "function" ? { default: layout.render } : layout.render;
197
+ const inspectionStore = inheritedInspection?.store ?? inspection.store;
198
+ const layoutId = inheritedInspection?.layout ?? inspectionStore.node({
199
+ id: inspectionId("layout"),
200
+ kind: "layout",
201
+ label: name ?? String(layoutOptionProps.resource),
202
+ details: {
203
+ resource: layoutOptionProps.resource,
204
+ props: legacyLayoutProps,
205
+ propSchemas: rawResolvedOptions
206
+ }
207
+ });
208
+ const resourceId = inheritedInspection?.resource ?? inspection?.resourceIds.get(String(layoutOptionProps.resource));
209
+ if (inspection) {
210
+ inspectionStore.edge(inspection.definition, layoutId, "defines");
211
+ if (resourceId) inspectionStore.edge(resourceId, layoutId, "renders");
212
+ }
213
+ const stateIds = new Map(Object.keys(renderStates).map((state) => [state, inheritedInspection?.state ?? inspectionStore.node({
214
+ id: inspectionId("state"),
215
+ kind: "state",
216
+ label: state,
217
+ unresolved: isLazyRenderState(renderStates[state]) || isDeferredRenderState(renderStates[state])
218
+ })]));
219
+ for (const id of stateIds.values()) inspectionStore.edge(layoutId, id, "defines");
220
+ const activeInspection = {
221
+ store: inspectionStore,
222
+ layout: layoutId,
223
+ resource: resourceId,
224
+ state: stateIds.get("default")
225
+ };
226
+ const referenceStateIds = /* @__PURE__ */ new Map();
227
+ function getReferenceStateId(input, label) {
228
+ let id = referenceStateIds.get(input);
229
+ if (!id) {
230
+ id = inspectionStore.node({
231
+ id: inspectionId("state-reference"),
232
+ kind: "state",
233
+ label,
234
+ details: { relationship: "Referenced render state" }
235
+ });
236
+ referenceStateIds.set(input, id);
237
+ }
238
+ return id;
239
+ }
174
240
  const referenceComponents = /* @__PURE__ */ new Map();
175
241
  const stateScope = inheritedStateScope ?? {
176
242
  states: createStateReferences(renderStates),
@@ -178,7 +244,7 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
178
244
  for (const [stateName, input] of Object.entries(renderStates)) if (input === source.input) return stateName === "default" ? Component : stateComponents[stateName];
179
245
  let reference = referenceComponents.get(source.input);
180
246
  if (!reference) {
181
- reference = createStateComponent(source.name, source.input, false);
247
+ reference = createStateComponent(source.name, source.input, false, source.fallbackStateName);
182
248
  referenceComponents.set(source.input, reference);
183
249
  }
184
250
  return reference;
@@ -189,8 +255,18 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
189
255
  const defaultRenderDefinition = getSynchronousRenderStateDefinition(defaultRenderInput, legacyLayoutProps) ?? { render: () => null };
190
256
  if (typeof defaultRenderDefinition !== "object" || defaultRenderDefinition === null || !("render" in defaultRenderDefinition) || typeof defaultRenderDefinition.render !== "function") throw new LayoutConfigurationError("The \"default\" render state must define a render function");
191
257
  const defaultState = defaultRenderDefinition;
258
+ if (!inheritedInspection) inspectionStore.node({
259
+ id: activeInspection.state,
260
+ kind: "state",
261
+ label: "default",
262
+ unresolved: createdDefaultState,
263
+ details: {
264
+ props: mergeLayoutProps(legacyLayoutProps, defaultState.props),
265
+ propSchemas: rawResolvedOptions
266
+ }
267
+ });
192
268
  const render = defaultState.render;
193
- const layoutProps = defaultState.props ?? legacyLayoutProps;
269
+ const layoutProps = mergeLayoutProps(legacyLayoutProps, defaultState.props);
194
270
  const customLayoutProps = layoutProps?.custom;
195
271
  const includeLayoutProps = layoutProps?.include;
196
272
  const layoutOptionValues = layoutOptionProps;
@@ -208,7 +284,26 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
208
284
  ...composables?.(create, stateScope.states) ?? {},
209
285
  ...defaultState.composables?.(create, stateScope.states)
210
286
  }) : void 0;
211
- const resolvedComposables = defaultComposables ? resolveLayoutComposables(defaultComposables, layoutContext) : void 0;
287
+ const resolvedComposables = defaultComposables ? { ...resolveLayoutComposables(defaultComposables, layoutContext) } : void 0;
288
+ for (const [key, component] of Object.entries(resolvedComposables ?? {})) {
289
+ const id = inspectionStore.node({
290
+ id: inspectionId("composable"),
291
+ kind: "composable",
292
+ label: key,
293
+ details: {
294
+ displayName: component.displayName,
295
+ relationship: "declared; may not be rendered"
296
+ }
297
+ });
298
+ inspectionStore.edge(activeInspection.state, id, "declares");
299
+ resolvedComposables[key] = trackComposable(component, inspectionStore, id);
300
+ const reference = component[stateReferenceSource];
301
+ if (reference) {
302
+ const stateName = Object.entries(renderStates).find(([, input]) => input === reference.input)?.[0];
303
+ const target = stateName ? stateIds.get(stateName) : getReferenceStateId(reference.input, reference.name);
304
+ inspectionStore.edge(id, target, "references");
305
+ }
306
+ }
212
307
  const mergedResolvedInProps = { ...resolvedInProps };
213
308
  for (const { props: presetPropDefinitions } of collectComposablePresetEntries(resolvedComposables)) Object.assign(mergedResolvedInProps, presetPropDefinitions);
214
309
  const composablePresetProps = Object.fromEntries(collectComposablePresetEntries(resolvedComposables).map(({ key, props: presetPropDefinitions }) => {
@@ -228,6 +323,10 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
228
323
  const stateComponents = {};
229
324
  let CreatedDefaultStateComponent;
230
325
  function RenderDefaultState({ renderProps }) {
326
+ useLayoutEffect(() => {
327
+ if (CreatedDefaultStateComponent) return;
328
+ return inspectionStore.mount(activeInspection.layout, activeInspection.state, ...resourceId ? [resourceId] : []);
329
+ }, []);
231
330
  if (CreatedDefaultStateComponent) return /* @__PURE__ */ jsx(CreatedDefaultStateComponent, { ...renderProps });
232
331
  return render(renderProps, mergedRenderContext);
233
332
  }
@@ -271,7 +370,8 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
271
370
  children: /* @__PURE__ */ jsx(StateComposableContext.Provider, {
272
371
  value: {
273
372
  scope: stateScope,
274
- props: layoutRenderProps
373
+ props: layoutRenderProps,
374
+ definitions: mergedResolvedInProps
275
375
  },
276
376
  children: /* @__PURE__ */ jsx(RenderDefaultState, { renderProps: layoutRenderProps })
277
377
  })
@@ -293,24 +393,25 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
293
393
  if (!compositionOptions.components) return {};
294
394
  return { makeComposable: createComposableLayout(compositionOptions) };
295
395
  }
296
- function createStateComponent(stateName, input, validateStateName = true) {
396
+ function createStateComponent(stateName, input, validateStateName = true, fallbackStateName = stateName) {
397
+ const inspectedId = validateStateName ? stateIds.get(stateName) : getReferenceStateId(input, stateName);
297
398
  if (isLazyRenderState(input)) {
298
399
  const loadState = input[lazyRenderStateSymbol];
299
400
  function createLazyState() {
300
401
  return lazy(async () => {
301
- const stateDefinition = findDefinedRenderState(await loadState().catch((error) => {
402
+ const stateDefinition = await findDefinedRenderState(await loadState().catch((error) => {
302
403
  throw new ResourceModuleLoadError(String(layoutContext.resource), error);
303
404
  }));
304
405
  if (validateStateName && stateDefinition.state !== void 0 && stateDefinition.state !== stateName) throw new LayoutConfigurationError(`Lazy render state "${stateDefinition.state}" cannot be used as "${stateName}"`);
305
- return { default: createLoadedStateComponent(validateStateName ? stateName : stateDefinition.state ?? stateName, stateDefinition) };
406
+ return { default: createLoadedStateComponent(validateStateName ? stateName : stateDefinition.state ?? stateName, stateDefinition, inspectedId) };
306
407
  });
307
408
  }
308
409
  function LazyStateComponent(props) {
309
410
  const [, rerender] = useReducer((version) => version + 1, 0);
310
411
  const LazyState = useRef(createLazyState());
311
412
  const CurrentLazyState = LazyState.current;
312
- const LoadingComponent = stateName === "Loading" ? void 0 : stateComponents.Loading;
313
- const ErrorComponent = stateName === "Error" ? void 0 : stateComponents.Error;
413
+ const LoadingComponent = fallbackStateName === "Loading" ? void 0 : stateComponents.Loading;
414
+ const ErrorComponent = fallbackStateName === "Error" ? void 0 : stateComponents.Error;
314
415
  function retry() {
315
416
  LazyState.current = createLazyState();
316
417
  rerender();
@@ -335,12 +436,12 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
335
436
  }
336
437
  const definition = isDeferredRenderState(input) ? input[deferredRenderStateSymbol] : typeof input === "function" ? { render: input } : input;
337
438
  if (typeof definition !== "object" || definition === null || !("render" in definition) || typeof definition.render !== "function") throw new LayoutConfigurationError(`Render state "${stateName}" must define a render function`);
338
- const StateComponent = createLoadedStateComponent(stateName, definition);
439
+ const StateComponent = createLoadedStateComponent(stateName, definition, inspectedId);
339
440
  if (!isDeferredRenderState(input)) return StateComponent;
340
441
  const DeferredState = lazy(() => Promise.resolve({ default: StateComponent }));
341
442
  function DeferredStateComponent(props) {
342
- const LoadingComponent = stateName === "Loading" ? void 0 : stateComponents.Loading;
343
- const ErrorComponent = stateName === "Error" ? void 0 : stateComponents.Error;
443
+ const LoadingComponent = fallbackStateName === "Loading" ? void 0 : stateComponents.Loading;
444
+ const ErrorComponent = fallbackStateName === "Error" ? void 0 : stateComponents.Error;
344
445
  const rendered = /* @__PURE__ */ jsx(Suspense, {
345
446
  fallback: LoadingComponent ? /* @__PURE__ */ jsx(LoadingComponent, {}) : null,
346
447
  children: /* @__PURE__ */ jsx(DeferredState, { ...props })
@@ -358,7 +459,17 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
358
459
  }
359
460
  return DeferredStateComponent;
360
461
  }
361
- function createLoadedStateComponent(stateName, definition) {
462
+ function createLoadedStateComponent(stateName, definition, inspectedState = stateIds.get(stateName)) {
463
+ if (inspectedState) inspectionStore.node({
464
+ id: inspectedState,
465
+ kind: "state",
466
+ label: stateName,
467
+ unresolved: false,
468
+ details: {
469
+ props: mergeLayoutProps(legacyLayoutProps, definition.props),
470
+ propSchemas: rawResolvedOptions
471
+ }
472
+ });
362
473
  const stateComposables = composables || definition.composables ? (create) => ({
363
474
  ...composables?.(create, stateScope.states) ?? {},
364
475
  ...definition.composables?.(create, stateScope.states)
@@ -372,11 +483,15 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
372
483
  options: inProps,
373
484
  layout: {
374
485
  composables: stateComposables,
375
- props: definition.props,
486
+ props: mergeLayoutProps(legacyLayoutProps, definition.props),
376
487
  render: stateRender
377
488
  }
378
- }, stateScope).createResourceLayout({
489
+ }, stateScope, {
490
+ ...activeInspection,
491
+ state: inspectedState ?? getReferenceStateId(definition, stateName)
492
+ }).createResourceLayout({
379
493
  ...layoutOptions,
494
+ name,
380
495
  namespace: false
381
496
  });
382
497
  StateComponent.displayName = `${name}.${stateName}`;
@@ -408,7 +523,7 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
408
523
  const definition = mergedResolvedInProps[key];
409
524
  return [[key, isIncludedPropRequired(includeLayoutProps?.[key]) ? definition : definition.optional?.() ?? definition]];
410
525
  }));
411
- const rootComponent = attachComponentPropDefinitions(Object.assign(Component, {
526
+ const createdComponent = Object.assign(Component, {
412
527
  displayName: name,
413
528
  props: void 0,
414
529
  resource: void 0,
@@ -418,7 +533,9 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
418
533
  }),
419
534
  ...stateComponents,
420
535
  [definedResourceLayoutComponentSymbol]: true
421
- }), {
536
+ });
537
+ inspectionStore.attach(createdComponent);
538
+ const rootComponent = attachComponentPropDefinitions(createdComponent, {
422
539
  ...customLayoutProps,
423
540
  ...includedComponentDefinitions
424
541
  });
@@ -462,7 +579,7 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
462
579
  for (const { props: presetPropDefinitions } of collectComposablePresetEntries(resolvedComposables)) Object.assign(resolvedInProps, presetPropDefinitions);
463
580
  return {
464
581
  ...resolvedInProps,
465
- ...(defaultState?.props ?? layout.props)?.custom
582
+ ...mergeLayoutProps(layout.props, defaultState?.props)?.custom
466
583
  };
467
584
  }
468
585
  const { createLayoutForResourceBuilder, forResource } = createForResource({
@@ -479,14 +596,16 @@ function defineResourceLayoutImpl(options, inheritedStateScope) {
479
596
  })
480
597
  };
481
598
  if (layout.composables) createResourceLayoutExtras.makeComposable = createTopLevelMakeComposable();
482
- return {
599
+ const createResourceLayout = Object.assign(definedResourceLayout, createResourceLayoutExtras);
600
+ const createResourceLinks = createResourceLinksFn(resources);
601
+ return (inspection?.store.attach ?? ((value) => value))({
483
602
  createResourceConfig,
484
- createResourceLayout: Object.assign(definedResourceLayout, createResourceLayoutExtras),
485
- createResourceLinks: createResourceLinksFn(resources),
603
+ createResourceLayout,
604
+ createResourceLinks,
486
605
  resources: resourcesAccessor,
487
606
  ResourceProvider,
488
607
  useResource
489
- };
608
+ });
490
609
  }
491
610
  function defineResources(...resources) {
492
611
  return resources;