@superblocksteam/util 0.0.22 → 0.0.23
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/component-configs.js +7 -4
- package/dist/generate-component-types.js +12 -6
- package/dist/resource-configs.js +15 -9
- package/dist/types.d.ts +35 -7
- package/dist/validation.js +23 -1
- package/package.json +3 -2
- package/src/component-configs.ts +8 -5
- package/src/generate-component-types.ts +12 -9
- package/src/resource-configs.ts +18 -9
- package/src/types.ts +57 -7
- package/src/validation.ts +23 -1
|
@@ -15,7 +15,8 @@ const compileTypeScript = (inputFilePath, outputDir) => {
|
|
|
15
15
|
try {
|
|
16
16
|
const tscPath = require.resolve("typescript/bin/tsc");
|
|
17
17
|
if (tscPath) {
|
|
18
|
-
(0, child_process_1.execFile)(
|
|
18
|
+
(0, child_process_1.execFile)("node", [
|
|
19
|
+
tscPath,
|
|
19
20
|
node_path_1.default.resolve(inputFilePath),
|
|
20
21
|
"--outDir",
|
|
21
22
|
outputDir,
|
|
@@ -61,7 +62,7 @@ async function getFolderPaths() {
|
|
|
61
62
|
// filter out any non-directory items
|
|
62
63
|
const directories = folderPaths.filter((dirent) => dirent.isDirectory());
|
|
63
64
|
// map each directory to its path
|
|
64
|
-
const folderPathsArray = directories.map((dirent) =>
|
|
65
|
+
const folderPathsArray = directories.map((dirent) => `${constants_1.CUSTOM_COMPONENTS_PATH}/${dirent.name}`);
|
|
65
66
|
return folderPathsArray;
|
|
66
67
|
}
|
|
67
68
|
catch {
|
|
@@ -72,9 +73,10 @@ async function getComponentConfigs(generateTypesFiles) {
|
|
|
72
73
|
const folderPaths = await getFolderPaths();
|
|
73
74
|
let hasError = false;
|
|
74
75
|
const promiseConfigFiles = folderPaths.map(async (ccpath) => {
|
|
76
|
+
const absPath = node_path_1.default.resolve(ccpath);
|
|
75
77
|
try {
|
|
76
|
-
const config = await fs.readJSON(`${
|
|
77
|
-
console.log(`Found component in ${
|
|
78
|
+
const config = await fs.readJSON(`${absPath}/config.json`);
|
|
79
|
+
console.log(`Found component in ${absPath}`);
|
|
78
80
|
return { ccpath, config };
|
|
79
81
|
}
|
|
80
82
|
catch (e) {
|
|
@@ -91,6 +93,7 @@ async function getComponentConfigs(generateTypesFiles) {
|
|
|
91
93
|
const outputDirectory = node_path_1.default.resolve(`${node_os_1.default.tmpdir()}/superblocks/${ccpath}/config.timestamp-${Date.now()}-${Math.random()
|
|
92
94
|
.toString(16)
|
|
93
95
|
.slice(2)}`);
|
|
96
|
+
await fs.ensureDir(outputDirectory);
|
|
94
97
|
await compileTypeScript(fileName, outputDirectory);
|
|
95
98
|
console.log(`Typescript compiled to ${ccpath}`);
|
|
96
99
|
const config = (await Promise.resolve(`${outputDirectory + "/config.js"}`).then(s => tslib_1.__importStar(require(s)))).default;
|
|
@@ -10,31 +10,37 @@ const indent = (str, spaces) => {
|
|
|
10
10
|
.join("\n");
|
|
11
11
|
};
|
|
12
12
|
function renderInputTypeAsTS(name, type, trailingChars, indentSpaces) {
|
|
13
|
-
|
|
13
|
+
let { tsType } = data_types_1.dataTypeDefinions[type];
|
|
14
|
+
if (["number", "string"].includes(type)) {
|
|
15
|
+
tsType += "| null";
|
|
16
|
+
}
|
|
17
|
+
return indent(`${name}: ${tsType}${trailingChars}`, indentSpaces);
|
|
14
18
|
}
|
|
15
19
|
function generateComponentTypesFile(config) {
|
|
16
20
|
var _a, _b;
|
|
17
21
|
const properties = (_a = config.properties) !== null && _a !== void 0 ? _a : [];
|
|
18
22
|
const eventHandlers = (_b = config.events) !== null && _b !== void 0 ? _b : [];
|
|
19
|
-
return `//
|
|
23
|
+
return `// GENERATED CODE -- DO NOT EDIT!
|
|
24
|
+
//
|
|
25
|
+
// This file is automatically generated by the Superblocks CLI
|
|
20
26
|
// Use the \`superblocks components watch\` command to regenerate this file from its source in config.ts
|
|
21
27
|
|
|
22
28
|
// All properties of your component are defined here.
|
|
23
29
|
// These are the properties which are surfaced in the Superblocks properties panel
|
|
24
30
|
// and can be referenced throughout your Superblocks Application
|
|
25
|
-
export
|
|
31
|
+
export type Props = {
|
|
26
32
|
${properties
|
|
27
33
|
.map((v) => renderInputTypeAsTS(v.path, v.dataType, ";", 2) + "\n")
|
|
28
|
-
.join("")}}
|
|
34
|
+
.join("")}};
|
|
29
35
|
|
|
30
|
-
export
|
|
36
|
+
export type EventTriggers = {
|
|
31
37
|
// Call the subsequent function(s) to trigger event(s) in Superblocks from your component.
|
|
32
38
|
// These events can be wired up to event handlers in your Superblocks App
|
|
33
39
|
${eventHandlers.length === 0
|
|
34
40
|
? " // Note: no event handlers defined\n"
|
|
35
41
|
: eventHandlers
|
|
36
42
|
.map((v) => indent(v.path, 2) + ": () => void;" + "\n")
|
|
37
|
-
.join("")}}
|
|
43
|
+
.join("")}};
|
|
38
44
|
`;
|
|
39
45
|
}
|
|
40
46
|
exports.generateComponentTypesFile = generateComponentTypesFile;
|
package/dist/resource-configs.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getSuperblocksResourceConfigIfExists = exports.getSuperblocksBackendConfigJson = exports.getSuperblocksApplicationConfigJson = exports.getSuperblocksMonorepoConfigJson = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
5
6
|
const fs = tslib_1.__importStar(require("fs-extra"));
|
|
6
7
|
const constants_1 = require("./constants");
|
|
7
8
|
/**
|
|
@@ -9,27 +10,32 @@ const constants_1 = require("./constants");
|
|
|
9
10
|
* @param checkParentDir Whether to recursively check the parent directory for a Superblocks config file
|
|
10
11
|
*/
|
|
11
12
|
async function getSuperblocksMonorepoConfigJson(checkParentDir = false, pathPrefix = "") {
|
|
13
|
+
const absolutePath = path_1.default.resolve(pathPrefix);
|
|
14
|
+
let hasReachedFilesystemRoot = false;
|
|
15
|
+
try {
|
|
16
|
+
hasReachedFilesystemRoot = path_1.default.parse(absolutePath).root == absolutePath;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
throw new Error("Could not parse path " + absolutePath);
|
|
20
|
+
}
|
|
12
21
|
let superblocksConfig;
|
|
13
|
-
if (pathPrefix && !fs.existsSync(
|
|
22
|
+
if ((pathPrefix && !fs.existsSync(absolutePath)) ||
|
|
23
|
+
hasReachedFilesystemRoot) {
|
|
14
24
|
throw new Error("No Superblocks config file found in current directory hierarchy " +
|
|
15
25
|
pathPrefix);
|
|
16
26
|
}
|
|
27
|
+
const attemptedPath = path_1.default.join(absolutePath, constants_1.RESOURCE_CONFIG_PATH);
|
|
17
28
|
try {
|
|
18
|
-
superblocksConfig = await fs.readJSON(
|
|
29
|
+
superblocksConfig = await fs.readJSON(attemptedPath);
|
|
19
30
|
if (superblocksConfig.configType !== "ROOT") {
|
|
20
31
|
throw new Error("Not the root Superblocks config file");
|
|
21
32
|
}
|
|
22
|
-
return [
|
|
23
|
-
superblocksConfig,
|
|
24
|
-
pathPrefix + constants_1.RESOURCE_CONFIG_PATH,
|
|
25
|
-
];
|
|
33
|
+
return [superblocksConfig, attemptedPath];
|
|
26
34
|
}
|
|
27
35
|
catch {
|
|
28
36
|
if (!checkParentDir) {
|
|
29
37
|
// no superblocks config file found
|
|
30
|
-
throw new Error("No Superblocks config file found in current directory " +
|
|
31
|
-
pathPrefix +
|
|
32
|
-
constants_1.RESOURCE_CONFIG_PATH);
|
|
38
|
+
throw new Error("No Superblocks config file found in current directory " + attemptedPath);
|
|
33
39
|
}
|
|
34
40
|
return getSuperblocksMonorepoConfigJson(true, "../" + pathPrefix);
|
|
35
41
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { type UUID } from "node:crypto";
|
|
3
3
|
import { type DataType } from "./data-types";
|
|
4
|
-
interface PropertiesPanelDisplay {
|
|
4
|
+
interface PropertiesPanelDisplay<T extends DataType> {
|
|
5
5
|
/**
|
|
6
6
|
* Determines what form item type is shown in the Superblocks properties panel.
|
|
7
|
+
*
|
|
8
|
+
* Only booleans are allowed to use the "switch" control
|
|
7
9
|
*/
|
|
8
|
-
controlType
|
|
10
|
+
controlType?: T extends "boolean" ? "text" | "js-expr" | "switch" : "text" | "js-expr";
|
|
9
11
|
/**
|
|
10
12
|
* Determines form item label in the Superblocks properties panel.
|
|
11
13
|
*/
|
|
@@ -18,18 +20,39 @@ interface PropertiesPanelDisplay {
|
|
|
18
20
|
/**
|
|
19
21
|
* This shows up in the popover as a user types into the properties panel.
|
|
20
22
|
* This is a documentation field that helps users understand what type of data is accepted
|
|
21
|
-
* by this property.
|
|
23
|
+
* by this property. You should give a specific example, not a generic type
|
|
24
|
+
*
|
|
25
|
+
* @example {
|
|
26
|
+
* label: "My Label",
|
|
27
|
+
* value: "myValue"
|
|
28
|
+
* }
|
|
22
29
|
*/
|
|
23
30
|
exampleData?: string;
|
|
31
|
+
/**
|
|
32
|
+
* This shows up in the popover as a user types into the properties panel.
|
|
33
|
+
* This is a documentation field that helps users understand what type of data is accepted
|
|
34
|
+
* by this property. Typescript notation is recommended.
|
|
35
|
+
*
|
|
36
|
+
* @example "Array<{ label: string; value: string; }>"
|
|
37
|
+
*/
|
|
38
|
+
expectedType?: string;
|
|
39
|
+
/**
|
|
40
|
+
* The default value should match the dataType of the property.
|
|
41
|
+
*
|
|
42
|
+
* When dataType is "any", you must provide a string default value.
|
|
43
|
+
* Your string will be interpreted based on the controlType, so if you have controlType "js-expr",
|
|
44
|
+
* you should provide a string that is a valid javascript expression including quotations marks.
|
|
45
|
+
*/
|
|
46
|
+
defaultValue?: T extends "number" ? number : T extends "boolean" ? boolean : string;
|
|
24
47
|
}
|
|
25
|
-
export interface
|
|
48
|
+
export interface PropertyForData<T extends DataType> {
|
|
26
49
|
path: string;
|
|
27
|
-
dataType:
|
|
50
|
+
dataType: T;
|
|
28
51
|
/**
|
|
29
52
|
* The presence of this object determines whether or not this property
|
|
30
53
|
* shows up in the Superblocks properties panel.
|
|
31
54
|
**/
|
|
32
|
-
propertiesPanelDisplay?: PropertiesPanelDisplay
|
|
55
|
+
propertiesPanelDisplay?: PropertiesPanelDisplay<T>;
|
|
33
56
|
/**
|
|
34
57
|
* A description of this property. This is used in the Superblocks properties panel
|
|
35
58
|
* as well as in the custom component's autocomplete.
|
|
@@ -48,6 +71,7 @@ export interface Property {
|
|
|
48
71
|
**/
|
|
49
72
|
isExternallySettable?: boolean;
|
|
50
73
|
}
|
|
74
|
+
export type Property = PropertyForData<"string"> | PropertyForData<"number"> | PropertyForData<"boolean"> | PropertyForData<"any">;
|
|
51
75
|
export interface ComponentConfig {
|
|
52
76
|
id: UUID;
|
|
53
77
|
/**
|
|
@@ -62,7 +86,7 @@ export interface ComponentConfig {
|
|
|
62
86
|
* @example "components/myComponent/component.tsx"
|
|
63
87
|
*/
|
|
64
88
|
componentPath: string;
|
|
65
|
-
properties:
|
|
89
|
+
properties: Array<PropertyForData<"string"> | PropertyForData<"number"> | PropertyForData<"boolean"> | PropertyForData<"any">>;
|
|
66
90
|
/**
|
|
67
91
|
* @example [{
|
|
68
92
|
* label: "On Click",
|
|
@@ -73,5 +97,9 @@ export interface ComponentConfig {
|
|
|
73
97
|
label: string;
|
|
74
98
|
path: string;
|
|
75
99
|
}>;
|
|
100
|
+
gridDimensions?: {
|
|
101
|
+
initialColumns: number;
|
|
102
|
+
initialRows: number;
|
|
103
|
+
};
|
|
76
104
|
}
|
|
77
105
|
export {};
|
package/dist/validation.js
CHANGED
|
@@ -24,6 +24,15 @@ const componentSchema = {
|
|
|
24
24
|
$ref: "#/definitions/EventHandler",
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
|
+
gridDimensions: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
initialColumns: { type: "number" },
|
|
31
|
+
initialRows: { type: "number" },
|
|
32
|
+
},
|
|
33
|
+
additionalProperties: false,
|
|
34
|
+
required: ["initialColumns", "initialRows"],
|
|
35
|
+
},
|
|
27
36
|
},
|
|
28
37
|
required: [
|
|
29
38
|
"id",
|
|
@@ -44,9 +53,22 @@ const componentSchema = {
|
|
|
44
53
|
properties: {
|
|
45
54
|
label: { type: "string" },
|
|
46
55
|
controlType: { enum: ["text", "js-expr", "switch"] },
|
|
47
|
-
defaultValue: {
|
|
56
|
+
defaultValue: {
|
|
57
|
+
oneOf: [
|
|
58
|
+
{
|
|
59
|
+
type: "string",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
type: "boolean",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: "number",
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
48
69
|
placeholder: { type: "string" },
|
|
49
70
|
exampleData: { type: "string" },
|
|
71
|
+
expectedType: { type: "string" },
|
|
50
72
|
},
|
|
51
73
|
required: ["controlType", "label"],
|
|
52
74
|
additionalProperties: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superblocksteam/util",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"homepage": "https://www.superblocks.com",
|
|
6
6
|
"scripts": {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"clean": "npm run clean:build && rm -rf node_modules",
|
|
10
10
|
"clean:build": "tsc --build --clean && rm -rf dist tsconfig.tsbuildinfo",
|
|
11
11
|
"lint": "eslint . --ext .ts --config .eslintrc.json",
|
|
12
|
-
"lint:fix": "eslint . --ext .ts --config .eslintrc.json --fix"
|
|
12
|
+
"lint:fix": "eslint . --ext .ts --config .eslintrc.json --fix",
|
|
13
|
+
"typecheck": "tsc --noEmit"
|
|
13
14
|
},
|
|
14
15
|
"license": "Superblocks Community Software License",
|
|
15
16
|
"description": "",
|
package/src/component-configs.ts
CHANGED
|
@@ -13,8 +13,9 @@ const compileTypeScript = (inputFilePath: string, outputDir: string) => {
|
|
|
13
13
|
const tscPath = require.resolve("typescript/bin/tsc");
|
|
14
14
|
if (tscPath) {
|
|
15
15
|
execFile(
|
|
16
|
-
|
|
16
|
+
"node",
|
|
17
17
|
[
|
|
18
|
+
tscPath,
|
|
18
19
|
path.resolve(inputFilePath),
|
|
19
20
|
"--outDir",
|
|
20
21
|
outputDir,
|
|
@@ -66,8 +67,8 @@ async function getFolderPaths() {
|
|
|
66
67
|
// filter out any non-directory items
|
|
67
68
|
const directories = folderPaths.filter((dirent) => dirent.isDirectory());
|
|
68
69
|
// map each directory to its path
|
|
69
|
-
const folderPathsArray = directories.map(
|
|
70
|
-
|
|
70
|
+
const folderPathsArray = directories.map(
|
|
71
|
+
(dirent) => `${CUSTOM_COMPONENTS_PATH}/${dirent.name}`
|
|
71
72
|
);
|
|
72
73
|
return folderPathsArray;
|
|
73
74
|
} catch {
|
|
@@ -86,9 +87,10 @@ export async function getComponentConfigs(
|
|
|
86
87
|
const folderPaths = await getFolderPaths();
|
|
87
88
|
let hasError = false;
|
|
88
89
|
const promiseConfigFiles = folderPaths.map(async (ccpath) => {
|
|
90
|
+
const absPath = path.resolve(ccpath);
|
|
89
91
|
try {
|
|
90
|
-
const config = await fs.readJSON(`${
|
|
91
|
-
console.log(`Found component in ${
|
|
92
|
+
const config = await fs.readJSON(`${absPath}/config.json`);
|
|
93
|
+
console.log(`Found component in ${absPath}`);
|
|
92
94
|
return { ccpath, config };
|
|
93
95
|
} catch (e: any) {
|
|
94
96
|
// Noop because there is a fallback
|
|
@@ -107,6 +109,7 @@ export async function getComponentConfigs(
|
|
|
107
109
|
.toString(16)
|
|
108
110
|
.slice(2)}`
|
|
109
111
|
);
|
|
112
|
+
await fs.ensureDir(outputDirectory);
|
|
110
113
|
await compileTypeScript(fileName, outputDirectory);
|
|
111
114
|
console.log(`Typescript compiled to ${ccpath}`);
|
|
112
115
|
const config = (await import(outputDirectory + "/config.js")).default;
|
|
@@ -16,27 +16,30 @@ function renderInputTypeAsTS(
|
|
|
16
16
|
trailingChars: string,
|
|
17
17
|
indentSpaces: number
|
|
18
18
|
) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
let { tsType } = dataTypeDefinions[type];
|
|
20
|
+
if (["number", "string"].includes(type)) {
|
|
21
|
+
tsType += "| null";
|
|
22
|
+
}
|
|
23
|
+
return indent(`${name}: ${tsType}${trailingChars}`, indentSpaces);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export function generateComponentTypesFile(config: ComponentConfig) {
|
|
26
27
|
const properties = config.properties ?? [];
|
|
27
28
|
const eventHandlers = config.events ?? [];
|
|
28
|
-
return `//
|
|
29
|
+
return `// GENERATED CODE -- DO NOT EDIT!
|
|
30
|
+
//
|
|
31
|
+
// This file is automatically generated by the Superblocks CLI
|
|
29
32
|
// Use the \`superblocks components watch\` command to regenerate this file from its source in config.ts
|
|
30
33
|
|
|
31
34
|
// All properties of your component are defined here.
|
|
32
35
|
// These are the properties which are surfaced in the Superblocks properties panel
|
|
33
36
|
// and can be referenced throughout your Superblocks Application
|
|
34
|
-
export
|
|
37
|
+
export type Props = {
|
|
35
38
|
${properties
|
|
36
39
|
.map((v) => renderInputTypeAsTS(v.path, v.dataType, ";", 2) + "\n")
|
|
37
|
-
.join("")}}
|
|
40
|
+
.join("")}};
|
|
38
41
|
|
|
39
|
-
export
|
|
42
|
+
export type EventTriggers = {
|
|
40
43
|
// Call the subsequent function(s) to trigger event(s) in Superblocks from your component.
|
|
41
44
|
// These events can be wired up to event handlers in your Superblocks App
|
|
42
45
|
${
|
|
@@ -45,6 +48,6 @@ ${
|
|
|
45
48
|
: eventHandlers
|
|
46
49
|
.map((v: any) => indent(v.path, 2) + ": () => void;" + "\n")
|
|
47
50
|
.join("")
|
|
48
|
-
}}
|
|
51
|
+
}};
|
|
49
52
|
`;
|
|
50
53
|
}
|
package/src/resource-configs.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from "path";
|
|
1
2
|
import * as fs from "fs-extra";
|
|
2
3
|
import { RESOURCE_CONFIG_PATH } from "./constants";
|
|
3
4
|
|
|
@@ -45,30 +46,38 @@ export async function getSuperblocksMonorepoConfigJson(
|
|
|
45
46
|
checkParentDir = false,
|
|
46
47
|
pathPrefix = ""
|
|
47
48
|
): Promise<[SuperblocksMonorepoConfig, string]> {
|
|
49
|
+
const absolutePath = path.resolve(pathPrefix);
|
|
50
|
+
|
|
51
|
+
let hasReachedFilesystemRoot = false;
|
|
52
|
+
try {
|
|
53
|
+
hasReachedFilesystemRoot = path.parse(absolutePath).root == absolutePath;
|
|
54
|
+
} catch {
|
|
55
|
+
throw new Error("Could not parse path " + absolutePath);
|
|
56
|
+
}
|
|
57
|
+
|
|
48
58
|
let superblocksConfig;
|
|
49
|
-
if (
|
|
59
|
+
if (
|
|
60
|
+
(pathPrefix && !fs.existsSync(absolutePath)) ||
|
|
61
|
+
hasReachedFilesystemRoot
|
|
62
|
+
) {
|
|
50
63
|
throw new Error(
|
|
51
64
|
"No Superblocks config file found in current directory hierarchy " +
|
|
52
65
|
pathPrefix
|
|
53
66
|
);
|
|
54
67
|
}
|
|
55
68
|
|
|
69
|
+
const attemptedPath = path.join(absolutePath, RESOURCE_CONFIG_PATH);
|
|
56
70
|
try {
|
|
57
|
-
superblocksConfig = await fs.readJSON(
|
|
71
|
+
superblocksConfig = await fs.readJSON(attemptedPath);
|
|
58
72
|
if (superblocksConfig.configType !== "ROOT") {
|
|
59
73
|
throw new Error("Not the root Superblocks config file");
|
|
60
74
|
}
|
|
61
|
-
return [
|
|
62
|
-
superblocksConfig as SuperblocksMonorepoConfig,
|
|
63
|
-
pathPrefix + RESOURCE_CONFIG_PATH,
|
|
64
|
-
];
|
|
75
|
+
return [superblocksConfig as SuperblocksMonorepoConfig, attemptedPath];
|
|
65
76
|
} catch {
|
|
66
77
|
if (!checkParentDir) {
|
|
67
78
|
// no superblocks config file found
|
|
68
79
|
throw new Error(
|
|
69
|
-
"No Superblocks config file found in current directory " +
|
|
70
|
-
pathPrefix +
|
|
71
|
-
RESOURCE_CONFIG_PATH
|
|
80
|
+
"No Superblocks config file found in current directory " + attemptedPath
|
|
72
81
|
);
|
|
73
82
|
}
|
|
74
83
|
return getSuperblocksMonorepoConfigJson(true, "../" + pathPrefix);
|
package/src/types.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { type UUID } from "node:crypto";
|
|
2
2
|
import { type DataType } from "./data-types";
|
|
3
3
|
|
|
4
|
-
interface PropertiesPanelDisplay {
|
|
4
|
+
interface PropertiesPanelDisplay<T extends DataType> {
|
|
5
5
|
/**
|
|
6
6
|
* Determines what form item type is shown in the Superblocks properties panel.
|
|
7
|
+
*
|
|
8
|
+
* Only booleans are allowed to use the "switch" control
|
|
7
9
|
*/
|
|
8
|
-
controlType
|
|
10
|
+
controlType?: T extends "boolean"
|
|
11
|
+
? "text" | "js-expr" | "switch"
|
|
12
|
+
: "text" | "js-expr";
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* Determines form item label in the Superblocks properties panel.
|
|
@@ -21,20 +25,47 @@ interface PropertiesPanelDisplay {
|
|
|
21
25
|
/**
|
|
22
26
|
* This shows up in the popover as a user types into the properties panel.
|
|
23
27
|
* This is a documentation field that helps users understand what type of data is accepted
|
|
24
|
-
* by this property.
|
|
28
|
+
* by this property. You should give a specific example, not a generic type
|
|
29
|
+
*
|
|
30
|
+
* @example {
|
|
31
|
+
* label: "My Label",
|
|
32
|
+
* value: "myValue"
|
|
33
|
+
* }
|
|
25
34
|
*/
|
|
26
35
|
exampleData?: string;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* This shows up in the popover as a user types into the properties panel.
|
|
39
|
+
* This is a documentation field that helps users understand what type of data is accepted
|
|
40
|
+
* by this property. Typescript notation is recommended.
|
|
41
|
+
*
|
|
42
|
+
* @example "Array<{ label: string; value: string; }>"
|
|
43
|
+
*/
|
|
44
|
+
expectedType?: string;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The default value should match the dataType of the property.
|
|
48
|
+
*
|
|
49
|
+
* When dataType is "any", you must provide a string default value.
|
|
50
|
+
* Your string will be interpreted based on the controlType, so if you have controlType "js-expr",
|
|
51
|
+
* you should provide a string that is a valid javascript expression including quotations marks.
|
|
52
|
+
*/
|
|
53
|
+
defaultValue?: T extends "number"
|
|
54
|
+
? number
|
|
55
|
+
: T extends "boolean"
|
|
56
|
+
? boolean
|
|
57
|
+
: string;
|
|
27
58
|
}
|
|
28
59
|
|
|
29
|
-
export interface
|
|
60
|
+
export interface PropertyForData<T extends DataType> {
|
|
30
61
|
path: string;
|
|
31
|
-
dataType:
|
|
62
|
+
dataType: T;
|
|
32
63
|
|
|
33
64
|
/**
|
|
34
65
|
* The presence of this object determines whether or not this property
|
|
35
66
|
* shows up in the Superblocks properties panel.
|
|
36
67
|
**/
|
|
37
|
-
propertiesPanelDisplay?: PropertiesPanelDisplay
|
|
68
|
+
propertiesPanelDisplay?: PropertiesPanelDisplay<T>;
|
|
38
69
|
|
|
39
70
|
/**
|
|
40
71
|
* A description of this property. This is used in the Superblocks properties panel
|
|
@@ -57,6 +88,12 @@ export interface Property {
|
|
|
57
88
|
isExternallySettable?: boolean;
|
|
58
89
|
}
|
|
59
90
|
|
|
91
|
+
export type Property =
|
|
92
|
+
| PropertyForData<"string">
|
|
93
|
+
| PropertyForData<"number">
|
|
94
|
+
| PropertyForData<"boolean">
|
|
95
|
+
| PropertyForData<"any">;
|
|
96
|
+
|
|
60
97
|
export interface ComponentConfig {
|
|
61
98
|
id: UUID;
|
|
62
99
|
|
|
@@ -75,7 +112,15 @@ export interface ComponentConfig {
|
|
|
75
112
|
*/
|
|
76
113
|
componentPath: string;
|
|
77
114
|
|
|
78
|
-
properties:
|
|
115
|
+
properties: Array<
|
|
116
|
+
// Note to devs: The reason we are duplicating the Property type above is that it produces a better
|
|
117
|
+
// error message. The user will see 'is not assignable to type PropertyForData<"string"> | PropertyForData<"number">'
|
|
118
|
+
// instead of seeing "is not assignable to type Property"
|
|
119
|
+
| PropertyForData<"string">
|
|
120
|
+
| PropertyForData<"number">
|
|
121
|
+
| PropertyForData<"boolean">
|
|
122
|
+
| PropertyForData<"any">
|
|
123
|
+
>;
|
|
79
124
|
|
|
80
125
|
/**
|
|
81
126
|
* @example [{
|
|
@@ -87,4 +132,9 @@ export interface ComponentConfig {
|
|
|
87
132
|
label: string;
|
|
88
133
|
path: string;
|
|
89
134
|
}>;
|
|
135
|
+
|
|
136
|
+
gridDimensions?: {
|
|
137
|
+
initialColumns: number;
|
|
138
|
+
initialRows: number;
|
|
139
|
+
};
|
|
90
140
|
}
|
package/src/validation.ts
CHANGED
|
@@ -22,6 +22,15 @@ const componentSchema: Schema = {
|
|
|
22
22
|
$ref: "#/definitions/EventHandler",
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
|
+
gridDimensions: {
|
|
26
|
+
type: "object",
|
|
27
|
+
properties: {
|
|
28
|
+
initialColumns: { type: "number" },
|
|
29
|
+
initialRows: { type: "number" },
|
|
30
|
+
},
|
|
31
|
+
additionalProperties: false,
|
|
32
|
+
required: ["initialColumns", "initialRows"],
|
|
33
|
+
},
|
|
25
34
|
},
|
|
26
35
|
required: [
|
|
27
36
|
"id",
|
|
@@ -42,9 +51,22 @@ const componentSchema: Schema = {
|
|
|
42
51
|
properties: {
|
|
43
52
|
label: { type: "string" },
|
|
44
53
|
controlType: { enum: ["text", "js-expr", "switch"] },
|
|
45
|
-
defaultValue: {
|
|
54
|
+
defaultValue: {
|
|
55
|
+
oneOf: [
|
|
56
|
+
{
|
|
57
|
+
type: "string",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: "boolean",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: "number",
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
46
67
|
placeholder: { type: "string" },
|
|
47
68
|
exampleData: { type: "string" },
|
|
69
|
+
expectedType: { type: "string" },
|
|
48
70
|
},
|
|
49
71
|
required: ["controlType", "label"],
|
|
50
72
|
additionalProperties: false,
|