Track HiveGrid Cloud planning reference
This commit is contained in:
1 parent
b3d5ea6764
commit
e341c5938a
5784 files changed
+1104929
-3
No files matched your search
@@ -0,0 +1,66 @@
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import { builtinModules } from "node:module";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { build } from "esbuild";
|
||||
|
||||
const apiDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const entryPoint = path.join(apiDir, "src/server.ts");
|
||||
const outputFile = path.join(apiDir, "dist/server.js");
|
||||
const nodeBuiltins = new Set([...builtinModules, ...builtinModules.map((moduleName) => `node:${moduleName}`)]);
|
||||
const sourcemap = process.env.SOURCEMAP === "true" || process.env.BUILD_SOURCEMAPS === "true";
|
||||
|
||||
const externalizeRuntimeDependencies = {
|
||||
name: "externalize-runtime-dependencies",
|
||||
setup(buildContext) {
|
||||
buildContext.onResolve({ filter: /.*/ }, (args) => {
|
||||
if (nodeBuiltins.has(args.path)) {
|
||||
return { path: args.path, external: true };
|
||||
}
|
||||
|
||||
if (isExternalRuntimePackage(args.path)) {
|
||||
return { path: args.path, external: true };
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
await mkdir(path.dirname(outputFile), { recursive: true });
|
||||
|
||||
await build({
|
||||
entryPoints: [entryPoint],
|
||||
outfile: outputFile,
|
||||
bundle: true,
|
||||
platform: "node",
|
||||
format: "esm",
|
||||
target: "node20",
|
||||
sourcemap,
|
||||
banner: {
|
||||
js: 'import { createRequire as __toolctrlCreateRequire } from "node:module"; const require = __toolctrlCreateRequire(import.meta.url);',
|
||||
},
|
||||
plugins: [externalizeRuntimeDependencies],
|
||||
logLevel: "warning",
|
||||
});
|
||||
|
||||
function isBarePackageSpecifier(specifier) {
|
||||
return !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("#");
|
||||
}
|
||||
|
||||
function isExternalRuntimePackage(specifier) {
|
||||
if (!isBarePackageSpecifier(specifier)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
specifier === "@prisma/client" ||
|
||||
specifier.startsWith("@prisma/client/") ||
|
||||
specifier === "@prisma/adapter-pg" ||
|
||||
specifier.startsWith("@prisma/adapter-pg/") ||
|
||||
specifier === "jsonwebtoken" ||
|
||||
specifier.startsWith("jsonwebtoken/") ||
|
||||
specifier === "pino" ||
|
||||
specifier.startsWith("pino/")
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env tsx
|
||||
/**
|
||||
* Sentry smoke test for the API process.
|
||||
*
|
||||
* Triggers a fake captureException + a fake `Sentry.startSpan` transaction
|
||||
* so an operator can verify end-to-end that:
|
||||
* - the API DSN is wired,
|
||||
* - `beforeSend` sanitises PII,
|
||||
* - the matching Sentry project receives both an Issue and a Transaction.
|
||||
*
|
||||
* Run from the repo root with one of:
|
||||
* pnpm --filter @toolctrl/api exec tsx scripts/smoke-sentry.ts
|
||||
* SENTRY_DSN_API=... pnpm --filter @toolctrl/api exec tsx scripts/smoke-sentry.ts
|
||||
*
|
||||
* Exits 0 on a clean run, 1 when the SDK fails to load. A no-DSN run is
|
||||
* intentionally a successful no-op so CI can call it unconditionally.
|
||||
*
|
||||
* @see docs/improvement-plan/02-observability/sentry-wiring-api-worker.md
|
||||
*/
|
||||
import { initApiSentry, readApiSentryConfig } from "../src/sentry.js";
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const config = readApiSentryConfig();
|
||||
if (!config.dsn) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn("[smoke-sentry] SENTRY_DSN_API is not set; nothing to do.");
|
||||
return;
|
||||
}
|
||||
|
||||
const reporter = initApiSentry(config);
|
||||
|
||||
// 1) Fake captureException — exercises beforeSend + sanitisation.
|
||||
await reporter.report({
|
||||
component: "api",
|
||||
operation: "smoke.exception",
|
||||
severity: "error",
|
||||
error: new Error(`smoke-sentry: fake exception at ${new Date().toISOString()}`),
|
||||
// Include obvious PII fields so the operator can confirm redaction in the
|
||||
// Sentry UI (`token` / `password` should render as [Redacted]).
|
||||
token: "fake-token-must-be-redacted",
|
||||
password: "fake-password-must-be-redacted",
|
||||
});
|
||||
|
||||
// 2) Fake transaction — exercises @sentry/node startSpan.
|
||||
try {
|
||||
const moduleName = "@sentry/node";
|
||||
const sentry = (await import(/* @vite-ignore */ moduleName)) as {
|
||||
startSpan?: (args: { op: string; name: string }, cb: () => Promise<void> | void) => Promise<void> | void;
|
||||
default?: {
|
||||
startSpan?: (args: { op: string; name: string }, cb: () => Promise<void> | void) => Promise<void> | void;
|
||||
};
|
||||
};
|
||||
const startSpan = sentry.startSpan ?? sentry.default?.startSpan;
|
||||
if (typeof startSpan === "function") {
|
||||
await startSpan({ op: "test", name: "smoke-sentry/api" }, async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 25));
|
||||
});
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn("[smoke-sentry] @sentry/node loaded but startSpan is unavailable; transaction skipped.");
|
||||
}
|
||||
} catch (cause) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("[smoke-sentry] failed to load @sentry/node for the transaction smoke:", cause);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
// Give the SDK enough time to flush. Sentry's `close()` would be more
|
||||
// precise but pulling the type via dynamic import is more trouble than it
|
||||
// is worth for a manual smoke script.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("[smoke-sentry] done — check the Sentry UI (Issues + Performance) for boilerplate-api.");
|
||||
}
|
||||
|
||||
main().catch((cause) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("[smoke-sentry] unexpected failure:", cause);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in new issue
Block a user