@superblocksteam/sdk 2.0.6 → 2.0.7
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/application-build.mjs +6 -2
- package/dist/application-build.mjs.map +1 -1
- package/dist/cli-replacement/automatic-upgrades.d.ts +5 -2
- package/dist/cli-replacement/automatic-upgrades.d.ts.map +1 -1
- package/dist/cli-replacement/automatic-upgrades.js +221 -93
- package/dist/cli-replacement/automatic-upgrades.js.map +1 -1
- package/dist/cli-replacement/dev.d.mts +1 -2
- package/dist/cli-replacement/dev.d.mts.map +1 -1
- package/dist/cli-replacement/dev.mjs +57 -32
- package/dist/cli-replacement/dev.mjs.map +1 -1
- package/dist/client.d.ts +34 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +92 -1
- package/dist/client.js.map +1 -1
- package/dist/dev-utils/dev-logger.d.mts +17 -7
- package/dist/dev-utils/dev-logger.d.mts.map +1 -1
- package/dist/dev-utils/dev-logger.mjs +50 -9
- package/dist/dev-utils/dev-logger.mjs.map +1 -1
- package/dist/dev-utils/dev-server.d.mts.map +1 -1
- package/dist/dev-utils/dev-server.mjs +8 -12
- package/dist/dev-utils/dev-server.mjs.map +1 -1
- package/dist/dev-utils/dev-tracer.d.ts +2 -0
- package/dist/dev-utils/dev-tracer.d.ts.map +1 -1
- package/dist/dev-utils/dev-tracer.js +42 -35
- package/dist/dev-utils/dev-tracer.js.map +1 -1
- package/dist/dev-utils/vite-plugin-build-manifest-stub.d.mts +10 -0
- package/dist/dev-utils/vite-plugin-build-manifest-stub.d.mts.map +1 -0
- package/dist/dev-utils/vite-plugin-build-manifest-stub.mjs +27 -0
- package/dist/dev-utils/vite-plugin-build-manifest-stub.mjs.map +1 -0
- package/dist/dev-utils/vite-plugin-sb-cdn.d.mts.map +1 -1
- package/dist/dev-utils/vite-plugin-sb-cdn.mjs +13 -3
- package/dist/dev-utils/vite-plugin-sb-cdn.mjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/vite-plugin-generate-build-manifest.d.mts +21 -0
- package/dist/vite-plugin-generate-build-manifest.d.mts.map +1 -0
- package/dist/vite-plugin-generate-build-manifest.mjs +130 -0
- package/dist/vite-plugin-generate-build-manifest.mjs.map +1 -0
- package/dist/vite-plugin-inject-sb-ids-transform.mjs +1 -1
- package/dist/vite-plugin-inject-sb-ids-transform.mjs.map +1 -1
- package/package.json +6 -4
- package/src/application-build.mts +6 -3
- package/src/cli-replacement/automatic-upgrades.ts +278 -113
- package/src/cli-replacement/dev.mts +77 -43
- package/src/client.ts +115 -0
- package/src/dev-utils/dev-logger.mts +94 -20
- package/src/dev-utils/dev-server.mts +10 -12
- package/src/dev-utils/dev-tracer.ts +48 -37
- package/src/dev-utils/vite-plugin-build-manifest-stub.mts +30 -0
- package/src/dev-utils/vite-plugin-sb-cdn.mts +14 -3
- package/src/index.ts +4 -0
- package/src/vite-plugin-generate-build-manifest.mts +192 -0
- package/src/vite-plugin-inject-sb-ids-transform.mts +1 -1
- package/test/clients.test.mts +120 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import "../dev-utils/dev-tracer.js";
|
|
2
2
|
|
|
3
3
|
import * as child_process from "node:child_process";
|
|
4
|
-
import * as fsp from "node:fs/promises";
|
|
5
4
|
import path from "node:path";
|
|
6
5
|
import { promisify } from "node:util";
|
|
7
6
|
import { maskUnixSignals } from "@superblocksteam/util";
|
|
@@ -18,15 +17,16 @@ import fs from "fs-extra";
|
|
|
18
17
|
import { resolveCommand } from "package-manager-detector";
|
|
19
18
|
import { detect } from "package-manager-detector/detect";
|
|
20
19
|
|
|
21
|
-
import { getLogger } from "../dev-utils/dev-logger.mjs";
|
|
20
|
+
import { getErrorMeta, getLogger } from "../dev-utils/dev-logger.mjs";
|
|
22
21
|
import { createDevServer } from "../dev-utils/dev-server.mjs";
|
|
23
|
-
import tracer from "../dev-utils/dev-tracer.js";
|
|
22
|
+
import tracer, { initializeTracingSdk } from "../dev-utils/dev-tracer.js";
|
|
24
23
|
import { SuperblocksSdk } from "../sdk.js";
|
|
25
24
|
import {
|
|
26
25
|
checkVersionsAndUpgrade,
|
|
27
26
|
getCurrentCliVersion,
|
|
28
27
|
getCurrentLibraryVersionWithoutPM,
|
|
29
28
|
} from "./automatic-upgrades.js";
|
|
29
|
+
import { AUTO_UPGRADE_EXIT_CODE } from "./automatic-upgrades.js";
|
|
30
30
|
import type { DevLogger } from "../dev-utils/dev-logger.mjs";
|
|
31
31
|
import type { ApplicationConfig } from "../types/common.js";
|
|
32
32
|
import type { DraftInterface } from "@superblocksteam/vite-plugin-file-sync/draft-interface";
|
|
@@ -93,7 +93,6 @@ async function installPackages(cwd: string, logger: DevLogger) {
|
|
|
93
93
|
export async function dev(options: {
|
|
94
94
|
/* cwd is required */
|
|
95
95
|
cwd: string;
|
|
96
|
-
pidfilePath?: string;
|
|
97
96
|
devServerPort?: number;
|
|
98
97
|
|
|
99
98
|
/* user control of sync operations */
|
|
@@ -107,7 +106,7 @@ export async function dev(options: {
|
|
|
107
106
|
/* For debugging purposes to get location of the cli */
|
|
108
107
|
superblocksPath?: string;
|
|
109
108
|
/* For redirecting output, like when running outside of the CLI */
|
|
110
|
-
logger?: (
|
|
109
|
+
logger?: (...messages: (string | Error)[]) => void;
|
|
111
110
|
|
|
112
111
|
/* For a child process when restarting the dev server for automatic upgrades */
|
|
113
112
|
skipAutoUpgrade?: boolean;
|
|
@@ -119,7 +118,6 @@ export async function dev(options: {
|
|
|
119
118
|
|
|
120
119
|
const {
|
|
121
120
|
cwd,
|
|
122
|
-
pidfilePath,
|
|
123
121
|
devServerPort,
|
|
124
122
|
downloadFirst,
|
|
125
123
|
uploadFirst,
|
|
@@ -127,12 +125,7 @@ export async function dev(options: {
|
|
|
127
125
|
applicationConfig,
|
|
128
126
|
skipAutoUpgrade,
|
|
129
127
|
} = options;
|
|
130
|
-
|
|
131
|
-
const cliVersion = await getCurrentCliVersion();
|
|
132
|
-
const libraryVersion = await getCurrentLibraryVersionWithoutPM();
|
|
133
|
-
logger.info(
|
|
134
|
-
`Running command: ${options.superblocksPath} dev${options.uploadFirst ? " --upload-first" : ""}${options.downloadFirst ? " --download-first" : ""} with baseUrl: ${applicationConfig?.superblocksBaseUrl}, cliVersion: ${cliVersion}, libraryVersion: ${libraryVersion?.alias} ${libraryVersion?.version}`,
|
|
135
|
-
);
|
|
128
|
+
initializeTracingSdk(applicationConfig);
|
|
136
129
|
|
|
137
130
|
// Add check for node_modules
|
|
138
131
|
if (!fs.existsSync(path.join(cwd, "node_modules"))) {
|
|
@@ -141,9 +134,13 @@ export async function dev(options: {
|
|
|
141
134
|
);
|
|
142
135
|
}
|
|
143
136
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
137
|
+
logger.info("Starting dev server");
|
|
138
|
+
|
|
139
|
+
const cliVersion = await getCurrentCliVersion();
|
|
140
|
+
const libraryVersion = await getCurrentLibraryVersionWithoutPM();
|
|
141
|
+
logger.info(
|
|
142
|
+
`Running command: ${options.superblocksPath} dev${options.uploadFirst ? " --upload-first" : ""}${options.downloadFirst ? " --download-first" : ""} with baseUrl: ${applicationConfig?.superblocksBaseUrl}, cliVersion: ${cliVersion?.alias} ${cliVersion?.version}, libraryVersion: ${libraryVersion?.alias} ${libraryVersion?.version}`,
|
|
143
|
+
);
|
|
147
144
|
|
|
148
145
|
const port = devServerPort ?? 5173;
|
|
149
146
|
|
|
@@ -188,17 +185,11 @@ export async function dev(options: {
|
|
|
188
185
|
if (lockService) {
|
|
189
186
|
try {
|
|
190
187
|
await lockService!.acquireLock();
|
|
191
|
-
|
|
192
|
-
// TODO(code-mode): package naming is preventing upgrade in ephemeral environments
|
|
193
|
-
if (
|
|
194
|
-
!process.env.PACKAGE_SUFFIX ||
|
|
195
|
-
process.env.PACKAGE_SUFFIX === "" ||
|
|
196
|
-
!skipAutoUpgrade
|
|
197
|
-
) {
|
|
198
|
-
await checkVersionsAndUpgrade(lockService, applicationConfig);
|
|
199
|
-
}
|
|
200
188
|
} catch (error) {
|
|
201
|
-
logger.error(
|
|
189
|
+
logger.error(
|
|
190
|
+
"Failed to acquire lock on application",
|
|
191
|
+
getErrorMeta(error),
|
|
192
|
+
);
|
|
202
193
|
passErrorToVSCode(
|
|
203
194
|
(error as { context?: { message: string } }).context?.message,
|
|
204
195
|
logger,
|
|
@@ -222,7 +213,6 @@ export async function dev(options: {
|
|
|
222
213
|
appRootDirPath: options.cwd,
|
|
223
214
|
applicationId: applicationConfig.id,
|
|
224
215
|
organizationId: currentUser.organizations[0].id,
|
|
225
|
-
anthropicApiKey: process.env.ANTHROPIC_API_KEY || "",
|
|
226
216
|
fsOperationQueue,
|
|
227
217
|
draftInterface: syncService! as DraftInterface,
|
|
228
218
|
tracer,
|
|
@@ -231,12 +221,15 @@ export async function dev(options: {
|
|
|
231
221
|
const isSynced = localContents.hash === serverHash;
|
|
232
222
|
|
|
233
223
|
if (isSynced) {
|
|
234
|
-
logger.info(
|
|
235
|
-
|
|
224
|
+
logger.info(
|
|
225
|
+
`Local files are in sync with the server on branch '${applicationConfig.branchName}'`,
|
|
226
|
+
);
|
|
227
|
+
} else {
|
|
228
|
+
logger.info(
|
|
229
|
+
`Local files are out of sync with the server on branch '${applicationConfig.branchName}'`,
|
|
230
|
+
);
|
|
236
231
|
}
|
|
237
232
|
|
|
238
|
-
logger.info("Local files are out of sync with the server");
|
|
239
|
-
|
|
240
233
|
if (!(downloadFirst || uploadFirst)) {
|
|
241
234
|
throw new Error(
|
|
242
235
|
"You must choose --download-first or --upload-first to use the dev command",
|
|
@@ -246,37 +239,74 @@ export async function dev(options: {
|
|
|
246
239
|
throw new Error("Choose either --download-first or --upload-first");
|
|
247
240
|
}
|
|
248
241
|
|
|
242
|
+
let hasPackageChanged = false;
|
|
243
|
+
|
|
249
244
|
if (downloadFirst) {
|
|
250
245
|
logger.info(
|
|
251
|
-
|
|
246
|
+
`Starting download of branch '${applicationConfig.branchName}'`,
|
|
252
247
|
);
|
|
253
248
|
|
|
254
|
-
// Read package.json before download
|
|
255
249
|
const packageJsonBefore = await readPkgJson(cwd);
|
|
256
|
-
|
|
257
250
|
await syncService!.downloadDirectory();
|
|
258
|
-
|
|
259
|
-
// Read package.json after download and compare
|
|
260
251
|
const packageJsonAfter = await readPkgJson(cwd);
|
|
261
252
|
|
|
262
|
-
// Check if package.json changed
|
|
263
253
|
if (packageJsonBefore && packageJsonAfter) {
|
|
264
254
|
const diff = diffJson(packageJsonBefore, packageJsonAfter);
|
|
265
|
-
|
|
255
|
+
hasPackageChanged = diff.some((part) => part.added || part.removed);
|
|
256
|
+
} else if (packageJsonAfter) {
|
|
257
|
+
hasPackageChanged = true;
|
|
258
|
+
logger.info("package.json was created, installing packages…");
|
|
259
|
+
}
|
|
260
|
+
}
|
|
266
261
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
262
|
+
let hasCliUpdated = false;
|
|
263
|
+
if (
|
|
264
|
+
!process.env.PACKAGE_SUFFIX ||
|
|
265
|
+
process.env.PACKAGE_SUFFIX === "" ||
|
|
266
|
+
!skipAutoUpgrade
|
|
267
|
+
) {
|
|
268
|
+
if (lockService) {
|
|
269
|
+
const result = await checkVersionsAndUpgrade(
|
|
270
|
+
lockService,
|
|
271
|
+
applicationConfig,
|
|
272
|
+
);
|
|
273
|
+
if (result?.libraryUpdated) {
|
|
274
|
+
hasPackageChanged = true;
|
|
270
275
|
}
|
|
276
|
+
hasCliUpdated = result?.cliUpdated ?? false;
|
|
277
|
+
} else {
|
|
278
|
+
logger.warn(
|
|
279
|
+
"Lock service is not available, skipping version check and upgrade",
|
|
280
|
+
);
|
|
271
281
|
}
|
|
272
|
-
}
|
|
273
|
-
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (hasPackageChanged) {
|
|
285
|
+
logger.info("Installing packages…");
|
|
286
|
+
await installPackages(cwd, logger);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (hasPackageChanged || uploadFirst) {
|
|
290
|
+
logger.info(
|
|
291
|
+
`Uploading local files to branch '${applicationConfig.branchName}' on server before starting`,
|
|
292
|
+
);
|
|
274
293
|
await syncService!.uploadDirectory();
|
|
294
|
+
await syncService!.uploadDirectoryNowIfNeeded();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (hasCliUpdated) {
|
|
298
|
+
logger.info("CLI was updated, restarting the dev server…");
|
|
299
|
+
process.exit(AUTO_UPGRADE_EXIT_CODE);
|
|
275
300
|
}
|
|
276
301
|
});
|
|
277
302
|
} catch (error: any) {
|
|
278
303
|
logger.error(error.message);
|
|
279
|
-
|
|
304
|
+
try {
|
|
305
|
+
await lockService?.shutdownAndExit();
|
|
306
|
+
} finally {
|
|
307
|
+
// this is redundant, but it's here to make sure the lock service is shutdown and the process exits
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
280
310
|
}
|
|
281
311
|
} else {
|
|
282
312
|
logger.info("Skipping directory sync");
|
|
@@ -296,6 +326,10 @@ export async function dev(options: {
|
|
|
296
326
|
options.signal?.addEventListener("abort", () => {
|
|
297
327
|
logger.info("Server closed");
|
|
298
328
|
httpServer.close();
|
|
329
|
+
lockService?.shutdownAndExit().catch(() => {
|
|
330
|
+
// this is redundant, but it's here to make sure the lock service is shutdown and the process exits
|
|
331
|
+
process.exit(1);
|
|
332
|
+
});
|
|
299
333
|
});
|
|
300
334
|
|
|
301
335
|
logger.debug(green(`Local server started at port ${port}`));
|
package/src/client.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
NotFoundError,
|
|
12
12
|
BadRequestError,
|
|
13
13
|
unreachable,
|
|
14
|
+
getSuperblocksDevEnvironmentConfigJson,
|
|
14
15
|
} from "@superblocksteam/util";
|
|
15
16
|
import axios, { AxiosError } from "axios";
|
|
16
17
|
import FormData from "form-data";
|
|
@@ -24,6 +25,10 @@ import { signingEnabled } from "./flag.js";
|
|
|
24
25
|
import { connectToISocketRPCServer } from "./socket/index.js";
|
|
25
26
|
import { AgentType } from "./types/index.js";
|
|
26
27
|
import { getAgentUrl } from "./utils.js";
|
|
28
|
+
import {
|
|
29
|
+
DEFAULT_BRANCH,
|
|
30
|
+
getCurrentGitBranchIfGit,
|
|
31
|
+
} from "./version-control.mjs";
|
|
27
32
|
import type { StdISocketRPCClient } from "./socket/index.js";
|
|
28
33
|
import type {
|
|
29
34
|
ApiWithPb,
|
|
@@ -133,6 +138,116 @@ enum ResourceType {
|
|
|
133
138
|
BACKEND = "BACKEND",
|
|
134
139
|
}
|
|
135
140
|
|
|
141
|
+
export enum BranchSource {
|
|
142
|
+
DEV_ENVIRONMENT = "dev environment config file",
|
|
143
|
+
COMMAND_LINE = "command line",
|
|
144
|
+
GIT_REPO = "current git repository",
|
|
145
|
+
DEFAULT = "default",
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export class CurrentBranch {
|
|
149
|
+
public readonly branchName: string;
|
|
150
|
+
public readonly source: BranchSource;
|
|
151
|
+
public readonly sourcePath?: string;
|
|
152
|
+
public readonly userSpecifiedBranch?: string;
|
|
153
|
+
|
|
154
|
+
constructor({
|
|
155
|
+
branchName,
|
|
156
|
+
source,
|
|
157
|
+
sourcePath,
|
|
158
|
+
userSpecifiedBranch,
|
|
159
|
+
}: {
|
|
160
|
+
branchName: string;
|
|
161
|
+
source: BranchSource;
|
|
162
|
+
sourcePath?: string;
|
|
163
|
+
userSpecifiedBranch?: string;
|
|
164
|
+
}) {
|
|
165
|
+
this.branchName = branchName;
|
|
166
|
+
this.source = source;
|
|
167
|
+
this.sourcePath = sourcePath;
|
|
168
|
+
this.userSpecifiedBranch = userSpecifiedBranch;
|
|
169
|
+
}
|
|
170
|
+
isDevEnvironmentWithUserSpecifiedBranch() {
|
|
171
|
+
return (
|
|
172
|
+
this.isDefinedInDevEnvironmentConfig() &&
|
|
173
|
+
this.userSpecifiedBranch !== undefined
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
isDefinedInDevEnvironmentConfig(): boolean {
|
|
177
|
+
return this.source === BranchSource.DEV_ENVIRONMENT;
|
|
178
|
+
}
|
|
179
|
+
isDefaultBranch(): boolean {
|
|
180
|
+
return this.source === BranchSource.DEFAULT;
|
|
181
|
+
}
|
|
182
|
+
isGitBranch(): boolean {
|
|
183
|
+
return this.source === BranchSource.GIT_REPO;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const DEFAULT_BRANCH_INFO = new CurrentBranch({
|
|
188
|
+
branchName: DEFAULT_BRANCH,
|
|
189
|
+
source: BranchSource.DEFAULT,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// TODO (randall): Remove this and the 'index.ts' export when it is no longer needed in the CLI.
|
|
193
|
+
export function getDefaultBranchInfo(): CurrentBranch {
|
|
194
|
+
return DEFAULT_BRANCH_INFO;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Returns the current branch name, in the following order of precedence:
|
|
199
|
+
* 1. If a branch name is specified in the dev environment config, use that
|
|
200
|
+
* 2. If a branch name is specified, use that
|
|
201
|
+
* 3. If this is in a git repo, use the current branch
|
|
202
|
+
* 4. If this is not in a git repo, use the default branch
|
|
203
|
+
* @param userSpecifiedBranch - The branch name specified by the user
|
|
204
|
+
* @param pathPrefix - The path prefix to use when looking for the dev environment config
|
|
205
|
+
* @returns The current branch information
|
|
206
|
+
*/
|
|
207
|
+
export async function getCurrentBranchInfo(
|
|
208
|
+
userSpecifiedBranch?: string,
|
|
209
|
+
pathPrefix?: string,
|
|
210
|
+
): Promise<CurrentBranch> {
|
|
211
|
+
// First, if there is a dev environment config and a branch name is specified, use that
|
|
212
|
+
try {
|
|
213
|
+
const [devEnvironmentConfig, devEnvConfigPath] =
|
|
214
|
+
await getSuperblocksDevEnvironmentConfigJson(true, pathPrefix);
|
|
215
|
+
if (devEnvironmentConfig.branch) {
|
|
216
|
+
return new CurrentBranch({
|
|
217
|
+
branchName: devEnvironmentConfig.branch,
|
|
218
|
+
source: BranchSource.DEV_ENVIRONMENT,
|
|
219
|
+
sourcePath: devEnvConfigPath,
|
|
220
|
+
userSpecifiedBranch: userSpecifiedBranch,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
} catch {
|
|
224
|
+
// Did not find or could not parse the dev environment config, so continue
|
|
225
|
+
}
|
|
226
|
+
// Second, if the user specified a branch name, use that
|
|
227
|
+
if (userSpecifiedBranch) {
|
|
228
|
+
return new CurrentBranch({
|
|
229
|
+
branchName: userSpecifiedBranch,
|
|
230
|
+
source: BranchSource.COMMAND_LINE,
|
|
231
|
+
userSpecifiedBranch: userSpecifiedBranch,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
// Third, if this is in a git repo, use the current branch
|
|
235
|
+
const currentGitBranch = await getCurrentGitBranchIfGit();
|
|
236
|
+
if (currentGitBranch) {
|
|
237
|
+
return new CurrentBranch({
|
|
238
|
+
branchName: currentGitBranch,
|
|
239
|
+
source: BranchSource.GIT_REPO,
|
|
240
|
+
userSpecifiedBranch: userSpecifiedBranch,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
// Fourth, if this is not in a git repo, use the default branch
|
|
244
|
+
return new CurrentBranch({
|
|
245
|
+
branchName: DEFAULT_BRANCH,
|
|
246
|
+
source: BranchSource.DEFAULT,
|
|
247
|
+
userSpecifiedBranch: userSpecifiedBranch,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
136
251
|
export async function fetchApplication({
|
|
137
252
|
cliVersion,
|
|
138
253
|
applicationId,
|
|
@@ -1,39 +1,113 @@
|
|
|
1
1
|
import { createLogger, format, transports } from "winston";
|
|
2
|
+
import type winston from "winston";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
const activeTransports: winston.transport[] = [];
|
|
5
|
+
|
|
6
|
+
if (process.env.SUPERBLOCKS_IS_CSB === "true") {
|
|
7
|
+
activeTransports.push(
|
|
8
|
+
new transports.File({
|
|
9
|
+
format: format.json(),
|
|
10
|
+
filename: `/tmp/dev-server.log`,
|
|
11
|
+
level: "info",
|
|
12
|
+
}),
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
activeTransports.push(
|
|
17
|
+
new transports.Console({
|
|
18
|
+
format: format.combine(
|
|
19
|
+
format.colorize(),
|
|
20
|
+
format.timestamp({
|
|
21
|
+
format: "HH:mm:ss.SSS",
|
|
22
|
+
}),
|
|
23
|
+
format.printf((props) => {
|
|
24
|
+
const { message, timestamp, error, level } = props;
|
|
25
|
+
const base =
|
|
26
|
+
process.env.SUPERBLOCKS_IS_CSB === "true"
|
|
27
|
+
? `${timestamp} ${message}`
|
|
28
|
+
: `${message}`;
|
|
29
|
+
if (level === "error") {
|
|
30
|
+
return `${base} ${(error as ErrorMeta["error"]).message} ${(error as ErrorMeta["error"]).stack}`;
|
|
31
|
+
}
|
|
32
|
+
return base;
|
|
33
|
+
}),
|
|
34
|
+
),
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
9
37
|
|
|
10
38
|
const winstonLogger = createLogger({
|
|
11
|
-
level: "
|
|
39
|
+
level: "debug",
|
|
12
40
|
exitOnError: false,
|
|
13
41
|
format: format.json(),
|
|
14
|
-
transports:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
42
|
+
transports: activeTransports,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
interface ErrorMeta {
|
|
46
|
+
error: {
|
|
47
|
+
kind: string;
|
|
48
|
+
message: string;
|
|
49
|
+
stack?: string;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface DevLogger {
|
|
54
|
+
log: (...messages: string[]) => void;
|
|
55
|
+
debug: (...messages: string[]) => void;
|
|
56
|
+
info: (...messages: string[]) => void;
|
|
57
|
+
warn: (...messages: string[]) => void;
|
|
58
|
+
error: (message: string, meta?: ErrorMeta) => void;
|
|
59
|
+
}
|
|
60
|
+
const logger: DevLogger = Object.freeze({
|
|
61
|
+
debug: (...messages: string[]) =>
|
|
62
|
+
winstonLogger.debug(
|
|
63
|
+
messages.length > 0 ? messages.join(" ") : (messages[0] as string),
|
|
64
|
+
),
|
|
65
|
+
log: (...messages: string[]) =>
|
|
66
|
+
winstonLogger.info(
|
|
67
|
+
messages.length > 0 ? messages.join(" ") : (messages[0] as string),
|
|
68
|
+
),
|
|
69
|
+
info: (...messages: string[]) =>
|
|
70
|
+
winstonLogger.info(
|
|
71
|
+
messages.length > 0 ? messages.join(" ") : (messages[0] as string),
|
|
72
|
+
),
|
|
73
|
+
warn: (...messages: string[]) =>
|
|
74
|
+
winstonLogger.warn(
|
|
75
|
+
messages.length > 0 ? messages.join(" ") : (messages[0] as string),
|
|
76
|
+
),
|
|
77
|
+
error: (message: string, meta?: ErrorMeta) =>
|
|
78
|
+
winstonLogger.error(message, meta),
|
|
24
79
|
});
|
|
25
80
|
|
|
26
81
|
export function getLogger(
|
|
27
|
-
loggerOverride?: (
|
|
82
|
+
loggerOverride?: (...messages: string[]) => void,
|
|
28
83
|
): DevLogger {
|
|
29
84
|
if (!loggerOverride) {
|
|
30
|
-
return
|
|
85
|
+
return logger;
|
|
31
86
|
}
|
|
32
87
|
|
|
33
88
|
return {
|
|
34
89
|
debug: loggerOverride,
|
|
35
90
|
info: loggerOverride,
|
|
36
91
|
warn: loggerOverride,
|
|
37
|
-
|
|
92
|
+
log: loggerOverride,
|
|
93
|
+
error: loggerOverride as any,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function getErrorMeta(error: unknown): ErrorMeta {
|
|
98
|
+
if (error instanceof Error) {
|
|
99
|
+
return {
|
|
100
|
+
error: {
|
|
101
|
+
kind: error.name,
|
|
102
|
+
message: error.message,
|
|
103
|
+
stack: error.stack,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
error: {
|
|
109
|
+
kind: "Unknown Error",
|
|
110
|
+
message: JSON.stringify(error),
|
|
111
|
+
},
|
|
38
112
|
};
|
|
39
113
|
}
|
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
customComponentsPlugin,
|
|
19
19
|
isCustomComponentsEnabled,
|
|
20
20
|
} from "./custom-build.mjs";
|
|
21
|
-
import { getLogger } from "./dev-logger.mjs";
|
|
21
|
+
import { getErrorMeta, getLogger } from "./dev-logger.mjs";
|
|
22
|
+
import { buildManifestStubPlugin } from "./vite-plugin-build-manifest-stub.mjs";
|
|
22
23
|
import { ddRumPlugin } from "./vite-plugin-dd-rum.mjs";
|
|
23
24
|
import { superblocksCdnPlugin } from "./vite-plugin-sb-cdn.mjs";
|
|
24
25
|
import type { AiService } from "@superblocksteam/vite-plugin-file-sync/ai-service";
|
|
@@ -187,13 +188,6 @@ export async function createDevServer({
|
|
|
187
188
|
}, viteReject);
|
|
188
189
|
});
|
|
189
190
|
|
|
190
|
-
// TODO(code-mode): remove this soon
|
|
191
|
-
app.get("/_sb_disconnect", async (_req, res) => {
|
|
192
|
-
console.log("GET /_sb_disconnect");
|
|
193
|
-
// TODO(code-mode): should this include any validation checks, such as getting a token?
|
|
194
|
-
await gracefulShutdown({ logger, serverInitiated: false });
|
|
195
|
-
res.send("ok");
|
|
196
|
-
});
|
|
197
191
|
app.post("/_sb_disconnect", async (req, res) => {
|
|
198
192
|
const { initiatedByEmail, switchingTo } = req.body;
|
|
199
193
|
// TODO(code-mode): should this include any validation checks, such as getting a token?
|
|
@@ -206,7 +200,7 @@ export async function createDevServer({
|
|
|
206
200
|
});
|
|
207
201
|
res.send("ok");
|
|
208
202
|
} catch (e) {
|
|
209
|
-
|
|
203
|
+
logger.error("Error disconnecting from dev server", getErrorMeta(e));
|
|
210
204
|
res.status(500).send("Error disconnecting from dev server");
|
|
211
205
|
}
|
|
212
206
|
});
|
|
@@ -260,7 +254,7 @@ async function startVite({
|
|
|
260
254
|
}) {
|
|
261
255
|
const viteLogger = createLogger();
|
|
262
256
|
const logger = getLogger(loggerOverride);
|
|
263
|
-
viteLogger.info = logger.info;
|
|
257
|
+
viteLogger.info = (msg: string) => logger.info(msg);
|
|
264
258
|
viteLogger.warn = (msg: string) => {
|
|
265
259
|
logger.warn(yellow(msg));
|
|
266
260
|
};
|
|
@@ -276,6 +270,8 @@ async function startVite({
|
|
|
276
270
|
const isCustomBuildEnabled = await isCustomComponentsEnabled();
|
|
277
271
|
const customFolder = path.join(root, "custom");
|
|
278
272
|
|
|
273
|
+
const draftsFolder = path.join(root, ".superblocks");
|
|
274
|
+
|
|
279
275
|
const cdnUrl = process.env.SUPERBLOCKS_CDN_URL ?? "http://localhost:4040/cdn";
|
|
280
276
|
|
|
281
277
|
const env = loadEnv(mode, root, "");
|
|
@@ -313,7 +309,7 @@ async function startVite({
|
|
|
313
309
|
server: {
|
|
314
310
|
middlewareMode: true,
|
|
315
311
|
watch: {
|
|
316
|
-
ignored: [`${customFolder}/**/*`],
|
|
312
|
+
ignored: [`${customFolder}/**/*`, `${draftsFolder}/**/*`],
|
|
317
313
|
},
|
|
318
314
|
hmr: hmrOptions,
|
|
319
315
|
cors: {
|
|
@@ -342,11 +338,13 @@ async function startVite({
|
|
|
342
338
|
aiService,
|
|
343
339
|
httpServer,
|
|
344
340
|
tracer,
|
|
345
|
-
logger,
|
|
346
341
|
},
|
|
347
342
|
{ isCustomBuildEnabled },
|
|
348
343
|
) as Plugin,
|
|
349
344
|
|
|
345
|
+
// Add a virtual "stub" module for the build manifest
|
|
346
|
+
buildManifestStubPlugin(),
|
|
347
|
+
|
|
350
348
|
// for now, only use the CDN locally
|
|
351
349
|
superblocksCdnPlugin({
|
|
352
350
|
imports: {
|
|
@@ -6,8 +6,13 @@ import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
|
|
|
6
6
|
import { Resource } from "@opentelemetry/resources";
|
|
7
7
|
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
8
8
|
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
9
|
+
import {
|
|
10
|
+
OBS_TAG_APPLICATION_ID,
|
|
11
|
+
OBS_TAG_BRANCH,
|
|
12
|
+
} from "@superblocksteam/shared";
|
|
9
13
|
import { getLocalTokenWithUrl } from "@superblocksteam/util";
|
|
10
14
|
import packageJson from "../../package.json" with { type: "json" };
|
|
15
|
+
import type { ApplicationConfig } from "../types/index.js";
|
|
11
16
|
import type { Span } from "@opentelemetry/api";
|
|
12
17
|
|
|
13
18
|
// NOTE: @joeyagreco - this is how the "env" facet is determined in datadog: https://docs.datadoghq.com/opentelemetry/setup/collector_exporter/#3---configure-your-application
|
|
@@ -15,6 +20,7 @@ const ATTR_DEPLOYMENT_ENVIRONMENT = "deployment.environment";
|
|
|
15
20
|
// NOTE: @joeyagreco - this can be used to determine if we are using mock-csb, staging-csb, prod-csb, etc
|
|
16
21
|
const ATTR_SUPERBLOCKS_BASE_URL = "superblocks.base_url";
|
|
17
22
|
const ATTR_SUPERBLOCKS_CLI_TOKEN = "superblocks.cli_token";
|
|
23
|
+
const ATTR_SUPERBLOCKS_IS_CSB = "superblocks.is_csb";
|
|
18
24
|
let superblocksTracesUrl = undefined;
|
|
19
25
|
let superblocksHostname = "unknown";
|
|
20
26
|
let token = "unknown";
|
|
@@ -30,45 +36,50 @@ try {
|
|
|
30
36
|
console.error("[tracing init] could not determine superblocks base url", e);
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
export const initializeTracingSdk = (applicationConfig?: ApplicationConfig) => {
|
|
40
|
+
// Initialize the OpenTelemetry SDK
|
|
41
|
+
const sdk = new NodeSDK({
|
|
42
|
+
resource: Resource.default().merge(
|
|
43
|
+
new Resource({
|
|
44
|
+
[ATTR_SERVICE_NAME]: "sdk-dev-server",
|
|
45
|
+
[ATTR_DEPLOYMENT_ENVIRONMENT]: process.env.SUPERBLOCKS_CLI_ENV,
|
|
46
|
+
[ATTR_SUPERBLOCKS_BASE_URL]: superblocksHostname,
|
|
47
|
+
[ATTR_SUPERBLOCKS_CLI_TOKEN]: token,
|
|
48
|
+
[OBS_TAG_APPLICATION_ID]: applicationConfig?.id,
|
|
49
|
+
[OBS_TAG_BRANCH]: applicationConfig?.branchName,
|
|
50
|
+
[ATTR_SUPERBLOCKS_IS_CSB]: process.env.SUPERBLOCKS_IS_CSB,
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
53
|
+
traceExporter: new OTLPTraceExporter({
|
|
54
|
+
url: superblocksTracesUrl, // OTLPTraceExporter defaults to sending traffic to http://localhost:4318/v1/traces
|
|
41
55
|
}),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
},
|
|
67
|
-
}),
|
|
68
|
-
],
|
|
69
|
-
});
|
|
56
|
+
contextManager: new AsyncLocalStorageContextManager(),
|
|
57
|
+
instrumentations: [
|
|
58
|
+
// Configure HTTP instrumentation with custom attributes
|
|
59
|
+
new HttpInstrumentation({
|
|
60
|
+
requestHook: (span: Span, request: any) => {
|
|
61
|
+
let resource = "GET";
|
|
62
|
+
if (request) {
|
|
63
|
+
resource = `${request.method} ${request.url || request.path}`;
|
|
64
|
+
}
|
|
65
|
+
span.setAttributes({
|
|
66
|
+
"resource.name": resource,
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
// Configure Express instrumentation
|
|
71
|
+
new ExpressInstrumentation({
|
|
72
|
+
requestHook: (span: Span, request: any) => {
|
|
73
|
+
span.setAttributes({
|
|
74
|
+
"resource.name": `${request.method} ${request.url}`,
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
],
|
|
79
|
+
});
|
|
70
80
|
|
|
71
|
-
sdk.start();
|
|
81
|
+
sdk.start();
|
|
82
|
+
};
|
|
72
83
|
|
|
73
84
|
// Get a tracer instance
|
|
74
85
|
const tracer = trace.getTracer("sdk-dev-server", packageJson.version);
|