@superblocksteam/cli 0.0.19 → 0.0.21
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/README.md +20 -4
- package/assets/custom-components/example/component.tsx +15 -12
- package/assets/custom-components/setup/package.json +1 -1
- package/dist/commands/components/create.d.ts +1 -0
- package/dist/commands/components/create.js +101 -67
- package/dist/commands/components/upload.js +1 -32
- package/dist/commands/components/watch.js +1 -2
- package/dist/commands/init.js +3 -6
- package/dist/commands/login.js +1 -1
- package/dist/commands/migrate.d.ts +9 -0
- package/dist/commands/migrate.js +147 -0
- package/dist/commands/pull.js +3 -11
- package/dist/common/authenticated-command.d.ts +1 -0
- package/dist/common/authenticated-command.js +103 -1
- package/dist/common/defaults/create-component-defaults.d.ts +4 -4
- package/dist/common/defaults/create-component-defaults.js +14 -12
- package/dist/common/version-control.d.ts +0 -6
- package/dist/common/version-control.js +52 -4
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/util/migrationWarningsForApplications.d.ts +1 -0
- package/dist/util/migrationWarningsForApplications.js +38 -0
- package/dist/util/migrationsForDotfiles.d.ts +10 -0
- package/dist/util/migrationsForDotfiles.js +55 -0
- package/oclif.manifest.json +16 -2
- package/package.json +7 -8
- package/dist/common/types.d.ts +0 -7
- package/dist/common/types.js +0 -2
- package/dist/exportedTypes.d.ts +0 -20
- package/dist/exportedTypes.js +0 -2
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
6
|
+
const node_util_1 = tslib_1.__importDefault(require("node:util"));
|
|
7
|
+
const util_1 = require("@superblocksteam/util");
|
|
8
|
+
const colorette_1 = require("colorette");
|
|
9
|
+
const fs = tslib_1.__importStar(require("fs-extra"));
|
|
10
|
+
const listr2_1 = require("listr2");
|
|
11
|
+
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
12
|
+
const authenticated_command_1 = require("../common/authenticated-command");
|
|
13
|
+
const version_control_1 = require("../common/version-control");
|
|
14
|
+
class Migrate extends authenticated_command_1.AuthenticatedCommand {
|
|
15
|
+
async run() {
|
|
16
|
+
const tasks = this.createTasks();
|
|
17
|
+
await tasks.run();
|
|
18
|
+
}
|
|
19
|
+
createTasks() {
|
|
20
|
+
const tasks = new listr2_1.Listr([
|
|
21
|
+
{
|
|
22
|
+
title: "Checking for existing Superblocks project...",
|
|
23
|
+
task: async (ctx) => {
|
|
24
|
+
try {
|
|
25
|
+
[
|
|
26
|
+
ctx.existingSuperblocksRootConfig,
|
|
27
|
+
ctx.superblocksRootConfigPath,
|
|
28
|
+
] = await (0, util_1.getSuperblocksMonorepoConfigJson)(true);
|
|
29
|
+
ctx.existingSuperblocksResourceConfig =
|
|
30
|
+
await (0, util_1.getSuperblocksResourceConfigIfExists)();
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// no existing superblocks config
|
|
34
|
+
this.error(`No Superblocks project found in the current folder hierarchy. Run ${(0, colorette_1.cyan)("superblocks init")} to initialize a new project.`);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
title: "Migrating resources...",
|
|
40
|
+
task: async (ctx, task) => {
|
|
41
|
+
var _a;
|
|
42
|
+
const resourceIdsToMigrate = await this.getResourceIdsToMigrate(ctx, task);
|
|
43
|
+
const subtasks = [];
|
|
44
|
+
const superblocksRootPath = node_path_1.default.resolve(node_path_1.default.dirname(ctx.superblocksRootConfigPath), "..");
|
|
45
|
+
for (const resourceId of resourceIdsToMigrate) {
|
|
46
|
+
const resource = (_a = ctx.existingSuperblocksRootConfig) === null || _a === void 0 ? void 0 : _a.resources[resourceId];
|
|
47
|
+
switch (resource === null || resource === void 0 ? void 0 : resource.resourceType) {
|
|
48
|
+
case "APPLICATION": {
|
|
49
|
+
subtasks.push({
|
|
50
|
+
title: `Migrating application ${resource.location}...`,
|
|
51
|
+
task: async (_ctx, task) => {
|
|
52
|
+
await this.migrateApplication(resource, superblocksRootPath);
|
|
53
|
+
task.title += `: done`;
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case "BACKEND": {
|
|
59
|
+
subtasks.push({
|
|
60
|
+
title: `Migrating backend ${resource.location}...`,
|
|
61
|
+
task: async (_ctx, task) => {
|
|
62
|
+
task.title += `: done`;
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
default: {
|
|
68
|
+
this.error(`Unsupported resource type, resource: ${JSON.stringify(resource)}
|
|
69
|
+
`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return task.newListr(subtasks, {
|
|
74
|
+
concurrent: true,
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
], {
|
|
79
|
+
concurrent: false,
|
|
80
|
+
});
|
|
81
|
+
return tasks;
|
|
82
|
+
}
|
|
83
|
+
async getResourceIdsToMigrate(ctx, task) {
|
|
84
|
+
var _a, _b, _c, _d, _e;
|
|
85
|
+
const choices = [];
|
|
86
|
+
const initialSelections = [];
|
|
87
|
+
choices.push({
|
|
88
|
+
name: "All Resources",
|
|
89
|
+
message: "",
|
|
90
|
+
});
|
|
91
|
+
let counter = 1;
|
|
92
|
+
for (const [resourceId, resource] of Object.entries((_b = (_a = ctx.existingSuperblocksRootConfig) === null || _a === void 0 ? void 0 : _a.resources) !== null && _b !== void 0 ? _b : {})) {
|
|
93
|
+
choices.push({
|
|
94
|
+
name: resourceId,
|
|
95
|
+
message: resource.location,
|
|
96
|
+
});
|
|
97
|
+
if (((_c = ctx.existingSuperblocksResourceConfig) === null || _c === void 0 ? void 0 : _c.id) === resourceId) {
|
|
98
|
+
initialSelections.push(counter);
|
|
99
|
+
}
|
|
100
|
+
counter++;
|
|
101
|
+
}
|
|
102
|
+
const resourceIdsToMigrate = choices.length === 1
|
|
103
|
+
? [choices[0].name]
|
|
104
|
+
: await task.prompt([
|
|
105
|
+
{
|
|
106
|
+
type: "MultiSelect",
|
|
107
|
+
name: "resourceIdsToMigrate",
|
|
108
|
+
message: `Select resources to migrate (${version_control_1.MULTI_SELECT_PROMPT_HELP})`,
|
|
109
|
+
choices: choices,
|
|
110
|
+
initial: initialSelections,
|
|
111
|
+
validate: version_control_1.atLeastOneSelection,
|
|
112
|
+
// @ts-expect-error listr2 types are wrong for prefix
|
|
113
|
+
prefix: "▸",
|
|
114
|
+
indicator: "◉",
|
|
115
|
+
},
|
|
116
|
+
]);
|
|
117
|
+
if (resourceIdsToMigrate[0] === "All Resources") {
|
|
118
|
+
return Object.entries((_e = (_d = ctx.existingSuperblocksRootConfig) === null || _d === void 0 ? void 0 : _d.resources) !== null && _e !== void 0 ? _e : {}).map(([id]) => id);
|
|
119
|
+
}
|
|
120
|
+
return resourceIdsToMigrate;
|
|
121
|
+
}
|
|
122
|
+
async migrateApplication(applicationResource, superblocksRootPath) {
|
|
123
|
+
var _a;
|
|
124
|
+
this.log("Checking CLI version compatibility...");
|
|
125
|
+
try {
|
|
126
|
+
const packageJson = await fs.readJson(node_path_1.default.join(superblocksRootPath, applicationResource.location, "package.json"));
|
|
127
|
+
const versionStr = (_a = packageJson.dependencies) === null || _a === void 0 ? void 0 : _a["@superblocksteam/custom-components"];
|
|
128
|
+
if (!semver_1.default.satisfies(this.config.version, versionStr)) {
|
|
129
|
+
this.log("Migrating application dependencies...");
|
|
130
|
+
await node_util_1.default.promisify(node_child_process_1.exec)(`npm install @superblocksteam/custom-components@${this.config.version}`, {
|
|
131
|
+
cwd: node_path_1.default.join(superblocksRootPath, applicationResource.location),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
this.log("CLI version matches package.json version");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (e) {
|
|
139
|
+
this.error(e.message, {
|
|
140
|
+
exit: 1,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
Migrate.description = "Migrate files to use the current CLI version";
|
|
146
|
+
Migrate.examples = ["<%= config.bin %> <%= command.id %>"];
|
|
147
|
+
exports.default = Migrate;
|
package/dist/commands/pull.js
CHANGED
|
@@ -87,20 +87,12 @@ class Pull extends authenticated_command_1.AuthenticatedCommand {
|
|
|
87
87
|
{
|
|
88
88
|
title: "Updating Superblocks project file...",
|
|
89
89
|
task: async (ctx) => {
|
|
90
|
-
|
|
91
|
-
const superblocksRootConfig = {
|
|
92
|
-
configType: "ROOT",
|
|
93
|
-
resources: ctx.existingSuperblocksRootConfig.resources,
|
|
94
|
-
metadata: {
|
|
95
|
-
...(_a = ctx.existingSuperblocksRootConfig) === null || _a === void 0 ? void 0 : _a.metadata,
|
|
96
|
-
lastUpdated: ctx.now,
|
|
97
|
-
},
|
|
98
|
-
};
|
|
90
|
+
const [superblocksRootConfig, rootConfigPath] = await (0, util_1.getSuperblocksMonorepoConfigJson)(true);
|
|
99
91
|
for (const [resourceId, resource] of Object.entries(ctx.writtenResources)) {
|
|
100
92
|
superblocksRootConfig.resources[resourceId] = resource;
|
|
101
93
|
}
|
|
102
94
|
// update superblocks.json file
|
|
103
|
-
await fs.writeFile(
|
|
95
|
+
await fs.writeFile(rootConfigPath, JSON.stringify((0, version_control_1.sortByKey)(superblocksRootConfig), null, 2));
|
|
104
96
|
},
|
|
105
97
|
},
|
|
106
98
|
], {
|
|
@@ -128,7 +120,7 @@ class Pull extends authenticated_command_1.AuthenticatedCommand {
|
|
|
128
120
|
for (const [resourceId, resource] of Object.entries((_f = (_e = ctx.existingSuperblocksRootConfig) === null || _e === void 0 ? void 0 : _e.resources) !== null && _f !== void 0 ? _f : {})) {
|
|
129
121
|
choices.push({
|
|
130
122
|
name: resourceId,
|
|
131
|
-
message:
|
|
123
|
+
message: resource.location,
|
|
132
124
|
});
|
|
133
125
|
if (((_g = ctx.existingSuperblocksResourceConfig) === null || _g === void 0 ? void 0 : _g.id) === resourceId) {
|
|
134
126
|
initialSelections.push(counter);
|
|
@@ -6,6 +6,7 @@ export declare abstract class AuthenticatedCommand extends Command {
|
|
|
6
6
|
protected init(): Promise<void>;
|
|
7
7
|
protected getBaseUrl(): Promise<string>;
|
|
8
8
|
protected getSdk(): SuperblocksSdk;
|
|
9
|
+
protected runAutomatedDotfileUpdates(): Promise<void>;
|
|
9
10
|
}
|
|
10
11
|
export declare abstract class AuthenticatedApplicationCommand extends AuthenticatedCommand {
|
|
11
12
|
applicationConfig: SuperblocksApplicationConfig;
|
|
@@ -2,10 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AuthenticatedApplicationCommand = exports.AuthenticatedCommand = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
5
6
|
const core_1 = require("@oclif/core");
|
|
6
7
|
const sdk_1 = require("@superblocksteam/sdk");
|
|
7
8
|
const util_1 = require("@superblocksteam/util");
|
|
9
|
+
const colorette_1 = require("colorette");
|
|
8
10
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
11
|
+
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
12
|
+
const yaml_1 = require("yaml");
|
|
13
|
+
const migrationWarningsForApplications_1 = require("../util/migrationWarningsForApplications");
|
|
14
|
+
const migrationsForDotfiles_1 = require("../util/migrationsForDotfiles");
|
|
15
|
+
const version_control_1 = require("./version-control");
|
|
9
16
|
class AuthenticatedCommand extends core_1.Command {
|
|
10
17
|
async init() {
|
|
11
18
|
await super.init();
|
|
@@ -16,8 +23,10 @@ class AuthenticatedCommand extends core_1.Command {
|
|
|
16
23
|
}
|
|
17
24
|
const { token, superblocksBaseUrl } = result;
|
|
18
25
|
this.sdk = new sdk_1.SuperblocksSdk(token, superblocksBaseUrl);
|
|
26
|
+
await this.runAutomatedDotfileUpdates();
|
|
19
27
|
}
|
|
20
|
-
catch {
|
|
28
|
+
catch (e) {
|
|
29
|
+
console.log(e.message);
|
|
21
30
|
this.error("Please run 'superblocks login' first", { exit: 1 });
|
|
22
31
|
}
|
|
23
32
|
}
|
|
@@ -32,6 +41,62 @@ class AuthenticatedCommand extends core_1.Command {
|
|
|
32
41
|
}
|
|
33
42
|
return this.sdk;
|
|
34
43
|
}
|
|
44
|
+
async runAutomatedDotfileUpdates() {
|
|
45
|
+
let previousConfig;
|
|
46
|
+
let rootConfigPath;
|
|
47
|
+
try {
|
|
48
|
+
[previousConfig, rootConfigPath] = await (0, util_1.getSuperblocksMonorepoConfigJson)(true);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// This might fail for a brand-new project folder, which is deliberately ignored
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (previousConfig &&
|
|
55
|
+
rootConfigPath &&
|
|
56
|
+
(0, migrationsForDotfiles_1.isDotfileMigrationNeeded)(previousConfig.metadata.cliVersion, this.config.version)) {
|
|
57
|
+
this.log(`Migrating Superblocks settings from ${previousConfig.metadata.cliVersion} to ${this.config.version}...`);
|
|
58
|
+
try {
|
|
59
|
+
const newConfig = await (0, migrationsForDotfiles_1.migrateSuperblocksMonorepoConfig)(previousConfig, {
|
|
60
|
+
previousVersion: previousConfig.metadata.cliVersion,
|
|
61
|
+
currentVersion: this.config.version,
|
|
62
|
+
});
|
|
63
|
+
await fs_extra_1.default.writeFile(rootConfigPath, JSON.stringify((0, version_control_1.sortByKey)(newConfig), null, 2));
|
|
64
|
+
await Promise.all(Object.entries(newConfig.resources).map(async ([, resource]) => {
|
|
65
|
+
this.log(`Migrating ${resource.location}`);
|
|
66
|
+
try {
|
|
67
|
+
const resourcePath = node_path_1.default.join(rootConfigPath, "../..", resource.location, ".superblocks/superblocks.json");
|
|
68
|
+
const resourceConfig = await fs_extra_1.default.readJSON(resourcePath);
|
|
69
|
+
const newConfig = await (0, migrationsForDotfiles_1.migrateSuperblocksEntityConfig)(resourceConfig, {
|
|
70
|
+
previousVersion: previousConfig
|
|
71
|
+
.metadata.cliVersion,
|
|
72
|
+
currentVersion: this.config.version,
|
|
73
|
+
});
|
|
74
|
+
await fs_extra_1.default.writeFile(resourcePath, JSON.stringify((0, version_control_1.sortByKey)(newConfig), null, 2));
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
this.error(e);
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
this.log(`Finalizing migration`);
|
|
81
|
+
this.log(`After upgrading the CLI version, you may need to perform additional migrations using
|
|
82
|
+
${(0, colorette_1.cyan)("superblocks migrate")}`);
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
this.error(e);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (previousConfig.metadata.cliVersion) {
|
|
89
|
+
const warningMessage = (0, migrationWarningsForApplications_1.getWarningsForApplicationMigration)(previousConfig.metadata.cliVersion, this.config.version);
|
|
90
|
+
if (warningMessage) {
|
|
91
|
+
this.log(warningMessage);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Always upgrade the root config even if there's no migration
|
|
95
|
+
if (rootConfigPath) {
|
|
96
|
+
previousConfig.metadata.cliVersion = this.config.version;
|
|
97
|
+
await fs_extra_1.default.writeFile(rootConfigPath, JSON.stringify((0, version_control_1.sortByKey)(previousConfig), null, 2));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
35
100
|
}
|
|
36
101
|
exports.AuthenticatedCommand = AuthenticatedCommand;
|
|
37
102
|
class AuthenticatedApplicationCommand extends AuthenticatedCommand {
|
|
@@ -50,6 +115,7 @@ class AuthenticatedApplicationCommand extends AuthenticatedCommand {
|
|
|
50
115
|
return new URL(`/applications/${this.applicationConfig.id}/pages/${this.applicationConfig.defaultPageId}/edit`, baseUrl).toString();
|
|
51
116
|
}
|
|
52
117
|
async init() {
|
|
118
|
+
var _a;
|
|
53
119
|
await super.init();
|
|
54
120
|
try {
|
|
55
121
|
this.applicationConfig = await (0, util_1.getSuperblocksApplicationConfigJson)();
|
|
@@ -59,8 +125,44 @@ class AuthenticatedApplicationCommand extends AuthenticatedCommand {
|
|
|
59
125
|
exit: 1,
|
|
60
126
|
});
|
|
61
127
|
}
|
|
128
|
+
try {
|
|
129
|
+
const appYaml = await fs_extra_1.default.readFile("application.yaml", "utf-8");
|
|
130
|
+
const appJson = await (0, yaml_1.parse)(appYaml);
|
|
131
|
+
if ((_a = appJson === null || appJson === void 0 ? void 0 : appJson.settings) === null || _a === void 0 ? void 0 : _a.cliVersion) {
|
|
132
|
+
const warningMessage = (0, migrationWarningsForApplications_1.getWarningsForApplicationMigration)(appJson.settings.cliVersion, this.config.version);
|
|
133
|
+
if (warningMessage) {
|
|
134
|
+
this.log(warningMessage);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (e) {
|
|
139
|
+
this.warn(`Could not read page.yaml to determine version compatibility: ${e.message}`);
|
|
140
|
+
}
|
|
62
141
|
}
|
|
63
142
|
async registerComponents() {
|
|
143
|
+
var _a;
|
|
144
|
+
core_1.ux.action.start("Checking CLI version compatibility...");
|
|
145
|
+
try {
|
|
146
|
+
const packageJson = await fs_extra_1.default.readJson("package.json");
|
|
147
|
+
const versionStr = (_a = packageJson.dependencies) === null || _a === void 0 ? void 0 : _a["@superblocksteam/custom-components"];
|
|
148
|
+
if (!versionStr) {
|
|
149
|
+
throw new Error(`You must install the @superblocksteam/custom-components library as a dependency in your package.json file. Run:
|
|
150
|
+
|
|
151
|
+
${(0, colorette_1.cyan)("superblocks migrate")}`);
|
|
152
|
+
}
|
|
153
|
+
if (!semver_1.default.satisfies(this.config.version, versionStr)) {
|
|
154
|
+
throw new Error(`You must upgrade the @superblocksteam/custom-components library. You are using ${versionStr} but the CLI is ${this.config.version}. Run:
|
|
155
|
+
|
|
156
|
+
${(0, colorette_1.cyan)("superblocks migrate")}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
core_1.ux.action.stop();
|
|
161
|
+
this.error(e.message, {
|
|
162
|
+
exit: 1,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
core_1.ux.action.stop();
|
|
64
166
|
core_1.ux.action.start("Scanning for Superblocks components...");
|
|
65
167
|
const exists = await fs_extra_1.default.pathExists(util_1.CUSTOM_COMPONENTS_PATH);
|
|
66
168
|
if (!exists) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const getDefaultConfigTs: ({ id, name, displayName,
|
|
1
|
+
import { type Property } from "@superblocksteam/util";
|
|
2
|
+
export declare const getDefaultConfigTs: ({ id, name, displayName, propertiesRendered, eventHandlersRendered, }: {
|
|
3
3
|
id: string;
|
|
4
4
|
name: string;
|
|
5
5
|
displayName: string;
|
|
6
|
-
|
|
6
|
+
propertiesRendered: string;
|
|
7
7
|
eventHandlersRendered: string;
|
|
8
8
|
}) => string;
|
|
9
|
-
export declare const getDefaultComponentTsx: (
|
|
9
|
+
export declare const getDefaultComponentTsx: (properties: Property[], eventHandlers: string[]) => string;
|
|
@@ -8,7 +8,7 @@ const indent = (str, spaces) => {
|
|
|
8
8
|
.map((line) => `${spacesString}${line}`)
|
|
9
9
|
.join("\n");
|
|
10
10
|
};
|
|
11
|
-
const getDefaultConfigTs = ({ id, name, displayName,
|
|
11
|
+
const getDefaultConfigTs = ({ id, name, displayName, propertiesRendered, eventHandlersRendered, }) => `import { type ComponentConfig } from "@superblocksteam/custom-components";
|
|
12
12
|
|
|
13
13
|
export default {
|
|
14
14
|
// DO NOT CHANGE THE ID ONCE THE COMPONENT HAS BEEN REGISTERED!
|
|
@@ -16,21 +16,23 @@ export default {
|
|
|
16
16
|
name: "${name}",
|
|
17
17
|
displayName: "${displayName}",
|
|
18
18
|
componentPath: "components/${name}/component.tsx",
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
properties: [${indent(propertiesRendered, 4).trim()}],
|
|
20
|
+
events: [${indent(eventHandlersRendered, 4).trim()}],
|
|
21
21
|
} satisfies ComponentConfig;
|
|
22
22
|
`;
|
|
23
23
|
exports.getDefaultConfigTs = getDefaultConfigTs;
|
|
24
|
-
const getDefaultComponentTsx = (
|
|
25
|
-
import {
|
|
24
|
+
const getDefaultComponentTsx = (properties, eventHandlers) => `import React from "react";
|
|
25
|
+
import { useSuperblocksContext } from "@superblocksteam/custom-components";
|
|
26
|
+
import { type Props, type EventTriggers } from "./types";
|
|
27
|
+
|
|
28
|
+
export default function Component({${properties.length === 0
|
|
29
|
+
? ""
|
|
30
|
+
: "\n" + properties.map((v) => indent(v.path, 2) + ",\n").join("")}}: Props) {
|
|
31
|
+
const {
|
|
32
|
+
updateProperties,
|
|
33
|
+
events: {${"\n" + eventHandlers.map((v) => indent(v, 6) + ",\n").join("")} },
|
|
34
|
+
} = useSuperblocksContext<Props, EventTriggers>();
|
|
26
35
|
|
|
27
|
-
export default function Component({
|
|
28
|
-
updateStatefulProperties${statefulProps.length > 0
|
|
29
|
-
? ",\n" + statefulProps.map((v) => indent(v.path, 2)).join(",\n")
|
|
30
|
-
: ""}${eventHandlers.length > 0
|
|
31
|
-
? ",\n" + eventHandlers.map((v) => indent(v, 2)).join(",\n")
|
|
32
|
-
: ""}
|
|
33
|
-
}: Props) {
|
|
34
36
|
return (
|
|
35
37
|
<div
|
|
36
38
|
style={{
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { ViewMode } from "@superblocksteam/sdk";
|
|
2
2
|
import { VersionedResourceConfig } from "@superblocksteam/util";
|
|
3
|
-
export type SuperblocksMetadata = {
|
|
4
|
-
cliVersion: string;
|
|
5
|
-
remote: string;
|
|
6
|
-
lastUpdated: number;
|
|
7
|
-
created: number;
|
|
8
|
-
};
|
|
9
3
|
export declare const LATEST_EDITS_MODE = "latest-edits";
|
|
10
4
|
export declare const MOST_RECENT_COMMIT_MODE = "most-recent-commit";
|
|
11
5
|
export declare const DEPLOYED_MODE = "deployed";
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sortByKey = exports.getMode = exports.writeResourceToDisk = exports.atLeastOneSelection = exports.MULTI_SELECT_PROMPT_HELP = exports.SELECT_PROMPT_HELP = exports.modeFlagToViewMode = exports.modeFlagValuesMap = exports.DEPLOYED_MODE = exports.MOST_RECENT_COMMIT_MODE = exports.LATEST_EDITS_MODE = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const https = tslib_1.__importStar(require("https"));
|
|
5
6
|
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
7
|
+
const path_1 = require("path");
|
|
6
8
|
const util_1 = require("@superblocksteam/util");
|
|
7
9
|
const colorette_1 = require("colorette");
|
|
8
10
|
const fs = tslib_1.__importStar(require("fs-extra"));
|
|
@@ -46,8 +48,47 @@ function slugifyName(originalName) {
|
|
|
46
48
|
lower: true,
|
|
47
49
|
});
|
|
48
50
|
}
|
|
51
|
+
// resolves a true promise when download is complete. If there's an error, resolve false
|
|
52
|
+
async function downloadFile(rootDirectory, filepath, url) {
|
|
53
|
+
const fullPath = `${rootDirectory}/${filepath}`;
|
|
54
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
55
|
+
const result = await new Promise(async (resolve) => {
|
|
56
|
+
try {
|
|
57
|
+
// create directory path if it doesn't exist yet
|
|
58
|
+
if (!(await fs.pathExists(fullPath))) {
|
|
59
|
+
await fs.mkdir((0, path_1.dirname)(fullPath), { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
const file = fs.createWriteStream(fullPath);
|
|
62
|
+
https.get(url, (resp) => {
|
|
63
|
+
resp.pipe(file);
|
|
64
|
+
file
|
|
65
|
+
.on("finish", () => {
|
|
66
|
+
file.end(() => resolve(true));
|
|
67
|
+
})
|
|
68
|
+
.on("error", () => {
|
|
69
|
+
fs.unlink(filepath);
|
|
70
|
+
resolve(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
return resolve(false);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
// failed to download correctly, attempt to clean up file
|
|
79
|
+
if (!result) {
|
|
80
|
+
try {
|
|
81
|
+
await fs.unlink(fullPath);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
console.log("Failed to delete file", fullPath);
|
|
85
|
+
}
|
|
86
|
+
return Promise.resolve(fullPath);
|
|
87
|
+
}
|
|
88
|
+
return Promise.resolve("");
|
|
89
|
+
}
|
|
49
90
|
async function writeResourceToDisk(resourceType, resourceId, resource, now, rootPath, existingRelativeLocation) {
|
|
50
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
91
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
51
92
|
switch (resourceType) {
|
|
52
93
|
case "APPLICATION": {
|
|
53
94
|
const parentDirName = "apps";
|
|
@@ -94,15 +135,23 @@ async function writeResourceToDisk(resourceType, resourceId, resource, now, root
|
|
|
94
135
|
}
|
|
95
136
|
await fs.ensureDir(`${appDirName}/${util_1.SUPERBLOCKS_HOME_FOLDER_NAME}`);
|
|
96
137
|
await fs.writeFile(`${appDirName}/${util_1.RESOURCE_CONFIG_PATH}`, JSON.stringify(sortByKey(applicationConfig), null, 2));
|
|
138
|
+
const createdFiles = await Promise.resolve(
|
|
139
|
+
// Defensive check for when application settings are missing componentFiles
|
|
140
|
+
(_f = (_e = resource.componentFiles) === null || _e === void 0 ? void 0 : _e.map((file) => downloadFile(appDirName, file.filename, file.url))) !== null && _f !== void 0 ? _f : []);
|
|
141
|
+
// print out failed downloads synchronously here
|
|
142
|
+
createdFiles
|
|
143
|
+
.filter((createdFiles) => createdFiles.length)
|
|
144
|
+
.forEach((createdFile) => {
|
|
145
|
+
console.log(`Unable to download ${createdFile}`);
|
|
146
|
+
});
|
|
97
147
|
return {
|
|
98
148
|
location: relativeLocation,
|
|
99
|
-
lastUpdated: now,
|
|
100
149
|
resourceType: "APPLICATION",
|
|
101
150
|
};
|
|
102
151
|
}
|
|
103
152
|
case "BACKEND": {
|
|
104
153
|
const parentDirName = "backends";
|
|
105
|
-
const apiName = slugifyName((
|
|
154
|
+
const apiName = slugifyName((_j = (_h = (_g = resource.apiPb) === null || _g === void 0 ? void 0 : _g.metadata) === null || _h === void 0 ? void 0 : _h.name) !== null && _j !== void 0 ? _j : resource.actions.name);
|
|
106
155
|
// server is still sending actions for a backwards compatibility
|
|
107
156
|
delete resource.actions;
|
|
108
157
|
const newRelativeLocation = `${parentDirName}/${apiName}`;
|
|
@@ -123,7 +172,6 @@ async function writeResourceToDisk(resourceType, resourceId, resource, now, root
|
|
|
123
172
|
await fs.writeFile(`${backendDirName}/${util_1.RESOURCE_CONFIG_PATH}`, JSON.stringify(sortByKey(backendConfig), null, 2));
|
|
124
173
|
return {
|
|
125
174
|
location: relativeLocation,
|
|
126
|
-
lastUpdated: now,
|
|
127
175
|
resourceType: "BACKEND",
|
|
128
176
|
};
|
|
129
177
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.run = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
4
|
var core_1 = require("@oclif/core");
|
|
6
5
|
Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
|
|
7
|
-
tslib_1.__exportStar(require("./exportedTypes"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getWarningsForApplicationMigration(previousVersion: string, newVersion: string): string | undefined;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getWarningsForApplicationMigration = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const colorette_1 = require("colorette");
|
|
6
|
+
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
7
|
+
// If you are changing how application files work on disk, for example changing the directory layout,
|
|
8
|
+
// you need to tell the user how to upgrade manually.
|
|
9
|
+
const BREAKING_APPLICATION_VERSIONS = [
|
|
10
|
+
{
|
|
11
|
+
version: "0.0.20",
|
|
12
|
+
// This is an example message because 0.0.20 does not have a docs page for any migrations. This will be added
|
|
13
|
+
// in a future release
|
|
14
|
+
message: `${(0, colorette_1.red)("Warning")}: Your code must be updated due to a breaking change in custom component definitions. See docs.`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
version: "0.0.21",
|
|
18
|
+
// This is an example message because 0.0.21 does not have a docs page for any migrations. This will be added
|
|
19
|
+
// in a future release
|
|
20
|
+
message: `${(0, colorette_1.red)("Warning")}: You will not be able to use CLI commands on custom components until you manually migrate your components,
|
|
21
|
+
due to breaking changes in the config.ts format and custom component API.
|
|
22
|
+
|
|
23
|
+
${(0, colorette_1.bold)("Your existing components are safe.")}
|
|
24
|
+
|
|
25
|
+
To manually migrate:
|
|
26
|
+
|
|
27
|
+
1. Rename "eventHandlers" to "events".
|
|
28
|
+
2. Update your properties to use the new format: ${(0, colorette_1.magenta)("https://docs.superblocks.com/applications/custom-components/development-lifecycle#configts")}
|
|
29
|
+
`,
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
function getWarningsForApplicationMigration(previousVersion, newVersion) {
|
|
33
|
+
const firstBreakingChange = BREAKING_APPLICATION_VERSIONS.find(({ version }) => {
|
|
34
|
+
return (semver_1.default.lt(previousVersion, version) && semver_1.default.lte(version, newVersion));
|
|
35
|
+
});
|
|
36
|
+
return firstBreakingChange === null || firstBreakingChange === void 0 ? void 0 : firstBreakingChange.message;
|
|
37
|
+
}
|
|
38
|
+
exports.getWarningsForApplicationMigration = getWarningsForApplicationMigration;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SuperblocksApplicationConfig, SuperblocksBackendConfig, SuperblocksMonorepoConfig } from "@superblocksteam/util";
|
|
2
|
+
export declare function migrateSuperblocksMonorepoConfig(config: SuperblocksMonorepoConfig, options: {
|
|
3
|
+
previousVersion: string;
|
|
4
|
+
currentVersion: string;
|
|
5
|
+
}): Promise<SuperblocksMonorepoConfig>;
|
|
6
|
+
export declare function migrateSuperblocksEntityConfig(config: SuperblocksApplicationConfig | SuperblocksBackendConfig, options: {
|
|
7
|
+
previousVersion: string;
|
|
8
|
+
currentVersion: string;
|
|
9
|
+
}): Promise<SuperblocksApplicationConfig | SuperblocksBackendConfig>;
|
|
10
|
+
export declare function isDotfileMigrationNeeded(previousVersion: string, currentVersion: string): boolean;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isDotfileMigrationNeeded = exports.migrateSuperblocksEntityConfig = exports.migrateSuperblocksMonorepoConfig = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
6
|
+
// These migrations are used to upgrade the Superblocks config files as needed.
|
|
7
|
+
// For example if we add a new required field
|
|
8
|
+
const MonorepoMigratorsFromOldVersion = [
|
|
9
|
+
{
|
|
10
|
+
migrateWhenUpgradingTo: "0.0.19",
|
|
11
|
+
migrator: (config) => config,
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
// Recursively migrate configs to the latest version
|
|
15
|
+
async function migrateSuperblocksMonorepoConfig(config, options) {
|
|
16
|
+
return await sharedMigrator(MonorepoMigratorsFromOldVersion, config, options);
|
|
17
|
+
}
|
|
18
|
+
exports.migrateSuperblocksMonorepoConfig = migrateSuperblocksMonorepoConfig;
|
|
19
|
+
// These migrations are used to upgrade the Superblocks config files as needed.
|
|
20
|
+
// For example if we add a new required field
|
|
21
|
+
const EntityMigratorsFromOldVersion = [
|
|
22
|
+
{
|
|
23
|
+
migrateWhenUpgradingTo: "0.0.19",
|
|
24
|
+
migrator: (config) => config,
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
async function migrateSuperblocksEntityConfig(config, options) {
|
|
28
|
+
return await sharedMigrator(EntityMigratorsFromOldVersion, config, options);
|
|
29
|
+
}
|
|
30
|
+
exports.migrateSuperblocksEntityConfig = migrateSuperblocksEntityConfig;
|
|
31
|
+
function isDotfileMigrationNeeded(previousVersion, currentVersion) {
|
|
32
|
+
return (previousVersion !== currentVersion &&
|
|
33
|
+
(MonorepoMigratorsFromOldVersion.some(({ migrateWhenUpgradingTo }) => semver_1.default.gt(migrateWhenUpgradingTo, previousVersion) &&
|
|
34
|
+
semver_1.default.lte(migrateWhenUpgradingTo, currentVersion)) ||
|
|
35
|
+
EntityMigratorsFromOldVersion.some(({ migrateWhenUpgradingTo }) => semver_1.default.gt(migrateWhenUpgradingTo, previousVersion) &&
|
|
36
|
+
semver_1.default.lte(migrateWhenUpgradingTo, currentVersion))));
|
|
37
|
+
}
|
|
38
|
+
exports.isDotfileMigrationNeeded = isDotfileMigrationNeeded;
|
|
39
|
+
async function sharedMigrator(migratorObject, config, { previousVersion, currentVersion, }) {
|
|
40
|
+
let newConfig = JSON.parse(JSON.stringify(config));
|
|
41
|
+
// Find all migrators in the range between previousVersion and currentVersion
|
|
42
|
+
const migratorFns = migratorObject.filter(({ migrateWhenUpgradingTo }) => semver_1.default.gt(migrateWhenUpgradingTo, previousVersion) &&
|
|
43
|
+
semver_1.default.lte(migrateWhenUpgradingTo, currentVersion));
|
|
44
|
+
migratorFns.forEach(({ migrator, migrateWhenUpgradingTo }) => {
|
|
45
|
+
try {
|
|
46
|
+
newConfig = migrator(newConfig);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
// Migrations fail if our preconditions aren't met
|
|
50
|
+
console.warn(`Error while migrating config to version ${migrateWhenUpgradingTo}: ${e.message}`);
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return newConfig;
|
|
55
|
+
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.21",
|
|
3
3
|
"commands": {
|
|
4
4
|
"init": {
|
|
5
5
|
"id": "init",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"login": {
|
|
39
39
|
"id": "login",
|
|
40
|
-
"description": "
|
|
40
|
+
"description": "Authenticate with Superblocks cloud",
|
|
41
41
|
"strict": true,
|
|
42
42
|
"pluginName": "@superblocksteam/cli",
|
|
43
43
|
"pluginAlias": "@superblocksteam/cli",
|
|
@@ -54,6 +54,20 @@
|
|
|
54
54
|
},
|
|
55
55
|
"args": {}
|
|
56
56
|
},
|
|
57
|
+
"migrate": {
|
|
58
|
+
"id": "migrate",
|
|
59
|
+
"description": "Migrate files to use the current CLI version",
|
|
60
|
+
"strict": true,
|
|
61
|
+
"pluginName": "@superblocksteam/cli",
|
|
62
|
+
"pluginAlias": "@superblocksteam/cli",
|
|
63
|
+
"pluginType": "core",
|
|
64
|
+
"aliases": [],
|
|
65
|
+
"examples": [
|
|
66
|
+
"<%= config.bin %> <%= command.id %>"
|
|
67
|
+
],
|
|
68
|
+
"flags": {},
|
|
69
|
+
"args": {}
|
|
70
|
+
},
|
|
57
71
|
"pull": {
|
|
58
72
|
"id": "pull",
|
|
59
73
|
"description": "Download objects from Superblocks and save them locally",
|