@hawk.so/nextjs 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,533 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ withHawkConfig: () => withHawkConfig
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/with-hawk-config.ts
38
+ var import_node_module = require("module");
39
+ var import_node_path4 = __toESM(require("path"), 1);
40
+ var import_node_process2 = __toESM(require("process"), 1);
41
+
42
+ // src/release.ts
43
+ var import_node_child_process = require("child_process");
44
+ var import_node_process = __toESM(require("process"), 1);
45
+ var RELEASE_ENV_VARIABLE = "HAWK_RELEASE";
46
+ var COMMIT_SHA_ENV_VARIABLES = [
47
+ "GITHUB_SHA",
48
+ "CI_COMMIT_SHA",
49
+ "CI_MERGE_REQUEST_SOURCE_BRANCH_SHA",
50
+ "BITBUCKET_COMMIT",
51
+ "CIRCLE_SHA1",
52
+ "BUILDKITE_COMMIT",
53
+ "DRONE_COMMIT_SHA",
54
+ "TRAVIS_COMMIT",
55
+ "VERCEL_GIT_COMMIT_SHA",
56
+ "CF_PAGES_COMMIT_SHA",
57
+ "RAILWAY_GIT_COMMIT_SHA",
58
+ "RENDER_GIT_COMMIT",
59
+ "HEROKU_BUILD_COMMIT",
60
+ "SOURCE_VERSION",
61
+ "GIT_COMMIT",
62
+ "COMMIT_REF"
63
+ ];
64
+ function getGitRevision(cwd) {
65
+ try {
66
+ const revision = (0, import_node_child_process.execFileSync)("git", ["rev-parse", "HEAD"], {
67
+ cwd,
68
+ encoding: "utf8",
69
+ stdio: ["ignore", "pipe", "ignore"]
70
+ }).trim();
71
+ return revision !== "" ? revision : void 0;
72
+ } catch (_error) {
73
+ return void 0;
74
+ }
75
+ }
76
+ function resolveRelease(release, cwd) {
77
+ if (release !== void 0 && String(release) !== "") {
78
+ return String(release);
79
+ }
80
+ const candidates = [RELEASE_ENV_VARIABLE, ...COMMIT_SHA_ENV_VARIABLES].map((name) => import_node_process.default.env[name]);
81
+ const fromEnv = candidates.find((value) => value !== void 0 && value !== "");
82
+ if (fromEnv !== void 0) {
83
+ return fromEnv;
84
+ }
85
+ return getGitRevision(cwd) ?? (/* @__PURE__ */ new Date()).toISOString();
86
+ }
87
+
88
+ // src/token.ts
89
+ var import_node_buffer = require("buffer");
90
+ function getIntegrationId(token) {
91
+ try {
92
+ const payload = JSON.parse(import_node_buffer.Buffer.from(token, "base64").toString("utf-8"));
93
+ if (typeof payload.integrationId === "string" && payload.integrationId !== "") {
94
+ return payload.integrationId;
95
+ }
96
+ } catch (_error) {
97
+ }
98
+ return void 0;
99
+ }
100
+ function getDefaultCollectorEndpoint(integrationId) {
101
+ return `https://${integrationId}.k1.hawk.so/release`;
102
+ }
103
+
104
+ // src/upload-release.ts
105
+ var import_promises4 = require("fs/promises");
106
+
107
+ // src/cleanup.ts
108
+ var import_promises3 = require("fs/promises");
109
+ var import_node_path3 = __toESM(require("path"), 1);
110
+
111
+ // src/sourcemaps.ts
112
+ var import_node_crypto = require("crypto");
113
+ var import_promises2 = require("fs/promises");
114
+ var import_node_path2 = __toESM(require("path"), 1);
115
+
116
+ // src/utils/fs.ts
117
+ var import_node_buffer2 = require("buffer");
118
+ var import_promises = require("fs/promises");
119
+ var import_node_path = __toESM(require("path"), 1);
120
+ var MAX_PARALLEL_FILE_OPERATIONS = 16;
121
+ async function listFiles(dir) {
122
+ try {
123
+ const entries = await (0, import_promises.readdir)(dir, { withFileTypes: true });
124
+ const files = await Promise.all(entries.map(async (entry) => {
125
+ if (entry.isDirectory()) {
126
+ return (await listFiles(import_node_path.default.join(dir, entry.name))).map((file) => `${entry.name}/${file}`);
127
+ }
128
+ return entry.isFile() ? [entry.name] : [];
129
+ }));
130
+ return files.flat();
131
+ } catch (error) {
132
+ if (error.code === "ENOENT") {
133
+ return [];
134
+ }
135
+ throw error;
136
+ }
137
+ }
138
+ async function readFileTail(filePath, maxBytes) {
139
+ const file = await (0, import_promises.open)(filePath, "r");
140
+ try {
141
+ const { size } = await file.stat();
142
+ const length = Math.min(maxBytes, size);
143
+ const { bytesRead, buffer } = await file.read(import_node_buffer2.Buffer.alloc(length), 0, length, size - length);
144
+ const tail = buffer.subarray(0, bytesRead).toString("utf8");
145
+ if (length === size) {
146
+ return tail;
147
+ }
148
+ const cutLineEnd = tail.indexOf("\n");
149
+ return cutLineEnd === -1 ? "" : tail.slice(cutLineEnd);
150
+ } finally {
151
+ await file.close();
152
+ }
153
+ }
154
+
155
+ // src/utils/pool.ts
156
+ async function mapConcurrently(items, limit, mapper) {
157
+ const results = [];
158
+ let nextIndex = 0;
159
+ const runWorker = async () => {
160
+ while (nextIndex < items.length) {
161
+ const index = nextIndex;
162
+ nextIndex += 1;
163
+ results[index] = await mapper(items[index]);
164
+ }
165
+ };
166
+ const workersCount = Math.max(1, Math.min(limit, items.length));
167
+ await Promise.all(Array.from({ length: workersCount }, runWorker));
168
+ return results;
169
+ }
170
+
171
+ // src/sourcemaps.ts
172
+ var STATIC_DIR = "static";
173
+ var PUBLIC_PATH_PREFIX = "/_next/";
174
+ var PATH_HASH_LENGTH = 8;
175
+ var CHUNK_TAIL_SIZE = 4096;
176
+ var JS_SOURCE_MAPPING_URL = /(?:^|\n)\/\/[#@] sourceMappingURL=([^\s'"`*]+)\s*$/;
177
+ var SOURCE_PATH_PREFIXES = [
178
+ /^turbopack:\/\/\/\[project\]\//,
179
+ /^webpack:\/\/[^/]*\/(\.\/)?/
180
+ ];
181
+ function isRawSourceMap(value) {
182
+ return typeof value === "object" && value !== null && !Array.isArray(value);
183
+ }
184
+ function normalizeSourcePath(source) {
185
+ const prefix = SOURCE_PATH_PREFIXES.find((pattern) => pattern.test(source));
186
+ return prefix !== void 0 ? source.replace(prefix, "") : source;
187
+ }
188
+ function normalizeSources(map) {
189
+ if (Array.isArray(map.sources)) {
190
+ map.sources = map.sources.map((source) => typeof source === "string" ? normalizeSourcePath(source) : source);
191
+ }
192
+ }
193
+ function getSourceMapPath(chunk, content) {
194
+ const url = JS_SOURCE_MAPPING_URL.exec(content)?.[1];
195
+ if (url === void 0 || url.startsWith("/") || /^[a-z][a-z\d+.-]*:/i.test(url)) {
196
+ return void 0;
197
+ }
198
+ try {
199
+ const mapPath = import_node_path2.default.posix.join(import_node_path2.default.posix.dirname(chunk), decodeURIComponent(url));
200
+ return mapPath.startsWith("../") ? void 0 : mapPath;
201
+ } catch (_error) {
202
+ return void 0;
203
+ }
204
+ }
205
+ function encodeUrlPath(filePath) {
206
+ return filePath.split("/").map((segment) => encodeURIComponent(segment)).join("/");
207
+ }
208
+ function getSourceMapName(chunk) {
209
+ const extension = import_node_path2.default.posix.extname(chunk);
210
+ const hash = (0, import_node_crypto.createHash)("sha256").update(chunk).digest("hex").slice(0, PATH_HASH_LENGTH);
211
+ return `${import_node_path2.default.posix.basename(chunk, extension)}.${hash}${extension}.map`;
212
+ }
213
+ async function fileExists(filePath) {
214
+ try {
215
+ await (0, import_promises2.access)(filePath);
216
+ return true;
217
+ } catch (_error) {
218
+ return false;
219
+ }
220
+ }
221
+ async function findClientSourceMaps(distDir) {
222
+ const staticDir = import_node_path2.default.join(distDir, STATIC_DIR);
223
+ const chunks = (await listFiles(staticDir)).filter((entry) => /\.[cm]?js$/.test(entry)).sort();
224
+ const maps = await mapConcurrently(chunks, MAX_PARALLEL_FILE_OPERATIONS, async (chunk) => {
225
+ const mapPath = getSourceMapPath(chunk, await readFileTail(import_node_path2.default.join(staticDir, chunk), CHUNK_TAIL_SIZE));
226
+ if (mapPath === void 0 || !await fileExists(import_node_path2.default.join(staticDir, mapPath))) {
227
+ return void 0;
228
+ }
229
+ return {
230
+ path: import_node_path2.default.join(staticDir, mapPath),
231
+ chunkUrl: `${PUBLIC_PATH_PREFIX}${STATIC_DIR}/${encodeUrlPath(chunk)}`,
232
+ name: getSourceMapName(chunk)
233
+ };
234
+ });
235
+ return maps.filter((map) => map !== void 0);
236
+ }
237
+ function prepareSourceMap(content, chunkUrl) {
238
+ const map = JSON.parse(content);
239
+ if (!isRawSourceMap(map)) {
240
+ throw new Error("Source map is not a JSON object");
241
+ }
242
+ map.file = chunkUrl;
243
+ normalizeSources(map);
244
+ if (Array.isArray(map.sections)) {
245
+ for (const section of map.sections) {
246
+ const sectionMap = isRawSourceMap(section) ? section.map : void 0;
247
+ if (isRawSourceMap(sectionMap)) {
248
+ normalizeSources(sectionMap);
249
+ }
250
+ }
251
+ }
252
+ return JSON.stringify(map);
253
+ }
254
+
255
+ // src/cleanup.ts
256
+ var CSS_SOURCE_MAPPING_URL = /(?:^|\n)\/\*[#@] sourceMappingURL=[^\s*]+\s*\*\/\s*$/;
257
+ async function deleteClientSourceMaps(distDir) {
258
+ const staticDir = import_node_path3.default.join(distDir, STATIC_DIR);
259
+ const maps = (await listFiles(staticDir)).filter((entry) => entry.endsWith(".map"));
260
+ await mapConcurrently(maps, MAX_PARALLEL_FILE_OPERATIONS, (entry) => (0, import_promises3.unlink)(import_node_path3.default.join(staticDir, entry)));
261
+ return maps.length;
262
+ }
263
+ async function stripSourceMappingUrlComments(distDir) {
264
+ const staticDir = import_node_path3.default.join(distDir, STATIC_DIR);
265
+ const assets = (await listFiles(staticDir)).filter((entry) => /\.([cm]?js|css)$/.test(entry));
266
+ const updated = await mapConcurrently(assets, MAX_PARALLEL_FILE_OPERATIONS, async (entry) => {
267
+ const filePath = import_node_path3.default.join(staticDir, entry);
268
+ const pattern = entry.endsWith(".css") ? CSS_SOURCE_MAPPING_URL : JS_SOURCE_MAPPING_URL;
269
+ const content = await (0, import_promises3.readFile)(filePath, "utf8");
270
+ const stripped = content.replace(pattern, "");
271
+ if (stripped === content) {
272
+ return false;
273
+ }
274
+ await (0, import_promises3.writeFile)(filePath, stripped);
275
+ return true;
276
+ });
277
+ return updated.filter(Boolean).length;
278
+ }
279
+
280
+ // src/commits.ts
281
+ var import_node_child_process2 = require("child_process");
282
+ var import_node_util = require("util");
283
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
284
+ var FIELD_SEPARATOR = "";
285
+ var RECORD_SEPARATOR = "";
286
+ async function getCommits(repo, count) {
287
+ const { stdout } = await execFileAsync("git", [
288
+ "log",
289
+ `--max-count=${count}`,
290
+ "--format=%H%x1f%s%x1f%ae%x1f%aI%x1e"
291
+ ], {
292
+ cwd: repo,
293
+ encoding: "utf8"
294
+ });
295
+ return stdout.split(RECORD_SEPARATOR).map((record) => record.trim()).filter((record) => record !== "").map((record) => {
296
+ const [hash, title, author, date] = record.split(FIELD_SEPARATOR);
297
+ return {
298
+ hash,
299
+ title,
300
+ author,
301
+ date
302
+ };
303
+ });
304
+ }
305
+
306
+ // src/uploader.ts
307
+ var MAX_RESPONSE_PREVIEW_LENGTH = 200;
308
+ function sanitizeCollectorMessage(message) {
309
+ return message.startsWith("Integration token invalid") ? "Integration token invalid" : message;
310
+ }
311
+ async function send(collector, body) {
312
+ const response = await fetch(collector.endpoint, {
313
+ method: "POST",
314
+ body,
315
+ headers: [["Authorization", `Bearer ${collector.token}`]],
316
+ signal: AbortSignal.timeout(collector.timeout)
317
+ });
318
+ const text = await response.text();
319
+ let data;
320
+ try {
321
+ data = JSON.parse(text);
322
+ } catch (_error) {
323
+ throw new Error(`Unexpected collector response (HTTP ${response.status}): ${text.slice(0, MAX_RESPONSE_PREVIEW_LENGTH)}`);
324
+ }
325
+ if (data.error === true || !response.ok) {
326
+ throw new Error(sanitizeCollectorMessage(data.message ?? `HTTP ${response.status}`));
327
+ }
328
+ }
329
+ async function sendSourceMap(collector, name, content) {
330
+ const body = new FormData();
331
+ body.set("release", collector.release);
332
+ body.set("file", new Blob([content], { type: "application/json" }), name);
333
+ await send(collector, body);
334
+ }
335
+ async function sendCommits(collector, commits) {
336
+ const body = new FormData();
337
+ body.set("release", collector.release);
338
+ body.set("commits", JSON.stringify(commits));
339
+ await send(collector, body);
340
+ }
341
+
342
+ // src/utils/log.ts
343
+ var consoleColors = {
344
+ fgRed: 31,
345
+ fgGreen: 32,
346
+ fgYellow: 33,
347
+ fgCyan: 36
348
+ };
349
+ function wrapInColor(message, color) {
350
+ return `\x1B[${color}m${message}\x1B[0m`;
351
+ }
352
+ function log(message, color = consoleColors.fgCyan) {
353
+ console.log(wrapInColor("\u{1F985} Hawk | " + message, color));
354
+ }
355
+ function getErrorMessage(error) {
356
+ return error instanceof Error ? error.message : String(error);
357
+ }
358
+
359
+ // src/upload-release.ts
360
+ var MAX_PARALLEL_UPLOADS = 5;
361
+ var REQUEST_TIMEOUT = 3e4;
362
+ function getCollector(options) {
363
+ if (options.token === void 0 || options.token === "") {
364
+ log("Integration Token is not provided, release will not be sent", consoleColors.fgYellow);
365
+ return void 0;
366
+ }
367
+ const integrationId = getIntegrationId(options.token);
368
+ const endpoint = options.collectorEndpoint ?? (integrationId !== void 0 ? getDefaultCollectorEndpoint(integrationId) : void 0);
369
+ if (endpoint === void 0) {
370
+ log("Invalid Integration Token, release will not be sent", consoleColors.fgRed);
371
+ return void 0;
372
+ }
373
+ return {
374
+ endpoint,
375
+ token: options.token,
376
+ release: options.release,
377
+ timeout: REQUEST_TIMEOUT
378
+ };
379
+ }
380
+ async function uploadCommits(collector, repo, count) {
381
+ let commits;
382
+ try {
383
+ commits = await getCommits(repo, count);
384
+ } catch (_error) {
385
+ log("Commits are not sent: git history is not available. Pass `commits: false` to skip them", consoleColors.fgYellow);
386
+ return;
387
+ }
388
+ if (commits.length === 0) {
389
+ return;
390
+ }
391
+ try {
392
+ await sendCommits(collector, commits);
393
+ log(`Recent commits sent: ${commits.length}`, consoleColors.fgGreen);
394
+ } catch (error) {
395
+ log(`(\u2310\u25A0_\u25A0) Sending commits failed: ${getErrorMessage(error)}`, consoleColors.fgRed);
396
+ }
397
+ }
398
+ async function uploadSourceMaps(collector, distDir) {
399
+ const maps = await findClientSourceMaps(distDir);
400
+ if (maps.length === 0) {
401
+ log("No client source maps found. Make sure `productionBrowserSourceMaps` is not disabled in next.config", consoleColors.fgYellow);
402
+ return;
403
+ }
404
+ let sentCount = 0;
405
+ await mapConcurrently(maps, MAX_PARALLEL_UPLOADS, async (map) => {
406
+ try {
407
+ const content = prepareSourceMap(await (0, import_promises4.readFile)(map.path, "utf8"), map.chunkUrl);
408
+ await sendSourceMap(collector, map.name, content);
409
+ sentCount += 1;
410
+ } catch (error) {
411
+ log(`(\u2310\u25A0_\u25A0) ${map.chunkUrl}.map \u2013 sending failed: ${getErrorMessage(error)}`, consoleColors.fgRed);
412
+ }
413
+ });
414
+ const color = sentCount === maps.length ? consoleColors.fgGreen : consoleColors.fgYellow;
415
+ log(`${sentCount} of ${maps.length} source maps sent for release "${collector.release}"`, color);
416
+ }
417
+ async function removeSourceMaps(distDir, stripSourceMappingUrls) {
418
+ const removedCount = await deleteClientSourceMaps(distDir);
419
+ if (removedCount > 0) {
420
+ log(`${removedCount} client source maps removed`);
421
+ }
422
+ if (stripSourceMappingUrls) {
423
+ await stripSourceMappingUrlComments(distDir);
424
+ }
425
+ }
426
+ async function uploadRelease(metadata, options) {
427
+ const startedAt = Date.now();
428
+ try {
429
+ const collector = getCollector(options);
430
+ if (collector === void 0) {
431
+ return;
432
+ }
433
+ try {
434
+ if (options.commits !== false) {
435
+ await uploadCommits(collector, options.commits.repo ?? metadata.projectDir, options.commits.number);
436
+ }
437
+ await uploadSourceMaps(collector, metadata.distDir);
438
+ } finally {
439
+ if (options.removeSourceMaps) {
440
+ await removeSourceMaps(metadata.distDir, options.stripSourceMappingUrls);
441
+ }
442
+ }
443
+ log(`Release "${collector.release}" processed in ${Date.now() - startedAt} ms`);
444
+ } catch (error) {
445
+ log(`(\u2310\u25A0_\u25A0) Release uploading failed: ${getErrorMessage(error)}`, consoleColors.fgRed);
446
+ }
447
+ }
448
+
449
+ // src/with-hawk-config.ts
450
+ var MIN_NEXT_VERSION = "15.4.1";
451
+ var DEFAULT_COMMITS_NUMBER = 5;
452
+ function isVersionAtLeast(version, minVersion) {
453
+ const toNumbers = (value) => value.split("-")[0].split(".").map(Number);
454
+ const actual = toNumbers(version);
455
+ const min = toNumbers(minVersion);
456
+ for (const [i, minPart] of min.entries()) {
457
+ const part = actual[i] ?? 0;
458
+ if (part !== minPart) {
459
+ return part > minPart;
460
+ }
461
+ }
462
+ return true;
463
+ }
464
+ function getNextVersion(projectDir) {
465
+ try {
466
+ const requireFromProject = (0, import_node_module.createRequire)(import_node_path4.default.join(projectDir, "package.json"));
467
+ return requireFromProject("next/package.json").version;
468
+ } catch (_error) {
469
+ return void 0;
470
+ }
471
+ }
472
+ function getCommitsOptions(commits = true) {
473
+ if (commits === false) {
474
+ return false;
475
+ }
476
+ const custom = commits === true ? {} : commits;
477
+ return {
478
+ repo: custom.repo,
479
+ number: custom.number ?? DEFAULT_COMMITS_NUMBER
480
+ };
481
+ }
482
+ function applyHawkConfig(config, options) {
483
+ const projectDir = import_node_process2.default.cwd();
484
+ const release = resolveRelease(options.release, projectDir);
485
+ import_node_process2.default.env[RELEASE_ENV_VARIABLE] = release;
486
+ const result = {
487
+ ...config,
488
+ env: {
489
+ ...config.env,
490
+ [RELEASE_ENV_VARIABLE]: release
491
+ }
492
+ };
493
+ const nextVersion = getNextVersion(projectDir);
494
+ if (nextVersion !== void 0 && !isVersionAtLeast(nextVersion, MIN_NEXT_VERSION)) {
495
+ log(`Next.js ${nextVersion} is not supported, update it to ${MIN_NEXT_VERSION} or newer to send releases`, consoleColors.fgYellow);
496
+ return result;
497
+ }
498
+ const token = options.token ?? import_node_process2.default.env.HAWK_TOKEN;
499
+ const hasToken = token !== void 0 && token !== "";
500
+ const canUpload = hasToken && (options.collectorEndpoint !== void 0 || getIntegrationId(token) !== void 0);
501
+ if (canUpload && config.productionBrowserSourceMaps === void 0) {
502
+ result.productionBrowserSourceMaps = true;
503
+ }
504
+ const uploadOptions = {
505
+ token,
506
+ release,
507
+ collectorEndpoint: options.collectorEndpoint,
508
+ removeSourceMaps: options.removeSourceMaps ?? true,
509
+ stripSourceMappingUrls: config.experimental?.sri === void 0,
510
+ commits: getCommitsOptions(options.commits)
511
+ };
512
+ const userHook = config.compiler?.runAfterProductionCompile;
513
+ result.compiler = {
514
+ ...config.compiler,
515
+ runAfterProductionCompile: async (metadata) => {
516
+ if (userHook !== void 0) {
517
+ await userHook(metadata);
518
+ }
519
+ await uploadRelease(metadata, uploadOptions);
520
+ }
521
+ };
522
+ return result;
523
+ }
524
+ function withHawkConfig(nextConfig, options = {}) {
525
+ if (typeof nextConfig === "function") {
526
+ return async (phase, context) => applyHawkConfig(await nextConfig(phase, context), options);
527
+ }
528
+ return applyHawkConfig(nextConfig, options);
529
+ }
530
+ // Annotate the CommonJS export names for ESM import in node:
531
+ 0 && (module.exports = {
532
+ withHawkConfig
533
+ });
@@ -0,0 +1,75 @@
1
+ /// <reference path="../global.d.ts" />
2
+ import { NextConfig } from 'next';
3
+
4
+ /**
5
+ * Options of the commits collecting
6
+ */
7
+ interface CommitsOptions {
8
+ /**
9
+ * Path to the repository with `.git` directory. Default is the Next.js project directory
10
+ */
11
+ repo?: string;
12
+ /**
13
+ * How many recent commits to send. Default is 5
14
+ */
15
+ number?: number;
16
+ }
17
+
18
+ /**
19
+ * Options of the Hawk Next.js integration
20
+ */
21
+ interface HawkNextOptions {
22
+ /**
23
+ * Hawk Integration Token. Default is the HAWK_TOKEN environment variable
24
+ */
25
+ token?: string;
26
+ /**
27
+ * Unique identifier of the release.
28
+ * Default is HAWK_RELEASE environment variable, commit SHA from CI or git, or the build time
29
+ */
30
+ release?: string | number;
31
+ /**
32
+ * Whether to remove client source maps after sending. Default is true
33
+ */
34
+ removeSourceMaps?: boolean;
35
+ /**
36
+ * Options for sending recent commits with the release, or false to skip. Enabled by default
37
+ */
38
+ commits?: boolean | CommitsOptions;
39
+ /**
40
+ * Collector endpoint overwrite
41
+ */
42
+ collectorEndpoint?: string;
43
+ }
44
+ /**
45
+ * Context passed by Next.js to the config function
46
+ */
47
+ interface NextConfigContext {
48
+ /**
49
+ * Default Next.js config
50
+ */
51
+ defaultConfig: NextConfig;
52
+ }
53
+ /**
54
+ * Next.js config exported as a function
55
+ */
56
+ type NextConfigFunction = (phase: string, context: NextConfigContext) => NextConfig | Promise<NextConfig>;
57
+ /**
58
+ * Wraps Next.js config to send releases with source maps to Hawk.
59
+ *
60
+ * - exposes the release id to the app code as `process.env.HAWK_RELEASE`
61
+ * - enables client source maps for production builds
62
+ * - after `next build` sends client source maps and recent commits to Hawk and removes the maps
63
+ * @param nextConfig - Next.js config object
64
+ * @param options - Hawk plugin options
65
+ */
66
+ declare function withHawkConfig(nextConfig: NextConfig, options?: HawkNextOptions): NextConfig;
67
+ /**
68
+ * Wraps Next.js config function to send releases with source maps to Hawk
69
+ * @param nextConfig - function returning Next.js config
70
+ * @param options - Hawk plugin options
71
+ */
72
+ declare function withHawkConfig(nextConfig: NextConfigFunction, options?: HawkNextOptions): NextConfigFunction;
73
+
74
+ export { withHawkConfig };
75
+ export type { CommitsOptions, HawkNextOptions, NextConfigFunction };
@@ -0,0 +1,75 @@
1
+ /// <reference path="../global.d.ts" />
2
+ import { NextConfig } from 'next';
3
+
4
+ /**
5
+ * Options of the commits collecting
6
+ */
7
+ interface CommitsOptions {
8
+ /**
9
+ * Path to the repository with `.git` directory. Default is the Next.js project directory
10
+ */
11
+ repo?: string;
12
+ /**
13
+ * How many recent commits to send. Default is 5
14
+ */
15
+ number?: number;
16
+ }
17
+
18
+ /**
19
+ * Options of the Hawk Next.js integration
20
+ */
21
+ interface HawkNextOptions {
22
+ /**
23
+ * Hawk Integration Token. Default is the HAWK_TOKEN environment variable
24
+ */
25
+ token?: string;
26
+ /**
27
+ * Unique identifier of the release.
28
+ * Default is HAWK_RELEASE environment variable, commit SHA from CI or git, or the build time
29
+ */
30
+ release?: string | number;
31
+ /**
32
+ * Whether to remove client source maps after sending. Default is true
33
+ */
34
+ removeSourceMaps?: boolean;
35
+ /**
36
+ * Options for sending recent commits with the release, or false to skip. Enabled by default
37
+ */
38
+ commits?: boolean | CommitsOptions;
39
+ /**
40
+ * Collector endpoint overwrite
41
+ */
42
+ collectorEndpoint?: string;
43
+ }
44
+ /**
45
+ * Context passed by Next.js to the config function
46
+ */
47
+ interface NextConfigContext {
48
+ /**
49
+ * Default Next.js config
50
+ */
51
+ defaultConfig: NextConfig;
52
+ }
53
+ /**
54
+ * Next.js config exported as a function
55
+ */
56
+ type NextConfigFunction = (phase: string, context: NextConfigContext) => NextConfig | Promise<NextConfig>;
57
+ /**
58
+ * Wraps Next.js config to send releases with source maps to Hawk.
59
+ *
60
+ * - exposes the release id to the app code as `process.env.HAWK_RELEASE`
61
+ * - enables client source maps for production builds
62
+ * - after `next build` sends client source maps and recent commits to Hawk and removes the maps
63
+ * @param nextConfig - Next.js config object
64
+ * @param options - Hawk plugin options
65
+ */
66
+ declare function withHawkConfig(nextConfig: NextConfig, options?: HawkNextOptions): NextConfig;
67
+ /**
68
+ * Wraps Next.js config function to send releases with source maps to Hawk
69
+ * @param nextConfig - function returning Next.js config
70
+ * @param options - Hawk plugin options
71
+ */
72
+ declare function withHawkConfig(nextConfig: NextConfigFunction, options?: HawkNextOptions): NextConfigFunction;
73
+
74
+ export { withHawkConfig };
75
+ export type { CommitsOptions, HawkNextOptions, NextConfigFunction };