@cedarjs/cli 8.0.0-canary.3600 → 8.0.0-canary.3601

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,5 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { context } from "@opentelemetry/api";
4
- import { suppressTracing } from "@opentelemetry/core";
5
3
  import { Listr } from "listr2";
6
4
  import { Parser } from "yargs/helpers";
7
5
  import { colors as c } from "@cedarjs/cli-helpers/colors";
@@ -103,9 +101,7 @@ No script called \`${name}\` in the ./scripts folder.
103
101
  renderer: args.silent ? "silent" : "verbose"
104
102
  });
105
103
  try {
106
- await context.with(suppressTracing(context.active()), async () => {
107
- await tasks.run();
108
- });
104
+ await tasks.run();
109
105
  } catch {
110
106
  process.exit(1);
111
107
  }
package/dist/index.js CHANGED
@@ -1,14 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from "node:fs";
3
3
  import path from "path";
4
- import { trace, SpanStatusCode } from "@opentelemetry/api";
5
4
  import { hideBin, Parser } from "yargs/helpers";
6
5
  import yargs from "yargs/yargs";
7
6
  import { colors as c } from "@cedarjs/cli-helpers/colors";
8
7
  import { loadEnvFiles } from "@cedarjs/cli-helpers/loadEnvFiles";
9
8
  import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
10
9
  import { findUp, getConfigPath } from "@cedarjs/project-config";
11
- import { telemetryMiddleware } from "@cedarjs/telemetry";
10
+ import {
11
+ startTelemetry,
12
+ shutdownTelemetry,
13
+ telemetryMiddleware
14
+ } from "@cedarjs/telemetry/cli";
12
15
  import * as buildCommand from "./commands/build.js";
13
16
  import * as checkCommand from "./commands/check.js";
14
17
  import * as consoleCommand from "./commands/console.js";
@@ -33,7 +36,6 @@ import * as upgradeCommand from "./commands/upgrade/upgrade.js";
33
36
  import { exitWithError } from "./lib/exit.js";
34
37
  import * as updateCheck from "./lib/updateCheck.js";
35
38
  import { loadPlugins } from "./plugin.js";
36
- import { startTelemetry, shutdownTelemetry } from "./telemetry/index.js";
37
39
  const {
38
40
  telemetry,
39
41
  help,
@@ -72,31 +74,26 @@ if (process.cwd() !== cwd) {
72
74
  }
73
75
  loadEnvFiles();
74
76
  async function main() {
77
+ const pkgJson = await import("../package.json", { with: { type: "json" } });
75
78
  if (telemetry) {
76
- startTelemetry();
79
+ startTelemetry({ cedarVersion: pkgJson.default["version"] });
77
80
  }
78
- const tracer = trace.getTracer("redwoodjs");
79
- await tracer.startActiveSpan("cli", async (span) => {
80
- const telemetryTimeoutTimer = setTimeout(() => {
81
- shutdownTelemetry();
82
- }, 5 * 6e4);
83
- if (version) {
84
- recordTelemetryAttributes({ command: "--version" });
85
- }
86
- if (help) {
87
- recordTelemetryAttributes({ command: "--help" });
88
- }
89
- try {
90
- await runYargs();
91
- } catch (error) {
92
- exitWithError(error);
93
- }
94
- if (span?.isRecording()) {
95
- span?.setStatus({ code: SpanStatusCode.OK });
96
- span?.end();
97
- }
98
- clearTimeout(telemetryTimeoutTimer);
99
- });
81
+ const telemetryTimeoutTimer = setTimeout(() => {
82
+ shutdownTelemetry();
83
+ }, 5 * 6e4);
84
+ telemetryTimeoutTimer.unref();
85
+ if (version) {
86
+ recordTelemetryAttributes({ command: "--version" });
87
+ }
88
+ if (help) {
89
+ recordTelemetryAttributes({ command: "--help" });
90
+ }
91
+ try {
92
+ await runYargs();
93
+ } catch (error) {
94
+ exitWithError(error);
95
+ }
96
+ clearTimeout(telemetryTimeoutTimer);
100
97
  if (telemetry) {
101
98
  shutdownTelemetry();
102
99
  }
@@ -125,7 +122,7 @@ async function runYargs() {
125
122
  "yarn cedar exec migrateUsers --load-env-files stripe nakama",
126
123
  "Run a script, also loading env vars from '.env.stripe' and '.env.nakama'"
127
124
  ).option("telemetry", {
128
- describe: "Whether to send anonymous usage telemetry to RedwoodJS",
125
+ describe: "Whether to send anonymous usage telemetry to CedarJS",
129
126
  boolean: true
130
127
  // hidden: true,
131
128
  }).example(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/cli",
3
- "version": "8.0.0-canary.3600",
3
+ "version": "8.0.0-canary.3601",
4
4
  "description": "The CedarJS Command Line",
5
5
  "repository": {
6
6
  "type": "git",
@@ -36,24 +36,18 @@
36
36
  "@babel/preset-typescript": "7.29.7",
37
37
  "@babel/traverse": "7.29.12",
38
38
  "@babel/types": "7.29.11",
39
- "@cedarjs/api-server": "8.0.0-canary.3600",
40
- "@cedarjs/babel-config": "8.0.0-canary.3600",
41
- "@cedarjs/cli-helpers": "8.0.0-canary.3600",
42
- "@cedarjs/internal": "8.0.0-canary.3600",
43
- "@cedarjs/prerender": "8.0.0-canary.3600",
44
- "@cedarjs/project-config": "8.0.0-canary.3600",
45
- "@cedarjs/structure": "8.0.0-canary.3600",
46
- "@cedarjs/telemetry": "8.0.0-canary.3600",
47
- "@cedarjs/utils": "8.0.0-canary.3600",
48
- "@cedarjs/vite": "8.0.0-canary.3600",
49
- "@cedarjs/web-server": "8.0.0-canary.3600",
39
+ "@cedarjs/api-server": "8.0.0-canary.3601",
40
+ "@cedarjs/babel-config": "8.0.0-canary.3601",
41
+ "@cedarjs/cli-helpers": "8.0.0-canary.3601",
42
+ "@cedarjs/internal": "8.0.0-canary.3601",
43
+ "@cedarjs/prerender": "8.0.0-canary.3601",
44
+ "@cedarjs/project-config": "8.0.0-canary.3601",
45
+ "@cedarjs/structure": "8.0.0-canary.3601",
46
+ "@cedarjs/telemetry": "8.0.0-canary.3601",
47
+ "@cedarjs/utils": "8.0.0-canary.3601",
48
+ "@cedarjs/vite": "8.0.0-canary.3601",
49
+ "@cedarjs/web-server": "8.0.0-canary.3601",
50
50
  "@listr2/prompt-adapter-enquirer": "4.4.3",
51
- "@opentelemetry/api": "1.9.1",
52
- "@opentelemetry/core": "2.12.0",
53
- "@opentelemetry/exporter-trace-otlp-http": "0.223.0",
54
- "@opentelemetry/resources": "2.12.0",
55
- "@opentelemetry/sdk-trace-node": "2.12.0",
56
- "@opentelemetry/semantic-conventions": "1.43.0",
57
51
  "@prisma/internals": "7.10.1",
58
52
  "ansis": "4.4.0",
59
53
  "archiver": "7.0.1",
@@ -93,7 +87,7 @@
93
87
  "yargs": "18.2.0"
94
88
  },
95
89
  "devDependencies": {
96
- "@cedarjs/framework-tools": "8.0.0-canary.3600",
90
+ "@cedarjs/framework-tools": "8.0.0-canary.3601",
97
91
  "@prisma/dmmf": "7.10.1",
98
92
  "@types/archiver": "^7.0.0",
99
93
  "memfs": "4.80.0",
@@ -1,70 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "path";
3
- import { getPaths } from "@cedarjs/project-config";
4
- class CustomFileExporter {
5
- /**
6
- * @type string
7
- * @private
8
- */
9
- #storageFileName;
10
- /**
11
- * @type string
12
- * @private
13
- */
14
- #storageFilePath;
15
- /**
16
- * @type boolean
17
- * @private
18
- */
19
- #isShutdown = false;
20
- constructor() {
21
- this.#storageFileName = `${Date.now()}.json`;
22
- this.#storageFilePath = path.join(
23
- getPaths().generated.base,
24
- "telemetry",
25
- this.#storageFileName
26
- );
27
- fs.mkdirSync(path.dirname(this.#storageFilePath), { recursive: true });
28
- fs.writeFileSync(this.#storageFilePath, "[");
29
- }
30
- /**
31
- * Called to export sampled {@link ReadableSpan}s.
32
- * @param spans the list of sampled Spans to be exported.
33
- */
34
- export(spans, resultCallback) {
35
- for (const span of spans) {
36
- fs.appendFileSync(
37
- this.#storageFilePath,
38
- JSON.stringify(
39
- span,
40
- (key, value) => {
41
- if (key === "_spanProcessor") {
42
- return void 0;
43
- }
44
- return value;
45
- },
46
- 2
47
- )
48
- );
49
- fs.appendFileSync(this.#storageFilePath, ",");
50
- }
51
- resultCallback({ code: 0 });
52
- }
53
- /** Stops the exporter. */
54
- async shutdown() {
55
- if (!this.#isShutdown) {
56
- fs.truncateSync(
57
- this.#storageFilePath,
58
- fs.statSync(this.#storageFilePath).size - 1
59
- );
60
- fs.appendFileSync(this.#storageFilePath, "]");
61
- this.#isShutdown = true;
62
- }
63
- }
64
- /** Immediately export all spans */
65
- forceFlush() {
66
- }
67
- }
68
- export {
69
- CustomFileExporter
70
- };
@@ -1,85 +0,0 @@
1
- import path from "path";
2
- import { diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
3
- import opentelemetry from "@opentelemetry/api";
4
- import {
5
- NodeTracerProvider,
6
- SimpleSpanProcessor,
7
- SamplingDecision
8
- } from "@opentelemetry/sdk-trace-node";
9
- import { hideBin } from "yargs/helpers";
10
- import { getNodeRunnerArgs } from "@cedarjs/cli-helpers/packageManager/exec";
11
- import { spawnBackgroundProcess } from "../lib/background.js";
12
- import { CustomFileExporter } from "./exporter.js";
13
- let traceProvider;
14
- let traceProcessor;
15
- let traceExporter;
16
- let isStarted = false;
17
- let isShutdown = false;
18
- async function startTelemetry() {
19
- if (isStarted) {
20
- return;
21
- }
22
- isStarted = true;
23
- try {
24
- diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR);
25
- traceExporter = new CustomFileExporter();
26
- traceProcessor = new SimpleSpanProcessor(traceExporter);
27
- traceProvider = new NodeTracerProvider({
28
- sampler: {
29
- shouldSample: () => {
30
- return {
31
- decision: isShutdown ? SamplingDecision.NOT_RECORD : SamplingDecision.RECORD_AND_SAMPLED
32
- };
33
- },
34
- toString: () => {
35
- return "AlwaysSampleWhenNotShutdown";
36
- }
37
- },
38
- spanProcessors: [traceProcessor]
39
- });
40
- traceProvider.register();
41
- const cleanArgv = hideBin(process.argv);
42
- if (!cleanArgv.includes("sb") && !cleanArgv.includes("storybook")) {
43
- for (const signal of ["SIGTERM", "SIGINT", "SIGHUP"]) {
44
- process.on(signal, () => {
45
- if (process.listenerCount(signal) === 1) {
46
- process.exit();
47
- }
48
- });
49
- }
50
- } else {
51
- process.on("shutdown-telemetry", () => {
52
- shutdownTelemetry();
53
- });
54
- }
55
- process.on("exit", () => {
56
- shutdownTelemetry();
57
- });
58
- } catch (error) {
59
- console.error("Telemetry error");
60
- console.error(error);
61
- }
62
- }
63
- function shutdownTelemetry() {
64
- if (isShutdown || !isStarted) {
65
- return;
66
- }
67
- isShutdown = true;
68
- try {
69
- while (opentelemetry.trace.getActiveSpan()?.isRecording()) {
70
- opentelemetry.trace.getActiveSpan()?.end();
71
- }
72
- traceExporter?.shutdown();
73
- const [cmd, args] = getNodeRunnerArgs(
74
- path.join(import.meta.dirname, "send.js")
75
- );
76
- spawnBackgroundProcess("telemetry", cmd, args);
77
- } catch (error) {
78
- console.error("Telemetry error");
79
- console.error(error);
80
- }
81
- }
82
- export {
83
- shutdownTelemetry,
84
- startTelemetry
85
- };
@@ -1,94 +0,0 @@
1
- import fs from "node:fs";
2
- import os from "node:os";
3
- import path from "path";
4
- import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
5
- import ci from "ci-info";
6
- import envinfo from "envinfo";
7
- import { v4 as uuidv4, validate as validateUUID } from "uuid";
8
- import { getPaths, getRawConfig } from "@cedarjs/project-config";
9
- import { RWProject } from "@cedarjs/structure/dist/model/RWProject";
10
- async function getResources() {
11
- const packageJson = await import("../../package.json", { with: { type: "json" } });
12
- const packageName = packageJson.default["name"];
13
- const packageVersion = packageJson.default["version"];
14
- let UID = uuidv4();
15
- try {
16
- const telemetryFile = path.join(getPaths().generated.base, "telemetry.txt");
17
- if (!fs.existsSync(telemetryFile)) {
18
- fs.mkdirSync(path.dirname(telemetryFile), { recursive: true });
19
- fs.writeFileSync(telemetryFile, "");
20
- }
21
- if (fs.statSync(telemetryFile).mtimeMs < Date.now() - 864e5) {
22
- fs.writeFileSync(telemetryFile, UID);
23
- } else {
24
- const storedUID = fs.readFileSync(telemetryFile, { encoding: "utf8" });
25
- if (storedUID && validateUUID(storedUID)) {
26
- UID = storedUID;
27
- } else {
28
- fs.writeFileSync(telemetryFile, UID);
29
- }
30
- }
31
- } catch {
32
- }
33
- const info = JSON.parse(
34
- await envinfo.run(
35
- {
36
- System: ["OS", "Shell"],
37
- Binaries: ["Node", "Yarn", "npm"],
38
- npmPackages: "@cedarjs/*",
39
- IDEs: ["VSCode"]
40
- },
41
- { json: true }
42
- )
43
- );
44
- const shell = info.System?.Shell;
45
- if (shell?.path?.match("/")) {
46
- info.System.Shell.name = info.System.Shell.path.split("/").pop();
47
- } else if (shell?.path.match("\\")) {
48
- info.System.Shell.name = info.System.Shell.path.split("\\").pop();
49
- }
50
- const cpuCount = os.availableParallelism();
51
- const memoryGb = Math.round(os.totalmem() / 1073741824);
52
- let developmentEnvironment = void 0;
53
- if (Object.keys(process.env).some((key) => key.startsWith("GITPOD_"))) {
54
- developmentEnvironment = "gitpod";
55
- }
56
- const experiments = Object.keys(getRawConfig()["experimental"] || {});
57
- const project = new RWProject();
58
- const routes = project.getRouter().routes;
59
- const prerenderedRoutes = routes.filter(
60
- (route) => route.hasPrerender
61
- );
62
- const complexity = [
63
- routes.length,
64
- prerenderedRoutes.length,
65
- project.services.length,
66
- project.cells.length,
67
- project.pages.length
68
- ].join(".");
69
- const sides = project.sides.join(",");
70
- return {
71
- [SemanticResourceAttributes.SERVICE_NAME]: packageName,
72
- [SemanticResourceAttributes.SERVICE_VERSION]: packageVersion,
73
- [SemanticResourceAttributes.OS_TYPE]: info.System?.OS?.split(" ")[0],
74
- [SemanticResourceAttributes.OS_VERSION]: info.System?.OS?.split(" ")[1],
75
- "shell.name": info.System?.Shell?.name,
76
- "node.version": info.Binaries?.Node?.version,
77
- "yarn.version": info.Binaries?.Yarn?.version,
78
- "npm.version": info.Binaries?.npm?.version,
79
- "vscode.version": info.IDEs?.VSCode?.version,
80
- "cpu.count": cpuCount,
81
- "memory.gb": memoryGb,
82
- "env.node_env": process.env.NODE_ENV || void 0,
83
- "ci.redwood": !!process.env.CEDAR_CI,
84
- "ci.isci": ci.isCI,
85
- "dev.environment": developmentEnvironment,
86
- complexity,
87
- sides,
88
- experiments: JSON.stringify(experiments),
89
- uid: UID
90
- };
91
- }
92
- export {
93
- getResources
94
- };
@@ -1,92 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "path";
3
- import { ExportResultCode } from "@opentelemetry/core";
4
- import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
5
- import {
6
- defaultResource,
7
- resourceFromAttributes
8
- } from "@opentelemetry/resources";
9
- import { getPaths } from "@cedarjs/project-config";
10
- import { getResources } from "./resource.js";
11
- async function main() {
12
- console.log(
13
- "You can disable telemetry by:\n - setting the 'CEDAR_DISABLE_TELEMETRY' environment variable\n - passing the '--no-telemetry' flag when using the CLI"
14
- );
15
- console.log(
16
- "Information about Cedar telemetry can be found at:\n - https://telemetry.redwoodjs.com\n"
17
- );
18
- const telemetryDir = path.join(getPaths().generated.base, "telemetry");
19
- fs.mkdirSync(telemetryDir, { recursive: true });
20
- const telemetryFiles = fs.readdirSync(
21
- path.join(getPaths().generated.base, "telemetry")
22
- );
23
- console.time("Computed resource information");
24
- const customResourceData = await getResources();
25
- console.timeEnd("Computed resource information");
26
- const resource = defaultResource().merge(
27
- resourceFromAttributes(customResourceData)
28
- );
29
- const url = process.env.CEDAR_REDIRECT_TELEMETRY || process.env.REDWOOD_REDIRECT_TELEMETRY || "https://quark.quantumparticle.io/v1/traces";
30
- const traceExporter = new OTLPTraceExporter({
31
- url
32
- });
33
- console.log(`Sending telemetry data to '${url}'`);
34
- for (const [index, file] of telemetryFiles.entries()) {
35
- if (file.startsWith("_")) {
36
- continue;
37
- }
38
- console.log(`Sending data from telemetry file '${file}'`);
39
- let spans = [];
40
- try {
41
- spans = JSON.parse(fs.readFileSync(path.join(telemetryDir, file), "utf8"));
42
- } catch (error) {
43
- console.error(`Error reading telemetry file '${file}'`);
44
- console.error(error);
45
- console.error("Deleting this file to prevent further errors");
46
- fs.unlinkSync(path.join(telemetryDir, file));
47
- continue;
48
- }
49
- if (!Array.isArray(spans)) {
50
- console.error(
51
- `Telemetry file '${file}' does not contain an array of spans. Deleting this file to prevent further errors.`
52
- );
53
- fs.unlinkSync(path.join(telemetryDir, file));
54
- continue;
55
- }
56
- for (const span of spans) {
57
- span.resource = resource;
58
- span.attributes ??= span._attributes ?? {};
59
- span.spanContext = () => span._spanContext;
60
- span.events = [];
61
- }
62
- traceExporter.export(
63
- spans,
64
- ({ code, error }) => {
65
- if (code !== ExportResultCode.SUCCESS) {
66
- console.error("Encountered:");
67
- console.error(error);
68
- console.error("while exporting the following spans:");
69
- console.error(spans);
70
- }
71
- }
72
- );
73
- fs.writeFileSync(
74
- path.join(telemetryDir, `_${file}`),
75
- JSON.stringify(spans, null, 2)
76
- );
77
- fs.unlinkSync(path.join(telemetryDir, file));
78
- telemetryFiles[index] = `_${file}`;
79
- }
80
- traceExporter.shutdown();
81
- console.log(
82
- "Keeping the lastest 8 telemetry files for visibility/transparency."
83
- );
84
- const sortedTelemetryFiles = telemetryFiles.sort((a, b) => {
85
- return parseInt(b.split(".")[0].replace("_", "")) - parseInt(a.split(".")[0].replace("_", ""));
86
- });
87
- for (let i = 8; i < sortedTelemetryFiles.length; i++) {
88
- console.log(`Removing telemetry file '${sortedTelemetryFiles[i]}'`);
89
- fs.unlinkSync(path.join(telemetryDir, sortedTelemetryFiles[i]));
90
- }
91
- }
92
- main();