@superblocksteam/cli 1.9.2 → 1.10.0

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 CHANGED
@@ -12,7 +12,7 @@ $ npm install -g @superblocksteam/cli
12
12
  $ superblocks COMMAND
13
13
  running command...
14
14
  $ superblocks (--version)
15
- @superblocksteam/cli/1.9.2 linux-x64 node-v20.18.2
15
+ @superblocksteam/cli/1.10.0 linux-x64 node-v20.18.2
16
16
  $ superblocks --help [COMMAND]
17
17
  USAGE
18
18
  $ superblocks COMMAND
@@ -7,7 +7,7 @@
7
7
  "lint:fix": "npx eslint . --fix"
8
8
  },
9
9
  "dependencies": {
10
- "@superblocksteam/custom-components": "1.9.2",
10
+ "@superblocksteam/custom-components": "1.10.0",
11
11
  "react": "^18",
12
12
  "react-dom": "^18"
13
13
  },
@@ -0,0 +1,15 @@
1
+ import React, { createElement } from "react";
2
+ import ReactDOM from "react-dom";
3
+ import { setRenderHelper, registerPortal, removePortal } from "./injectedReactShimShared";
4
+
5
+ let isLoaded = false;
6
+
7
+ export function loadReact(rootEl) {
8
+ setRenderHelper((component) => ReactDOM.render(component, rootEl));
9
+ if (!isLoaded) {
10
+ ReactDOM.render(createElement(React.Fragment), rootEl);
11
+ isLoaded = true;
12
+ }
13
+
14
+ return { registerPortal, removePortal, React };
15
+ };
@@ -0,0 +1,16 @@
1
+ import React, { createElement } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { setRenderHelper, registerPortal, removePortal } from "./injectedReactShimShared";
4
+
5
+ let isLoaded = false;
6
+
7
+ export function loadReact(rootEl) {
8
+ if (!isLoaded) {
9
+ const root = createRoot(rootEl);
10
+ root.render(createElement(React.Fragment));
11
+ setRenderHelper((component) => root.render(component));
12
+ isLoaded = true;
13
+ }
14
+
15
+ return { registerPortal, removePortal, React };
16
+ };
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Detect and support multiple React version
3
+ * this file is served by the user's code
4
+ */
5
+ import React, { createElement } from "react";
6
+ import { createPortal } from "react-dom";
7
+
8
+ let renderHelper;
9
+ export function setRenderHelper(helper) {
10
+ renderHelper = helper;
11
+ }
12
+
13
+ /** @type Array<React.ReactPortal> */
14
+ const portals = new Map();
15
+
16
+ export function registerPortal(
17
+ Component,
18
+ props,
19
+ element,
20
+ ccRenderingContext,
21
+ SuperblocksCCReactContext
22
+ ) {
23
+ if (!ccRenderingContext)
24
+ throw new TypeError("ccRenderingContext is required");
25
+ const portal = createPortal(
26
+ <SuperblocksCCReactContext.Provider value={ccRenderingContext}>
27
+ <CustomComponentErrorBoundary componentRef={Component}>
28
+ <Component {...props} />
29
+ </CustomComponentErrorBoundary>
30
+ </SuperblocksCCReactContext.Provider>,
31
+ element,
32
+ ccRenderingContext.widgetId
33
+ );
34
+ portals.set(ccRenderingContext.widgetId, portal);
35
+ renderHelper(
36
+ createElement(React.Fragment, null, Array.from(portals.values()))
37
+ );
38
+ }
39
+ export function removePortal(key) {
40
+ portals.delete(key);
41
+ renderHelper(
42
+ createElement(React.Fragment, null, Array.from(portals.values()))
43
+ );
44
+ }
45
+
46
+ class CustomComponentErrorBoundary extends React.Component {
47
+ constructor(props) {
48
+ super(props);
49
+ this.state = { hasError: false, errorDisplay: null };
50
+ }
51
+
52
+ static getDerivedStateFromError(error) {
53
+ // Update state so the next render will show the fallback UI.
54
+ const errorDisplay = error ?? null;
55
+ return { hasError: true, errorDisplay };
56
+ }
57
+
58
+ componentDidCatch(error) {
59
+ console.error(error);
60
+ }
61
+
62
+ componentDidUpdate(prevProps) {
63
+ if (prevProps.componentRef !== this.props.componentRef) {
64
+ // Clear error boundary if component is changed
65
+ this.setState({ hasError: false, errorDisplay: null });
66
+ }
67
+ }
68
+
69
+ render() {
70
+ return (
71
+ <div
72
+ style={{
73
+ height: "100%",
74
+ width: "100%",
75
+ }}
76
+ >
77
+ {this.state.hasError && this.state.errorDisplay ? (
78
+ <div
79
+ style={{
80
+ height: "100%",
81
+ width: "100%",
82
+ backgroundColor: "white",
83
+ display: "flex",
84
+ flexDirection: "column",
85
+ justifyContent: "center",
86
+ alignItems: "center",
87
+ textAlign: "center",
88
+ borderRadius: "4px",
89
+ border: "1px solid #F45252",
90
+ }}
91
+ >
92
+ <p>
93
+ <span
94
+ style={{
95
+ display: "inline-block",
96
+ cursor: "pointer",
97
+ color: "#29bbff",
98
+ }}
99
+ role="button"
100
+ tabIndex={0}
101
+ onClick={() => {
102
+ this.setState({ hasError: false, errorDisplay: null });
103
+ }}
104
+ >
105
+ &#8635; Reload component
106
+ </span>{" "}
107
+ </p>
108
+ <p>
109
+ <span
110
+ style={{
111
+ display: "inline-block",
112
+ cursor: "pointer",
113
+ color: "#F45252",
114
+ textDecorationLine: "underline",
115
+ }}
116
+ role="button"
117
+ tabIndex={1}
118
+ onClick={() => {
119
+ const errorEvent = new CustomEvent("cc-error-display", {
120
+ detail: {
121
+ stack: this.state.errorDisplay?.stack,
122
+ message: this.state.errorDisplay?.message,
123
+ },
124
+ });
125
+ window.dispatchEvent(errorEvent);
126
+ }}
127
+ >
128
+ &#10071; View Error
129
+ </span>
130
+ </p>
131
+ </div>
132
+ ) : (
133
+ this.props.children
134
+ )}
135
+ </div>
136
+ );
137
+ }
138
+ }
139
+
140
+ export { CustomComponentErrorBoundary };
@@ -0,0 +1,2 @@
1
+ import { Plugin } from "vite";
2
+ export declare const appendHotReloadEventPlugin: (getBranch: () => Promise<string | null>) => Plugin;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.appendHotReloadEventPlugin = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path_1 = tslib_1.__importDefault(require("path"));
6
+ const sdk_1 = require("@superblocksteam/sdk");
7
+ const util_1 = require("@superblocksteam/util");
8
+ const appendHotReloadEventPlugin = (getBranch) => {
9
+ return {
10
+ name: "append-code-plugin",
11
+ enforce: "pre",
12
+ apply: "serve",
13
+ async handleHotUpdate(ctx) {
14
+ const isConfigFile = path_1.default.basename(ctx.file) === "config.ts";
15
+ if (!isConfigFile)
16
+ return;
17
+ try {
18
+ const result = await (0, util_1.getLocalTokenWithUrl)();
19
+ if (!result || !("token" in result)) {
20
+ throw new Error("Please run `superblocks login` to login.");
21
+ }
22
+ const { token, superblocksBaseUrl } = result;
23
+ const resourceConfig = await (0, util_1.getSuperblocksApplicationConfigJson)();
24
+ const { configs, hasError } = await (0, util_1.getComponentConfigs)(true);
25
+ if (hasError)
26
+ return;
27
+ const [rootSettings] = await (0, util_1.getSuperblocksMonorepoConfigJson)(true);
28
+ const sdk = new sdk_1.SuperblocksSdk(token, superblocksBaseUrl, rootSettings.metadata.cliVersion);
29
+ console.log("Registering components...");
30
+ const branch = await getBranch();
31
+ const headers = {
32
+ [util_1.COMPONENT_EVENT_HEADER]: util_1.ComponentEvent.REGISTER,
33
+ };
34
+ await sdk.registerComponents(resourceConfig.id, configs, branch, headers);
35
+ console.log("Re-registered components!");
36
+ ctx.server.ws.send({
37
+ type: "custom",
38
+ event: "config-reloaded",
39
+ data: {},
40
+ });
41
+ }
42
+ catch (e) {
43
+ console.error(e.message);
44
+ }
45
+ },
46
+ };
47
+ };
48
+ exports.appendHotReloadEventPlugin = appendHotReloadEventPlugin;
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const path_1 = tslib_1.__importDefault(require("path"));
5
5
  const core_1 = require("@oclif/core");
6
- const css_plugin_1 = require("@superblocksteam/css-plugin");
7
- const react_shim_1 = require("@superblocksteam/react-shim");
8
6
  const util_1 = require("@superblocksteam/util");
9
7
  const plugin_react_1 = tslib_1.__importDefault(require("@vitejs/plugin-react"));
10
8
  const colorette_1 = require("colorette");
11
9
  const fs = tslib_1.__importStar(require("fs-extra"));
12
10
  const vite_1 = require("vite");
13
11
  const authenticated_command_1 = require("../../common/authenticated-command");
12
+ const productionCssPlugin_1 = require("../../productionCssPlugin");
13
+ const reactShimPlugin_1 = require("../../reactShimPlugin");
14
14
  class Upload extends authenticated_command_1.AuthenticatedApplicationCommand {
15
15
  async run() {
16
16
  const { flags } = await this.parse(Upload);
@@ -57,8 +57,8 @@ class Upload extends authenticated_command_1.AuthenticatedApplicationCommand {
57
57
  customLogger: viteLogger,
58
58
  plugins: [
59
59
  (0, plugin_react_1.default)(),
60
- (0, react_shim_1.injectReactVersionsPlugin)(),
61
- (0, css_plugin_1.productionCssPlugin)(),
60
+ (0, reactShimPlugin_1.injectReactVersionsPlugin)(),
61
+ (0, productionCssPlugin_1.productionCssPlugin)(),
62
62
  {
63
63
  name: "remove-node-module-maps",
64
64
  apply: "build",
@@ -2,14 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.healthEndpointMiddleware = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const react_shim_1 = require("@superblocksteam/react-shim");
6
5
  const util_1 = require("@superblocksteam/util");
7
- const vite_custom_component_reload_plugin_1 = require("@superblocksteam/vite-custom-component-reload-plugin");
8
6
  const plugin_react_1 = tslib_1.__importDefault(require("@vitejs/plugin-react"));
9
7
  const colorette_1 = require("colorette");
10
8
  const vite_1 = require("vite");
9
+ const appendHotReloadEventPlugin_1 = require("../../appendHotReloadEventPlugin");
11
10
  const authenticated_command_1 = require("../../common/authenticated-command");
12
11
  const version_control_1 = require("../../common/version-control");
12
+ const reactShimPlugin_1 = require("../../reactShimPlugin");
13
13
  function healthEndpointMiddleware(getBranch) {
14
14
  return {
15
15
  name: "health-endpoint-middleware",
@@ -102,8 +102,8 @@ class Watch extends authenticated_command_1.AuthenticatedApplicationCommand {
102
102
  plugins: [
103
103
  healthEndpointMiddleware(getBranch),
104
104
  (0, plugin_react_1.default)(),
105
- (0, vite_custom_component_reload_plugin_1.appendHotReloadEventPlugin)(getBranch),
106
- (0, react_shim_1.injectReactVersionsPlugin)(),
105
+ (0, appendHotReloadEventPlugin_1.appendHotReloadEventPlugin)(getBranch),
106
+ (0, reactShimPlugin_1.injectReactVersionsPlugin)(),
107
107
  ],
108
108
  });
109
109
  await server.listen();
@@ -28,6 +28,8 @@ class Initialize extends authenticated_command_1.AuthenticatedCommand {
28
28
  task: async (ctx) => {
29
29
  ctx.fetchedResources = {};
30
30
  ctx.writtenResources = {};
31
+ ctx.featureFlags =
32
+ await this.getSdk().getFeatureFlagsForCurrentUser();
31
33
  try {
32
34
  [
33
35
  ctx.existingSuperblocksRootConfig,
@@ -153,7 +155,7 @@ class Initialize extends authenticated_command_1.AuthenticatedCommand {
153
155
  task.title += `: fetched`;
154
156
  if (application) {
155
157
  ctx.writtenResources[resourceId] =
156
- await (0, version_control_1.writeMultiPageApplicationToDisk)(application, superblocksRootPath !== null && superblocksRootPath !== void 0 ? superblocksRootPath : process.cwd());
158
+ await (0, version_control_1.writeMultiPageApplicationToDisk)(application, superblocksRootPath !== null && superblocksRootPath !== void 0 ? superblocksRootPath : process.cwd(), ctx.featureFlags);
157
159
  }
158
160
  task.title += `: done`;
159
161
  },
@@ -171,8 +173,10 @@ class Initialize extends authenticated_command_1.AuthenticatedCommand {
171
173
  skipSigningVerification,
172
174
  });
173
175
  task.title += `: fetched`;
174
- ctx.writtenResources[resourceId] =
175
- await (0, version_control_1.writeResourceToDisk)("BACKEND", resourceId, backend, process.cwd());
176
+ if (backend) {
177
+ ctx.writtenResources[resourceId] =
178
+ await (0, version_control_1.writeResourceToDisk)("BACKEND", resourceId, backend, superblocksRootPath !== null && superblocksRootPath !== void 0 ? superblocksRootPath : process.cwd(), ctx.featureFlags);
179
+ }
176
180
  task.title += `: done`;
177
181
  },
178
182
  });
@@ -49,7 +49,7 @@ class Migrate extends authenticated_command_1.AuthenticatedCommand {
49
49
  subtasks.push({
50
50
  title: `Migrating application ${resource.location}...`,
51
51
  task: async (_ctx, task) => {
52
- await this.migrateApplication(resource, superblocksRootPath);
52
+ await this.migrateApplication(resource, superblocksRootPath, ctx.featureFlags);
53
53
  task.title += `: done`;
54
54
  },
55
55
  });
@@ -119,7 +119,7 @@ class Migrate extends authenticated_command_1.AuthenticatedCommand {
119
119
  }
120
120
  return resourceIdsToMigrate;
121
121
  }
122
- async migrateSinglePageApplicationToMultiPage(applicationResource, superblocksRootPath) {
122
+ async migrateSinglePageApplicationToMultiPage(applicationResource, superblocksRootPath, featureFlags) {
123
123
  const fileStructure = await (0, version_control_1.getFileStructureType)(superblocksRootPath, applicationResource.location);
124
124
  if (fileStructure == version_control_1.FileStructureType.SINGLE_PAGE) {
125
125
  this.log(`Migrating single page application at ${applicationResource.location} to multi-page application...`);
@@ -141,7 +141,7 @@ class Migrate extends authenticated_command_1.AuthenticatedCommand {
141
141
  ],
142
142
  componentFiles: [],
143
143
  };
144
- await (0, version_control_1.writeMultiPageApplicationToDisk)(multiPageApplication, superblocksRootPath, applicationResource.location, true);
144
+ await (0, version_control_1.writeMultiPageApplicationToDisk)(multiPageApplication, superblocksRootPath, featureFlags, applicationResource.location, true);
145
145
  this.log(`Successfully migrated single page application at ${applicationResource.location} to multi-page application.`);
146
146
  }
147
147
  }
@@ -166,10 +166,10 @@ class Migrate extends authenticated_command_1.AuthenticatedCommand {
166
166
  this.log(`No package.json found in ${applicationResource.location}. Skipping migration of dependencies.`);
167
167
  }
168
168
  }
169
- async migrateApplication(applicationResource, superblocksRootPath) {
169
+ async migrateApplication(applicationResource, superblocksRootPath, featureFlags) {
170
170
  try {
171
171
  await this.migrateCustomComponentVersion(applicationResource, superblocksRootPath);
172
- await this.migrateSinglePageApplicationToMultiPage(applicationResource, superblocksRootPath);
172
+ await this.migrateSinglePageApplicationToMultiPage(applicationResource, superblocksRootPath, featureFlags);
173
173
  }
174
174
  catch (e) {
175
175
  this.error(e.message, {
@@ -21,6 +21,8 @@ class Pull extends authenticated_command_1.AuthenticatedCommand {
21
21
  task: async (ctx) => {
22
22
  ctx.writtenResources = {};
23
23
  ctx.removedResourceIds = [];
24
+ ctx.featureFlags =
25
+ await this.getSdk().getFeatureFlagsForCurrentUser();
24
26
  try {
25
27
  [
26
28
  ctx.existingSuperblocksRootConfig,
@@ -219,7 +221,7 @@ Would you like to also delete these resources from your filesystem?`,
219
221
  return;
220
222
  }
221
223
  ctx.writtenResources[resourceId] =
222
- await (0, version_control_1.writeMultiPageApplicationToDisk)(application, ctx.superblocksRootPath, resource.location, false);
224
+ await (0, version_control_1.writeMultiPageApplicationToDisk)(application, ctx.superblocksRootPath, ctx.featureFlags, resource.location, false);
223
225
  }
224
226
  task.title += `: done`;
225
227
  }
@@ -250,7 +252,7 @@ Would you like to also delete these resources from your filesystem?`,
250
252
  });
251
253
  task.title += `: fetched`;
252
254
  ctx.writtenResources[resourceId] =
253
- await (0, version_control_1.writeResourceToDisk)("BACKEND", resourceId, backend, ctx.superblocksRootPath, resource.location);
255
+ await (0, version_control_1.writeResourceToDisk)("BACKEND", resourceId, backend, ctx.superblocksRootPath, ctx.featureFlags, resource.location);
254
256
  task.title += `: done`;
255
257
  },
256
258
  });
@@ -1,7 +1,6 @@
1
- import { ApiWrapper, ApplicationWrapper, MultiPageApplicationWrapper } from "@superblocksteam/sdk";
2
- import { ViewMode } from "@superblocksteam/sdk/dist/types";
3
- import { LocalGitRepoState, SuperblocksMonorepoConfig } from "@superblocksteam/util";
4
- import { VersionedResourceConfig } from "@superblocksteam/util";
1
+ import { ApiWrapper, ApplicationWrapper, FeatureFlags, MultiPageApplicationWrapper } from "@superblocksteam/sdk";
2
+ import { Api, ViewMode } from "@superblocksteam/sdk/dist/types";
3
+ import { LocalGitRepoState, SuperblocksMonorepoConfig, SuperblocksResourceConfig, VersionedResourceConfig, ApiInfo } from "@superblocksteam/util";
5
4
  export declare const LATEST_EDITS_MODE = "latest-edits";
6
5
  export declare const MOST_RECENT_COMMIT_MODE = "most-recent-commit";
7
6
  export declare const DEPLOYED_MODE = "deployed";
@@ -16,14 +15,21 @@ export type ModeFlag = (keyof typeof modeFlagValuesMap)[number];
16
15
  export declare const SELECT_PROMPT_HELP = "Use \u2191/\u2193 arrow keys, Enter to confirm";
17
16
  export declare const MULTI_SELECT_PROMPT_HELP = "Type to filter, Use \u2191/\u2193 arrow keys, Space to select, Enter to confirm";
18
17
  export declare const atLeastOneSelection: (value: string[]) => string | true;
18
+ export type ApiRepresentation = {
19
+ extractLargeSourceFiles: boolean;
20
+ minLinesForExtraction: number;
21
+ };
22
+ export declare function getApiRepresentation(featureFlags: FeatureFlags, resourceConfig: SuperblocksResourceConfig): ApiRepresentation;
23
+ export declare function readAppApiYamlFile(parentDirectory: string, apiName?: string): Promise<Api>;
19
24
  export declare function getFileStructureType(rootPath: string, existingRelativeLocation: string): Promise<FileStructureType>;
20
25
  export declare function readApplicationFromDisk(rootPath: string, existingRelativeLocation: string): Promise<ApplicationWrapper>;
21
26
  export declare function readMultiPageApplicationFromDisk(rootPath: string, existingRelativeLocation: string): Promise<MultiPageApplicationWrapper>;
22
27
  export declare function readApiFromDisk(rootPath: string, existingRelativeLocation: string): Promise<ApiWrapper>;
23
- export declare function writeResourceToDisk(resourceType: string, resourceId: string, resource: any, rootPath: string, existingRelativeLocation?: string): Promise<VersionedResourceConfig>;
28
+ export declare function writeResourceToDisk(resourceType: string, resourceId: string, resource: any, rootPath: string, featureFlags: FeatureFlags, existingRelativeLocation?: string, preferredApiRepresentation?: ApiRepresentation): Promise<VersionedResourceConfig>;
24
29
  export declare function writeMultiPageApplicationToDisk(resource: MultiPageApplicationWrapper & {
25
30
  componentFiles: any;
26
- }, rootPath: string, existingRelativeLocation?: string, migrateFromSinglePage?: boolean): Promise<VersionedResourceConfig>;
31
+ }, rootPath: string, featureFlags: FeatureFlags, existingRelativeLocation?: string, migrateFromSinglePage?: boolean, preferredApiRepresentation?: ApiRepresentation): Promise<VersionedResourceConfig>;
32
+ export declare function addExistingFilePathsForApi(api: ApiInfo, location: string, paths: Set<string>, useNestedFolder: boolean): Set<string>;
27
33
  export declare function removeResourceFromDisk(rootPath: string, resourceRelativeLocation: string): Promise<void>;
28
34
  export declare function getMode(task: any, mode: ModeFlag): Promise<ViewMode>;
29
35
  export declare function sortByKey(obj: unknown): unknown;
@@ -40,5 +46,6 @@ export declare function getHeadCommit(branch: string): Promise<[string, string]>
40
46
  export declare function isCI(): boolean;
41
47
  export declare function isGitRepoDirty(): Promise<boolean>;
42
48
  export declare function extractApiName(api: ApiWrapper): string;
49
+ export declare function writeAppApi(api: ApiWrapper, directoryPath: string, existingFilePaths: Set<string>, apiPromises: Array<Promise<void>>, apiRepresentation?: ApiRepresentation): Promise<ApiInfo>;
43
50
  export declare function validateLocalResource(superblocksRootPath: string, resource: VersionedResourceConfig): Promise<string | undefined>;
44
51
  export declare function deleteResourcesAndUpdateRootConfig(removedResourceIds: string[], existingSuperblocksRootConfig: SuperblocksMonorepoConfig, superblocksRootPath: string, superblocksRootConfigPath: string): Promise<void>;