@player-tools/dsl 0.4.0-next.4 → 0.4.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/dist/index.cjs.js CHANGED
@@ -3,7 +3,6 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
- var flattenChildren = require('react-flatten-children');
7
6
  var mergeRefs = require('react-merge-refs');
8
7
  var reactJsonReconciler = require('react-json-reconciler');
9
8
  var player = require('@player-ui/player');
@@ -14,7 +13,6 @@ var sourceMapJs = require('source-map-js');
14
13
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
15
14
 
16
15
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
17
- var flattenChildren__default = /*#__PURE__*/_interopDefaultLegacy(flattenChildren);
18
16
  var mergeRefs__default = /*#__PURE__*/_interopDefaultLegacy(mergeRefs);
19
17
 
20
18
  const IDSuffixContext = React__default["default"].createContext("root");
@@ -252,6 +250,16 @@ function normalizeToCollection(options) {
252
250
  }
253
251
  return normalizeText(__spreadProps$3(__spreadValues$4({}, options), { node }));
254
252
  }
253
+ function flattenChildren(children) {
254
+ const childrenArray = React__default["default"].Children.toArray(children);
255
+ return childrenArray.reduce((flatChildren, child) => {
256
+ if (child.type === React__default["default"].Fragment) {
257
+ return flatChildren.concat(flattenChildren(child.props.children));
258
+ }
259
+ flatChildren.push(child);
260
+ return flatChildren;
261
+ }, []);
262
+ }
255
263
 
256
264
  var __defProp$3 = Object.defineProperty;
257
265
  var __defProps$2 = Object.defineProperties;
@@ -347,7 +355,7 @@ View.defaultProps = {
347
355
  const Slot = (props) => {
348
356
  var _a, _b;
349
357
  const { TextComp, CollectionComp } = props;
350
- const children = flattenChildren__default["default"](props.children);
358
+ const children = flattenChildren(props.children);
351
359
  const propRef = React__default["default"].useRef(null);
352
360
  return /* @__PURE__ */ React__default["default"].createElement("property", {
353
361
  ref: propRef,
@@ -696,6 +704,9 @@ function makeBindingsForObject(obj, arrayAccessorKeys = ["_index_"]) {
696
704
  },
697
705
  get(target, key) {
698
706
  const bindingKeys = Object.keys(target);
707
+ if (Array.isArray(target[key]) && target[key].length > 0 && target[key].every((it) => typeof it !== "object")) {
708
+ return [...target[key]];
709
+ }
699
710
  if (!bindingMap.has(target)) {
700
711
  bindingMap.set(target, binding`${paths.join(".")}`);
701
712
  }
@@ -729,6 +740,20 @@ const getRefStringFromObject = (obj) => {
729
740
  return getBindingFromObject(obj).toRefString();
730
741
  };
731
742
 
743
+ const fingerprintContent = (content, filename) => {
744
+ if (content !== null || content !== void 0) {
745
+ if (React__default["default"].isValidElement(content)) {
746
+ return "view";
747
+ }
748
+ if (typeof content === "object" && "navigation" in content) {
749
+ return "flow";
750
+ }
751
+ if (!filename || filename.includes("schema")) {
752
+ return "schema";
753
+ }
754
+ }
755
+ };
756
+
732
757
  var __defProp = Object.defineProperty;
733
758
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
734
759
  var __hasOwnProp = Object.prototype.hasOwnProperty;
@@ -818,51 +843,53 @@ class DSLCompiler {
818
843
  };
819
844
  this.logger = logger != null ? logger : console;
820
845
  }
821
- serialize(value) {
846
+ serialize(value, context) {
822
847
  return __async(this, null, function* () {
823
848
  var _a, _b;
824
849
  if (typeof value !== "object" || value === null) {
825
850
  throw new Error("Unable to serialize non-object");
826
851
  }
852
+ const type = (context == null ? void 0 : context.type) ? context.type : fingerprintContent(value);
827
853
  const schemaGenerator = new SchemaGenerator(this.logger);
828
854
  this.hooks.schemaGenerator.call(schemaGenerator);
829
- if (React__default["default"].isValidElement(value)) {
855
+ if (type === "view") {
830
856
  const { jsonValue, sourceMap } = yield reactJsonReconciler.render(value, {
831
857
  collectSourceMap: true
832
858
  });
833
859
  return {
834
860
  value: jsonValue,
835
- sourceMap,
836
- contentType: "view"
861
+ sourceMap
837
862
  };
838
863
  }
839
- const preProcessedValue = yield this.hooks.preProcessFlow.call(value);
840
- if ("navigation" in preProcessedValue) {
864
+ if (type === "flow") {
841
865
  const allSourceMaps = [];
842
- const copiedValue = __spreadValues({}, preProcessedValue);
866
+ const copiedValue = __spreadValues({}, value);
843
867
  copiedValue.views = yield Promise.all((_b = (_a = copiedValue == null ? void 0 : copiedValue.views) == null ? void 0 : _a.map((node) => __async(this, null, function* () {
844
- const { jsonValue, sourceMap, stringValue } = yield reactJsonReconciler.render(node, {
845
- collectSourceMap: true
846
- });
847
- if (sourceMap) {
848
- const searchIdLine = stringValue.split("\n").find((line) => line.includes(`"id": "${jsonValue.id}"`));
849
- if (searchIdLine) {
850
- allSourceMaps.push({
851
- sourceMap,
852
- offsetIndexSearch: searchIdLine,
853
- source: stringValue
854
- });
868
+ if (React__default["default"].isValidElement(node)) {
869
+ const { jsonValue, sourceMap, stringValue } = yield reactJsonReconciler.render(node, {
870
+ collectSourceMap: true
871
+ });
872
+ if (sourceMap) {
873
+ const searchIdLine = stringValue.split("\n").find((line) => line.includes(`"id": "${jsonValue.id}"`));
874
+ if (searchIdLine) {
875
+ allSourceMaps.push({
876
+ sourceMap,
877
+ offsetIndexSearch: searchIdLine,
878
+ source: stringValue
879
+ });
880
+ }
855
881
  }
882
+ return jsonValue;
856
883
  }
857
- return jsonValue;
884
+ return node;
858
885
  }))) != null ? _b : []);
859
- if ("navigation" in preProcessedValue) {
860
- Object.entries(preProcessedValue.navigation).forEach(([navKey, node]) => {
886
+ if ("navigation" in value) {
887
+ Object.entries(value.navigation).forEach(([navKey, node]) => {
861
888
  if (typeof node === "object") {
862
889
  Object.entries(node).forEach(([nodeKey, flowNode]) => {
863
890
  var _a2, _b2, _c, _d;
864
891
  if (flowNode && typeof flowNode === "object" && "state_type" in flowNode && flowNode.state_type === "VIEW" && React__default["default"].isValidElement(flowNode.ref)) {
865
- const actualViewIndex = (_b2 = (_a2 = preProcessedValue.views) == null ? void 0 : _a2.indexOf) == null ? void 0 : _b2.call(_a2, flowNode.ref);
892
+ const actualViewIndex = (_b2 = (_a2 = value.views) == null ? void 0 : _a2.indexOf) == null ? void 0 : _b2.call(_a2, flowNode.ref);
866
893
  if (actualViewIndex !== void 0 && actualViewIndex > -1) {
867
894
  const actualId = (_d = (_c = copiedValue.views) == null ? void 0 : _c[actualViewIndex]) == null ? void 0 : _d.id;
868
895
  copiedValue.navigation[navKey][nodeKey].ref = actualId;
@@ -871,7 +898,7 @@ class DSLCompiler {
871
898
  });
872
899
  }
873
900
  });
874
- if ("schema" in preProcessedValue) {
901
+ if ("schema" in copiedValue) {
875
902
  copiedValue.schema = schemaGenerator.toSchema(copiedValue.schema);
876
903
  }
877
904
  copiedValue.navigation = parseNavigationExpressions(copiedValue.navigation);
@@ -880,19 +907,25 @@ class DSLCompiler {
880
907
  const postProcessFlow = yield this.hooks.postProcessFlow.call(copiedValue);
881
908
  return {
882
909
  value: postProcessFlow,
883
- contentType: "flow",
884
910
  sourceMap: mergeSourceMaps(allSourceMaps, JSON.stringify(copiedValue, null, 2))
885
911
  };
886
912
  }
887
913
  }
888
- return {
889
- value: schemaGenerator.toSchema(preProcessedValue),
890
- contentType: "schema"
891
- };
914
+ if (type === "schema") {
915
+ return {
916
+ value: schemaGenerator.toSchema(value)
917
+ };
918
+ }
919
+ throw Error("DSL Compiler Error: Unable to determine type to compile as");
892
920
  });
893
921
  }
894
922
  }
895
923
 
924
+ const DefaultCompilerContentTypes = ["view", "flow", "schema"];
925
+ function isDefaultCompilerContentType(t) {
926
+ return DefaultCompilerContentTypes.includes(t);
927
+ }
928
+
896
929
  exports.Asset = Asset;
897
930
  exports.AssetWrapper = AssetWrapper;
898
931
  exports.DSLCompiler = DSLCompiler;
@@ -914,9 +947,12 @@ exports.View = View;
914
947
  exports.binding = binding;
915
948
  exports.createSlot = createSlot;
916
949
  exports.expression = expression;
950
+ exports.fingerprintContent = fingerprintContent;
951
+ exports.flattenChildren = flattenChildren;
917
952
  exports.getBindingFromObject = getBindingFromObject;
918
953
  exports.getBindingStringFromObject = getBindingStringFromObject;
919
954
  exports.getRefStringFromObject = getRefStringFromObject;
955
+ exports.isDefaultCompilerContentType = isDefaultCompilerContentType;
920
956
  exports.isTemplateStringInstance = isTemplateStringInstance;
921
957
  exports.makeBindingsForObject = makeBindingsForObject;
922
958
  exports.normalizeText = normalizeText;
package/dist/index.d.ts CHANGED
@@ -230,6 +230,13 @@ declare function normalizeToCollection(options: {
230
230
  /** A collection asset */
231
231
  CollectionComp?: React$1.ComponentType;
232
232
  }): React$1.ReactNode;
233
+ declare type ReactChildArray = ReturnType<typeof React$1.Children.toArray>;
234
+ /**
235
+ *
236
+ * Hoisted from https://github.com/gregberge/react-flatten-children/blob/master/src/index.tsx
237
+ * Peer dependencies were wrong and can't be reasonably patch it everywhere
238
+ */
239
+ declare function flattenChildren(children: React$1.ReactNode): ReactChildArray;
233
240
 
234
241
  interface SwitchProps {
235
242
  /** defaults to a staticSwitch */
@@ -302,7 +309,7 @@ declare type MakeArrayIntoIndexRef<T extends any[]> = {
302
309
  _index_: MakeBindingRefable<T[0]>;
303
310
  } & BindingTemplateInstance;
304
311
  declare type MakeBindingRefable<T> = {
305
- [P in keyof T]: T[P] extends any[] ? MakeArrayIntoIndexRef<T[P]> : MakeBindingRefable<T[P]>;
312
+ [P in keyof T]: T[P] extends object[] ? MakeArrayIntoIndexRef<T[P]> : T[P] extends unknown[] ? T[P] : MakeBindingRefable<T[P]>;
306
313
  } & BindingTemplateInstance;
307
314
  /**
308
315
  * Adds bindings to an object so that the object can be directly used in JSX
@@ -344,6 +351,29 @@ interface DSLSchema {
344
351
  declare type SerializeType = 'view' | 'flow' | 'schema' | 'navigation';
345
352
  declare type SerializablePlayerExportTypes = React.ReactElement | FlowWithReactViews | Schema.Schema | Navigation$1;
346
353
  declare type LoggingInterface = Pick<Console, 'warn' | 'error' | 'log'>;
354
+ declare type CompilationResult = {
355
+ /** What type of file is generated */
356
+ contentType: string;
357
+ /** The output path */
358
+ outputFile: string;
359
+ /** the input file */
360
+ inputFile: string;
361
+ };
362
+ declare type CompilerReturn = {
363
+ /** the JSON value of the source */
364
+ value: JsonType | undefined;
365
+ /** The sourcemap of the content */
366
+ sourceMap?: string;
367
+ };
368
+ /** The different type of default content items the compiler handles */
369
+ declare const DefaultCompilerContentTypes: readonly ["view", "flow", "schema"];
370
+ declare type DefaultCompilerContentType = typeof DefaultCompilerContentTypes[number];
371
+ /** Helper function to determine whether a content type is compiler default */
372
+ declare function isDefaultCompilerContentType(t: string): t is DefaultCompilerContentType;
373
+ interface SerializeContext {
374
+ /** The type of the content being compiled */
375
+ type: DefaultCompilerContentType;
376
+ }
347
377
 
348
378
  /**
349
379
  * Argument passed to the DSLCompiler onEnd hook
@@ -364,14 +394,10 @@ declare class DSLCompiler {
364
394
  };
365
395
  constructor(logger?: LoggingInterface);
366
396
  /** Convert an object (flow, view, schema, etc) into it's JSON representation */
367
- serialize(value: unknown): Promise<{
368
- /** the JSON value of the source */
369
- value: JsonType | undefined;
370
- /** the fingerprinted content type of the source */
371
- contentType: SerializeType;
372
- /** The sourcemap of the content */
373
- sourceMap?: string;
374
- }>;
397
+ serialize(value: unknown, context?: SerializeContext): Promise<CompilerReturn | undefined>;
375
398
  }
376
399
 
377
- export { AddUnknownIndex, Asset, AssetProps, AssetPropsWithChildren, AssetWrapper, BindingTemplateInstance, CaseProps, DSLCompiler, DSLFlow, DSLSchema, ExpressionTemplateInstance, FlowWithReactViews, FlowWithoutUnknown, GeneratedIDProperty, IDProvider, IDSuffixIndexProvider, IDSuffixProvider, IndexSuffixStopContext, LoggingInterface, MakeArrayIntoIndexRef, MakeBindingRefable, NavFlowState, Navigation, NavigationFlowReactViewState, NavigationFlowWithReactView, NavigationWithReactViews, OmitProp, OnEndArg, OptionalIDSuffixProvider, PlayerApplicability, RemoveUnknownIndex, SchemaGenerator, SchemaTypeName, SerializablePlayerExportTypes, SerializeType, Slot, SlotContext, SwapKeysToType, Switch, SwitchProps, Template, TemplateContext, TemplateContextType, TemplateInstanceRefStringContext, TemplateInstanceRefStringOptions, TemplateProps, TemplateRefStringOptions, TemplateStringComponent, TemplateStringType, View, WithChildren, WithTemplateTypes, binding, createSlot, expression, getBindingFromObject, getBindingStringFromObject, getRefStringFromObject, isTemplateStringInstance, makeBindingsForObject, normalizeText, normalizeToCollection, toArray, toJsonElement, toJsonOptions, toJsonProperties, useGetIdPrefix, useIndexInSlot };
400
+ /** Basic way of identifying the type of file based on the default content export */
401
+ declare const fingerprintContent: (content: unknown, filename?: string) => DefaultCompilerContentType | undefined;
402
+
403
+ export { AddUnknownIndex, Asset, AssetProps, AssetPropsWithChildren, AssetWrapper, BindingTemplateInstance, CaseProps, CompilationResult, CompilerReturn, DSLCompiler, DSLFlow, DSLSchema, DefaultCompilerContentType, ExpressionTemplateInstance, FlowWithReactViews, FlowWithoutUnknown, GeneratedIDProperty, IDProvider, IDSuffixIndexProvider, IDSuffixProvider, IndexSuffixStopContext, LoggingInterface, MakeArrayIntoIndexRef, MakeBindingRefable, NavFlowState, Navigation, NavigationFlowReactViewState, NavigationFlowWithReactView, NavigationWithReactViews, OmitProp, OnEndArg, OptionalIDSuffixProvider, PlayerApplicability, RemoveUnknownIndex, SchemaGenerator, SchemaTypeName, SerializablePlayerExportTypes, SerializeContext, SerializeType, Slot, SlotContext, SwapKeysToType, Switch, SwitchProps, Template, TemplateContext, TemplateContextType, TemplateInstanceRefStringContext, TemplateInstanceRefStringOptions, TemplateProps, TemplateRefStringOptions, TemplateStringComponent, TemplateStringType, View, WithChildren, WithTemplateTypes, binding, createSlot, expression, fingerprintContent, flattenChildren, getBindingFromObject, getBindingStringFromObject, getRefStringFromObject, isDefaultCompilerContentType, isTemplateStringInstance, makeBindingsForObject, normalizeText, normalizeToCollection, toArray, toJsonElement, toJsonOptions, toJsonProperties, useGetIdPrefix, useIndexInSlot };
package/dist/index.esm.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import flattenChildren from 'react-flatten-children';
3
2
  import mergeRefs from 'react-merge-refs';
4
3
  import { flattenNodes, ProxyNode, createPortal, PropertyNode, ValueNode, ArrayNode, toJSON, render } from 'react-json-reconciler';
5
4
  export * from 'react-json-reconciler';
@@ -243,6 +242,16 @@ function normalizeToCollection(options) {
243
242
  }
244
243
  return normalizeText(__spreadProps$3(__spreadValues$4({}, options), { node }));
245
244
  }
245
+ function flattenChildren(children) {
246
+ const childrenArray = React.Children.toArray(children);
247
+ return childrenArray.reduce((flatChildren, child) => {
248
+ if (child.type === React.Fragment) {
249
+ return flatChildren.concat(flattenChildren(child.props.children));
250
+ }
251
+ flatChildren.push(child);
252
+ return flatChildren;
253
+ }, []);
254
+ }
246
255
 
247
256
  var __defProp$3 = Object.defineProperty;
248
257
  var __defProps$2 = Object.defineProperties;
@@ -687,6 +696,9 @@ function makeBindingsForObject(obj, arrayAccessorKeys = ["_index_"]) {
687
696
  },
688
697
  get(target, key) {
689
698
  const bindingKeys = Object.keys(target);
699
+ if (Array.isArray(target[key]) && target[key].length > 0 && target[key].every((it) => typeof it !== "object")) {
700
+ return [...target[key]];
701
+ }
690
702
  if (!bindingMap.has(target)) {
691
703
  bindingMap.set(target, binding`${paths.join(".")}`);
692
704
  }
@@ -720,6 +732,20 @@ const getRefStringFromObject = (obj) => {
720
732
  return getBindingFromObject(obj).toRefString();
721
733
  };
722
734
 
735
+ const fingerprintContent = (content, filename) => {
736
+ if (content !== null || content !== void 0) {
737
+ if (React.isValidElement(content)) {
738
+ return "view";
739
+ }
740
+ if (typeof content === "object" && "navigation" in content) {
741
+ return "flow";
742
+ }
743
+ if (!filename || filename.includes("schema")) {
744
+ return "schema";
745
+ }
746
+ }
747
+ };
748
+
723
749
  var __defProp = Object.defineProperty;
724
750
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
725
751
  var __hasOwnProp = Object.prototype.hasOwnProperty;
@@ -809,51 +835,53 @@ class DSLCompiler {
809
835
  };
810
836
  this.logger = logger != null ? logger : console;
811
837
  }
812
- serialize(value) {
838
+ serialize(value, context) {
813
839
  return __async(this, null, function* () {
814
840
  var _a, _b;
815
841
  if (typeof value !== "object" || value === null) {
816
842
  throw new Error("Unable to serialize non-object");
817
843
  }
844
+ const type = (context == null ? void 0 : context.type) ? context.type : fingerprintContent(value);
818
845
  const schemaGenerator = new SchemaGenerator(this.logger);
819
846
  this.hooks.schemaGenerator.call(schemaGenerator);
820
- if (React.isValidElement(value)) {
847
+ if (type === "view") {
821
848
  const { jsonValue, sourceMap } = yield render(value, {
822
849
  collectSourceMap: true
823
850
  });
824
851
  return {
825
852
  value: jsonValue,
826
- sourceMap,
827
- contentType: "view"
853
+ sourceMap
828
854
  };
829
855
  }
830
- const preProcessedValue = yield this.hooks.preProcessFlow.call(value);
831
- if ("navigation" in preProcessedValue) {
856
+ if (type === "flow") {
832
857
  const allSourceMaps = [];
833
- const copiedValue = __spreadValues({}, preProcessedValue);
858
+ const copiedValue = __spreadValues({}, value);
834
859
  copiedValue.views = yield Promise.all((_b = (_a = copiedValue == null ? void 0 : copiedValue.views) == null ? void 0 : _a.map((node) => __async(this, null, function* () {
835
- const { jsonValue, sourceMap, stringValue } = yield render(node, {
836
- collectSourceMap: true
837
- });
838
- if (sourceMap) {
839
- const searchIdLine = stringValue.split("\n").find((line) => line.includes(`"id": "${jsonValue.id}"`));
840
- if (searchIdLine) {
841
- allSourceMaps.push({
842
- sourceMap,
843
- offsetIndexSearch: searchIdLine,
844
- source: stringValue
845
- });
860
+ if (React.isValidElement(node)) {
861
+ const { jsonValue, sourceMap, stringValue } = yield render(node, {
862
+ collectSourceMap: true
863
+ });
864
+ if (sourceMap) {
865
+ const searchIdLine = stringValue.split("\n").find((line) => line.includes(`"id": "${jsonValue.id}"`));
866
+ if (searchIdLine) {
867
+ allSourceMaps.push({
868
+ sourceMap,
869
+ offsetIndexSearch: searchIdLine,
870
+ source: stringValue
871
+ });
872
+ }
846
873
  }
874
+ return jsonValue;
847
875
  }
848
- return jsonValue;
876
+ return node;
849
877
  }))) != null ? _b : []);
850
- if ("navigation" in preProcessedValue) {
851
- Object.entries(preProcessedValue.navigation).forEach(([navKey, node]) => {
878
+ if ("navigation" in value) {
879
+ Object.entries(value.navigation).forEach(([navKey, node]) => {
852
880
  if (typeof node === "object") {
853
881
  Object.entries(node).forEach(([nodeKey, flowNode]) => {
854
882
  var _a2, _b2, _c, _d;
855
883
  if (flowNode && typeof flowNode === "object" && "state_type" in flowNode && flowNode.state_type === "VIEW" && React.isValidElement(flowNode.ref)) {
856
- const actualViewIndex = (_b2 = (_a2 = preProcessedValue.views) == null ? void 0 : _a2.indexOf) == null ? void 0 : _b2.call(_a2, flowNode.ref);
884
+ const actualViewIndex = (_b2 = (_a2 = value.views) == null ? void 0 : _a2.indexOf) == null ? void 0 : _b2.call(_a2, flowNode.ref);
857
885
  if (actualViewIndex !== void 0 && actualViewIndex > -1) {
858
886
  const actualId = (_d = (_c = copiedValue.views) == null ? void 0 : _c[actualViewIndex]) == null ? void 0 : _d.id;
859
887
  copiedValue.navigation[navKey][nodeKey].ref = actualId;
@@ -862,7 +890,7 @@ class DSLCompiler {
862
890
  });
863
891
  }
864
892
  });
865
- if ("schema" in preProcessedValue) {
893
+ if ("schema" in copiedValue) {
866
894
  copiedValue.schema = schemaGenerator.toSchema(copiedValue.schema);
867
895
  }
868
896
  copiedValue.navigation = parseNavigationExpressions(copiedValue.navigation);
@@ -871,18 +899,24 @@ class DSLCompiler {
871
899
  const postProcessFlow = yield this.hooks.postProcessFlow.call(copiedValue);
872
900
  return {
873
901
  value: postProcessFlow,
874
- contentType: "flow",
875
902
  sourceMap: mergeSourceMaps(allSourceMaps, JSON.stringify(copiedValue, null, 2))
876
903
  };
877
904
  }
878
905
  }
879
- return {
880
- value: schemaGenerator.toSchema(preProcessedValue),
881
- contentType: "schema"
882
- };
906
+ if (type === "schema") {
907
+ return {
908
+ value: schemaGenerator.toSchema(value)
909
+ };
910
+ }
911
+ throw Error("DSL Compiler Error: Unable to determine type to compile as");
883
912
  });
884
913
  }
885
914
  }
886
915
 
887
- export { Asset, AssetWrapper, DSLCompiler, GeneratedIDProperty, IDProvider, IDSuffixIndexProvider, IDSuffixProvider, IndexSuffixStopContext, OptionalIDSuffixProvider, SchemaGenerator, SchemaTypeName, Slot, SlotContext, Switch, Template, TemplateContext, TemplateStringComponent, View, binding, createSlot, expression, getBindingFromObject, getBindingStringFromObject, getRefStringFromObject, isTemplateStringInstance, makeBindingsForObject, normalizeText, normalizeToCollection, toArray, toJsonElement, toJsonProperties, useGetIdPrefix, useIndexInSlot };
916
+ const DefaultCompilerContentTypes = ["view", "flow", "schema"];
917
+ function isDefaultCompilerContentType(t) {
918
+ return DefaultCompilerContentTypes.includes(t);
919
+ }
920
+
921
+ export { Asset, AssetWrapper, DSLCompiler, GeneratedIDProperty, IDProvider, IDSuffixIndexProvider, IDSuffixProvider, IndexSuffixStopContext, OptionalIDSuffixProvider, SchemaGenerator, SchemaTypeName, Slot, SlotContext, Switch, Template, TemplateContext, TemplateStringComponent, View, binding, createSlot, expression, fingerprintContent, flattenChildren, getBindingFromObject, getBindingStringFromObject, getRefStringFromObject, isDefaultCompilerContentType, isTemplateStringInstance, makeBindingsForObject, normalizeText, normalizeToCollection, toArray, toJsonElement, toJsonProperties, useGetIdPrefix, useIndexInSlot };
888
922
  //# sourceMappingURL=index.esm.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@player-tools/dsl",
3
- "version": "0.4.0-next.4",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org"
@@ -9,8 +9,8 @@
9
9
  "react": "^17.0.2"
10
10
  },
11
11
  "dependencies": {
12
- "@player-ui/types": "0.4.0-next.7",
13
- "@player-ui/player": "0.4.0-next.7",
12
+ "@player-ui/types": "0.4.1",
13
+ "@player-ui/player": "0.4.1",
14
14
  "@types/mkdirp": "^1.0.2",
15
15
  "chalk": "^4.0.1",
16
16
  "command-line-application": "^0.10.1",
@@ -24,7 +24,7 @@
24
24
  "source-map-js": "^1.0.2",
25
25
  "ts-node": "^10.4.0",
26
26
  "typescript": "4.8.4",
27
- "tapable-ts": "^0.1.0",
27
+ "tapable-ts": "^0.2.4",
28
28
  "dequal": "^2.0.2",
29
29
  "@babel/runtime": "7.15.4"
30
30
  },
@@ -8,7 +8,12 @@ import {
8
8
  AsyncSeriesWaterfallHook,
9
9
  SyncHook,
10
10
  } from 'tapable-ts';
11
- import type { LoggingInterface, SerializeType } from './types';
11
+ import { fingerprintContent } from './utils';
12
+ import type {
13
+ LoggingInterface,
14
+ CompilerReturn,
15
+ SerializeContext,
16
+ } from './types';
12
17
  import type { Navigation } from '../types';
13
18
  import { SchemaGenerator } from './schema';
14
19
 
@@ -123,24 +128,20 @@ export class DSLCompiler {
123
128
  }
124
129
 
125
130
  /** Convert an object (flow, view, schema, etc) into it's JSON representation */
126
- async serialize(value: unknown): Promise<{
127
- /** the JSON value of the source */
128
- value: JsonType | undefined;
129
-
130
- /** the fingerprinted content type of the source */
131
- contentType: SerializeType;
132
-
133
- /** The sourcemap of the content */
134
- sourceMap?: string;
135
- }> {
131
+ async serialize(
132
+ value: unknown,
133
+ context?: SerializeContext
134
+ ): Promise<CompilerReturn | undefined> {
136
135
  if (typeof value !== 'object' || value === null) {
137
136
  throw new Error('Unable to serialize non-object');
138
137
  }
139
138
 
139
+ const type = context?.type ? context.type : fingerprintContent(value);
140
+
140
141
  const schemaGenerator = new SchemaGenerator(this.logger);
141
142
  this.hooks.schemaGenerator.call(schemaGenerator);
142
143
 
143
- if (React.isValidElement(value)) {
144
+ if (type === 'view') {
144
145
  const { jsonValue, sourceMap } = await render(value, {
145
146
  collectSourceMap: true,
146
147
  });
@@ -148,82 +149,81 @@ export class DSLCompiler {
148
149
  return {
149
150
  value: jsonValue,
150
151
  sourceMap,
151
- contentType: 'view',
152
152
  };
153
153
  }
154
154
 
155
- const preProcessedValue = await this.hooks.preProcessFlow.call(value);
156
-
157
- if ('navigation' in preProcessedValue) {
155
+ if (type === 'flow') {
158
156
  // Source maps from all the nested views
159
157
  // Merge these together before returning
160
158
  const allSourceMaps: SourceMapList = [];
161
159
 
162
160
  // Assume this is a flow
163
161
  const copiedValue: Flow = {
164
- ...(preProcessedValue as any),
162
+ ...(value as any),
165
163
  };
166
164
 
167
165
  copiedValue.views = (await Promise.all(
168
166
  copiedValue?.views?.map(async (node: any) => {
169
- const { jsonValue, sourceMap, stringValue } = await render(node, {
170
- collectSourceMap: true,
171
- });
172
-
173
- if (sourceMap) {
174
- // Find the line that is the id of the view
175
- // Use that as the identifier for the sourcemap offset calc
176
- const searchIdLine = stringValue
177
- .split('\n')
178
- .find((line) =>
179
- line.includes(
180
- `"id": "${(jsonValue as Record<string, string>).id}"`
181
- )
182
- );
183
-
184
- if (searchIdLine) {
185
- allSourceMaps.push({
186
- sourceMap,
187
- offsetIndexSearch: searchIdLine,
188
- source: stringValue,
189
- });
167
+ if (React.isValidElement(node)) {
168
+ const { jsonValue, sourceMap, stringValue } = await render(node, {
169
+ collectSourceMap: true,
170
+ });
171
+
172
+ if (sourceMap) {
173
+ // Find the line that is the id of the view
174
+ // Use that as the identifier for the sourcemap offset calc
175
+ const searchIdLine = stringValue
176
+ .split('\n')
177
+ .find((line) =>
178
+ line.includes(
179
+ `"id": "${(jsonValue as Record<string, string>).id}"`
180
+ )
181
+ );
182
+
183
+ if (searchIdLine) {
184
+ allSourceMaps.push({
185
+ sourceMap,
186
+ offsetIndexSearch: searchIdLine,
187
+ source: stringValue,
188
+ });
189
+ }
190
190
  }
191
+
192
+ return jsonValue;
191
193
  }
192
194
 
193
- return jsonValue;
195
+ return node;
194
196
  }) ?? []
195
197
  )) as View[];
196
198
 
197
199
  // Go through the flow and sub out any view refs that are react elements w/ the right id
198
- if ('navigation' in preProcessedValue) {
199
- Object.entries((preProcessedValue as Flow).navigation).forEach(
200
- ([navKey, node]) => {
201
- if (typeof node === 'object') {
202
- Object.entries(node).forEach(([nodeKey, flowNode]) => {
203
- if (
204
- flowNode &&
205
- typeof flowNode === 'object' &&
206
- 'state_type' in flowNode &&
207
- flowNode.state_type === 'VIEW' &&
208
- React.isValidElement(flowNode.ref)
209
- ) {
210
- const actualViewIndex = (
211
- preProcessedValue as Flow
212
- ).views?.indexOf?.(flowNode.ref as any);
213
-
214
- if (actualViewIndex !== undefined && actualViewIndex > -1) {
215
- const actualId = copiedValue.views?.[actualViewIndex]?.id;
216
-
217
- (copiedValue as any).navigation[navKey][nodeKey].ref =
218
- actualId;
219
- }
200
+ if ('navigation' in value) {
201
+ Object.entries((value as Flow).navigation).forEach(([navKey, node]) => {
202
+ if (typeof node === 'object') {
203
+ Object.entries(node).forEach(([nodeKey, flowNode]) => {
204
+ if (
205
+ flowNode &&
206
+ typeof flowNode === 'object' &&
207
+ 'state_type' in flowNode &&
208
+ flowNode.state_type === 'VIEW' &&
209
+ React.isValidElement(flowNode.ref)
210
+ ) {
211
+ const actualViewIndex = (value as Flow).views?.indexOf?.(
212
+ flowNode.ref as any
213
+ );
214
+
215
+ if (actualViewIndex !== undefined && actualViewIndex > -1) {
216
+ const actualId = copiedValue.views?.[actualViewIndex]?.id;
217
+
218
+ (copiedValue as any).navigation[navKey][nodeKey].ref =
219
+ actualId;
220
220
  }
221
- });
222
- }
221
+ }
222
+ });
223
223
  }
224
- );
224
+ });
225
225
 
226
- if ('schema' in preProcessedValue) {
226
+ if ('schema' in copiedValue) {
227
227
  copiedValue.schema = schemaGenerator.toSchema(copiedValue.schema);
228
228
  }
229
229
 
@@ -239,7 +239,6 @@ export class DSLCompiler {
239
239
 
240
240
  return {
241
241
  value: postProcessFlow as JsonType,
242
- contentType: 'flow',
243
242
  sourceMap: mergeSourceMaps(
244
243
  allSourceMaps,
245
244
  JSON.stringify(copiedValue, null, 2)
@@ -248,9 +247,12 @@ export class DSLCompiler {
248
247
  }
249
248
  }
250
249
 
251
- return {
252
- value: schemaGenerator.toSchema(preProcessedValue) as JsonType,
253
- contentType: 'schema',
254
- };
250
+ if (type === 'schema') {
251
+ return {
252
+ value: schemaGenerator.toSchema(value) as JsonType,
253
+ };
254
+ }
255
+
256
+ throw Error('DSL Compiler Error: Unable to determine type to compile as');
255
257
  }
256
258
  }
@@ -1,2 +1,3 @@
1
1
  export * from './compiler';
2
2
  export * from './types';
3
+ export * from './utils';
@@ -188,8 +188,10 @@ export type MakeArrayIntoIndexRef<T extends any[]> = {
188
188
  } & BindingTemplateInstance;
189
189
 
190
190
  export type MakeBindingRefable<T> = {
191
- [P in keyof T]: T[P] extends any[]
191
+ [P in keyof T]: T[P] extends object[]
192
192
  ? MakeArrayIntoIndexRef<T[P]>
193
+ : T[P] extends unknown[]
194
+ ? T[P]
193
195
  : MakeBindingRefable<T[P]>;
194
196
  } & BindingTemplateInstance;
195
197
 
@@ -212,6 +214,15 @@ export function makeBindingsForObject<Type>(
212
214
  get(target: any, key: any): any {
213
215
  const bindingKeys = Object.keys(target);
214
216
 
217
+ // If there is an array of primitives, just return a copy of that array
218
+ if (
219
+ Array.isArray(target[key]) &&
220
+ target[key].length > 0 &&
221
+ target[key].every((it: any) => typeof it !== 'object')
222
+ ) {
223
+ return [...target[key]];
224
+ }
225
+
215
226
  if (!bindingMap.has(target)) {
216
227
  bindingMap.set(target, b`${paths.join('.')}`);
217
228
  }
@@ -8,6 +8,7 @@ import type {
8
8
  NavigationFlowState,
9
9
  NavigationFlowViewState,
10
10
  } from '@player-ui/types';
11
+ import type { JsonType } from 'react-json-reconciler';
11
12
  import type { RemoveUnknownIndex, AddUnknownIndex } from '../types';
12
13
 
13
14
  export type NavigationFlowReactViewState = Omit<
@@ -63,3 +64,38 @@ export type SerializablePlayerExportTypes =
63
64
  | Navigation;
64
65
 
65
66
  export type LoggingInterface = Pick<Console, 'warn' | 'error' | 'log'>;
67
+
68
+ export type CompilationResult = {
69
+ /** What type of file is generated */
70
+ contentType: string;
71
+ /** The output path */
72
+ outputFile: string;
73
+ /** the input file */
74
+ inputFile: string;
75
+ };
76
+
77
+ export type CompilerReturn = {
78
+ /** the JSON value of the source */
79
+ value: JsonType | undefined;
80
+
81
+ /** The sourcemap of the content */
82
+ sourceMap?: string;
83
+ };
84
+
85
+ /** The different type of default content items the compiler handles */
86
+ const DefaultCompilerContentTypes = ['view', 'flow', 'schema'] as const;
87
+
88
+ export type DefaultCompilerContentType =
89
+ typeof DefaultCompilerContentTypes[number];
90
+
91
+ /** Helper function to determine whether a content type is compiler default */
92
+ export function isDefaultCompilerContentType(
93
+ t: string
94
+ ): t is DefaultCompilerContentType {
95
+ return DefaultCompilerContentTypes.includes(t as DefaultCompilerContentType);
96
+ }
97
+
98
+ export interface SerializeContext {
99
+ /** The type of the content being compiled */
100
+ type: DefaultCompilerContentType;
101
+ }
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import type { DefaultCompilerContentType } from './types';
3
+
4
+ /** Basic way of identifying the type of file based on the default content export */
5
+ export const fingerprintContent = (
6
+ content: unknown,
7
+ filename?: string
8
+ ): DefaultCompilerContentType | undefined => {
9
+ if (content !== null || content !== undefined) {
10
+ if (React.isValidElement(content as any)) {
11
+ return 'view';
12
+ }
13
+
14
+ if (typeof content === 'object' && 'navigation' in (content as any)) {
15
+ return 'flow';
16
+ }
17
+
18
+ if (!filename || filename.includes('schema')) {
19
+ return 'schema';
20
+ }
21
+ }
22
+ };
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import flattenChildren from 'react-flatten-children';
3
2
  import type { ObjectNode, PropertyNode } from 'react-json-reconciler';
4
3
  import mergeRefs from 'react-merge-refs';
5
4
  import type { View as ViewType } from '@player-ui/types';
@@ -16,6 +15,7 @@ import {
16
15
  normalizeToCollection,
17
16
  toJsonElement,
18
17
  toJsonProperties,
18
+ flattenChildren,
19
19
  } from './utils';
20
20
 
21
21
  export type AssetProps = PlayerApplicability & {
package/src/index.ts CHANGED
@@ -8,3 +8,4 @@ export * from './template';
8
8
  export * from 'react-json-reconciler';
9
9
  export * from './compiler/schema';
10
10
  export * from './compiler';
11
+ export * from './compiler/types';
package/src/utils.tsx CHANGED
@@ -124,3 +124,25 @@ export function normalizeToCollection(options: {
124
124
 
125
125
  return normalizeText({ ...options, node });
126
126
  }
127
+
128
+ type ReactChildArray = ReturnType<typeof React.Children.toArray>;
129
+
130
+ /**
131
+ *
132
+ * Hoisted from https://github.com/gregberge/react-flatten-children/blob/master/src/index.tsx
133
+ * Peer dependencies were wrong and can't be reasonably patch it everywhere
134
+ */
135
+ export function flattenChildren(children: React.ReactNode): ReactChildArray {
136
+ const childrenArray = React.Children.toArray(children);
137
+ return childrenArray.reduce((flatChildren: ReactChildArray, child) => {
138
+ if ((child as React.ReactElement<any>).type === React.Fragment) {
139
+ return flatChildren.concat(
140
+ flattenChildren((child as React.ReactElement<any>).props.children)
141
+ );
142
+ }
143
+
144
+ flatChildren.push(child);
145
+
146
+ return flatChildren;
147
+ }, []);
148
+ }