@knapsack/renderer-react 4.69.13--canary.4860.ba46b2a.0 → 4.69.13--canary.4821.ae550c0.0

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.mjs CHANGED
@@ -17,9 +17,10 @@ var __dirname = /* @__PURE__ */ getDirname();
17
17
  // src/renderer-react.ts
18
18
  import sleep from "sleep-promise";
19
19
  import {
20
- RendererWebpackBase
20
+ RendererWebpackBase,
21
+ convertImportMapToNeededImportsByPath
21
22
  } from "@knapsack/renderer-webpack-base";
22
- import { pascalCase, isFirstLetterCapital, groupBy } from "@knapsack/utils";
23
+ import { pascalCase, isFirstLetterCapital } from "@knapsack/utils";
23
24
  import { knapsackEvents, log as log2 } from "@knapsack/app";
24
25
  import {
25
26
  babelCodeForBrowser,
@@ -34,9 +35,9 @@ import {
34
35
  getJsExportNames as getJsExportNames2,
35
36
  readFile as readFile2,
36
37
  formatCode as formatCode2,
37
- resolvePath as resolvePath2
38
+ assertFileExists
38
39
  } from "@knapsack/file-utils";
39
- import { join, relative, parse } from "path";
40
+ import { join, relative, parse, isAbsolute } from "path";
40
41
 
41
42
  // src/utils.ts
42
43
  import { log } from "@knapsack/app";
@@ -734,6 +735,7 @@ var rendererMetaScriptTagId = "ks-react-meta";
734
735
  // src/renderer-react.ts
735
736
  var { pkg } = findUpPkgJson(__dirname);
736
737
  log2.setupUpdateNotifier({ ...pkg, name: pkg.name, version: pkg.version });
738
+ var errorCatcherPath = join(__dirname, "./error-catcher.mjs");
737
739
  var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpackBase {
738
740
  static {
739
741
  __name(this, "KnapsackReactRenderer");
@@ -753,22 +755,29 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
753
755
  } = {}) {
754
756
  super({
755
757
  id,
756
- extension: ".jsx",
757
758
  language: "jsx",
758
759
  webpackConfig,
759
760
  extraScripts: [
760
761
  // this is the code in `./client/init.mts`
761
762
  "@knapsack/renderer-react/client"
762
- ]
763
+ ],
764
+ codeSrcs: [demoWrapperPath, errorCatcherPath]
763
765
  });
764
766
  this.language = "jsx";
765
767
  this.assets = [];
766
- this.demoWrapperPath = demoWrapperPath;
768
+ this.demoWrapperPath = isAbsolute(demoWrapperPath) ? demoWrapperPath : this.resolvePathSync({
769
+ path: demoWrapperPath,
770
+ resolveFromDir: this.userConfigDir
771
+ }).absolutePath;
772
+ assertFileExists(
773
+ this.demoWrapperPath,
774
+ `Could not find demo wrapper at: "${this.demoWrapperPath}"
775
+ Please adjust setting in "knapsack.config.js" or pass a different path when creating the React Renderer.`
776
+ );
767
777
  this.disableReactStrictMode = disableReactStrictMode;
768
778
  this.creators = [createReactPattern];
769
779
  }
770
- init = /* @__PURE__ */ __name(async (opt) => {
771
- await super.init(opt);
780
+ init = /* @__PURE__ */ __name(async () => {
772
781
  this.assets = await copyReactAssets(this.outputDir, this.publicPath);
773
782
  if (!await fileExists(this.demoWrapperPath)) {
774
783
  throw new Error(
@@ -814,80 +823,37 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
814
823
  };
815
824
  return config;
816
825
  }, "createWebpackConfig");
817
- getJsImports = /* @__PURE__ */ __name(() => {
818
- const imports = super.getJsImports();
819
- imports.push(
820
- {
821
- type: "extra",
822
- importInfo: {
823
- type: "default",
824
- path: this.demoWrapperPath,
825
- name: "DemoWrapper"
826
- }
827
- },
828
- {
829
- type: "extra",
830
- importInfo: {
831
- type: "default",
832
- path: join(__dirname, "./error-catcher.mjs"),
833
- name: "ErrorCatcher"
834
- }
835
- }
836
- );
837
- return imports;
838
- }, "getJsImports");
839
826
  async prepClientRenderResults({
840
827
  usage,
841
828
  demoApp,
842
- imports: xImports,
843
- renderOptions: { pattern, template, demo }
829
+ importMap,
830
+ renderOptions: { demo, state, patternId, templateId }
844
831
  }) {
845
- const extraImports = this.getJsImports().filter(
846
- (imp) => imp.type === "extra"
847
- );
848
- const { imports, isDeclaredVarsUnique, nameCollisions } = this.makeKsJsImportsUnique({ imports: [...xImports, ...extraImports] });
849
- if (!isDeclaredVarsUnique) {
850
- log2.error(`${nameCollisions.join(", ")} are declared multiple times`, {
851
- imports
852
- });
853
- }
854
- const importInfos = imports.map(({ importInfo }) => importInfo);
855
832
  const meta = {
856
833
  demo,
857
- moduleImports: groupBy(importInfos, (importInfo) => importInfo.path),
858
- patternId: pattern.id,
859
- templateId: template.id,
860
- imports,
861
834
  disableReactStrictMode: this.disableReactStrictMode,
835
+ neededImportsByPath: convertImportMapToNeededImportsByPath(importMap),
836
+ extraImports: {
837
+ DemoWrapper: {
838
+ type: "default",
839
+ path: this.demoWrapperPath,
840
+ name: "DemoWrapper"
841
+ },
842
+ ErrorCatcher: {
843
+ type: "default",
844
+ path: errorCatcherPath,
845
+ name: "ErrorCatcher"
846
+ }
847
+ },
862
848
  demoWrapperProps: {
863
- pattern,
864
- template,
865
- demo,
866
- patternsUsed: imports.flatMap((imp) => {
867
- if (imp.type === "pattern-template") {
868
- return [
869
- {
870
- patternId: imp.patternId,
871
- templateId: imp.templateId
872
- }
873
- ];
874
- }
875
- if (imp.type === "pattern-template-demo") {
876
- return [
877
- {
878
- patternId: imp.patternId,
879
- templateId: imp.templateId,
880
- demoId: imp.demoId
881
- }
882
- ];
883
- }
884
- return [];
885
- })
849
+ patternId,
850
+ templateId,
851
+ demo
886
852
  }
887
853
  };
888
854
  let code = `
889
855
  window.knapsack = window.knapsack || {};
890
- window.knapsack.getDemoApp = ({ ${imports.map((i) => i.importInfo.name).join(", ")} }) => {
856
+ window.knapsack.getDemoApp = ({ ${[...importMap.keys()].join(", ")} }) => {
891
857
  ${demoApp}
892
858
  return ${demoAppName}
893
859
  }
@@ -909,7 +875,7 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
909
875
  <script type="application/javascript">${code}</script>
910
876
  <div id="render-root" class="knapsack-pattern-direct-parent" data-dev-note="Knapsack React Template Wrapper"></div>
911
877
  ${this.assets.map((asset) => `<script src="${asset}"></script>`).join("\n")}
912
- ${this.createHtmlTagsForAssetPaths({
878
+ ${RendererWebpackBase.createHtmlTagsForAssetPaths({
913
879
  assets: this.getWebpackAssetPaths(),
914
880
  // we need the scripts to finish adding methods to the global knapsack object synchronously before the client-side code runs that is in the <script> tag below
915
881
  scriptTagsAreAsync: false
@@ -934,11 +900,9 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
934
900
  let attempt = 0;
935
901
  while (true) {
936
902
  try {
937
- const { absolutePath, exists } = await resolvePath2({
938
- path: opt.demo.templateInfo.path,
939
- pkgPathAliases: this.pkgPathAliases,
940
- resolveFromDir: this.dataDir
941
- });
903
+ const { absolutePath, exists } = await this.resolvePath(
904
+ opt.demo.templateInfo.path
905
+ );
942
906
  if (!exists) {
943
907
  throw new Error(
944
908
  `Template demo file does not exist: ${absolutePath}`
@@ -955,9 +919,12 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
955
919
  await sleep(waitTime);
956
920
  }
957
921
  }
958
- const [templateFileContents, { usage, imports }] = await Promise.all([
922
+ const [templateFileContents, { usage, importMap }] = await Promise.all([
959
923
  readFile2(templateDemoPath),
960
- this.getUsageAndImports(opt)
924
+ this.getUsageAndImports({
925
+ ...opt,
926
+ importMap: /* @__PURE__ */ new Map()
927
+ })
961
928
  ]);
962
929
  const demoApp = await getDemoAppUsage({
963
930
  children: usage
@@ -965,15 +932,18 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
965
932
  const results = await this.prepClientRenderResults({
966
933
  usage: templateFileContents,
967
934
  demoApp,
968
- imports,
969
- renderOptions: opt
935
+ renderOptions: opt,
936
+ importMap
970
937
  });
971
938
  return results;
972
939
  }
973
940
  if (opt.demo?.type === "data") {
974
- const { usage, imports } = await this.getUsageAndImports(opt);
975
- const { code: importCode } = this.createJsImportCodeBlock({
976
- imports
941
+ const { usage, importMap } = await this.getUsageAndImports({
942
+ ...opt,
943
+ importMap: /* @__PURE__ */ new Map()
944
+ });
945
+ const importCode = RendererWebpackBase.createJsImportCodeBlock({
946
+ importMap
977
947
  });
978
948
  const [demoAppUsage, demoApp] = await Promise.all([
979
949
  getDemoAppUsage({
@@ -988,32 +958,40 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
988
958
  return this.prepClientRenderResults({
989
959
  demoApp,
990
960
  usage: demoAppUsage,
991
- imports,
992
- renderOptions: opt
961
+ renderOptions: opt,
962
+ importMap
993
963
  });
994
964
  }
995
965
  }, "render");
996
966
  getUsageAndImports = /* @__PURE__ */ __name(async ({
997
- pattern,
998
- template,
999
- patternManifest,
1000
- demo
967
+ patternId,
968
+ templateId,
969
+ demo,
970
+ state,
971
+ importMap
1001
972
  }) => {
1002
- if (demo?.type && demo.type === "data") {
973
+ if (!demo) {
974
+ throw new Error(
975
+ `No demo provided while rendering ${patternId} ${templateId}`
976
+ );
977
+ }
978
+ const pattern = state.patterns[patternId];
979
+ if (!pattern) {
980
+ throw new Error(`Could not find pattern: ${patternId}`);
981
+ }
982
+ if (demo.type === "data") {
983
+ const template = pattern.templates.find((t) => t.id === templateId);
984
+ if (!template) {
985
+ throw new Error(`Could not find template: ${templateId}`);
986
+ }
1003
987
  const {
1004
988
  data: { props, slots, slotsOptionsComputed }
1005
989
  } = demo;
1006
- const importInfo = this.getJsImport({
1007
- patternId: pattern.id,
1008
- templateId: template.id
990
+ const { name: templateName } = await this.addUniqueValueToImportMap({
991
+ importMap,
992
+ path: template.path,
993
+ alias: template.alias || "default"
1009
994
  });
1010
- if (!importInfo) {
1011
- throw new Error(
1012
- `Could not find import for pattern-template: ${pattern.id}-${template.id}`
1013
- );
1014
- }
1015
- const { type, name: templateName } = importInfo.importInfo;
1016
- const importInfos = [importInfo];
1017
995
  const children = [];
1018
996
  const extraProps = [];
1019
997
  if (slots) {
@@ -1023,6 +1001,7 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
1023
1001
  const slotItems = slots[slotName];
1024
1002
  const slotItemsUsages = await Promise.all(
1025
1003
  slotItems.filter((slotItem) => {
1004
+ if (!slotItem) return false;
1026
1005
  if (slotItem.type !== "text") {
1027
1006
  if (!slotItem.patternId) return false;
1028
1007
  if (!slotItem.templateId) return false;
@@ -1038,31 +1017,39 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
1038
1017
  }
1039
1018
  return slotItem.text;
1040
1019
  }
1041
- const slotPattern = patternManifest.getPattern(
1042
- slotItem.patternId
1043
- );
1044
- const slotTemplate = slotPattern.templates.find(
1045
- (t) => t.id === slotItem.templateId
1046
- );
1047
1020
  if (slotItem.type === "template-reference") {
1048
- const { usage: usage2, imports } = await this.getUsageAndImports({
1049
- pattern: slotPattern,
1050
- template: slotTemplate,
1051
- patternManifest
1021
+ const slottedTemplate = state.patterns[slotItem.patternId]?.templates.find((t) => t.id === slotItem.templateId);
1022
+ if (!slottedTemplate) {
1023
+ throw new Error(
1024
+ `Could not find slotted template: ${slotItem.patternId} ${slotItem.templateId}`
1025
+ );
1026
+ }
1027
+ const templateRefImport = await this.addUniqueValueToImportMap({
1028
+ importMap,
1029
+ path: slottedTemplate.path,
1030
+ alias: slottedTemplate.alias || "default"
1052
1031
  });
1053
- importInfos.push(...imports);
1054
- return usage2;
1032
+ return templateRefImport.name;
1055
1033
  }
1056
1034
  if (slotItem.type === "template-demo") {
1057
- const { usage: usage2, imports } = await this.getUsageAndImports({
1058
- pattern: slotPattern,
1059
- template: slotTemplate,
1060
- demo: slotItem.demo || this.patterns.demosById[slotItem.demoId],
1061
- patternManifest
1035
+ const thisDemo = slotItem.demo;
1036
+ if (!thisDemo) {
1037
+ throw new Error(
1038
+ `Could not find slotted template demo ${JSON.stringify(
1039
+ slotItem
1040
+ )}`
1041
+ );
1042
+ }
1043
+ const { usage: usage2 } = await this.getUsageAndImports({
1044
+ patternId: thisDemo.patternId,
1045
+ templateId: thisDemo.templateId,
1046
+ demo: thisDemo,
1047
+ state,
1048
+ importMap
1062
1049
  });
1063
- importInfos.push(...imports);
1064
1050
  return usage2;
1065
1051
  }
1052
+ const _exhaustiveCheck2 = slotItem;
1066
1053
  throw new Error(
1067
1054
  `Unknown slot item: ${JSON.stringify(slotItem)}`
1068
1055
  );
@@ -1121,50 +1108,25 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
1121
1108
  });
1122
1109
  return {
1123
1110
  usage,
1124
- imports: importInfos
1111
+ importMap
1125
1112
  };
1126
1113
  }
1127
- if (demo?.type && demo.type === "template") {
1128
- const importInfo = this.getJsImport({
1129
- patternId: pattern.id,
1130
- templateId: template.id,
1131
- demoId: demo.id
1114
+ if (demo.type === "template") {
1115
+ const { templateInfo } = demo;
1116
+ const { name: templateName } = await this.addUniqueValueToImportMap({
1117
+ importMap,
1118
+ path: templateInfo.path,
1119
+ alias: templateInfo.alias || "default"
1132
1120
  });
1133
- if (!importInfo) {
1134
- throw new Error(
1135
- `Could not find import for pattern-template-demo: ${pattern.id}-${template.id}-${demo.id}`
1136
- );
1137
- }
1138
- const { type, name: templateName } = importInfo.importInfo;
1139
1121
  const usage = await getUsage({ templateName });
1140
1122
  return {
1141
1123
  usage,
1142
- imports: [importInfo]
1143
- };
1144
- }
1145
- if (!demo) {
1146
- const importInfo = this.getJsImport({
1147
- patternId: pattern.id,
1148
- templateId: template.id
1149
- });
1150
- if (!importInfo) {
1151
- throw new Error(
1152
- `Could not find import for pattern-template: ${pattern.id}-${template.id}`
1153
- );
1154
- }
1155
- const { type, name: templateName } = importInfo.importInfo;
1156
- return {
1157
- /**
1158
- * i.e. Given a React Component, `Button`, normally this would be `<Button>` with a demo, but since there is none this will just be a reference to it: `Button`
1159
- * @see {KsSlotInfo['isTemplateReference']}
1160
- * @see {SlottedTemplate}
1161
- */
1162
- usage: templateName,
1163
- imports: [importInfo]
1124
+ importMap
1164
1125
  };
1165
1126
  }
1127
+ const _exhaustiveCheck = demo;
1166
1128
  throw new Error(
1167
- `Unhandled demo type for ${pattern.id}-${template.id}: ${JSON.stringify(
1129
+ `Unhandled demo type for ${patternId}-${templateId}: ${JSON.stringify(
1168
1130
  demo
1169
1131
  )}`
1170
1132
  );
@@ -1187,8 +1149,8 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
1187
1149
  }
1188
1150
  return spec;
1189
1151
  }, "inferSpec");
1190
- watch = /* @__PURE__ */ __name(async (opt) => {
1191
- super.watch(opt);
1152
+ watch = /* @__PURE__ */ __name(async () => {
1153
+ super.watch();
1192
1154
  knapsackEvents.onPatternTemplateChanged(() => {
1193
1155
  clearInferSpecCache();
1194
1156
  });
@@ -1266,21 +1228,31 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
1266
1228
  ];
1267
1229
  }, "alterTemplateMetaFiles");
1268
1230
  getTemplateSuggestions = /* @__PURE__ */ __name(async ({
1269
- newPath
1231
+ newPath,
1232
+ state
1270
1233
  }) => {
1271
- const { data: dataDir } = this.patterns.userConfig;
1272
- const { allTemplateDemos, allTemplates } = this.getMyTemplates();
1273
- const usedSuggestions = [
1274
- ...allTemplateDemos,
1275
- ...allTemplates
1276
- ].map(({ path: path3, alias }) => {
1277
- return {
1278
- path: path3,
1279
- alias: alias || "default"
1280
- };
1281
- });
1234
+ const usedSuggestions = Object.values(state.patterns).reduce(
1235
+ (acc, { templateDemos, templates }) => {
1236
+ templates.forEach(({ path: path3, alias, templateLanguageId }) => {
1237
+ if (templateLanguageId !== this.id) return;
1238
+ acc.push({ path: path3, alias });
1239
+ });
1240
+ templateDemos.forEach(
1241
+ ({ templateInfo: { path: path3, alias }, templateLanguageId }) => {
1242
+ if (templateLanguageId !== this.id) return;
1243
+ acc.push({ path: path3, alias });
1244
+ }
1245
+ );
1246
+ return acc;
1247
+ },
1248
+ []
1249
+ );
1282
1250
  const allPaths = [
1283
- .../* @__PURE__ */ new Set([newPath, ...usedSuggestions.map(({ path: path3 }) => path3)])
1251
+ .../* @__PURE__ */ new Set([
1252
+ newPath,
1253
+ ...Object.keys(this.pkgPathAliases || {}),
1254
+ ...this.getCodeSrcs()
1255
+ ])
1284
1256
  ];
1285
1257
  const allSuggestions = await Promise.all(
1286
1258
  allPaths.map(async (path3) => {
@@ -1288,7 +1260,7 @@ var KnapsackReactRenderer = class _KnapsackReactRenderer extends RendererWebpack
1288
1260
  try {
1289
1261
  const { exports, errorMsg } = await getJsExportNames2({
1290
1262
  path: path3,
1291
- resolveFromDir: dataDir,
1263
+ resolveFromDir: this.dataDir,
1292
1264
  pkgPathAliases: this.pkgPathAliases
1293
1265
  });
1294
1266
  if (errorMsg) {