@interfere/next 0.1.0-alpha.10 → 0.1.0-alpha.9

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.
Files changed (111) hide show
  1. package/README.md +5 -33
  2. package/dist/build/env-config.d.mts.map +1 -1
  3. package/dist/build/loaders/value-injection-loader.d.mts +6 -0
  4. package/dist/build/loaders/value-injection-loader.d.mts.map +1 -1
  5. package/dist/build/loaders/value-injection-loader.mjs +9 -0
  6. package/dist/build/loaders/value-injection-loader.mjs.map +1 -1
  7. package/dist/build/logger.d.mts +2 -2
  8. package/dist/build/logger.d.mts.map +1 -1
  9. package/dist/build/logger.mjs +12 -10
  10. package/dist/build/logger.mjs.map +1 -1
  11. package/dist/build/release-program.d.mts +3 -5
  12. package/dist/build/release-program.d.mts.map +1 -1
  13. package/dist/build/release-program.mjs +6 -7
  14. package/dist/build/release-program.mjs.map +1 -1
  15. package/dist/build/secret-key.d.mts.map +1 -1
  16. package/dist/build/services/config.service.d.mts.map +1 -1
  17. package/dist/build/services/instrumentation-detection.service.d.mts +16 -13
  18. package/dist/build/services/instrumentation-detection.service.d.mts.map +1 -1
  19. package/dist/build/services/instrumentation-detection.service.mjs +48 -65
  20. package/dist/build/services/instrumentation-detection.service.mjs.map +1 -1
  21. package/dist/build/services/preflight.service.d.mts.map +1 -1
  22. package/dist/build/services/preflight.service.mjs +10 -10
  23. package/dist/build/services/preflight.service.mjs.map +1 -1
  24. package/dist/build/services/release-identity.service.d.mts.map +1 -1
  25. package/dist/build/services/release-identity.service.mjs +5 -5
  26. package/dist/build/services/release-identity.service.mjs.map +1 -1
  27. package/dist/build/services/source-map.service.d.mts +1 -1
  28. package/dist/build/services/source-map.service.d.mts.map +1 -1
  29. package/dist/build/services/source-map.service.mjs +4 -2
  30. package/dist/build/services/source-map.service.mjs.map +1 -1
  31. package/dist/build/source-maps/api.d.mts.map +1 -1
  32. package/dist/build/source-maps/client.d.mts +21 -29
  33. package/dist/build/source-maps/client.d.mts.map +1 -1
  34. package/dist/build/source-maps/client.mjs +8 -14
  35. package/dist/build/source-maps/client.mjs.map +1 -1
  36. package/dist/build/source-maps/errors.d.mts.map +1 -1
  37. package/dist/build/source-maps/files.d.mts +1 -1
  38. package/dist/build/source-maps/files.d.mts.map +1 -1
  39. package/dist/build/source-maps/files.mjs +15 -13
  40. package/dist/build/source-maps/files.mjs.map +1 -1
  41. package/dist/build/source-maps/providers/deployment/detector.d.mts +1 -1
  42. package/dist/build/source-maps/providers/deployment/detector.d.mts.map +1 -1
  43. package/dist/build/source-maps/providers/deployment/detector.mjs +13 -11
  44. package/dist/build/source-maps/providers/deployment/detector.mjs.map +1 -1
  45. package/dist/build/source-maps/providers/deployment/types.d.mts.map +1 -1
  46. package/dist/build/source-maps/providers/deployment/vercel.d.mts.map +1 -1
  47. package/dist/build/source-maps/providers/deployment/vercel.mjs +1 -1
  48. package/dist/build/source-maps/providers/deployment/vercel.mjs.map +1 -1
  49. package/dist/build/source-maps/providers/source-control/detector.d.mts +1 -1
  50. package/dist/build/source-maps/providers/source-control/detector.d.mts.map +1 -1
  51. package/dist/build/source-maps/providers/source-control/detector.mjs +13 -11
  52. package/dist/build/source-maps/providers/source-control/detector.mjs.map +1 -1
  53. package/dist/build/source-maps/providers/source-control/git.d.mts.map +1 -1
  54. package/dist/build/source-maps/providers/source-control/git.mjs +1 -1
  55. package/dist/build/source-maps/providers/source-control/git.mjs.map +1 -1
  56. package/dist/build/source-maps/providers/source-control/types.d.mts.map +1 -1
  57. package/dist/build/with-interfere.d.mts +21 -21
  58. package/dist/build/with-interfere.d.mts.map +1 -1
  59. package/dist/build/with-interfere.mjs +78 -85
  60. package/dist/build/with-interfere.mjs.map +1 -1
  61. package/dist/client/auto-init.d.mts +1 -0
  62. package/dist/client/auto-init.d.mts.map +1 -1
  63. package/dist/client/provider.d.mts.map +1 -1
  64. package/dist/lib/env.d.mts.map +1 -1
  65. package/dist/lib/test-utils/make-next-request.d.mts.map +1 -1
  66. package/dist/lib/types.d.mts.map +1 -1
  67. package/dist/server/middleware.d.mts.map +1 -1
  68. package/dist/server/middleware.mjs +3 -11
  69. package/dist/server/middleware.mjs.map +1 -1
  70. package/dist/server/proxy.d.mts.map +1 -1
  71. package/dist/server/route-handler.d.mts.map +1 -1
  72. package/dist/server/route-handler.mjs +15 -9
  73. package/dist/server/route-handler.mjs.map +1 -1
  74. package/dist/server/services/config.service.d.mts +3 -3
  75. package/dist/server/services/config.service.d.mts.map +1 -1
  76. package/dist/server/services/config.service.mjs +4 -4
  77. package/dist/server/services/config.service.mjs.map +1 -1
  78. package/dist/server/services/error-tracking.service.d.mts +3 -3
  79. package/dist/server/services/error-tracking.service.d.mts.map +1 -1
  80. package/dist/server/services/error-tracking.service.mjs +2 -4
  81. package/dist/server/services/error-tracking.service.mjs.map +1 -1
  82. package/package.json +8 -23
  83. package/dist/_virtual/rolldown_runtime.mjs +0 -7
  84. package/dist/build/nextjs-version.d.mts +0 -40
  85. package/dist/build/nextjs-version.d.mts.map +0 -1
  86. package/dist/build/nextjs-version.mjs +0 -66
  87. package/dist/build/nextjs-version.mjs.map +0 -1
  88. package/dist/build/services/release-api.service.d.mts +0 -11
  89. package/dist/build/services/release-api.service.d.mts.map +0 -1
  90. package/dist/build/services/release-api.service.mjs +0 -9
  91. package/dist/build/services/release-api.service.mjs.map +0 -1
  92. package/dist/build/services/source-map-failure-cleanup.service.d.mts +0 -11
  93. package/dist/build/services/source-map-failure-cleanup.service.d.mts.map +0 -1
  94. package/dist/build/services/source-map-failure-cleanup.service.mjs +0 -9
  95. package/dist/build/services/source-map-failure-cleanup.service.mjs.map +0 -1
  96. package/dist/server/auto-init.d.mts +0 -87
  97. package/dist/server/auto-init.d.mts.map +0 -1
  98. package/dist/server/auto-init.mjs +0 -101
  99. package/dist/server/auto-init.mjs.map +0 -1
  100. package/dist/server/on-request-error.d.mts +0 -27
  101. package/dist/server/on-request-error.d.mts.map +0 -1
  102. package/dist/server/on-request-error.mjs +0 -74
  103. package/dist/server/on-request-error.mjs.map +0 -1
  104. package/dist/server/sdk.d.mts +0 -96
  105. package/dist/server/sdk.d.mts.map +0 -1
  106. package/dist/server/sdk.mjs +0 -152
  107. package/dist/server/sdk.mjs.map +0 -1
  108. package/dist/server/session-context.d.mts +0 -60
  109. package/dist/server/session-context.d.mts.map +0 -1
  110. package/dist/server/session-context.mjs +0 -62
  111. package/dist/server/session-context.mjs.map +0 -1
package/README.md CHANGED
@@ -14,35 +14,7 @@ pnpm add @interfere/next
14
14
 
15
15
  ## Quick Start
16
16
 
17
- ### 1. Server-Side Error Tracking (Recommended)
18
-
19
- The recommended way to capture server-side errors in Next.js 15+ is via the `onRequestError` hook in `instrumentation.ts`. This captures errors from React Server Components, SSR, API routes, Server Actions, and more.
20
-
21
- Create `instrumentation.ts` in your project root (or `src/` directory):
22
-
23
- ```typescript
24
- import { captureRequestError } from '@interfere/next/server/on-request-error';
25
-
26
- export async function register() {
27
- if (process.env.NEXT_RUNTIME === 'nodejs') {
28
- const { autoInitServer } = await import('@interfere/next/server/auto-init');
29
- autoInitServer();
30
- }
31
- }
32
-
33
- export async function onRequestError(error, request, context) {
34
- await captureRequestError({ error, request, context });
35
- }
36
- ```
37
-
38
- The `onRequestError` hook provides rich context including:
39
- - **routerKind**: "App Router" or "Pages Router"
40
- - **routePath**: The route file path (e.g., `/app/api/users/route`)
41
- - **routeType**: "render", "route", "action", "middleware", or "proxy"
42
- - **renderSource**: For render errors - "react-server-components", "server-rendering", etc.
43
- - **error.digest**: Unique error identifier for deduplication
44
-
45
- ### 2. Initialize the Client SDK
17
+ ### 1. Initialize the SDK
46
18
 
47
19
  Create a file to initialize Interfere (e.g., `lib/interfere.ts`):
48
20
 
@@ -58,7 +30,7 @@ export const interfere = init({
58
30
  });
59
31
  ```
60
32
 
61
- ### 3. Add the Proxy Route
33
+ ### 2. Add the Proxy Route
62
34
 
63
35
  The SDK sends events through a server-side proxy route to keep your API credentials secure. Create `app/api/interfere/[[...path]]/route.ts`:
64
36
 
@@ -72,7 +44,7 @@ This route proxies client-side events to Interfere's ingest API using your `INTE
72
44
  INTERFERE_SECRET_KEY=if_sk_xxx
73
45
  ```
74
46
 
75
- ### 4. Add Error Boundary (App Directory)
47
+ ### 3. Add Error Boundary (App Directory)
76
48
 
77
49
  In your root layout (`app/layout.tsx`):
78
50
 
@@ -99,7 +71,7 @@ export default function RootLayout({
99
71
  }
100
72
  ```
101
73
 
102
- ### 5. Add Error Handler (App Directory)
74
+ ### 4. Add Error Handler (App Directory)
103
75
 
104
76
  Create `app/error.tsx`:
105
77
 
@@ -131,7 +103,7 @@ export default function Error({
131
103
  }
132
104
  ```
133
105
 
134
- ### 6. Add Global Error Handler
106
+ ### 5. Add Global Error Handler
135
107
 
136
108
  Create `app/global-error.tsx`:
137
109
 
@@ -1 +1 @@
1
- {"version":3,"file":"env-config.d.mts","names":[],"sources":["../../src/build/env-config.ts"],"mappings":";;;iBAGgB,aAAA,CAAA;AAAA,iBAWA,kBAAA,CAAA,GAAA,uBAEb,cAAA"}
1
+ {"version":3,"file":"env-config.d.mts","names":[],"sources":["../../src/build/env-config.ts"],"sourcesContent":[],"mappings":";;;iBAGgB,aAAA,CAAA;iBAWA,kBAAA,2BAEb"}
@@ -16,6 +16,12 @@ interface ValueInjectionLoaderOptions {
16
16
  * Supports two input formats:
17
17
  * - `values`: Direct object with key-value pairs (webpack)
18
18
  * - `serializedValues`: JSON-serialized string of values (turbopack)
19
+ *
20
+ * @example
21
+ * // With options: { values: { __BUILD_ID__: "abc123" } }
22
+ * // Input: console.log("hello");
23
+ * // Output: globalThis["__BUILD_ID__"] = "abc123";
24
+ * // console.log("hello");
19
25
  */
20
26
  declare function valueInjectionLoader(this: LoaderContext<ValueInjectionLoaderOptions>, userCode: string): string;
21
27
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"value-injection-loader.d.mts","names":[],"sources":["../../../src/build/loaders/value-injection-loader.ts"],"mappings":";;;UAEiB,2BAAA;EAAA;EAAA,MAAA,GAEN,MAAA;EAAA;EAAA,gBAAA;AAAA;AAAA;AAGV;;;;;;;;;AAHU,iBAea,oBAAA,CAAA,IAAA,EAChB,aAAA,CAAc,2BAAA,GAAA,QAAA"}
1
+ {"version":3,"file":"value-injection-loader.d.mts","names":[],"sources":["../../../src/build/loaders/value-injection-loader.ts"],"sourcesContent":[],"mappings":";;;UAEiB,2BAAA;;EAAA,MAAA,CAAA,EAEN,MAFM,CAAA,MAAA,EAAA,OAA2B,CAAA;EAuBpB;;;;;;;;;;;;;;;;;;;iBAAA,oBAAA,OAChB,cAAc"}
@@ -8,6 +8,12 @@
8
8
  * Supports two input formats:
9
9
  * - `values`: Direct object with key-value pairs (webpack)
10
10
  * - `serializedValues`: JSON-serialized string of values (turbopack)
11
+ *
12
+ * @example
13
+ * // With options: { values: { __BUILD_ID__: "abc123" } }
14
+ * // Input: console.log("hello");
15
+ * // Output: globalThis["__BUILD_ID__"] = "abc123";
16
+ * // console.log("hello");
11
17
  */
12
18
  function valueInjectionLoader(userCode) {
13
19
  const options = this.getOptions();
@@ -27,6 +33,9 @@ function valueInjectionLoader(userCode) {
27
33
  if (injectionLines.length === 0) return userCode;
28
34
  return `${injectionLines.join("\n")}\n${userCode}`;
29
35
  }
36
+ /**
37
+ * Escape special characters in object keys for safe string embedding.
38
+ */
30
39
  function escapeKey(key) {
31
40
  return key.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
32
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"value-injection-loader.mjs","names":[],"sources":["../../../src/build/loaders/value-injection-loader.ts"],"sourcesContent":["import type { LoaderContext } from \"webpack\";\n\nexport interface ValueInjectionLoaderOptions {\n /** Key-value pairs to inject into globalThis (used by webpack) */\n values?: Record<string, unknown>;\n /** Serialized JSON string of values (used by turbopack to preserve null values) */\n serializedValues?: string;\n}\n\n/**\n * Webpack/Turbopack loader that injects build-time values into globalThis.\n * \n * This loader prepends code that sets values on globalThis, making them\n * available at runtime without requiring environment variables.\n * \n * Supports two input formats:\n * - `values`: Direct object with key-value pairs (webpack)\n * - `serializedValues`: JSON-serialized string of values (turbopack)\n */\nexport default function valueInjectionLoader(\n this: LoaderContext<ValueInjectionLoaderOptions>,\n userCode: string\n): string {\n const options = this.getOptions();\n \n let values: Record<string, unknown> = {};\n if (options.serializedValues) {\n try {\n values = JSON.parse(options.serializedValues);\n } catch {\n values = {};\n }\n } else if (options.values) {\n values = options.values;\n }\n\n const injectionLines: string[] = [];\n\n for (const [key, value] of Object.entries(values)) {\n if (value === undefined) {\n continue;\n }\n\n const serialized = JSON.stringify(value);\n injectionLines.push(`globalThis[\"${escapeKey(key)}\"] = ${serialized};`);\n }\n\n if (injectionLines.length === 0) {\n return userCode;\n }\n\n const injectionCode = injectionLines.join(\"\\n\");\n return `${injectionCode}\\n${userCode}`;\n}\n\nfunction escapeKey(key: string): string {\n return key.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n"],"mappings":";;;;;;;;;;;AAmBA,SAAwB,qBAEtB,UACQ;CACR,MAAM,UAAU,KAAK,YAAY;CAEjC,IAAI,SAAkC,EAAE;AACxC,KAAI,QAAQ,iBACV,KAAI;AACF,WAAS,KAAK,MAAM,QAAQ,iBAAiB;SACvC;AACN,WAAS,EAAE;;UAEJ,QAAQ,OACjB,UAAS,QAAQ;CAGnB,MAAM,iBAA2B,EAAE;AAEnC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;AACjD,MAAI,UAAU,OACZ;EAGF,MAAM,aAAa,KAAK,UAAU,MAAM;AACxC,iBAAe,KAAK,eAAe,UAAU,IAAI,CAAC,OAAO,WAAW,GAAG;;AAGzE,KAAI,eAAe,WAAW,EAC5B,QAAO;AAIT,QAAO,GADe,eAAe,KAAK,KAAK,CACvB,IAAI;;AAG9B,SAAS,UAAU,KAAqB;AACtC,QAAO,IAAI,QAAQ,OAAO,OAAO,CAAC,QAAQ,MAAM,OAAM"}
1
+ {"version":3,"file":"value-injection-loader.mjs","names":["values: Record<string, unknown>","injectionLines: string[]"],"sources":["../../../src/build/loaders/value-injection-loader.ts"],"sourcesContent":["import type { LoaderContext } from \"webpack\";\n\nexport interface ValueInjectionLoaderOptions {\n /** Key-value pairs to inject into globalThis (used by webpack) */\n values?: Record<string, unknown>;\n /** Serialized JSON string of values (used by turbopack to preserve null values) */\n serializedValues?: string;\n}\n\n/**\n * Webpack/Turbopack loader that injects build-time values into globalThis.\n * \n * This loader prepends code that sets values on globalThis, making them\n * available at runtime without requiring environment variables.\n * \n * Supports two input formats:\n * - `values`: Direct object with key-value pairs (webpack)\n * - `serializedValues`: JSON-serialized string of values (turbopack)\n * \n * @example\n * // With options: { values: { __BUILD_ID__: \"abc123\" } }\n * // Input: console.log(\"hello\");\n * // Output: globalThis[\"__BUILD_ID__\"] = \"abc123\";\n * // console.log(\"hello\");\n */\nexport default function valueInjectionLoader(\n this: LoaderContext<ValueInjectionLoaderOptions>,\n userCode: string\n): string {\n const options = this.getOptions();\n \n // Determine the values to inject: either from direct object or parsed from JSON string\n let values: Record<string, unknown> = {};\n if (options.serializedValues) {\n // Turbopack passes values as a serialized JSON string to preserve null semantics\n try {\n values = JSON.parse(options.serializedValues);\n } catch {\n // If parsing fails, fall back to empty values\n values = {};\n }\n } else if (options.values) {\n // Webpack passes values directly\n values = options.values;\n }\n\n // Generate injection code for each value\n const injectionLines: string[] = [];\n\n for (const [key, value] of Object.entries(values)) {\n // Skip undefined values entirely\n if (value === undefined) {\n continue;\n }\n\n // Serialize value safely - handles null, strings, numbers, booleans, arrays, objects\n const serialized = JSON.stringify(value);\n injectionLines.push(`globalThis[\"${escapeKey(key)}\"] = ${serialized};`);\n }\n\n // If no values to inject, return original code unchanged\n if (injectionLines.length === 0) {\n return userCode;\n }\n\n // Prepend injection code to user's code\n const injectionCode = injectionLines.join(\"\\n\");\n return `${injectionCode}\\n${userCode}`;\n}\n\n/**\n * Escape special characters in object keys for safe string embedding.\n */\nfunction escapeKey(key: string): string {\n return key.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;AAyBA,SAAwB,qBAEtB,UACQ;CACR,MAAM,UAAU,KAAK,YAAY;CAGjC,IAAIA,SAAkC,EAAE;AACxC,KAAI,QAAQ,iBAEV,KAAI;AACF,WAAS,KAAK,MAAM,QAAQ,iBAAiB;SACvC;AAEN,WAAS,EAAE;;UAEJ,QAAQ,OAEjB,UAAS,QAAQ;CAInB,MAAMC,iBAA2B,EAAE;AAEnC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;AAEjD,MAAI,UAAU,OACZ;EAIF,MAAM,aAAa,KAAK,UAAU,MAAM;AACxC,iBAAe,KAAK,eAAe,UAAU,IAAI,CAAC,OAAO,WAAW,GAAG;;AAIzE,KAAI,eAAe,WAAW,EAC5B,QAAO;AAKT,QAAO,GADe,eAAe,KAAK,KAAK,CACvB,IAAI;;;;;AAM9B,SAAS,UAAU,KAAqB;AACtC,QAAO,IAAI,QAAQ,OAAO,OAAO,CAAC,QAAQ,MAAM,OAAM"}
@@ -5,7 +5,7 @@ declare const nextBuildLogger: Logger.Logger<unknown, void>;
5
5
  declare function logBuildResult(level: LogLevel.Literal, title: string, lines: string[]): Effect.Effect<void, never, never>;
6
6
  declare function setBuildLogTitle(level: LogLevel.Literal, title: string): Effect.Effect<void, never, never>;
7
7
  declare function appendBuildLogLine(line: string): Effect.Effect<void, never, never>;
8
- declare const flushBuildLog: () => Effect.Effect<void, never, never>;
9
- declare function withBufferedBuildLog<A, E, R>(level: LogLevel.Literal, title: string, use: (log: (line: string) => ReturnType<typeof appendBuildLogLine>) => Effect.Effect<A, E, R>): Effect.Effect<A, E, R>;
8
+ declare function flushBuildLog(): Effect.Effect<void, never, never>;
9
+ declare function withBufferedBuildLog(level: LogLevel.Literal, title: string, use: (log: (line: string) => ReturnType<typeof appendBuildLogLine>) => Effect.Effect<unknown, unknown, unknown>): Effect.Effect<unknown, unknown, unknown>;
10
10
  //#endregion
11
11
  export { appendBuildLogLine, flushBuildLog, logBuildResult, nextBuildLogger, setBuildLogTitle, withBufferedBuildLog };
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.mts","names":[],"sources":["../../src/build/logger.ts"],"mappings":";;;cA+CM,eAAA,EAAe,MAAA,CAAA,MAAA;AAAA,iBA0HL,cAAA,CAAA,KAAA,EAAsB,QAAA,CAAS,OAAA,EAAA,KAAA,UAAA,KAAA,aAAuC,MAAA,CAAA,MAAA;AAAA,iBAyCtE,gBAAA,CAAA,KAAA,EACP,QAAA,CAAS,OAAA,EAAA,KAAA,WACH,MAAA,CAAA,MAAA;AAAA,iBAQC,kBAAA,CAAA,IAAA,WAA+B,MAAA,CAAA,MAAA;AAAA,cAWlC,aAAA,QAAa,MAAA,CAAA,MAAA;AAAA,iBAiBV,oBAAA,SAAA,CAAA,KAAA,EACP,QAAA,CAAS,OAAA,EAAA,KAAA,UAAA,GAAA,GAAA,GAAA,GAAA,IAAA,aAGS,UAAA,QAAkB,kBAAA,MACtC,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,CAAA,EAAG,CAAA,IACxB,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,CAAA,EAAG,CAAA"}
1
+ {"version":3,"file":"logger.d.mts","names":[],"sources":["../../src/build/logger.ts"],"sourcesContent":[],"mappings":";;;cA+CM,iBAAe,MAAA,CAAA;AAAf,iBA0HU,cAAA,CA1HK,KAAA,EA0HiB,QAAA,CAAS,OA1H1B,EAAA,KAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,CAAA,EA0HiE,MAAA,CAAA,MA1HjE,CAAA,IAAA,EAAA,KAAA,EAAA,KAAA,CAAA;AA0HL,iBAyCA,gBAAA,CAzCsB,KAAS,EA0CtC,QAAA,CAAS,OA1CoE,EAAA,KAAA,EAAA,MAAA,CAAA,EA2CvE,MAAA,CAAA,MA3CuE,CAAA,IAAA,EAAA,KAAA,EAAA,KAAA,CAAA;AAyCtE,iBAUA,kBAAA,CATP,IAAS,EAAA,MACH,CAAA,EAQgC,MAAA,CAAA,MARhC,CAAA,IAAA,EAAA,KAAA,EAAA,KAAA,CAAA;AAQC,iBAWA,aAAA,CAAA,CAX+B,EAWlB,MAAA,CAAA,MAXkB,CAAA,IAAA,EAAA,KAAA,EAAA,KAAA,CAAA;AAW/B,iBAmBA,oBAAA,CAnBa,KAAA,EAoBpB,QAAA,CAAS,OApBW,EAAA,KAAA,EAAA,MAAA,EAAA,GAAA,EAAA,CAAA,GAAA,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAuBF,UAvBE,CAAA,OAuBgB,kBAvBhB,CAAA,EAAA,GAwBtB,MAAA,CAAO,MAxBe,CAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,CAAA,EAwBkB,MAAA,CAAA,MAxBlB,CAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA"}
@@ -125,16 +125,18 @@ function appendBuildLogLine(line) {
125
125
  buildLogState.lines.push(trimmed);
126
126
  });
127
127
  }
128
- const flushBuildLog = Effect.fn("flushBuildLog")(function* () {
129
- if (!buildLogState.title || buildLogState.lines.length === 0) return;
130
- const level = buildLogState.level;
131
- const title = buildLogState.title;
132
- const lines = [...buildLogState.lines];
133
- buildLogState.level = "Info";
134
- buildLogState.title = null;
135
- buildLogState.lines = [];
136
- yield* logBuildResult(level, title, lines);
137
- });
128
+ function flushBuildLog() {
129
+ return Effect.gen(function* () {
130
+ if (!buildLogState.title || buildLogState.lines.length === 0) return;
131
+ const level = buildLogState.level;
132
+ const title = buildLogState.title;
133
+ const lines = [...buildLogState.lines];
134
+ buildLogState.level = "Info";
135
+ buildLogState.title = null;
136
+ buildLogState.lines = [];
137
+ yield* logBuildResult(level, title, lines);
138
+ });
139
+ }
138
140
  function withBufferedBuildLog(level, title, use) {
139
141
  return Effect.acquireUseRelease(setBuildLogTitle(level, title), () => use((line) => appendBuildLogLine(line)), (_, _exit) => flushBuildLog());
140
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.mjs","names":[],"sources":["../../src/build/logger.ts"],"sourcesContent":["import { InterfereLogger } from \"@interfere/effect-utils/observability\";\nimport chalk, { type ChalkInstance } from \"chalk\";\nimport { Cause, Effect, Logger, LogLevel } from \"effect\";\n\nconst buildConsole = globalThis.console;\n\nconst prefixes: Record<LogLevel.Literal, string> = {\n Info: chalk.cyan.bold(\" \"),\n Debug: chalk.gray.bold(\" \"),\n All: chalk.gray.bold(\" \"),\n Trace: chalk.magenta.bold(\" \"),\n Warning: chalk.yellow.bold(\"⚠\"),\n Error: chalk.red.bold(\"⨯\"),\n Fatal: chalk.red.bold(\"⨯\"),\n None: chalk.white.bold(\" \"),\n} as const;\n\nconst textStyles: Record<LogLevel.Literal, ChalkInstance> = {\n Info: chalk.cyan.bold,\n Debug: chalk.gray.bold,\n All: chalk.gray.bold,\n Trace: chalk.magenta.bold,\n Warning: chalk.yellow.bold,\n Error: chalk.red.bold,\n Fatal: chalk.red.bold,\n None: chalk.white.bold,\n}\n\nconst logMethods: Partial<Record<LogLevel.Literal, keyof Console>> = {\n Warning: \"warn\",\n Error: \"error\",\n};\n\nfunction tagForLevel(level: LogLevel.Literal) {\n switch (level) {\n case \"Error\":\n case \"Fatal\":\n return \"[error]\";\n case \"Warning\":\n return \"[warn]\";\n case \"Debug\":\n return \"[debug]\";\n default:\n return \"\";\n }\n}\n\nconst nextBuildLogger = Logger.make<unknown, void>(\n ({ logLevel, message, cause }) => {\n if (!shouldLog(logLevel._tag)) {\n return;\n }\n\n const renderedMessage = coerceToArray(message)\n .map(formatValue)\n .filter(Boolean)\n .join(\" \")\n .trim();\n\n if (renderedMessage.length > 0) {\n levelLog(logLevel._tag, renderedMessage);\n } else {\n levelLog(logLevel._tag);\n }\n\n if (!Cause.isEmpty(cause)) {\n levelLog(\n logLevel._tag,\n `${chalk.dim(\"details\")} ${Cause.pretty(cause, {\n renderErrorCause: true,\n })}`\n );\n }\n }\n);\n\n\n\nfunction systemLog(level: LogLevel.Literal, ...message: string[]) {\n if (!shouldLog(level)) {\n return;\n }\n\n const consoleMethod = logMethods[level] ?? \"log\";\n\n const consoleFn = buildConsole[consoleMethod];\n if (typeof consoleFn !== \"function\") {\n return;\n }\n\n const invoke = (...args: unknown[]) =>\n Reflect.apply(consoleFn, buildConsole, args);\n\n if (message.length === 0) {\n invoke(\"\");\n return;\n }\n\n if (message.length === 1) {\n invoke(` ${message[0]}`);\n return;\n }\n\n invoke(` `, ...message);\n}\n\nfunction coerceToArray(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.map(formatValue);\n }\n\n return [formatValue(value)];\n}\n\nfunction formatValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (value instanceof Error) {\n return value.stack ?? value.message;\n }\n\n if (value === null || value === undefined) {\n return \"\";\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport { nextBuildLogger };\n\nfunction levelLog(level: LogLevel.Literal, ...message: string[]) {\n if (!shouldLog(level)) {\n return;\n }\n\n const consoleMethod = logMethods[level] ?? \"log\";\n const prefix = prefixes[level] ?? prefixes.Info;\n const tag = tagForLevel(level);\n\n const consoleFn = buildConsole[consoleMethod];\n\n if (typeof consoleFn !== \"function\") {\n return;\n }\n\n const invoke = (...args: unknown[]) =>\n Reflect.apply(consoleFn, buildConsole, args);\n\n if (message.length === 0) {\n invoke(\"\");\n return;\n }\n\n const tagPart = tag ? ` ${tag}` : \"\";\n\n if (message.length === 1) {\n invoke(` ${prefix}${tagPart} ${message[0]}`);\n return;\n }\n\n invoke(` ${prefix}${tagPart}`, ...message);\n}\n\nexport function logBuildResult(level: LogLevel.Literal, title: string, lines: string[]) {\n if (!shouldLog(level)) {\n return Effect.void;\n }\n\n return Effect.sync(() => {\n systemLog(level, `❖ ${chalk.white(\"Interfere →\")} ${textStyles[level](title)}`);\n\n if (lines.length === 0) {\n return;\n }\n\n const prefix = prefixes[level] ?? prefixes.Info;\n const tag = tagForLevel(level);\n const tagPart = tag ? `${tag} ` : \"\";\n const consoleMethod = logMethods[level] ?? \"log\";\n const consoleFn = buildConsole[consoleMethod];\n\n if (typeof consoleFn !== \"function\") {\n return;\n }\n\n const invoke = (...args: unknown[]) =>\n Reflect.apply(consoleFn, buildConsole, args);\n\n if (lines.length === 1) {\n // Single line - connector plus tag after the connector\n const connector = \"└\";\n invoke(` ${prefix} ${connector} ${tagPart}${lines[0]}`);\n return;\n }\n\n // Multi-line - tree structure with connectors and tag after connector\n lines.forEach((line, index) => {\n const isLast = index === lines.length - 1;\n const connector = isLast ? \"└\" : \"├\";\n invoke(` ${prefix} ${connector} ${tagPart}${line}`);\n });\n });\n}\n\nexport function setBuildLogTitle(\n level: LogLevel.Literal,\n title: string\n) {\n return Effect.sync(() => {\n buildLogState.level = level;\n buildLogState.title = title;\n });\n}\n\nexport function appendBuildLogLine(line: string) {\n return Effect.sync(() => {\n const trimmed = line.trim();\n if (trimmed.length === 0) {\n return;\n }\n\n buildLogState.lines.push(trimmed);\n });\n}\n\nexport const flushBuildLog = Effect.fn(\"flushBuildLog\")(function* () {\n if (!buildLogState.title || buildLogState.lines.length === 0) {\n return;\n }\n\n const level = buildLogState.level;\n const title = buildLogState.title;\n const lines = [...buildLogState.lines];\n\n // Reset state before logging in case logging itself fails\n buildLogState.level = \"Info\";\n buildLogState.title = null;\n buildLogState.lines = [];\n\n yield* logBuildResult(level, title, lines);\n });\n\nexport function withBufferedBuildLog<A, E, R>(\n level: LogLevel.Literal,\n title: string,\n use: (\n log: (line: string) => ReturnType<typeof appendBuildLogLine>\n ) => Effect.Effect<A, E, R>\n): Effect.Effect<A, E, R> {\n return Effect.acquireUseRelease(\n setBuildLogTitle(level, title),\n () => use((line) => appendBuildLogLine(line)),\n (_, _exit) => flushBuildLog()\n );\n}\n\ntype BuildLogState = {\n level: LogLevel.Literal;\n title: string | null;\n lines: string[];\n};\n\nconst buildLogState: BuildLogState = {\n level: \"Info\",\n title: null,\n lines: [],\n};\n\nfunction shouldLog(level: LogLevel.Literal) {\n const debugEnabled = process.env.INTERFERE_PLUGIN_DEBUG === \"1\";\n const minLevel = debugEnabled ? LogLevel.Debug : InterfereLogger.minimumLevel();\n const currentLevel = LogLevel.fromLiteral(level);\n return LogLevel.greaterThanEqual(currentLevel, minLevel);\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"logger.mjs","names":["prefixes: Record<LogLevel.Literal, string>","textStyles: Record<LogLevel.Literal, ChalkInstance>","logMethods: Partial<Record<LogLevel.Literal, keyof Console>>","buildLogState: BuildLogState"],"sources":["../../src/build/logger.ts"],"sourcesContent":["import { InterfereLogger } from \"@interfere/effect-utils/observability\";\nimport chalk, { type ChalkInstance } from \"chalk\";\nimport { Cause, Effect, Logger, LogLevel } from \"effect\";\n\nconst buildConsole = globalThis.console;\n\nconst prefixes: Record<LogLevel.Literal, string> = {\n Info: chalk.cyan.bold(\" \"),\n Debug: chalk.gray.bold(\" \"),\n All: chalk.gray.bold(\" \"),\n Trace: chalk.magenta.bold(\" \"),\n Warning: chalk.yellow.bold(\"⚠\"),\n Error: chalk.red.bold(\"⨯\"),\n Fatal: chalk.red.bold(\"⨯\"),\n None: chalk.white.bold(\" \"),\n} as const;\n\nconst textStyles: Record<LogLevel.Literal, ChalkInstance> = {\n Info: chalk.cyan.bold,\n Debug: chalk.gray.bold,\n All: chalk.gray.bold,\n Trace: chalk.magenta.bold,\n Warning: chalk.yellow.bold,\n Error: chalk.red.bold,\n Fatal: chalk.red.bold,\n None: chalk.white.bold,\n}\n\nconst logMethods: Partial<Record<LogLevel.Literal, keyof Console>> = {\n Warning: \"warn\",\n Error: \"error\",\n};\n\nfunction tagForLevel(level: LogLevel.Literal) {\n switch (level) {\n case \"Error\":\n case \"Fatal\":\n return \"[error]\";\n case \"Warning\":\n return \"[warn]\";\n case \"Debug\":\n return \"[debug]\";\n default:\n return \"\";\n }\n}\n\nconst nextBuildLogger = Logger.make<unknown, void>(\n ({ logLevel, message, cause }) => {\n if (!shouldLog(logLevel._tag)) {\n return;\n }\n\n const renderedMessage = coerceToArray(message)\n .map(formatValue)\n .filter(Boolean)\n .join(\" \")\n .trim();\n\n if (renderedMessage.length > 0) {\n levelLog(logLevel._tag, renderedMessage);\n } else {\n levelLog(logLevel._tag);\n }\n\n if (!Cause.isEmpty(cause)) {\n levelLog(\n logLevel._tag,\n `${chalk.dim(\"details\")} ${Cause.pretty(cause, {\n renderErrorCause: true,\n })}`\n );\n }\n }\n);\n\n\n\nfunction systemLog(level: LogLevel.Literal, ...message: string[]) {\n if (!shouldLog(level)) {\n return;\n }\n\n const consoleMethod = logMethods[level] ?? \"log\";\n\n const consoleFn = buildConsole[consoleMethod];\n if (typeof consoleFn !== \"function\") {\n return;\n }\n\n const invoke = (...args: unknown[]) =>\n Reflect.apply(consoleFn, buildConsole, args);\n\n if (message.length === 0) {\n invoke(\"\");\n return;\n }\n\n if (message.length === 1) {\n invoke(` ${message[0]}`);\n return;\n }\n\n invoke(` `, ...message);\n}\n\nfunction coerceToArray(value: unknown): string[] {\n if (Array.isArray(value)) {\n return value.map(formatValue);\n }\n\n return [formatValue(value)];\n}\n\nfunction formatValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (value instanceof Error) {\n return value.stack ?? value.message;\n }\n\n if (value === null || value === undefined) {\n return \"\";\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport { nextBuildLogger };\n\nfunction levelLog(level: LogLevel.Literal, ...message: string[]) {\n if (!shouldLog(level)) {\n return;\n }\n\n const consoleMethod = logMethods[level] ?? \"log\";\n const prefix = prefixes[level] ?? prefixes.Info;\n const tag = tagForLevel(level);\n\n const consoleFn = buildConsole[consoleMethod];\n\n if (typeof consoleFn !== \"function\") {\n return;\n }\n\n const invoke = (...args: unknown[]) =>\n Reflect.apply(consoleFn, buildConsole, args);\n\n if (message.length === 0) {\n invoke(\"\");\n return;\n }\n\n const tagPart = tag ? ` ${tag}` : \"\";\n\n if (message.length === 1) {\n invoke(` ${prefix}${tagPart} ${message[0]}`);\n return;\n }\n\n invoke(` ${prefix}${tagPart}`, ...message);\n}\n\nexport function logBuildResult(level: LogLevel.Literal, title: string, lines: string[]) {\n if (!shouldLog(level)) {\n return Effect.void;\n }\n\n return Effect.sync(() => {\n systemLog(level, `❖ ${chalk.white(\"Interfere →\")} ${textStyles[level](title)}`);\n\n if (lines.length === 0) {\n return;\n }\n\n const prefix = prefixes[level] ?? prefixes.Info;\n const tag = tagForLevel(level);\n const tagPart = tag ? `${tag} ` : \"\";\n const consoleMethod = logMethods[level] ?? \"log\";\n const consoleFn = buildConsole[consoleMethod];\n\n if (typeof consoleFn !== \"function\") {\n return;\n }\n\n const invoke = (...args: unknown[]) =>\n Reflect.apply(consoleFn, buildConsole, args);\n\n if (lines.length === 1) {\n // Single line - connector plus tag after the connector\n const connector = \"└\";\n invoke(` ${prefix} ${connector} ${tagPart}${lines[0]}`);\n return;\n }\n\n // Multi-line - tree structure with connectors and tag after connector\n lines.forEach((line, index) => {\n const isLast = index === lines.length - 1;\n const connector = isLast ? \"└\" : \"├\";\n invoke(` ${prefix} ${connector} ${tagPart}${line}`);\n });\n });\n}\n\nexport function setBuildLogTitle(\n level: LogLevel.Literal,\n title: string\n) {\n return Effect.sync(() => {\n buildLogState.level = level;\n buildLogState.title = title;\n });\n}\n\nexport function appendBuildLogLine(line: string) {\n return Effect.sync(() => {\n const trimmed = line.trim();\n if (trimmed.length === 0) {\n return;\n }\n\n buildLogState.lines.push(trimmed);\n });\n}\n\nexport function flushBuildLog() {\n return Effect.gen(function* () {\n if (!buildLogState.title || buildLogState.lines.length === 0) {\n return;\n }\n\n const level = buildLogState.level;\n const title = buildLogState.title;\n const lines = [...buildLogState.lines];\n\n // Reset state before logging in case logging itself fails\n buildLogState.level = \"Info\";\n buildLogState.title = null;\n buildLogState.lines = [];\n\n yield* logBuildResult(level, title, lines);\n });\n}\n\nexport function withBufferedBuildLog(\n level: LogLevel.Literal,\n title: string,\n use: (\n log: (line: string) => ReturnType<typeof appendBuildLogLine>\n ) => Effect.Effect<unknown, unknown, unknown>\n) {\n return Effect.acquireUseRelease(\n setBuildLogTitle(level, title),\n () => use((line) => appendBuildLogLine(line)),\n (_, _exit) => flushBuildLog()\n );\n}\n\ntype BuildLogState = {\n level: LogLevel.Literal;\n title: string | null;\n lines: string[];\n};\n\nconst buildLogState: BuildLogState = {\n level: \"Info\",\n title: null,\n lines: [],\n};\n\nfunction shouldLog(level: LogLevel.Literal) {\n const debugEnabled = process.env.INTERFERE_PLUGIN_DEBUG === \"1\";\n const minLevel = debugEnabled ? LogLevel.Debug : InterfereLogger.minimumLevel();\n const currentLevel = LogLevel.fromLiteral(level);\n return LogLevel.greaterThanEqual(currentLevel, minLevel);\n}\n\n"],"mappings":"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"}
@@ -1,21 +1,19 @@
1
1
  import { PreflightConfig } from "../lib/types.mjs";
2
- import { FileDeleteError, FileGlobError, MissingBuildIdError, MissingReleaseIdError } from "./source-maps/errors.mjs";
3
2
  import { ConfigService } from "./services/config.service.mjs";
4
3
  import { ReleaseIdentityService } from "./services/release-identity.service.mjs";
5
4
  import { SourceMapService } from "./services/source-map.service.mjs";
6
- import { ReleaseApiService } from "./services/release-api.service.mjs";
7
- import { SourceMapFailureCleanupService } from "./services/source-map-failure-cleanup.service.mjs";
8
5
  import { Effect, Layer } from "effect";
9
6
 
10
7
  //#region src/build/release-program.d.ts
8
+
11
9
  /**
12
10
  * The main release upload program.
13
11
  * This is a single Effect that orchestrates the entire release process.
14
12
  */
15
- declare const releaseProgram: Effect.Effect<void, MissingBuildIdError | MissingReleaseIdError | FileGlobError | FileDeleteError, ReleaseApiService | ReleaseIdentityService | SourceMapFailureCleanupService | ConfigService | SourceMapService>;
13
+ declare const releaseProgram: Effect.Effect<unknown, unknown, unknown>;
16
14
  /**
17
15
  * Create the layer stack for the release program
18
16
  */
19
- declare const createReleaseLayers: (config: PreflightConfig) => Layer.Layer<ReleaseApiService | ReleaseIdentityService | SourceMapFailureCleanupService | ConfigService | SourceMapService, never, never>;
17
+ declare const createReleaseLayers: (config: PreflightConfig) => Layer.Layer<ConfigService | SourceMapService | ReleaseIdentityService, never, never>;
20
18
  //#endregion
21
19
  export { createReleaseLayers, releaseProgram };
@@ -1 +1 @@
1
- {"version":3,"file":"release-program.d.mts","names":[],"sources":["../../src/build/release-program.ts"],"mappings":";;;;;;;;;;;AA6BA;;;cAAa,cAAA,EAAc,MAAA,CAAA,MAAA,OAwI1B,mBAAA,GAxI0B,qBAAA,GAAA,aAAA,GAAA,eAAA,EAAA,iBAAA,GAAA,sBAAA,GAAA,8BAAA,GAAA,aAAA,GAAA,gBAAA;AAAA;;;AAAA,cA6Id,mBAAA,GAAA,MAAA,EAA+B,eAAA,KAAe,KAAA,CAAA,KAAA,CAAA,iBAAA,GAAA,sBAAA,GAAA,8BAAA,GAAA,aAAA,GAAA,gBAAA"}
1
+ {"version":3,"file":"release-program.d.mts","names":[],"sources":["../../src/build/release-program.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAuBA;AA6IA;AAA4C,cA7I/B,cA6I+B,EA7IjB,MAAA,CAAA,MA6IiB,CAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA;;;;AAAe,cAA9C,mBAA8C,EAAA,CAAA,MAAA,EAAf,eAAe,EAAA,GAAA,KAAA,CAAA,KAAA,CAAA,aAAA,GAAA,gBAAA,GAAA,sBAAA,EAAA,KAAA,EAAA,KAAA,CAAA"}
@@ -2,9 +2,9 @@ import { resolveApiUrl } from "./env-config.mjs";
2
2
  import { logBuildResult, withBufferedBuildLog } from "./logger.mjs";
3
3
  import { ConfigService, ConfigServiceLive } from "./services/config.service.mjs";
4
4
  import { ReleaseIdentityService, ReleaseIdentityServiceLive } from "./services/release-identity.service.mjs";
5
- import { ReleaseApiService, ReleaseApiServiceLive } from "./services/release-api.service.mjs";
5
+ import { createRelease } from "./source-maps/api.mjs";
6
+ import { maybeCleanupAfterFailure } from "./source-maps/files.mjs";
6
7
  import { SourceMapService, SourceMapServiceLive } from "./services/source-map.service.mjs";
7
- import { SourceMapFailureCleanupService, SourceMapFailureCleanupServiceLive } from "./services/source-map-failure-cleanup.service.mjs";
8
8
  import { Effect, Layer } from "effect";
9
9
 
10
10
  //#region src/build/release-program.ts
@@ -49,7 +49,7 @@ const releaseProgram = Effect.gen(function* () {
49
49
  }
50
50
  yield* Effect.logDebug("Creating release");
51
51
  const createStart = Date.now();
52
- const releaseResponse = yield* (yield* ReleaseApiService).createRelease(config, {
52
+ const releaseResponse = yield* createRelease(config, {
53
53
  environment: config.environment,
54
54
  sourceId: identity.buildId,
55
55
  sourceType: identity.sourceControl.type,
@@ -73,11 +73,10 @@ const releaseProgram = Effect.gen(function* () {
73
73
  const cleanupStart = Date.now();
74
74
  yield* sourceMapService.cleanup(sourceMapFiles, !!config.debug);
75
75
  yield* Effect.logDebug(`Cleanup completed in ${Date.now() - cleanupStart}ms`);
76
- }).pipe(Effect.catchIf((error) => error._tag !== "MissingBuildIdError" && error._tag !== "MissingReleaseIdError", (error) => withBufferedBuildLog("Error", "Failed to upload source maps", Effect.fn("handleUploadError")(function* (log) {
76
+ }).pipe(Effect.catchIf((error) => error._tag !== "MissingBuildIdError" && error._tag !== "MissingReleaseIdError", (error) => withBufferedBuildLog("Error", "Failed to upload source maps", (log) => Effect.gen(function* () {
77
77
  const config = yield* ConfigService;
78
- const failureCleanup = yield* SourceMapFailureCleanupService;
79
78
  yield* log(String(error));
80
- if (config.environment === "production" && config.cleanupSourceMaps !== false) yield* failureCleanup.maybeCleanupAfterFailure(!!config.debug);
79
+ if (config.environment === "production" && config.cleanupSourceMaps !== false) yield* maybeCleanupAfterFailure(!!config.debug);
81
80
  }))), Effect.withSpan("interfere.release"));
82
81
  /**
83
82
  * Create the layer stack for the release program
@@ -86,7 +85,7 @@ const createReleaseLayers = (config) => {
86
85
  const configLayer = ConfigServiceLive(config);
87
86
  const identityLayer = ReleaseIdentityServiceLive;
88
87
  const sourceMapLayer = SourceMapServiceLive.pipe(Layer.provide(configLayer));
89
- return Layer.mergeAll(configLayer, identityLayer, sourceMapLayer, ReleaseApiServiceLive, SourceMapFailureCleanupServiceLive);
88
+ return Layer.mergeAll(configLayer, identityLayer, sourceMapLayer);
90
89
  };
91
90
 
92
91
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"release-program.mjs","names":[],"sources":["../../src/build/release-program.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\nimport type { PreflightConfig } from \"../lib/types.js\";\nimport { resolveApiUrl } from \"./env-config.js\";\nimport {\n logBuildResult,\n withBufferedBuildLog,\n} from \"./logger.js\";\nimport {\n ConfigService,\n ConfigServiceLive,\n} from \"./services/config.service.js\";\nimport {\n ReleaseIdentityService,\n ReleaseIdentityServiceLive,\n} from \"./services/release-identity.service.js\";\nimport {\n ReleaseApiService,\n ReleaseApiServiceLive,\n} from \"./services/release-api.service.js\";\nimport { SourceMapService, SourceMapServiceLive } from \"./services/source-map.service.js\";\nimport {\n SourceMapFailureCleanupService,\n SourceMapFailureCleanupServiceLive,\n} from \"./services/source-map-failure-cleanup.service.js\";\n\n/**\n * The main release upload program.\n * This is a single Effect that orchestrates the entire release process.\n */\nexport const releaseProgram = Effect.gen(function* () {\n const config = yield* ConfigService;\n\n // Early exits\n if (process.env.NODE_ENV === \"development\") {\n yield* logBuildResult(\"Info\", \"Skipping Release\", [\"Development build detected\"]);\n return;\n }\n\n if (!config.enabled) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\"Interfere is disabled. (`interfere.enabled` is `false` in your `next.config.(js|ts)`)\"]\n );\n return;\n }\n\n const sourceMapService = yield* SourceMapService;\n\n if (!config.secretKey) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\"Missing secret key. Please set the `INTERFERE_SECRET_KEY` environment variable.\"]\n );\n return;\n }\n\n // Get release identity (will fail if can't determine)\n yield* Effect.logDebug(\"Getting release identity\");\n const identityStart = Date.now();\n const identityEffect = yield* ReleaseIdentityService;\n const identity = yield* identityEffect;\n yield* Effect.logDebug(`Release identity resolved in ${Date.now() - identityStart}ms`);\n\n // Check for required metadata\n if (!identity.sourceControl) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\n \"Could not determine source control metadata (no supported VCS provider detected).\",\n \"Ensure your CI checks out the git repository and that a supported provider is configured.\",\n ]\n );\n return;\n }\n\n if (!identity.deployment) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\n \"Could not determine deployment metadata (no supported deployment provider detected).\",\n \"If this is a local build you can ignore this. Otherwise, expose your platform's system env vars (e.g. VERCEL_*).\",\n ]\n );\n return;\n }\n\n // Find source maps\n yield* Effect.logDebug(\"Finding source maps\");\n const findStart = Date.now();\n const sourceMapFiles = yield* sourceMapService.find;\n yield* Effect.logDebug(`Found ${sourceMapFiles.length} source maps in ${Date.now() - findStart}ms`);\n\n if (sourceMapFiles.length === 0) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\"No source maps found. Is `productionBrowserSourceMaps` set to `false` in your `next.config.js`?\"]\n );\n return;\n }\n\n // Create release\n yield* Effect.logDebug(\"Creating release\");\n const createStart = Date.now();\n const releaseApi = yield* ReleaseApiService;\n const releaseResponse = yield* releaseApi.createRelease(config, {\n environment: config.environment,\n sourceId: identity.buildId,\n sourceType: identity.sourceControl.type,\n sourceMetadata: identity.sourceControl.metadata,\n destinationType: identity.deployment.type,\n destinationMetadata: identity.deployment.metadata,\n });\n yield* Effect.logDebug(`Release created in ${Date.now() - createStart}ms`);\n\n // Read and upload source maps\n yield* Effect.logDebug(\"Reading source maps\");\n const readStart = Date.now();\n const sourceMaps = yield* sourceMapService.read(sourceMapFiles);\n yield* Effect.logDebug(`Read ${sourceMaps.length} source maps in ${Date.now() - readStart}ms`);\n \n yield* Effect.logDebug(\"Uploading source maps\");\n const uploadStart = Date.now();\n yield* sourceMapService.upload(sourceMaps, {\n ...releaseResponse,\n apiUrl: resolveApiUrl(),\n });\n yield* Effect.logDebug(`Source maps uploaded in ${Date.now() - uploadStart}ms`);\n\n // Cleanup\n yield* Effect.logDebug(\"Cleaning up source maps\");\n const cleanupStart = Date.now();\n yield* sourceMapService.cleanup(sourceMapFiles, !!config.debug);\n yield* Effect.logDebug(`Cleanup completed in ${Date.now() - cleanupStart}ms`);\n}).pipe(\n Effect.catchIf(\n // Only catch upload-related errors, let identity errors propagate\n (error) =>\n error._tag !== \"MissingBuildIdError\" &&\n error._tag !== \"MissingReleaseIdError\",\n (error) =>\n withBufferedBuildLog(\"Error\", \"Failed to upload source maps\", Effect.fn(\"handleUploadError\")(function* (log) {\n const config = yield* ConfigService;\n const failureCleanup = yield* SourceMapFailureCleanupService;\n\n // Queue up build log lines so they appear in a single structured block\n yield* log(String(error));\n\n // Cleanup on failure\n if (\n config.environment === \"production\" &&\n config.cleanupSourceMaps !== false\n ) {\n yield* failureCleanup.maybeCleanupAfterFailure(!!config.debug);\n }\n\n // Swallow the error so we don't surface a noisy FiberFailure stack trace\n return;\n }))\n ),\n Effect.withSpan(\"interfere.release\")\n);\n\n/**\n * Create the layer stack for the release program\n */\nexport const createReleaseLayers = (config: PreflightConfig) => {\n const configLayer = ConfigServiceLive(config);\n\n const identityLayer = ReleaseIdentityServiceLive;\n \n const sourceMapLayer = SourceMapServiceLive.pipe(\n Layer.provide(configLayer)\n );\n \n return Layer.mergeAll(\n configLayer,\n identityLayer,\n sourceMapLayer,\n ReleaseApiServiceLive,\n SourceMapFailureCleanupServiceLive\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"release-program.mjs","names":[],"sources":["../../src/build/release-program.ts"],"sourcesContent":["import { Effect, Layer } from \"effect\";\nimport type { PreflightConfig } from \"../lib/types.js\";\nimport { resolveApiUrl } from \"./env-config.js\";\nimport {\n logBuildResult,\n withBufferedBuildLog,\n} from \"./logger.js\";\nimport {\n ConfigService,\n ConfigServiceLive,\n} from \"./services/config.service.js\";\nimport {\n ReleaseIdentityService,\n ReleaseIdentityServiceLive,\n} from \"./services/release-identity.service.js\";\nimport { SourceMapService, SourceMapServiceLive } from \"./services/source-map.service.js\";\nimport { createRelease } from \"./source-maps/api.js\";\nimport { maybeCleanupAfterFailure } from \"./source-maps/files.js\";\n\n/**\n * The main release upload program.\n * This is a single Effect that orchestrates the entire release process.\n */\nexport const releaseProgram = Effect.gen(function* () {\n const config = yield* ConfigService;\n\n // Early exits\n if (process.env.NODE_ENV === \"development\") {\n yield* logBuildResult(\"Info\", \"Skipping Release\", [\"Development build detected\"]);\n return;\n }\n\n if (!config.enabled) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\"Interfere is disabled. (`interfere.enabled` is `false` in your `next.config.(js|ts)`)\"]\n );\n return;\n }\n\n const sourceMapService = yield* SourceMapService;\n\n if (!config.secretKey) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\"Missing secret key. Please set the `INTERFERE_SECRET_KEY` environment variable.\"]\n );\n return;\n }\n\n // Get release identity (will fail if can't determine)\n yield* Effect.logDebug(\"Getting release identity\");\n const identityStart = Date.now();\n const identityEffect = yield* ReleaseIdentityService;\n const identity = yield* identityEffect;\n yield* Effect.logDebug(`Release identity resolved in ${Date.now() - identityStart}ms`);\n\n // Check for required metadata\n if (!identity.sourceControl) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\n \"Could not determine source control metadata (no supported VCS provider detected).\",\n \"Ensure your CI checks out the git repository and that a supported provider is configured.\",\n ]\n );\n return;\n }\n\n if (!identity.deployment) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\n \"Could not determine deployment metadata (no supported deployment provider detected).\",\n \"If this is a local build you can ignore this. Otherwise, expose your platform's system env vars (e.g. VERCEL_*).\",\n ]\n );\n return;\n }\n\n // Find source maps\n yield* Effect.logDebug(\"Finding source maps\");\n const findStart = Date.now();\n const sourceMapFiles = yield* sourceMapService.find;\n yield* Effect.logDebug(`Found ${sourceMapFiles.length} source maps in ${Date.now() - findStart}ms`);\n\n if (sourceMapFiles.length === 0) {\n yield* logBuildResult(\n \"Warning\",\n \"Skipping Release\",\n [\"No source maps found. Is `productionBrowserSourceMaps` set to `false` in your `next.config.js`?\"]\n );\n return;\n }\n\n // Create release\n yield* Effect.logDebug(\"Creating release\");\n const createStart = Date.now();\n const releaseResponse = yield* createRelease(config, {\n environment: config.environment,\n sourceId: identity.buildId,\n sourceType: identity.sourceControl.type,\n sourceMetadata: identity.sourceControl.metadata,\n destinationType: identity.deployment.type,\n destinationMetadata: identity.deployment.metadata,\n });\n yield* Effect.logDebug(`Release created in ${Date.now() - createStart}ms`);\n\n // Read and upload source maps\n yield* Effect.logDebug(\"Reading source maps\");\n const readStart = Date.now();\n const sourceMaps = yield* sourceMapService.read(sourceMapFiles);\n yield* Effect.logDebug(`Read ${sourceMaps.length} source maps in ${Date.now() - readStart}ms`);\n \n yield* Effect.logDebug(\"Uploading source maps\");\n const uploadStart = Date.now();\n yield* sourceMapService.upload(sourceMaps, {\n ...releaseResponse,\n apiUrl: resolveApiUrl(),\n });\n yield* Effect.logDebug(`Source maps uploaded in ${Date.now() - uploadStart}ms`);\n\n // Cleanup\n yield* Effect.logDebug(\"Cleaning up source maps\");\n const cleanupStart = Date.now();\n yield* sourceMapService.cleanup(sourceMapFiles, !!config.debug);\n yield* Effect.logDebug(`Cleanup completed in ${Date.now() - cleanupStart}ms`);\n}).pipe(\n Effect.catchIf(\n // Only catch upload-related errors, let identity errors propagate\n (error) =>\n error._tag !== \"MissingBuildIdError\" &&\n error._tag !== \"MissingReleaseIdError\",\n (error) =>\n withBufferedBuildLog(\"Error\", \"Failed to upload source maps\", (log) =>\n Effect.gen(function* () {\n const config = yield* ConfigService;\n\n // Queue up build log lines so they appear in a single structured block\n yield* log(String(error));\n\n // Cleanup on failure\n if (\n config.environment === \"production\" &&\n config.cleanupSourceMaps !== false\n ) {\n yield* maybeCleanupAfterFailure(!!config.debug);\n }\n\n // Swallow the error so we don't surface a noisy FiberFailure stack trace\n return;\n })\n )\n ),\n Effect.withSpan(\"interfere.release\")\n);\n\n/**\n * Create the layer stack for the release program\n */\nexport const createReleaseLayers = (config: PreflightConfig) => {\n const configLayer = ConfigServiceLive(config);\n\n const identityLayer = ReleaseIdentityServiceLive;\n \n const sourceMapLayer = SourceMapServiceLive.pipe(\n Layer.provide(configLayer)\n );\n \n return Layer.mergeAll(\n configLayer,\n identityLayer,\n sourceMapLayer\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"secret-key.d.mts","names":[],"sources":["../../src/build/secret-key.ts"],"mappings":";;AAQA;;;;;iBAAgB,6BAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"secret-key.d.mts","names":[],"sources":["../../src/build/secret-key.ts"],"sourcesContent":[],"mappings":";;AAQA;;;;;iBAAgB,6BAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.service.d.mts","names":[],"sources":["../../../src/build/services/config.service.ts"],"mappings":";;;;cAC0E,kBAAA;cAE7D,aAAA,SAAsB,kBAAA;AAAA,cAKtB,iBAAA,GAAA,MAAA,EAA6B,eAAA,KAAe,KAAA,CAAA,KAAA,CAAA,aAAA"}
1
+ {"version":3,"file":"config.service.d.mts","names":[],"sources":["../../../src/build/services/config.service.ts"],"sourcesContent":[],"mappings":";;;;cAC0E;cAE7D,aAAA,SAAsB,kBAAA;cAKtB,4BAA6B,oBAAe,KAAA,CAAA,MAAA"}
@@ -3,17 +3,20 @@ interface InstrumentationFiles {
3
3
  readonly server: string | null;
4
4
  readonly client: string | null;
5
5
  }
6
- interface InstrumentationValidation {
7
- readonly hasFile: boolean;
8
- readonly hasRegisterFunction: boolean;
9
- readonly hasOnRequestError: boolean;
10
- readonly filePath: string | null;
11
- }
12
- declare function detectInstrumentationFilesSync(projectDir?: string): InstrumentationFiles;
13
- declare function validateInstrumentationContent(filePath: string | null): InstrumentationValidation;
14
- declare function detectAndValidateInstrumentationSync(projectDir?: string): {
15
- files: InstrumentationFiles;
16
- serverValidation: InstrumentationValidation;
17
- };
6
+ /**
7
+ * Synchronously detect instrumentation files at build time.
8
+ *
9
+ * Searches for:
10
+ * - Server instrumentation: `instrumentation.{ts,js,mts,mjs}`
11
+ * - Client instrumentation: `instrumentation-client.{ts,js,mts,mjs}`
12
+ *
13
+ * In the following directories (in order):
14
+ * 1. Project root
15
+ * 2. `src/` directory
16
+ *
17
+ * @param cwd - The current working directory (defaults to process.cwd())
18
+ * @returns An object with paths to the detected instrumentation files, or null if not found
19
+ */
20
+ declare function detectInstrumentationFilesSync(cwd?: string): InstrumentationFiles;
18
21
  //#endregion
19
- export { InstrumentationFiles, InstrumentationValidation, detectAndValidateInstrumentationSync, detectInstrumentationFilesSync, validateInstrumentationContent };
22
+ export { InstrumentationFiles, detectInstrumentationFilesSync };
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation-detection.service.d.mts","names":[],"sources":["../../../src/build/services/instrumentation-detection.service.ts"],"mappings":";UAGiB,oBAAA;EAAA,SAAA,MAAA;EAAA,SAAA,MAAA;AAAA;AAAA,UAKA,yBAAA;EAAA,SAAA,OAAA;EAAA,SAAA,mBAAA;EAAA,SAAA,iBAAA;EAAA,SAAA,QAAA;AAAA;AAAA,iBAiDD,8BAAA,CAAA,UAAA,YAEb,oBAAA;AAAA,iBAca,8BAAA,CAAA,QAAA,kBAEb,yBAAA;AAAA,iBAsCa,oCAAA,CAAA,UAAA;EAAA,KAAA,EACP,oBAAA;EAAA,gBAAA,EACW,yBAAA;AAAA"}
1
+ {"version":3,"file":"instrumentation-detection.service.d.mts","names":[],"sources":["../../../src/build/services/instrumentation-detection.service.ts"],"sourcesContent":[],"mappings":";UAGiB,oBAAA;EAAA,SAAA,MAAA,EAAA,MAAoB,GAAA,IAAA;EA6DrB,SAAA,MAAA,EAAA,MAAA,GAAA,IAAA;;;;;;;;;;;;;;;;iBAAA,8BAAA,gBAA8C"}
@@ -2,76 +2,59 @@ import * as path$1 from "node:path";
2
2
  import * as fs from "node:fs";
3
3
 
4
4
  //#region src/build/services/instrumentation-detection.service.ts
5
- const INSTRUMENTATION_SERVER_FILES = [
6
- "instrumentation.ts",
7
- "instrumentation.js",
8
- "instrumentation.mts",
9
- "instrumentation.mjs"
10
- ];
11
- const INSTRUMENTATION_CLIENT_FILES = [
12
- "instrumentation-client.ts",
13
- "instrumentation-client.js",
14
- "instrumentation-client.mts",
15
- "instrumentation-client.mjs"
16
- ];
17
- const SEARCH_DIRECTORIES = ["", "src"];
18
- const REGISTER_EXPORT_PATTERNS = [
19
- /export\s+(async\s+)?function\s+register\s*\(/,
20
- /export\s+const\s+register\s*=\s*(async\s*)?\(/,
21
- /export\s+const\s+register\s*=\s*(async\s+)?function/
22
- ];
23
- const ON_REQUEST_ERROR_EXPORT_PATTERNS = [/export\s+(async\s+)?function\s+onRequestError\s*\(/, /export\s+const\s+onRequestError\s*[=:]/];
24
- function findInstrumentationFile(projectDir, fileNames) {
25
- for (const dir of SEARCH_DIRECTORIES) for (const fileName of fileNames) {
26
- const filePath = path$1.join(projectDir, dir, fileName);
27
- if (fs.existsSync(filePath)) return path$1.resolve(filePath);
28
- }
29
- return null;
30
- }
31
- function detectInstrumentationFilesSync(projectDir) {
32
- const dir = projectDir ?? process.cwd();
33
- const resolvedDir = path$1.resolve(dir);
34
- if (!fs.existsSync(resolvedDir)) return {
35
- server: null,
36
- client: null
37
- };
38
- return {
39
- server: findInstrumentationFile(resolvedDir, INSTRUMENTATION_SERVER_FILES),
40
- client: findInstrumentationFile(resolvedDir, INSTRUMENTATION_CLIENT_FILES)
41
- };
5
+ const FILE_PATTERNS = {
6
+ server: [
7
+ "instrumentation.ts",
8
+ "instrumentation.js",
9
+ "instrumentation.mts",
10
+ "instrumentation.mjs"
11
+ ],
12
+ client: [
13
+ "instrumentation-client.ts",
14
+ "instrumentation-client.js",
15
+ "instrumentation-client.mts",
16
+ "instrumentation-client.mjs"
17
+ ]
18
+ };
19
+ /**
20
+ * Get the standard Next.js locations to search for instrumentation files.
21
+ */
22
+ function getSearchPaths(cwd) {
23
+ return [cwd, path$1.join(cwd, "src")];
42
24
  }
43
- function validateInstrumentationContent(filePath) {
44
- if (!filePath || !fs.existsSync(filePath)) return {
45
- hasFile: false,
46
- hasRegisterFunction: false,
47
- hasOnRequestError: false,
48
- filePath: null
49
- };
50
- let content;
51
- try {
52
- content = fs.readFileSync(filePath, "utf-8");
53
- } catch {
54
- return {
55
- hasFile: true,
56
- hasRegisterFunction: false,
57
- hasOnRequestError: false,
58
- filePath
59
- };
25
+ /**
26
+ * Find the first matching file from a list of file names in the search paths.
27
+ */
28
+ function findFirstMatchingFile(searchPaths, fileNames) {
29
+ for (const basePath of searchPaths) for (const fileName of fileNames) {
30
+ const filePath = path$1.join(basePath, fileName);
31
+ try {
32
+ if (fs.existsSync(filePath)) return filePath;
33
+ } catch {}
60
34
  }
61
- return {
62
- hasFile: true,
63
- hasRegisterFunction: REGISTER_EXPORT_PATTERNS.some((pattern) => pattern.test(content)),
64
- hasOnRequestError: ON_REQUEST_ERROR_EXPORT_PATTERNS.some((pattern) => pattern.test(content)),
65
- filePath
66
- };
35
+ return null;
67
36
  }
68
- function detectAndValidateInstrumentationSync(projectDir) {
69
- const files = detectInstrumentationFilesSync(projectDir);
37
+ /**
38
+ * Synchronously detect instrumentation files at build time.
39
+ *
40
+ * Searches for:
41
+ * - Server instrumentation: `instrumentation.{ts,js,mts,mjs}`
42
+ * - Client instrumentation: `instrumentation-client.{ts,js,mts,mjs}`
43
+ *
44
+ * In the following directories (in order):
45
+ * 1. Project root
46
+ * 2. `src/` directory
47
+ *
48
+ * @param cwd - The current working directory (defaults to process.cwd())
49
+ * @returns An object with paths to the detected instrumentation files, or null if not found
50
+ */
51
+ function detectInstrumentationFilesSync(cwd) {
52
+ const searchPaths = getSearchPaths(cwd ?? process.cwd());
70
53
  return {
71
- files,
72
- serverValidation: validateInstrumentationContent(files.server)
54
+ server: findFirstMatchingFile(searchPaths, FILE_PATTERNS.server),
55
+ client: findFirstMatchingFile(searchPaths, FILE_PATTERNS.client)
73
56
  };
74
57
  }
75
58
 
76
59
  //#endregion
77
- export { detectAndValidateInstrumentationSync, detectInstrumentationFilesSync, validateInstrumentationContent };
60
+ export { detectInstrumentationFilesSync };
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation-detection.service.mjs","names":["path"],"sources":["../../../src/build/services/instrumentation-detection.service.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nexport interface InstrumentationFiles {\n readonly server: string | null;\n readonly client: string | null;\n}\n\nexport interface InstrumentationValidation {\n readonly hasFile: boolean;\n readonly hasRegisterFunction: boolean;\n readonly hasOnRequestError: boolean;\n readonly filePath: string | null;\n}\n\nconst INSTRUMENTATION_SERVER_FILES = [\n \"instrumentation.ts\",\n \"instrumentation.js\",\n \"instrumentation.mts\",\n \"instrumentation.mjs\",\n] as const;\n\nconst INSTRUMENTATION_CLIENT_FILES = [\n \"instrumentation-client.ts\",\n \"instrumentation-client.js\",\n \"instrumentation-client.mts\",\n \"instrumentation-client.mjs\",\n] as const;\n\nconst SEARCH_DIRECTORIES = [\"\", \"src\"] as const;\n\nconst REGISTER_EXPORT_PATTERNS = [\n /export\\s+(async\\s+)?function\\s+register\\s*\\(/,\n /export\\s+const\\s+register\\s*=\\s*(async\\s*)?\\(/,\n /export\\s+const\\s+register\\s*=\\s*(async\\s+)?function/,\n];\n\nconst ON_REQUEST_ERROR_EXPORT_PATTERNS = [\n /export\\s+(async\\s+)?function\\s+onRequestError\\s*\\(/,\n /export\\s+const\\s+onRequestError\\s*[=:]/,\n];\n\nfunction findInstrumentationFile(\n projectDir: string,\n fileNames: readonly string[]\n): string | null {\n for (const dir of SEARCH_DIRECTORIES) {\n for (const fileName of fileNames) {\n const filePath = path.join(projectDir, dir, fileName);\n if (fs.existsSync(filePath)) {\n return path.resolve(filePath);\n }\n }\n }\n return null;\n}\n\nexport function detectInstrumentationFilesSync(\n projectDir?: string\n): InstrumentationFiles {\n const dir = projectDir ?? process.cwd();\n const resolvedDir = path.resolve(dir);\n\n if (!fs.existsSync(resolvedDir)) {\n return { server: null, client: null };\n }\n\n return {\n server: findInstrumentationFile(resolvedDir, INSTRUMENTATION_SERVER_FILES),\n client: findInstrumentationFile(resolvedDir, INSTRUMENTATION_CLIENT_FILES),\n };\n}\n\nexport function validateInstrumentationContent(\n filePath: string | null\n): InstrumentationValidation {\n if (!filePath || !fs.existsSync(filePath)) {\n return {\n hasFile: false,\n hasRegisterFunction: false,\n hasOnRequestError: false,\n filePath: null,\n };\n }\n\n let content: string;\n try {\n content = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return {\n hasFile: true,\n hasRegisterFunction: false,\n hasOnRequestError: false,\n filePath,\n };\n }\n\n const hasRegisterFunction = REGISTER_EXPORT_PATTERNS.some((pattern) =>\n pattern.test(content)\n );\n\n const hasOnRequestError = ON_REQUEST_ERROR_EXPORT_PATTERNS.some((pattern) =>\n pattern.test(content)\n );\n\n return {\n hasFile: true,\n hasRegisterFunction,\n hasOnRequestError,\n filePath,\n };\n}\n\nexport function detectAndValidateInstrumentationSync(projectDir?: string): {\n files: InstrumentationFiles;\n serverValidation: InstrumentationValidation;\n} {\n const files = detectInstrumentationFilesSync(projectDir);\n const serverValidation = validateInstrumentationContent(files.server);\n\n return { files, serverValidation };\n}\n"],"mappings":";;;;AAeA,MAAM,+BAA+B;CACnC;CACA;CACA;CACA;CACD;AAED,MAAM,+BAA+B;CACnC;CACA;CACA;CACA;CACD;AAED,MAAM,qBAAqB,CAAC,IAAI,MAAM;AAEtC,MAAM,2BAA2B;CAC/B;CACA;CACA;CACD;AAED,MAAM,mCAAmC,CACvC,sDACA,yCACD;AAED,SAAS,wBACP,YACA,WACe;AACf,MAAK,MAAM,OAAO,mBAChB,MAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAWA,OAAK,KAAK,YAAY,KAAK,SAAS;AACrD,MAAI,GAAG,WAAW,SAAS,CACzB,QAAOA,OAAK,QAAQ,SAAS;;AAInC,QAAO;;AAGT,SAAgB,+BACd,YACsB;CACtB,MAAM,MAAM,cAAc,QAAQ,KAAK;CACvC,MAAM,cAAcA,OAAK,QAAQ,IAAI;AAErC,KAAI,CAAC,GAAG,WAAW,YAAY,CAC7B,QAAO;EAAE,QAAQ;EAAM,QAAQ;EAAM;AAGvC,QAAO;EACL,QAAQ,wBAAwB,aAAa,6BAA6B;EAC1E,QAAQ,wBAAwB,aAAa,6BAA6B;EAC3E;;AAGH,SAAgB,+BACd,UAC2B;AAC3B,KAAI,CAAC,YAAY,CAAC,GAAG,WAAW,SAAS,CACvC,QAAO;EACL,SAAS;EACT,qBAAqB;EACrB,mBAAmB;EACnB,UAAU;EACX;CAGH,IAAI;AACJ,KAAI;AACF,YAAU,GAAG,aAAa,UAAU,QAAQ;SACtC;AACN,SAAO;GACL,SAAS;GACT,qBAAqB;GACrB,mBAAmB;GACnB;GACD;;AAWH,QAAO;EACL,SAAS;EACT,qBAV0B,yBAAyB,MAAM,YACzD,QAAQ,KAAK,QAAQ,CACtB;EASC,mBAPwB,iCAAiC,MAAM,YAC/D,QAAQ,KAAK,QAAQ,CACtB;EAMC;EACD;;AAGH,SAAgB,qCAAqC,YAGnD;CACA,MAAM,QAAQ,+BAA+B,WAAW;AAGxD,QAAO;EAAE;EAAO,kBAFS,+BAA+B,MAAM,OAAO;EAEnC"}
1
+ {"version":3,"file":"instrumentation-detection.service.mjs","names":["path"],"sources":["../../../src/build/services/instrumentation-detection.service.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nexport interface InstrumentationFiles {\n readonly server: string | null;\n readonly client: string | null;\n}\n\nconst FILE_PATTERNS = {\n server: [\"instrumentation.ts\", \"instrumentation.js\", \"instrumentation.mts\", \"instrumentation.mjs\"],\n client: [\n \"instrumentation-client.ts\",\n \"instrumentation-client.js\",\n \"instrumentation-client.mts\",\n \"instrumentation-client.mjs\",\n ],\n} as const;\n\n/**\n * Get the standard Next.js locations to search for instrumentation files.\n */\nfunction getSearchPaths(cwd: string): readonly string[] {\n return [\n cwd, // root\n path.join(cwd, \"src\"), // src/\n ];\n}\n\n/**\n * Find the first matching file from a list of file names in the search paths.\n */\nfunction findFirstMatchingFile(\n searchPaths: readonly string[],\n fileNames: readonly string[]\n): string | null {\n for (const basePath of searchPaths) {\n for (const fileName of fileNames) {\n const filePath = path.join(basePath, fileName);\n try {\n if (fs.existsSync(filePath)) {\n return filePath;\n }\n } catch {\n // Ignore errors and continue searching\n }\n }\n }\n return null;\n}\n\n/**\n * Synchronously detect instrumentation files at build time.\n * \n * Searches for:\n * - Server instrumentation: `instrumentation.{ts,js,mts,mjs}`\n * - Client instrumentation: `instrumentation-client.{ts,js,mts,mjs}`\n * \n * In the following directories (in order):\n * 1. Project root\n * 2. `src/` directory\n * \n * @param cwd - The current working directory (defaults to process.cwd())\n * @returns An object with paths to the detected instrumentation files, or null if not found\n */\nexport function detectInstrumentationFilesSync(cwd?: string): InstrumentationFiles {\n const effectiveCwd = cwd ?? process.cwd();\n const searchPaths = getSearchPaths(effectiveCwd);\n\n return {\n server: findFirstMatchingFile(searchPaths, FILE_PATTERNS.server),\n client: findFirstMatchingFile(searchPaths, FILE_PATTERNS.client),\n };\n}\n"],"mappings":";;;;AAQA,MAAM,gBAAgB;CACpB,QAAQ;EAAC;EAAsB;EAAsB;EAAuB;EAAsB;CAClG,QAAQ;EACN;EACA;EACA;EACA;EACD;CACF;;;;AAKD,SAAS,eAAe,KAAgC;AACtD,QAAO,CACL,KACAA,OAAK,KAAK,KAAK,MAAM,CACtB;;;;;AAMH,SAAS,sBACP,aACA,WACe;AACf,MAAK,MAAM,YAAY,YACrB,MAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAWA,OAAK,KAAK,UAAU,SAAS;AAC9C,MAAI;AACF,OAAI,GAAG,WAAW,SAAS,CACzB,QAAO;UAEH;;AAKZ,QAAO;;;;;;;;;;;;;;;;AAiBT,SAAgB,+BAA+B,KAAoC;CAEjF,MAAM,cAAc,eADC,OAAO,QAAQ,KAAK,CACO;AAEhD,QAAO;EACL,QAAQ,sBAAsB,aAAa,cAAc,OAAO;EAChE,QAAQ,sBAAsB,aAAa,cAAc,OAAO;EACjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"preflight.service.d.mts","names":[],"sources":["../../../src/build/services/preflight.service.ts"],"mappings":";;;;;cAWkC,qBAAA;sCAKM,MAAA,CAAO,MAAA,OAAa,uBAAA;EAAA,SAAA,iBAAA,GAAA,GAAA,oBACJ,MAAA,CAAO,MAAA,CAAO,cAAA,EAAgB,qBAAA;EAAA,SAAA,kBAAA,GAAA,GAAA,EAC/C,cAAA,KAAmB,MAAA,CAAO,MAAA,CAAO,cAAA,EAAgB,qBAAA;EAAA,SAAA,WAAA,GAAA,OAAA;IAAA,WAAA;IAAA,KAAA;IAAA,iBAAA;EAAA,MAK9E,MAAA,CAAO,MAAA,CAAO,eAAA,EAAiB,uBAAA;AAAA;AAAA,cAV5B,gBAAA,SAAyB,qBAAA;AAAA,cAsEzB,oBAAA,EAAoB,KAAA,CAAA,KAAA,CAAA,gBAAA"}
1
+ {"version":3,"file":"preflight.service.d.mts","names":[],"sources":["../../../src/build/services/preflight.service.ts"],"sourcesContent":[],"mappings":";;;;;cAWkC;sCAKM,MAAA,CAAO,aAAa;EAL1B,SAAA,iBAAA,EAAA,CAAA,GAAA,EAAA,MAAA,GAAA,IAAA,EAAA,GAMsB,MAAA,CAAO,MAN7B,CAMoC,cANpC,EAMoD,qBANpD,CAAA;qCAOK,mBAAmB,MAAA,CAAO,OAAO,gBAAgB;EAF5B,SAAA,WAAA,EAAA,CAAA,OAAA,EAAA;IAAb,WAAA,CAAA,EAAA,MAAA;IACuB,KAAA,CAAA,EAAA,OAAA;IAAgB,iBAAA,CAAA,EAAA,OAAA;EAA9B,CAAA,EAAA,GAM9C,MAAA,CAAO,MAN8C,CAMvC,eANuC,EAMtB,uBANsB,CAAA;CACxB,CAAA;AAAiC,cAL3D,gBAAA,SAAyB,qBAAA,CAKkC;AAAd,cAgF7C,oBAhFoD,EAgFhC,KAAA,CAAA,KAhFgC,CAgFhC,gBAhFgC,EAAA,KAAA,EAAA,KAAA,CAAA"}