@superblocksteam/util 0.0.15 → 0.0.16

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.
@@ -1,4 +1,4 @@
1
- export declare function getComponentConfigs(): Promise<{
1
+ export declare function getComponentConfigs(generateTypesFiles: boolean): Promise<{
2
2
  configs: Record<string, any>;
3
3
  hasError: boolean;
4
4
  }>;
@@ -7,6 +7,7 @@ const node_os_1 = tslib_1.__importDefault(require("node:os"));
7
7
  const node_path_1 = tslib_1.__importDefault(require("node:path"));
8
8
  const fs = tslib_1.__importStar(require("fs-extra"));
9
9
  const constants_1 = require("./constants");
10
+ const generate_component_types_1 = require("./generate-component-types");
10
11
  const validation_1 = require("./validation");
11
12
  const compileTypeScript = (inputFilePath, outputDir) => {
12
13
  return new Promise((resolve, reject) => {
@@ -66,14 +67,14 @@ async function getFolderPaths() {
66
67
  throw new Error("Could not access component directory, check your permissions");
67
68
  }
68
69
  }
69
- async function getComponentConfigs() {
70
+ async function getComponentConfigs(generateTypesFiles) {
70
71
  const folderPaths = await getFolderPaths();
71
72
  let hasError = false;
72
73
  const promiseConfigFiles = folderPaths.map(async (ccpath) => {
73
74
  try {
74
- const ret = await fs.readJSON(`${ccpath}/config.json`);
75
+ const config = await fs.readJSON(`${ccpath}/config.json`);
75
76
  console.log(`Found component in ${ccpath}`);
76
- return ret;
77
+ return { ccpath, config };
77
78
  }
78
79
  catch (e) {
79
80
  // Noop because there is a fallback
@@ -91,15 +92,15 @@ async function getComponentConfigs() {
91
92
  .slice(2)}`);
92
93
  await compileTypeScript(fileName, outputDirectory);
93
94
  console.log(`Typescript compiled to ${ccpath}`);
94
- const ret = (await Promise.resolve(`${outputDirectory + "/config.js"}`).then(s => tslib_1.__importStar(require(s)))).default;
95
- const isValid = (0, validation_1.validateCustomComponents)(ret);
95
+ const config = (await Promise.resolve(`${outputDirectory + "/config.js"}`).then(s => tslib_1.__importStar(require(s)))).default;
96
+ const isValid = (0, validation_1.validateCustomComponents)(config);
96
97
  if (!isValid.valid) {
97
98
  // Not throwing because we don't need a stack trace here
98
99
  console.log(`Invalid config.ts file found`);
99
100
  console.log(isValid.message);
100
101
  hasError = true;
101
102
  }
102
- return ret;
103
+ return { ccpath, config };
103
104
  }
104
105
  catch (e) {
105
106
  console.error(e);
@@ -107,14 +108,22 @@ async function getComponentConfigs() {
107
108
  throw e;
108
109
  }
109
110
  });
110
- const configFiles = (await Promise.all(promiseConfigFiles))
111
- .filter((file) => file !== null)
112
- .reduce((acc, config) => {
111
+ const configFiles = await Promise.all(promiseConfigFiles);
112
+ if (generateTypesFiles) {
113
+ for (const { config, ccpath } of configFiles) {
114
+ const typesFileContents = (0, generate_component_types_1.generateComponentTypesFile)(config);
115
+ await fs.writeFile(`${ccpath}/types.ts`, typesFileContents);
116
+ console.log(`Generated ${ccpath}/types.ts`);
117
+ }
118
+ }
119
+ const configs = configFiles
120
+ .filter((component) => component.config !== null)
121
+ .reduce((acc, { config }) => {
113
122
  acc[config.id] = config;
114
123
  return acc;
115
124
  }, {});
116
125
  return {
117
- configs: configFiles,
126
+ configs,
118
127
  hasError,
119
128
  };
120
129
  }
@@ -0,0 +1 @@
1
+ export declare function generateComponentTypesFile(config: any): string;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateComponentTypesFile = void 0;
4
+ const input_types_1 = require("./input-types");
5
+ const indent = (str, spaces) => {
6
+ const spacesString = " ".repeat(spaces);
7
+ return str
8
+ .split("\n")
9
+ .map((line) => `${spacesString}${line}`)
10
+ .join("\n");
11
+ };
12
+ function renderInputTypeAsTS(name, type, trailingChars, indentSpaces) {
13
+ return indent(`${name}: ${input_types_1.inputTypeDefinions[type].tsType}${trailingChars}`, indentSpaces);
14
+ }
15
+ function generateComponentTypesFile(config) {
16
+ var _a, _b;
17
+ const statefulProperties = (_a = config.statefulProperties) !== null && _a !== void 0 ? _a : [];
18
+ const eventHandlers = (_b = config.eventHandlers) !== null && _b !== void 0 ? _b : [];
19
+ return `// WARNING: This file is automatically generated and managed by Superblocks CLI and should not be edited manually.
20
+ // Use the \`superblocks components watch\` command to regenerate this file from its source in config.ts
21
+
22
+ // All stateful properties of your component are defined here.
23
+ // These are the properties which are surfaced in the Superblocks properties panel
24
+ // and can be referenced throughout your Superblocks Application
25
+ export interface StatefulProperties {
26
+ ${statefulProperties
27
+ .map((v) => renderInputTypeAsTS(v.path, v.inputType, ";", 2) + "\n")
28
+ .join("")}}
29
+
30
+ export interface Props extends StatefulProperties {
31
+ /**
32
+ * Update one (or more) of your component's stateful properties. This will cause the component to rerender,
33
+ * and will also notify any other components in your Application which depend on the updated properties, so they also rerender
34
+ * @param props An object with the properties to update along with their new values
35
+ */
36
+ updateStatefulProperties: (props: Partial<StatefulProperties>) => void;
37
+
38
+ // Call the subsequent function(s) to trigger event(s) in Superblocks from your component.
39
+ // These events can be wired up to event handlers in your Superblocks App
40
+ ${eventHandlers.length === 0
41
+ ? " // Note: no event handlers defined\n"
42
+ : eventHandlers
43
+ .map((v) => indent(v.path, 2) + ": () => void;" + "\n")
44
+ .join("")}}
45
+ `;
46
+ }
47
+ exports.generateComponentTypesFile = generateComponentTypesFile;
package/dist/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export * from "./constants";
2
2
  export * from "./component-configs";
3
3
  export * from "./login";
4
4
  export * from "./resource-configs";
5
+ export * from "./input-types";
package/dist/index.js CHANGED
@@ -5,3 +5,4 @@ tslib_1.__exportStar(require("./constants"), exports);
5
5
  tslib_1.__exportStar(require("./component-configs"), exports);
6
6
  tslib_1.__exportStar(require("./login"), exports);
7
7
  tslib_1.__exportStar(require("./resource-configs"), exports);
8
+ tslib_1.__exportStar(require("./input-types"), exports);
@@ -0,0 +1,9 @@
1
+ export declare const supportedInputTypes: readonly ["text", "number", "boolean", "js"];
2
+ export type InputType = (typeof supportedInputTypes)[number];
3
+ interface TypeInfo {
4
+ tsType: string;
5
+ prompt: string;
6
+ }
7
+ export declare const inputTypeDefinions: Record<InputType, TypeInfo>;
8
+ export declare function isValidInputType(input: string): input is InputType;
9
+ export {};
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isValidInputType = exports.inputTypeDefinions = exports.supportedInputTypes = void 0;
4
+ exports.supportedInputTypes = ["text", "number", "boolean", "js"];
5
+ exports.inputTypeDefinions = {
6
+ text: {
7
+ tsType: "string",
8
+ prompt: "text",
9
+ },
10
+ number: {
11
+ tsType: "number",
12
+ prompt: "number",
13
+ },
14
+ boolean: {
15
+ tsType: "boolean",
16
+ prompt: "boolean",
17
+ },
18
+ js: {
19
+ tsType: "any",
20
+ prompt: "any (raw js expression)",
21
+ },
22
+ };
23
+ function isValidInputType(input) {
24
+ return Object.prototype.hasOwnProperty.call(exports.inputTypeDefinions, input);
25
+ }
26
+ exports.isValidInputType = isValidInputType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superblocksteam/util",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "main": "dist/index.js",
5
5
  "homepage": "https://www.superblocks.com",
6
6
  "scripts": {
@@ -3,6 +3,7 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import * as fs from "fs-extra";
5
5
  import { CUSTOM_COMPONENTS_PATH } from "./constants";
6
+ import { generateComponentTypesFile } from "./generate-component-types";
6
7
  import { validateCustomComponents } from "./validation";
7
8
 
8
9
  const compileTypeScript = (inputFilePath: string, outputDir: string) => {
@@ -75,7 +76,9 @@ async function getFolderPaths() {
75
76
  }
76
77
  }
77
78
 
78
- export async function getComponentConfigs(): Promise<{
79
+ export async function getComponentConfigs(
80
+ generateTypesFiles: boolean
81
+ ): Promise<{
79
82
  configs: Record<string, any>;
80
83
  hasError: boolean;
81
84
  }> {
@@ -83,9 +86,9 @@ export async function getComponentConfigs(): Promise<{
83
86
  let hasError = false;
84
87
  const promiseConfigFiles = folderPaths.map(async (ccpath) => {
85
88
  try {
86
- const ret = await fs.readJSON(`${ccpath}/config.json`);
89
+ const config = await fs.readJSON(`${ccpath}/config.json`);
87
90
  console.log(`Found component in ${ccpath}`);
88
- return ret;
91
+ return { ccpath, config };
89
92
  } catch (e: any) {
90
93
  // Noop because there is a fallback
91
94
  }
@@ -105,30 +108,38 @@ export async function getComponentConfigs(): Promise<{
105
108
  );
106
109
  await compileTypeScript(fileName, outputDirectory);
107
110
  console.log(`Typescript compiled to ${ccpath}`);
108
- const ret = (await import(outputDirectory + "/config.js")).default;
111
+ const config = (await import(outputDirectory + "/config.js")).default;
109
112
 
110
- const isValid = validateCustomComponents(ret);
113
+ const isValid = validateCustomComponents(config);
111
114
  if (!isValid.valid) {
112
115
  // Not throwing because we don't need a stack trace here
113
116
  console.log(`Invalid config.ts file found`);
114
117
  console.log(isValid.message);
115
118
  hasError = true;
116
119
  }
117
- return ret;
120
+ return { ccpath, config };
118
121
  } catch (e: any) {
119
122
  console.error(e);
120
123
  console.error(e.message);
121
124
  throw e;
122
125
  }
123
126
  });
124
- const configFiles = (await Promise.all(promiseConfigFiles))
125
- .filter((file) => file !== null)
126
- .reduce((acc, config) => {
127
+ const configFiles = await Promise.all(promiseConfigFiles);
128
+ if (generateTypesFiles) {
129
+ for (const { config, ccpath } of configFiles) {
130
+ const typesFileContents = generateComponentTypesFile(config);
131
+ await fs.writeFile(`${ccpath}/types.ts`, typesFileContents);
132
+ console.log(`Generated ${ccpath}/types.ts`);
133
+ }
134
+ }
135
+ const configs = configFiles
136
+ .filter((component) => component.config !== null)
137
+ .reduce((acc: Record<string, any>, { config }) => {
127
138
  acc[config.id] = config;
128
139
  return acc;
129
140
  }, {});
130
141
  return {
131
- configs: configFiles,
142
+ configs,
132
143
  hasError,
133
144
  };
134
145
  }
@@ -0,0 +1,56 @@
1
+ import { inputTypeDefinions, type InputType } from "./input-types";
2
+
3
+ const indent = (str: string, spaces: number) => {
4
+ const spacesString = " ".repeat(spaces);
5
+
6
+ return str
7
+ .split("\n")
8
+ .map((line) => `${spacesString}${line}`)
9
+ .join("\n");
10
+ };
11
+
12
+ function renderInputTypeAsTS(
13
+ name: string,
14
+ type: InputType,
15
+ trailingChars: string,
16
+ indentSpaces: number
17
+ ) {
18
+ return indent(
19
+ `${name}: ${inputTypeDefinions[type].tsType}${trailingChars}`,
20
+ indentSpaces
21
+ );
22
+ }
23
+
24
+ export function generateComponentTypesFile(config: any) {
25
+ const statefulProperties = config.statefulProperties ?? [];
26
+ const eventHandlers = config.eventHandlers ?? [];
27
+ return `// WARNING: This file is automatically generated and managed by Superblocks CLI and should not be edited manually.
28
+ // Use the \`superblocks components watch\` command to regenerate this file from its source in config.ts
29
+
30
+ // All stateful properties of your component are defined here.
31
+ // These are the properties which are surfaced in the Superblocks properties panel
32
+ // and can be referenced throughout your Superblocks Application
33
+ export interface StatefulProperties {
34
+ ${statefulProperties
35
+ .map((v: any) => renderInputTypeAsTS(v.path, v.inputType, ";", 2) + "\n")
36
+ .join("")}}
37
+
38
+ export interface Props extends StatefulProperties {
39
+ /**
40
+ * Update one (or more) of your component's stateful properties. This will cause the component to rerender,
41
+ * and will also notify any other components in your Application which depend on the updated properties, so they also rerender
42
+ * @param props An object with the properties to update along with their new values
43
+ */
44
+ updateStatefulProperties: (props: Partial<StatefulProperties>) => void;
45
+
46
+ // Call the subsequent function(s) to trigger event(s) in Superblocks from your component.
47
+ // These events can be wired up to event handlers in your Superblocks App
48
+ ${
49
+ eventHandlers.length === 0
50
+ ? " // Note: no event handlers defined\n"
51
+ : eventHandlers
52
+ .map((v: any) => indent(v.path, 2) + ": () => void;" + "\n")
53
+ .join("")
54
+ }}
55
+ `;
56
+ }
package/src/index.ts CHANGED
@@ -2,3 +2,4 @@ export * from "./constants";
2
2
  export * from "./component-configs";
3
3
  export * from "./login";
4
4
  export * from "./resource-configs";
5
+ export * from "./input-types";
@@ -0,0 +1,34 @@
1
+ export const supportedInputTypes = ["text", "number", "boolean", "js"] as const;
2
+
3
+ export type InputType = (typeof supportedInputTypes)[number];
4
+
5
+ interface TypeInfo {
6
+ tsType: string;
7
+ prompt: string;
8
+ }
9
+
10
+ export const inputTypeDefinions: Record<InputType, TypeInfo> = {
11
+ text: {
12
+ tsType: "string",
13
+ prompt: "text",
14
+ },
15
+ number: {
16
+ tsType: "number",
17
+ prompt: "number",
18
+ },
19
+ boolean: {
20
+ tsType: "boolean",
21
+ prompt: "boolean",
22
+ },
23
+ js: {
24
+ tsType: "any",
25
+ prompt: "any (raw js expression)",
26
+ },
27
+ };
28
+
29
+ export function isValidInputType(input: string): input is InputType {
30
+ return Object.prototype.hasOwnProperty.call(
31
+ inputTypeDefinions,
32
+ input as InputType
33
+ );
34
+ }