@plasmicapp/cli 0.1.313 → 0.1.314

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/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Socket } from "socket.io-client";
2
- import { AuthConfig, CodeConfig, I18NConfig, ImagesConfig, StyleConfig } from "./utils/config-utils";
2
+ import { AuthConfig, CodeConfig, CustomFunctionConfig, I18NConfig, ImagesConfig, StyleConfig } from "./utils/config-utils";
3
3
  import { Metadata } from "./utils/get-context";
4
4
  export declare class AppServerError extends Error {
5
5
  constructor(message: string);
@@ -88,6 +88,7 @@ export interface ProjectMetaInfo {
88
88
  export interface ProjectBundle {
89
89
  components: ComponentBundle[];
90
90
  codeComponentMetas: CodeComponentMeta[];
91
+ customFunctionMetas: CustomFunctionConfig[];
91
92
  projectConfig: ProjectMetaBundle;
92
93
  globalVariants: GlobalVariantBundle[];
93
94
  usedTokens: StyleTokensMap;
package/dist/index.js CHANGED
@@ -498381,6 +498381,30 @@ function ensureImportSpecifierWithAlias(decl, imported, alias) {
498381
498381
  );
498382
498382
  }
498383
498383
  }
498384
+ var validJsIdentifierChars = [
498385
+ "\\u0621-\\u064A",
498386
+ // arabic
498387
+ "\\u3400-\\u4DB5",
498388
+ // chinese
498389
+ "\\u4E00-\\u9FCC",
498390
+ // chinese
498391
+ "\\u0400-\\u04FF",
498392
+ // cyrillic
498393
+ "\\u0370-\\u03ff",
498394
+ // greek
498395
+ "\\u1f00-\\u1fff",
498396
+ // greek
498397
+ "\\u0900-\\u097F",
498398
+ // hindi
498399
+ "\\u3041-\\u3094",
498400
+ // japanese
498401
+ "\\u30A1-\\u30FB",
498402
+ // japanese
498403
+ "\\u0E00-\\u0E7F",
498404
+ // thai
498405
+ "\\w",
498406
+ "-_"
498407
+ ];
498384
498408
  function tryParsePlasmicImportSpec(node) {
498385
498409
  var _a;
498386
498410
  const c = (_a = node.trailingComments) == null ? void 0 : _a[0];
@@ -498388,7 +498412,14 @@ function tryParsePlasmicImportSpec(node) {
498388
498412
  return void 0;
498389
498413
  }
498390
498414
  const m = c.value.match(
498391
- /plasmic-import:\s+([\w-]+)(?:\/(component|css|render|globalVariant|projectcss|defaultcss|icon|picture|jsBundle|codeComponent|globalContext))?/
498415
+ new RegExp(
498416
+ [
498417
+ "plasmic-import:\\s+([",
498418
+ ...validJsIdentifierChars,
498419
+ "\\.",
498420
+ "]+)(?:\\/(component|css|render|globalVariant|projectcss|defaultcss|icon|picture|jsBundle|codeComponent|globalContext|customFunction))?"
498421
+ ].join("")
498422
+ )
498392
498423
  );
498393
498424
  if (m) {
498394
498425
  return { id: m[1], type: m[2] };
@@ -498567,6 +498598,21 @@ function replaceImports(context, code, fromPath, fixImportContext, removeImportD
498567
498598
  true
498568
498599
  );
498569
498600
  stmt.source.value = realPath;
498601
+ } else if (type === "customFunction") {
498602
+ const meta = fixImportContext.customFunctionMetas[uuid];
498603
+ if (!(meta == null ? void 0 : meta.importPath)) {
498604
+ throw new HandledError(
498605
+ `Encountered custom function "${uuid}" that was not registered with an importPath, so we don't know where to import this function from. Please see https://docs.plasmic.app/learn/code-components-ref/`
498606
+ );
498607
+ }
498608
+ if (meta.importPath[0] === ".") {
498609
+ const toPath = import_upath2.default.join(context.rootDir, meta.importPath);
498610
+ assert(import_upath2.default.isAbsolute(toPath));
498611
+ const realPath = makeImportPath(context, fromPath, toPath, true, true);
498612
+ stmt.source.value = realPath;
498613
+ } else {
498614
+ stmt.source.value = meta.importPath;
498615
+ }
498570
498616
  }
498571
498617
  });
498572
498618
  if (!changed) {
@@ -498611,7 +498657,15 @@ var mkFixImportContext = (config) => {
498611
498657
  config.projects,
498612
498658
  (p) => p.codeComponents || []
498613
498659
  );
498660
+ const allCustomFunctions = flatMap(
498661
+ config.projects,
498662
+ (p) => {
498663
+ var _a;
498664
+ return (_a = p.customFunctions) != null ? _a : [];
498665
+ }
498666
+ );
498614
498667
  const codeComponentMetas = import_lodash4.default.keyBy(allCodeComponents, (c) => c.id);
498668
+ const customFunctionMetas = import_lodash4.default.keyBy(allCustomFunctions, (fn) => fn.id);
498615
498669
  const globalVariants = import_lodash4.default.keyBy(
498616
498670
  config.globalVariants.variantGroups,
498617
498671
  (c) => c.id
@@ -498629,6 +498683,7 @@ var mkFixImportContext = (config) => {
498629
498683
  config,
498630
498684
  components,
498631
498685
  codeComponentMetas,
498686
+ customFunctionMetas,
498632
498687
  globalVariants,
498633
498688
  icons,
498634
498689
  images,
@@ -502411,6 +502466,11 @@ async function syncProject(context, opts, projectIdsAndTokens, projectId, branch
502411
502466
  indirect
502412
502467
  );
502413
502468
  syncCodeComponentsMeta(context, projectId, projectBundle.codeComponentMetas);
502469
+ await syncCustomFunctionsMeta(
502470
+ context,
502471
+ projectId,
502472
+ projectBundle.customFunctionMetas
502473
+ );
502414
502474
  await upsertStyleTokens(
502415
502475
  context,
502416
502476
  projectBundle.usedTokens,
@@ -502544,6 +502604,19 @@ function syncCodeComponentsMeta(context, projectId, codeComponentBundles) {
502544
502604
  } : {}
502545
502605
  }));
502546
502606
  }
502607
+ function syncCustomFunctionsMeta(context, projectId, customFunctionBundles) {
502608
+ const projectConfig = getOrAddProjectConfig(context, projectId);
502609
+ projectConfig.customFunctions = customFunctionBundles.map((meta) => {
502610
+ var _a;
502611
+ return {
502612
+ defaultExport: meta.defaultExport,
502613
+ id: meta.id,
502614
+ importPath: meta.importPath,
502615
+ name: meta.name,
502616
+ namespace: (_a = meta.namespace) != null ? _a : null
502617
+ };
502618
+ });
502619
+ }
502547
502620
 
502548
502621
  // src/actions/upload-bundle.ts
502549
502622
  var import_pako = __toESM(require_pako());
@@ -502781,6 +502854,7 @@ async function exportProjectsCli(opts) {
502781
502854
  })
502782
502855
  },
502783
502856
  projects: result.map((bundle) => {
502857
+ var _a2;
502784
502858
  const projectName = (0, import_lodash19.snakeCase)(bundle.projectConfig.projectName);
502785
502859
  return {
502786
502860
  projectId: bundle.projectConfig.projectId,
@@ -502809,6 +502883,18 @@ async function exportProjectsCli(opts) {
502809
502883
  componentImportPath: comp.importPath,
502810
502884
  helper: comp.helper
502811
502885
  })),
502886
+ customFunctionMetas: ((_a2 = bundle.customFunctionMetas) != null ? _a2 : []).map(
502887
+ (meta) => {
502888
+ var _a3;
502889
+ return {
502890
+ id: meta.id,
502891
+ name: meta.name,
502892
+ importPath: meta.importPath,
502893
+ defaultExport: meta.defaultExport,
502894
+ namespace: (_a3 = meta.namespace) != null ? _a3 : null
502895
+ };
502896
+ }
502897
+ ),
502812
502898
  icons: bundle.iconAssets.map((icon) => ({
502813
502899
  id: icon.id,
502814
502900
  name: icon.name,
package/dist/lib.js CHANGED
@@ -493723,6 +493723,30 @@ function ensureImportSpecifierWithAlias(decl, imported, alias) {
493723
493723
  );
493724
493724
  }
493725
493725
  }
493726
+ var validJsIdentifierChars = [
493727
+ "\\u0621-\\u064A",
493728
+ // arabic
493729
+ "\\u3400-\\u4DB5",
493730
+ // chinese
493731
+ "\\u4E00-\\u9FCC",
493732
+ // chinese
493733
+ "\\u0400-\\u04FF",
493734
+ // cyrillic
493735
+ "\\u0370-\\u03ff",
493736
+ // greek
493737
+ "\\u1f00-\\u1fff",
493738
+ // greek
493739
+ "\\u0900-\\u097F",
493740
+ // hindi
493741
+ "\\u3041-\\u3094",
493742
+ // japanese
493743
+ "\\u30A1-\\u30FB",
493744
+ // japanese
493745
+ "\\u0E00-\\u0E7F",
493746
+ // thai
493747
+ "\\w",
493748
+ "-_"
493749
+ ];
493726
493750
  function tryParsePlasmicImportSpec(node) {
493727
493751
  var _a;
493728
493752
  const c = (_a = node.trailingComments) == null ? void 0 : _a[0];
@@ -493730,7 +493754,14 @@ function tryParsePlasmicImportSpec(node) {
493730
493754
  return void 0;
493731
493755
  }
493732
493756
  const m = c.value.match(
493733
- /plasmic-import:\s+([\w-]+)(?:\/(component|css|render|globalVariant|projectcss|defaultcss|icon|picture|jsBundle|codeComponent|globalContext))?/
493757
+ new RegExp(
493758
+ [
493759
+ "plasmic-import:\\s+([",
493760
+ ...validJsIdentifierChars,
493761
+ "\\.",
493762
+ "]+)(?:\\/(component|css|render|globalVariant|projectcss|defaultcss|icon|picture|jsBundle|codeComponent|globalContext|customFunction))?"
493763
+ ].join("")
493764
+ )
493734
493765
  );
493735
493766
  if (m) {
493736
493767
  return { id: m[1], type: m[2] };
@@ -493909,6 +493940,21 @@ function replaceImports(context, code, fromPath, fixImportContext, removeImportD
493909
493940
  true
493910
493941
  );
493911
493942
  stmt.source.value = realPath;
493943
+ } else if (type === "customFunction") {
493944
+ const meta = fixImportContext.customFunctionMetas[uuid];
493945
+ if (!(meta == null ? void 0 : meta.importPath)) {
493946
+ throw new HandledError(
493947
+ `Encountered custom function "${uuid}" that was not registered with an importPath, so we don't know where to import this function from. Please see https://docs.plasmic.app/learn/code-components-ref/`
493948
+ );
493949
+ }
493950
+ if (meta.importPath[0] === ".") {
493951
+ const toPath = import_upath2.default.join(context.rootDir, meta.importPath);
493952
+ assert(import_upath2.default.isAbsolute(toPath));
493953
+ const realPath = makeImportPath(context, fromPath, toPath, true, true);
493954
+ stmt.source.value = realPath;
493955
+ } else {
493956
+ stmt.source.value = meta.importPath;
493957
+ }
493912
493958
  }
493913
493959
  });
493914
493960
  if (!changed) {
@@ -493953,7 +493999,15 @@ var mkFixImportContext = (config) => {
493953
493999
  config.projects,
493954
494000
  (p) => p.codeComponents || []
493955
494001
  );
494002
+ const allCustomFunctions = flatMap(
494003
+ config.projects,
494004
+ (p) => {
494005
+ var _a;
494006
+ return (_a = p.customFunctions) != null ? _a : [];
494007
+ }
494008
+ );
493956
494009
  const codeComponentMetas = import_lodash4.default.keyBy(allCodeComponents, (c) => c.id);
494010
+ const customFunctionMetas = import_lodash4.default.keyBy(allCustomFunctions, (fn) => fn.id);
493957
494011
  const globalVariants = import_lodash4.default.keyBy(
493958
494012
  config.globalVariants.variantGroups,
493959
494013
  (c) => c.id
@@ -493971,6 +494025,7 @@ var mkFixImportContext = (config) => {
493971
494025
  config,
493972
494026
  components,
493973
494027
  codeComponentMetas,
494028
+ customFunctionMetas,
493974
494029
  globalVariants,
493975
494030
  icons,
493976
494031
  images,
@@ -497709,6 +497764,11 @@ async function syncProject(context, opts, projectIdsAndTokens, projectId, branch
497709
497764
  indirect
497710
497765
  );
497711
497766
  syncCodeComponentsMeta(context, projectId, projectBundle.codeComponentMetas);
497767
+ await syncCustomFunctionsMeta(
497768
+ context,
497769
+ projectId,
497770
+ projectBundle.customFunctionMetas
497771
+ );
497712
497772
  await upsertStyleTokens(
497713
497773
  context,
497714
497774
  projectBundle.usedTokens,
@@ -497842,6 +497902,19 @@ function syncCodeComponentsMeta(context, projectId, codeComponentBundles) {
497842
497902
  } : {}
497843
497903
  }));
497844
497904
  }
497905
+ function syncCustomFunctionsMeta(context, projectId, customFunctionBundles) {
497906
+ const projectConfig = getOrAddProjectConfig(context, projectId);
497907
+ projectConfig.customFunctions = customFunctionBundles.map((meta) => {
497908
+ var _a;
497909
+ return {
497910
+ defaultExport: meta.defaultExport,
497911
+ id: meta.id,
497912
+ importPath: meta.importPath,
497913
+ name: meta.name,
497914
+ namespace: (_a = meta.namespace) != null ? _a : null
497915
+ };
497916
+ });
497917
+ }
497845
497918
 
497846
497919
  // src/actions/upload-bundle.ts
497847
497920
  var import_pako = __toESM(require_pako());
@@ -498174,6 +498247,7 @@ async function exportProjectsCli(opts) {
498174
498247
  })
498175
498248
  },
498176
498249
  projects: result.map((bundle) => {
498250
+ var _a2;
498177
498251
  const projectName = (0, import_lodash20.snakeCase)(bundle.projectConfig.projectName);
498178
498252
  return {
498179
498253
  projectId: bundle.projectConfig.projectId,
@@ -498202,6 +498276,18 @@ async function exportProjectsCli(opts) {
498202
498276
  componentImportPath: comp.importPath,
498203
498277
  helper: comp.helper
498204
498278
  })),
498279
+ customFunctionMetas: ((_a2 = bundle.customFunctionMetas) != null ? _a2 : []).map(
498280
+ (meta) => {
498281
+ var _a3;
498282
+ return {
498283
+ id: meta.id,
498284
+ name: meta.name,
498285
+ importPath: meta.importPath,
498286
+ defaultExport: meta.defaultExport,
498287
+ namespace: (_a3 = meta.namespace) != null ? _a3 : null
498288
+ };
498289
+ }
498290
+ ),
498205
498291
  icons: bundle.iconAssets.map((icon) => ({
498206
498292
  id: icon.id,
498207
498293
  name: icon.name,
@@ -142,6 +142,35 @@
142
142
  ],
143
143
  "type": "object"
144
144
  },
145
+ "CustomFunctionConfig": {
146
+ "properties": {
147
+ "defaultExport": {
148
+ "type": "boolean"
149
+ },
150
+ "id": {
151
+ "type": "string"
152
+ },
153
+ "importPath": {
154
+ "type": "string"
155
+ },
156
+ "name": {
157
+ "type": "string"
158
+ },
159
+ "namespace": {
160
+ "type": [
161
+ "null",
162
+ "string"
163
+ ]
164
+ }
165
+ },
166
+ "required": [
167
+ "defaultExport",
168
+ "id",
169
+ "importPath",
170
+ "name"
171
+ ],
172
+ "type": "object"
173
+ },
145
174
  "GlobalVariantGroupConfig": {
146
175
  "properties": {
147
176
  "contextFilePath": {
@@ -325,6 +354,12 @@
325
354
  "description": "File location for the project-wide css styles. Relative to srcDir",
326
355
  "type": "string"
327
356
  },
357
+ "customFunctions": {
358
+ "items": {
359
+ "$ref": "#/definitions/CustomFunctionConfig"
360
+ },
361
+ "type": "array"
362
+ },
328
363
  "globalContextsFilePath": {
329
364
  "description": "File location for the project-wide global contexts. Relative to srcDir",
330
365
  "type": "string"
@@ -1,7 +1,6 @@
1
1
  import { ImportDeclaration } from "@babel/types";
2
- import L from "lodash";
3
2
  import { Options } from "prettier";
4
- import { CodeComponentConfig, ComponentConfig, GlobalVariantGroupConfig, IconConfig, ImageConfig, PlasmicConfig, PlasmicContext, ProjectConfig } from "./config-utils";
3
+ import { CodeComponentConfig, ComponentConfig, CustomFunctionConfig, GlobalVariantGroupConfig, IconConfig, ImageConfig, PlasmicConfig, PlasmicContext, ProjectConfig } from "./config-utils";
5
4
  export declare const formatAsLocal: (content: string, filePath: string, baseDir: string, defaultOpts?: Options) => string;
6
5
  export declare function ensureImportSpecifierWithAlias(decl: ImportDeclaration, imported: string, alias: string): void;
7
6
  export declare function ensureImportDefaultSpecifier(decl: ImportDeclaration, defaultExport: string): void;
@@ -22,20 +21,13 @@ export interface FixImportContext {
22
21
  config: PlasmicConfig;
23
22
  components: Record<string, ComponentConfig>;
24
23
  codeComponentMetas: Record<string, CodeComponentConfig>;
24
+ customFunctionMetas: Record<string, CustomFunctionConfig>;
25
25
  globalVariants: Record<string, GlobalVariantGroupConfig>;
26
26
  icons: Record<string, IconConfig>;
27
27
  images: Record<string, ImageConfig>;
28
28
  projects: Record<string, ProjectConfig>;
29
29
  }
30
- export declare const mkFixImportContext: (config: PlasmicConfig) => {
31
- config: PlasmicConfig;
32
- components: L.Dictionary<ComponentConfig>;
33
- codeComponentMetas: L.Dictionary<CodeComponentConfig>;
34
- globalVariants: L.Dictionary<GlobalVariantGroupConfig>;
35
- icons: L.Dictionary<IconConfig>;
36
- images: L.Dictionary<ImageConfig>;
37
- projects: L.Dictionary<ProjectConfig>;
38
- };
30
+ export declare const mkFixImportContext: (config: PlasmicConfig) => FixImportContext;
39
31
  /**
40
32
  * Assuming that all the files referenced in PlasmicConfig are correct, fixes import statements using PlasmicConfig
41
33
  * file locations as the source of truth.
@@ -108,6 +108,13 @@ export interface CodeComponentConfig {
108
108
  importPath: string;
109
109
  };
110
110
  }
111
+ export interface CustomFunctionConfig {
112
+ id: string;
113
+ name: string;
114
+ namespace?: string | null;
115
+ importPath: string;
116
+ defaultExport: boolean;
117
+ }
111
118
  export interface ProjectConfig {
112
119
  /** Project ID */
113
120
  projectId: string;
@@ -130,6 +137,7 @@ export interface ProjectConfig {
130
137
  globalContextsFilePath: string;
131
138
  jsBundleThemes?: JsBundleThemeConfig[];
132
139
  codeComponents?: CodeComponentConfig[];
140
+ customFunctions?: CustomFunctionConfig[];
133
141
  /** Metadata for each synced component in this project. */
134
142
  components: ComponentConfig[];
135
143
  /** Metadata for each synced icon in this project */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasmicapp/cli",
3
- "version": "0.1.313",
3
+ "version": "0.1.314",
4
4
  "description": "plasmic cli for syncing local code with Plasmic designs",
5
5
  "engines": {
6
6
  "node": ">=12"
@@ -78,5 +78,5 @@
78
78
  "wrap-ansi": "^7.0.0",
79
79
  "yargs": "^15.4.1"
80
80
  },
81
- "gitHead": "388b5829f67de3782fe8afdad0d153b5c6d0aac0"
81
+ "gitHead": "6e966ef24adb9af472b56a5051faf2b8e6e04f12"
82
82
  }
@@ -341,6 +341,7 @@ class PlasmicApi {
341
341
  const result = {
342
342
  components,
343
343
  codeComponentMetas: [],
344
+ customFunctionMetas: [],
344
345
  projectConfig: genProjectMetaBundle(projectId),
345
346
  globalVariants: [],
346
347
  usedTokens: genEmptyStyleTokensMap(),
@@ -10,11 +10,11 @@ import {
10
10
  } from "../utils/code-utils";
11
11
  import {
12
12
  CodeConfig,
13
+ findConfigFile,
13
14
  I18NConfig,
14
15
  ImagesConfig,
15
16
  PlasmicConfig,
16
17
  StyleConfig,
17
- findConfigFile,
18
18
  } from "../utils/config-utils";
19
19
  import { getContext, getCurrentOrDefaultAuth } from "../utils/get-context";
20
20
  import { tuple } from "../utils/lang-utils";
@@ -200,6 +200,15 @@ export async function exportProjectsCli(opts: ExportArgs): Promise<void> {
200
200
  componentImportPath: comp.importPath,
201
201
  helper: comp.helper,
202
202
  })),
203
+ customFunctionMetas: (bundle.customFunctionMetas ?? []).map(
204
+ (meta) => ({
205
+ id: meta.id,
206
+ name: meta.name,
207
+ importPath: meta.importPath,
208
+ defaultExport: meta.defaultExport,
209
+ namespace: meta.namespace ?? null,
210
+ })
211
+ ),
203
212
  icons: bundle.iconAssets.map((icon) => ({
204
213
  id: icon.id,
205
214
  name: icon.name,
@@ -22,25 +22,23 @@ import {
22
22
  } from "../utils/code-utils";
23
23
  import {
24
24
  CONFIG_FILE_NAME,
25
- PlasmicContext,
26
25
  createProjectConfig,
26
+ CustomFunctionConfig,
27
27
  getOrAddProjectConfig,
28
28
  getOrAddProjectLock,
29
+ PlasmicContext,
29
30
  updateConfig,
30
31
  } from "../utils/config-utils";
31
32
  import { HandledError } from "../utils/error";
32
33
  import {
33
34
  assertAllPathsInRootDir,
34
35
  defaultResourcePath,
35
- existsBuffered,
36
- readFileText,
37
36
  renameFile,
38
37
  stripExtension,
39
38
  withBufferedFs,
40
39
  writeFileContent,
41
- writeFileText,
42
40
  } from "../utils/file-utils";
43
- import { Metadata, generateMetadata, getContext } from "../utils/get-context";
41
+ import { generateMetadata, getContext, Metadata } from "../utils/get-context";
44
42
  import { printFirstSyncInfo } from "../utils/help";
45
43
  import { ensure, tuple } from "../utils/lang-utils";
46
44
  import {
@@ -604,6 +602,11 @@ async function syncProject(
604
602
  indirect
605
603
  );
606
604
  syncCodeComponentsMeta(context, projectId, projectBundle.codeComponentMetas);
605
+ await syncCustomFunctionsMeta(
606
+ context,
607
+ projectId,
608
+ projectBundle.customFunctionMetas
609
+ );
607
610
  await upsertStyleTokens(
608
611
  context,
609
612
  projectBundle.usedTokens,
@@ -807,3 +810,18 @@ function syncCodeComponentsMeta(
807
810
  : {}),
808
811
  }));
809
812
  }
813
+
814
+ function syncCustomFunctionsMeta(
815
+ context: PlasmicContext,
816
+ projectId: string,
817
+ customFunctionBundles: CustomFunctionConfig[]
818
+ ) {
819
+ const projectConfig = getOrAddProjectConfig(context, projectId);
820
+ projectConfig.customFunctions = customFunctionBundles.map((meta) => ({
821
+ defaultExport: meta.defaultExport,
822
+ id: meta.id,
823
+ importPath: meta.importPath,
824
+ name: meta.name,
825
+ namespace: meta.namespace ?? null,
826
+ }));
827
+ }
package/src/api.ts CHANGED
@@ -3,6 +3,7 @@ import socketio, { Socket } from "socket.io-client";
3
3
  import {
4
4
  AuthConfig,
5
5
  CodeConfig,
6
+ CustomFunctionConfig,
6
7
  DEFAULT_HOST,
7
8
  I18NConfig,
8
9
  ImagesConfig,
@@ -112,6 +113,7 @@ export interface ProjectMetaInfo {
112
113
  export interface ProjectBundle {
113
114
  components: ComponentBundle[];
114
115
  codeComponentMetas: CodeComponentMeta[];
116
+ customFunctionMetas: CustomFunctionConfig[];
115
117
  projectConfig: ProjectMetaBundle;
116
118
  globalVariants: GlobalVariantBundle[];
117
119
  usedTokens: StyleTokensMap;
@@ -5,7 +5,7 @@ import traverse, { Node } from "@babel/traverse";
5
5
  import { ImportDeclaration } from "@babel/types";
6
6
  import L from "lodash";
7
7
  import * as Prettier from "prettier";
8
- import { Options, resolveConfig } from "prettier";
8
+ import { Options } from "prettier";
9
9
  import * as ts from "typescript";
10
10
  import path from "upath";
11
11
  import { getGlobalContextsResourcePath } from "../actions/sync-global-contexts";
@@ -14,11 +14,13 @@ import {
14
14
  fixComponentImagesReferences,
15
15
  } from "../actions/sync-images";
16
16
  import { logger } from "../deps";
17
+ import { GLOBAL_SETTINGS } from "../globals";
17
18
  import { HandledError } from "../utils/error";
18
19
  import {
19
20
  CodeComponentConfig,
20
21
  ComponentConfig,
21
22
  CONFIG_FILE_NAME,
23
+ CustomFunctionConfig,
22
24
  GlobalVariantGroupConfig,
23
25
  IconConfig,
24
26
  ImageConfig,
@@ -34,7 +36,6 @@ import {
34
36
  writeFileContent,
35
37
  } from "./file-utils";
36
38
  import { assert, flatMap } from "./lang-utils";
37
- import { GLOBAL_SETTINGS } from "../globals";
38
39
 
39
40
  export const formatAsLocal = (
40
41
  content: string,
@@ -169,15 +170,38 @@ type PlasmicImportType =
169
170
  | "codeComponent"
170
171
  | "codeComponentHelper"
171
172
  | "globalContext"
173
+ | "customFunction"
172
174
  | undefined;
173
175
 
176
+ const validJsIdentifierChars = [
177
+ "\\u0621-\\u064A", // arabic
178
+ "\\u3400-\\u4DB5", // chinese
179
+ "\\u4E00-\\u9FCC", // chinese
180
+ "\\u0400-\\u04FF", // cyrillic
181
+ "\\u0370-\\u03ff", // greek
182
+ "\\u1f00-\\u1fff", // greek
183
+ "\\u0900-\\u097F", // hindi
184
+ "\\u3041-\\u3094", // japanese
185
+ "\\u30A1-\\u30FB", // japanese
186
+ "\\u0E00-\\u0E7F", // thai
187
+ "\\w",
188
+ "-_",
189
+ ];
190
+
174
191
  function tryParsePlasmicImportSpec(node: ImportDeclaration) {
175
192
  const c = node.trailingComments?.[0];
176
193
  if (!c) {
177
194
  return undefined;
178
195
  }
179
196
  const m = c.value.match(
180
- /plasmic-import:\s+([\w-]+)(?:\/(component|css|render|globalVariant|projectcss|defaultcss|icon|picture|jsBundle|codeComponent|globalContext))?/
197
+ new RegExp(
198
+ [
199
+ "plasmic-import:\\s+([",
200
+ ...validJsIdentifierChars,
201
+ "\\.",
202
+ "]+)(?:\\/(component|css|render|globalVariant|projectcss|defaultcss|icon|picture|jsBundle|codeComponent|globalContext|customFunction))?",
203
+ ].join("")
204
+ )
181
205
  );
182
206
  if (m) {
183
207
  return { id: m[1], type: m[2] as PlasmicImportType } as PlasmicImportSpec;
@@ -384,6 +408,23 @@ export function replaceImports(
384
408
  true
385
409
  );
386
410
  stmt.source.value = realPath;
411
+ } else if (type === "customFunction") {
412
+ const meta = fixImportContext.customFunctionMetas[uuid];
413
+ if (!meta?.importPath) {
414
+ throw new HandledError(
415
+ `Encountered custom function "${uuid}" that was not registered with an importPath, so we don't know where to import this function from. Please see https://docs.plasmic.app/learn/code-components-ref/`
416
+ );
417
+ }
418
+ if (meta.importPath[0] === ".") {
419
+ // Relative path from the project root
420
+ const toPath = path.join(context.rootDir, meta.importPath);
421
+ assert(path.isAbsolute(toPath));
422
+ const realPath = makeImportPath(context, fromPath, toPath, true, true);
423
+ stmt.source.value = realPath;
424
+ } else {
425
+ // npm package
426
+ stmt.source.value = meta.importPath;
427
+ }
387
428
  }
388
429
  });
389
430
 
@@ -454,20 +495,26 @@ export interface FixImportContext {
454
495
  config: PlasmicConfig;
455
496
  components: Record<string, ComponentConfig>;
456
497
  codeComponentMetas: Record<string, CodeComponentConfig>;
498
+ customFunctionMetas: Record<string, CustomFunctionConfig>;
457
499
  globalVariants: Record<string, GlobalVariantGroupConfig>;
458
500
  icons: Record<string, IconConfig>;
459
501
  images: Record<string, ImageConfig>;
460
502
  projects: Record<string, ProjectConfig>;
461
503
  }
462
504
 
463
- export const mkFixImportContext = (config: PlasmicConfig) => {
505
+ export const mkFixImportContext = (config: PlasmicConfig): FixImportContext => {
464
506
  const allComponents = flatMap(config.projects, (p) => p.components);
465
507
  const components = L.keyBy(allComponents, (c) => c.id);
466
508
  const allCodeComponents = flatMap(
467
509
  config.projects,
468
510
  (p) => p.codeComponents || []
469
511
  );
512
+ const allCustomFunctions = flatMap(
513
+ config.projects,
514
+ (p) => p.customFunctions ?? []
515
+ );
470
516
  const codeComponentMetas = L.keyBy(allCodeComponents, (c) => c.id);
517
+ const customFunctionMetas = L.keyBy(allCustomFunctions, (fn) => fn.id);
471
518
  const globalVariants = L.keyBy(
472
519
  config.globalVariants.variantGroups,
473
520
  (c) => c.id
@@ -485,6 +532,7 @@ export const mkFixImportContext = (config: PlasmicConfig) => {
485
532
  config,
486
533
  components,
487
534
  codeComponentMetas,
535
+ customFunctionMetas,
488
536
  globalVariants,
489
537
  icons,
490
538
  images,
@@ -1,6 +1,6 @@
1
1
  import L from "lodash";
2
2
  import { DeepPartial } from "utility-types";
3
- import { PlasmicApi, ProjectIdAndToken } from "../api";
3
+ import { PlasmicApi } from "../api";
4
4
  import { logger } from "../deps";
5
5
  import { HandledError } from "../utils/error";
6
6
  import { formatAsLocal } from "./code-utils";
@@ -152,6 +152,14 @@ export interface CodeComponentConfig {
152
152
  };
153
153
  }
154
154
 
155
+ export interface CustomFunctionConfig {
156
+ id: string;
157
+ name: string;
158
+ namespace?: string | null;
159
+ importPath: string;
160
+ defaultExport: boolean;
161
+ }
162
+
155
163
  export interface ProjectConfig {
156
164
  /** Project ID */
157
165
  projectId: string;
@@ -177,6 +185,7 @@ export interface ProjectConfig {
177
185
  // to the users nor appear to be missing in the documentation.
178
186
  jsBundleThemes?: JsBundleThemeConfig[];
179
187
  codeComponents?: CodeComponentConfig[];
188
+ customFunctions?: CustomFunctionConfig[];
180
189
 
181
190
  /** Metadata for each synced component in this project. */
182
191
  components: ComponentConfig[];