@spotpatch/next 0.1.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.
@@ -0,0 +1,235 @@
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/loader.ts
31
+ var loader_exports = {};
32
+ __export(loader_exports, {
33
+ default: () => spotPatchNextLoader
34
+ });
35
+ module.exports = __toCommonJS(loader_exports);
36
+ var import_node_path = __toESM(require("path"), 1);
37
+ var import_compiler = require("@spotpatch/compiler");
38
+
39
+ // src/internal/constants.ts
40
+ var NEXT_IPC_MESSAGE_LIMIT_BYTES = 256 * 1024;
41
+ var NEXT_INTERNAL_REGISTRATION_PATH = "/__spotpatch-internal/register";
42
+ var NEXT_ENVIRONMENT_KEYS = Object.freeze({
43
+ appRoot: "SPOTPATCH_NEXT_APP_ROOT",
44
+ bundler: "SPOTPATCH_NEXT_BUNDLER",
45
+ configurationSecret: "SPOTPATCH_NEXT_CONFIGURATION_SECRET",
46
+ internalOrigin: "SPOTPATCH_NEXT_INTERNAL_ORIGIN",
47
+ internalSecret: "SPOTPATCH_NEXT_INTERNAL_SECRET",
48
+ launchNonce: "SPOTPATCH_NEXT_LAUNCH_NONCE",
49
+ registryEpoch: "SPOTPATCH_NEXT_REGISTRY_EPOCH",
50
+ sidecarOrigin: "SPOTPATCH_NEXT_SIDECAR_ORIGIN"
51
+ });
52
+ var NEXT_SOURCE_RULE_KEYS = Object.freeze(["*.jsx", "*.tsx"]);
53
+ var NEXT_DEFAULT_INCLUDE = Object.freeze([/\.(?:jsx|tsx)$/u]);
54
+
55
+ // src/loader.ts
56
+ var MAX_CACHE_ENTRIES = 1024;
57
+ var MAX_RESPONSE_BYTES = 4096;
58
+ var REGISTRATION_TIMEOUT_MS = 3e3;
59
+ var ID_PATTERN = /^[A-Za-z0-9_-]{16,128}$/u;
60
+ var FILE_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/u;
61
+ var SAFE_FAILURE_CODES = /* @__PURE__ */ new Set([
62
+ "environment-missing",
63
+ "epoch-mismatch",
64
+ "options-invalid",
65
+ "origin-invalid",
66
+ "request-failed",
67
+ "response-invalid",
68
+ "response-too-large",
69
+ "timeout",
70
+ "transform-failed",
71
+ "upstream-source-map-unsupported"
72
+ ]);
73
+ var registrationCache = /* @__PURE__ */ new Map();
74
+ var warnedCodes = /* @__PURE__ */ new Set();
75
+ function failure(code) {
76
+ return new Error(code);
77
+ }
78
+ function safeFailureCode(error) {
79
+ return error instanceof Error && SAFE_FAILURE_CODES.has(error.message) ? error.message : "registration-unavailable";
80
+ }
81
+ function warnOnce(context, code) {
82
+ if (warnedCodes.has(code)) {
83
+ return;
84
+ }
85
+ warnedCodes.add(code);
86
+ context.emitWarning(
87
+ new Error(`[spotpatch:next:loader] ${code}; the original module was preserved.`)
88
+ );
89
+ }
90
+ function readRequiredEnvironment(name) {
91
+ const value = process.env[name];
92
+ if (typeof value !== "string" || value.length === 0) {
93
+ throw failure("environment-missing");
94
+ }
95
+ return value;
96
+ }
97
+ function parseOptions(context) {
98
+ const value = context.getOptions();
99
+ if (typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).length !== 1 || !("registryEpoch" in value) || typeof value.registryEpoch !== "string" || !ID_PATTERN.test(value.registryEpoch)) {
100
+ throw failure("options-invalid");
101
+ }
102
+ return Object.freeze({ registryEpoch: value.registryEpoch });
103
+ }
104
+ function pruneCache() {
105
+ while (registrationCache.size > MAX_CACHE_ENTRIES) {
106
+ const oldest = registrationCache.keys().next().value;
107
+ if (typeof oldest !== "string") {
108
+ return;
109
+ }
110
+ registrationCache.delete(oldest);
111
+ }
112
+ }
113
+ async function parseRegistrationResponse(response, expectedEpoch) {
114
+ const declaredLength = Number(response.headers.get("content-length"));
115
+ if (Number.isFinite(declaredLength) && declaredLength > MAX_RESPONSE_BYTES) {
116
+ throw failure("response-too-large");
117
+ }
118
+ const text = await response.text();
119
+ if (Buffer.byteLength(text, "utf8") > MAX_RESPONSE_BYTES) {
120
+ throw failure("response-too-large");
121
+ }
122
+ let value;
123
+ try {
124
+ value = JSON.parse(text);
125
+ } catch {
126
+ throw failure("response-invalid");
127
+ }
128
+ if (!response.ok || typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).length !== 2 || !("epoch" in value) || value.epoch !== expectedEpoch || !("fileId" in value) || typeof value.fileId !== "string" || !FILE_ID_PATTERN.test(value.fileId)) {
129
+ throw failure("response-invalid");
130
+ }
131
+ return Object.freeze({ epoch: value.epoch, fileId: value.fileId });
132
+ }
133
+ async function requestRegistration(resourcePath, options) {
134
+ const internalOrigin = readRequiredEnvironment(NEXT_ENVIRONMENT_KEYS.internalOrigin);
135
+ const internalSecret = readRequiredEnvironment(NEXT_ENVIRONMENT_KEYS.internalSecret);
136
+ const environmentEpoch = readRequiredEnvironment(NEXT_ENVIRONMENT_KEYS.registryEpoch);
137
+ if (environmentEpoch !== options.registryEpoch) {
138
+ throw failure("epoch-mismatch");
139
+ }
140
+ const endpoint = new URL(NEXT_INTERNAL_REGISTRATION_PATH, internalOrigin);
141
+ if (endpoint.protocol !== "http:" || endpoint.hostname !== "127.0.0.1" || endpoint.username !== "" || endpoint.password !== "") {
142
+ throw failure("origin-invalid");
143
+ }
144
+ let response;
145
+ try {
146
+ response = await fetch(endpoint, {
147
+ method: "POST",
148
+ headers: {
149
+ "Content-Type": "application/json",
150
+ "X-SpotPatch-Internal": internalSecret
151
+ },
152
+ body: JSON.stringify({
153
+ epoch: options.registryEpoch,
154
+ resourcePath
155
+ }),
156
+ signal: AbortSignal.timeout(REGISTRATION_TIMEOUT_MS)
157
+ });
158
+ } catch (error) {
159
+ throw failure(
160
+ error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError") ? "timeout" : "request-failed"
161
+ );
162
+ }
163
+ return (await parseRegistrationResponse(response, options.registryEpoch)).fileId;
164
+ }
165
+ function registerSource(resourcePath, options) {
166
+ const key = `${options.registryEpoch}\0${resourcePath}`;
167
+ const cached = registrationCache.get(key);
168
+ if (cached !== void 0) {
169
+ registrationCache.delete(key);
170
+ registrationCache.set(key, cached);
171
+ return cached;
172
+ }
173
+ const pending = requestRegistration(resourcePath, options).catch((error) => {
174
+ registrationCache.delete(key);
175
+ throw error;
176
+ });
177
+ registrationCache.set(key, pending);
178
+ pruneCache();
179
+ return pending;
180
+ }
181
+ function adaptSourceMap(sourceMap, resourcePath) {
182
+ const value = JSON.parse(sourceMap.toString());
183
+ if (process.env[NEXT_ENVIRONMENT_KEYS.bundler] === "turbopack" && typeof value === "object" && value !== null && "sources" in value && Array.isArray(value.sources)) {
184
+ return { ...value, sources: [import_node_path.default.basename(resourcePath)] };
185
+ }
186
+ return value;
187
+ }
188
+ function spotPatchNextLoader(source, inputMap, metadata) {
189
+ this.cacheable(true);
190
+ const callback = this.async();
191
+ const sourceText = typeof source === "string" ? source : source.toString("utf8");
192
+ if (!sourceText.includes("<")) {
193
+ callback(null, sourceText, inputMap, metadata);
194
+ return;
195
+ }
196
+ if (inputMap !== null && inputMap !== void 0) {
197
+ warnOnce(this, "upstream-source-map-unsupported");
198
+ callback(null, sourceText, inputMap, metadata);
199
+ return;
200
+ }
201
+ let options;
202
+ try {
203
+ options = parseOptions(this);
204
+ } catch (error) {
205
+ warnOnce(this, safeFailureCode(error));
206
+ callback(null, sourceText, inputMap, metadata);
207
+ return;
208
+ }
209
+ void registerSource(this.resourcePath, options).then(
210
+ (fileId) => {
211
+ try {
212
+ const result = (0, import_compiler.injectSourceMarkers)({
213
+ absolutePath: this.resourcePath,
214
+ code: sourceText,
215
+ fileId,
216
+ root: readRequiredEnvironment(NEXT_ENVIRONMENT_KEYS.appRoot)
217
+ });
218
+ callback(
219
+ null,
220
+ result?.code ?? sourceText,
221
+ result === void 0 ? inputMap : adaptSourceMap(result.map, this.resourcePath),
222
+ metadata
223
+ );
224
+ } catch {
225
+ warnOnce(this, "transform-failed");
226
+ callback(null, sourceText, inputMap, metadata);
227
+ }
228
+ },
229
+ (error) => {
230
+ warnOnce(this, safeFailureCode(error));
231
+ callback(null, sourceText, inputMap, metadata);
232
+ }
233
+ );
234
+ }
235
+ //# sourceMappingURL=loader.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/loader.ts","../src/internal/constants.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport {\n injectSourceMarkers,\n type InjectSourceMarkersResult,\n} from \"@spotpatch/compiler\";\n\nimport {\n NEXT_ENVIRONMENT_KEYS,\n NEXT_INTERNAL_REGISTRATION_PATH,\n} from \"./internal/constants.js\";\n\nconst MAX_CACHE_ENTRIES = 1_024;\nconst MAX_RESPONSE_BYTES = 4_096;\nconst REGISTRATION_TIMEOUT_MS = 3_000;\nconst ID_PATTERN = /^[A-Za-z0-9_-]{16,128}$/u;\nconst FILE_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/u;\nconst SAFE_FAILURE_CODES = new Set([\n \"environment-missing\",\n \"epoch-mismatch\",\n \"options-invalid\",\n \"origin-invalid\",\n \"request-failed\",\n \"response-invalid\",\n \"response-too-large\",\n \"timeout\",\n \"transform-failed\",\n \"upstream-source-map-unsupported\",\n]);\n\ninterface LoaderOptions {\n readonly registryEpoch: string;\n}\n\ninterface LoaderContext {\n readonly resourcePath: string;\n async(): LoaderCallback;\n cacheable(cacheable: boolean): void;\n emitWarning(warning: Error): void;\n getOptions(): unknown;\n}\n\ntype LoaderCallback = (\n error: Error | null,\n source?: string,\n sourceMap?: unknown,\n metadata?: unknown,\n) => void;\n\ninterface RegistrationResponse {\n readonly epoch: string;\n readonly fileId: string;\n}\n\nconst registrationCache = new Map<string, Promise<string>>();\nconst warnedCodes = new Set<string>();\n\nfunction failure(code: string): Error {\n return new Error(code);\n}\n\nfunction safeFailureCode(error: unknown): string {\n return error instanceof Error && SAFE_FAILURE_CODES.has(error.message)\n ? error.message\n : \"registration-unavailable\";\n}\n\nfunction warnOnce(context: LoaderContext, code: string): void {\n if (warnedCodes.has(code)) {\n return;\n }\n\n warnedCodes.add(code);\n context.emitWarning(\n new Error(`[spotpatch:next:loader] ${code}; the original module was preserved.`),\n );\n}\n\nfunction readRequiredEnvironment(name: string): string {\n const value = process.env[name];\n\n if (typeof value !== \"string\" || value.length === 0) {\n throw failure(\"environment-missing\");\n }\n\n return value;\n}\n\nfunction parseOptions(context: LoaderContext): LoaderOptions {\n const value = context.getOptions();\n\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n Object.keys(value).length !== 1 ||\n !(\"registryEpoch\" in value) ||\n typeof value.registryEpoch !== \"string\" ||\n !ID_PATTERN.test(value.registryEpoch)\n ) {\n throw failure(\"options-invalid\");\n }\n\n return Object.freeze({ registryEpoch: value.registryEpoch });\n}\n\nfunction pruneCache(): void {\n while (registrationCache.size > MAX_CACHE_ENTRIES) {\n const oldest = registrationCache.keys().next().value;\n\n if (typeof oldest !== \"string\") {\n return;\n }\n\n registrationCache.delete(oldest);\n }\n}\n\nasync function parseRegistrationResponse(\n response: Response,\n expectedEpoch: string,\n): Promise<RegistrationResponse> {\n const declaredLength = Number(response.headers.get(\"content-length\"));\n\n if (Number.isFinite(declaredLength) && declaredLength > MAX_RESPONSE_BYTES) {\n throw failure(\"response-too-large\");\n }\n\n const text = await response.text();\n\n if (Buffer.byteLength(text, \"utf8\") > MAX_RESPONSE_BYTES) {\n throw failure(\"response-too-large\");\n }\n\n let value: unknown;\n\n try {\n value = JSON.parse(text) as unknown;\n } catch {\n throw failure(\"response-invalid\");\n }\n\n if (\n !response.ok ||\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n Object.keys(value).length !== 2 ||\n !(\"epoch\" in value) ||\n value.epoch !== expectedEpoch ||\n !(\"fileId\" in value) ||\n typeof value.fileId !== \"string\" ||\n !FILE_ID_PATTERN.test(value.fileId)\n ) {\n throw failure(\"response-invalid\");\n }\n\n return Object.freeze({ epoch: value.epoch, fileId: value.fileId });\n}\n\nasync function requestRegistration(\n resourcePath: string,\n options: LoaderOptions,\n): Promise<string> {\n const internalOrigin = readRequiredEnvironment(NEXT_ENVIRONMENT_KEYS.internalOrigin);\n const internalSecret = readRequiredEnvironment(NEXT_ENVIRONMENT_KEYS.internalSecret);\n const environmentEpoch = readRequiredEnvironment(NEXT_ENVIRONMENT_KEYS.registryEpoch);\n\n if (environmentEpoch !== options.registryEpoch) {\n throw failure(\"epoch-mismatch\");\n }\n\n const endpoint = new URL(NEXT_INTERNAL_REGISTRATION_PATH, internalOrigin);\n\n if (\n endpoint.protocol !== \"http:\" ||\n endpoint.hostname !== \"127.0.0.1\" ||\n endpoint.username !== \"\" ||\n endpoint.password !== \"\"\n ) {\n throw failure(\"origin-invalid\");\n }\n\n let response: Response;\n\n try {\n response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-SpotPatch-Internal\": internalSecret,\n },\n body: JSON.stringify({\n epoch: options.registryEpoch,\n resourcePath,\n }),\n signal: AbortSignal.timeout(REGISTRATION_TIMEOUT_MS),\n });\n } catch (error: unknown) {\n throw failure(\n error instanceof Error &&\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n ? \"timeout\"\n : \"request-failed\",\n );\n }\n\n return (await parseRegistrationResponse(response, options.registryEpoch)).fileId;\n}\n\nfunction registerSource(resourcePath: string, options: LoaderOptions): Promise<string> {\n const key = `${options.registryEpoch}\\0${resourcePath}`;\n const cached = registrationCache.get(key);\n\n if (cached !== undefined) {\n registrationCache.delete(key);\n registrationCache.set(key, cached);\n return cached;\n }\n\n const pending = requestRegistration(resourcePath, options).catch((error: unknown) => {\n registrationCache.delete(key);\n throw error;\n });\n registrationCache.set(key, pending);\n pruneCache();\n return pending;\n}\n\nfunction adaptSourceMap(\n sourceMap: InjectSourceMarkersResult[\"map\"],\n resourcePath: string,\n): unknown {\n const value = JSON.parse(sourceMap.toString()) as unknown;\n\n if (\n process.env[NEXT_ENVIRONMENT_KEYS.bundler] === \"turbopack\" &&\n typeof value === \"object\" &&\n value !== null &&\n \"sources\" in value &&\n Array.isArray(value.sources)\n ) {\n return { ...value, sources: [path.basename(resourcePath)] };\n }\n\n return value;\n}\n\nexport default function spotPatchNextLoader(\n this: LoaderContext,\n source: string | Buffer,\n inputMap: unknown,\n metadata: unknown,\n): void {\n this.cacheable(true);\n const callback = this.async();\n const sourceText = typeof source === \"string\" ? source : source.toString(\"utf8\");\n\n if (!sourceText.includes(\"<\")) {\n callback(null, sourceText, inputMap, metadata);\n return;\n }\n\n if (inputMap !== null && inputMap !== undefined) {\n warnOnce(this, \"upstream-source-map-unsupported\");\n callback(null, sourceText, inputMap, metadata);\n return;\n }\n\n let options: LoaderOptions;\n\n try {\n options = parseOptions(this);\n } catch (error: unknown) {\n warnOnce(this, safeFailureCode(error));\n callback(null, sourceText, inputMap, metadata);\n return;\n }\n\n void registerSource(this.resourcePath, options).then(\n (fileId) => {\n try {\n const result = injectSourceMarkers({\n absolutePath: this.resourcePath,\n code: sourceText,\n fileId,\n root: readRequiredEnvironment(NEXT_ENVIRONMENT_KEYS.appRoot),\n });\n\n callback(\n null,\n result?.code ?? sourceText,\n result === undefined\n ? inputMap\n : adaptSourceMap(result.map, this.resourcePath),\n metadata,\n );\n } catch {\n warnOnce(this, \"transform-failed\");\n callback(null, sourceText, inputMap, metadata);\n }\n },\n (error: unknown) => {\n warnOnce(this, safeFailureCode(error));\n callback(null, sourceText, inputMap, metadata);\n },\n );\n}\n","export const NEXT_IPC_PROTOCOL_VERSION = 1 as const;\nexport const NEXT_IPC_MESSAGE_LIMIT_BYTES = 256 * 1024;\nexport const NEXT_IPC_TIMEOUT_MS = 15_000;\nexport const NEXT_INTERNAL_REGISTRATION_PATH =\n \"/__spotpatch-internal/register\" as const;\nexport const NEXT_INTERNAL_CONFIGURATION_PATH =\n \"/__spotpatch-internal/configure\" as const;\n\nexport const NEXT_ENVIRONMENT_KEYS = Object.freeze({\n appRoot: \"SPOTPATCH_NEXT_APP_ROOT\",\n bundler: \"SPOTPATCH_NEXT_BUNDLER\",\n configurationSecret: \"SPOTPATCH_NEXT_CONFIGURATION_SECRET\",\n internalOrigin: \"SPOTPATCH_NEXT_INTERNAL_ORIGIN\",\n internalSecret: \"SPOTPATCH_NEXT_INTERNAL_SECRET\",\n launchNonce: \"SPOTPATCH_NEXT_LAUNCH_NONCE\",\n registryEpoch: \"SPOTPATCH_NEXT_REGISTRY_EPOCH\",\n sidecarOrigin: \"SPOTPATCH_NEXT_SIDECAR_ORIGIN\",\n} as const);\n\nexport const NEXT_SOURCE_RULE_KEYS = Object.freeze([\"*.jsx\", \"*.tsx\"] as const);\nexport const NEXT_CLIENT_MODULE_ID = \"@spotpatch/next/client\" as const;\n\nexport const NEXT_DEFAULT_INCLUDE = Object.freeze([/\\.(?:jsx|tsx)$/u]);\n"],"mappings":"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","names":["path"]}
package/dist/noop.cjs ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+
16
+ // src/noop.ts
17
+ var noop_exports = {};
18
+ module.exports = __toCommonJS(noop_exports);
19
+ //# sourceMappingURL=noop.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/noop.ts"],"sourcesContent":["export {};\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/noop.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/noop.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=noop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/loader.cjs ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ module.exports = require("./dist/loader.cjs").default;
package/loader.d.cts ADDED
@@ -0,0 +1,23 @@
1
+ interface SpotPatchNextLoaderContext {
2
+ readonly resourcePath: string;
3
+ async(): SpotPatchNextLoaderCallback;
4
+ cacheable(cacheable: boolean): void;
5
+ emitWarning(warning: Error): void;
6
+ getOptions(): unknown;
7
+ }
8
+
9
+ type SpotPatchNextLoaderCallback = (
10
+ error: Error | null,
11
+ source?: string,
12
+ sourceMap?: unknown,
13
+ metadata?: unknown,
14
+ ) => void;
15
+
16
+ declare function spotPatchNextLoader(
17
+ this: SpotPatchNextLoaderContext,
18
+ source: string | Buffer,
19
+ inputMap: unknown,
20
+ metadata: unknown,
21
+ ): void;
22
+
23
+ export = spotPatchNextLoader;
package/package.json ADDED
@@ -0,0 +1,118 @@
1
+ {
2
+ "name": "@spotpatch/next",
3
+ "version": "0.1.0",
4
+ "description": "Development-only Next.js adapter and CLI for SpotPatch.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/huanglvjing/spotpatch.git",
9
+ "directory": "packages/next"
10
+ },
11
+ "homepage": "https://github.com/huanglvjing/spotpatch#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/huanglvjing/spotpatch/issues"
14
+ },
15
+ "keywords": [
16
+ "spotpatch",
17
+ "nextjs",
18
+ "react",
19
+ "developer-tools"
20
+ ],
21
+ "type": "module",
22
+ "sideEffects": [
23
+ "./dist/client.cjs",
24
+ "./dist/client.js"
25
+ ],
26
+ "engines": {
27
+ "node": ">=20.19.0"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "loader.cjs",
32
+ "loader.d.cts"
33
+ ],
34
+ "main": "./dist/index.cjs",
35
+ "module": "./dist/index.js",
36
+ "types": "./dist/index.d.ts",
37
+ "bin": {
38
+ "spotpatch-next": "./dist/cli.js"
39
+ },
40
+ "exports": {
41
+ ".": {
42
+ "import": {
43
+ "types": "./dist/index.d.ts",
44
+ "default": "./dist/index.js"
45
+ },
46
+ "require": {
47
+ "types": "./dist/index.d.cts",
48
+ "default": "./dist/index.cjs"
49
+ }
50
+ },
51
+ "./client": {
52
+ "import": {
53
+ "types": "./dist/client.d.ts",
54
+ "default": "./dist/client.js"
55
+ },
56
+ "require": {
57
+ "types": "./dist/client.d.cts",
58
+ "default": "./dist/client.cjs"
59
+ }
60
+ },
61
+ "./loader": {
62
+ "types": "./loader.d.cts",
63
+ "default": "./loader.cjs"
64
+ },
65
+ "./noop": {
66
+ "import": {
67
+ "types": "./dist/noop.d.ts",
68
+ "default": "./dist/noop.js"
69
+ },
70
+ "require": {
71
+ "types": "./dist/noop.d.cts",
72
+ "default": "./dist/noop.cjs"
73
+ }
74
+ }
75
+ },
76
+ "typesVersions": {
77
+ "*": {
78
+ "client": [
79
+ "dist/client.d.ts"
80
+ ],
81
+ "loader": [
82
+ "loader.d.cts"
83
+ ],
84
+ "noop": [
85
+ "dist/noop.d.ts"
86
+ ]
87
+ }
88
+ },
89
+ "dependencies": {
90
+ "bippy": "0.6.1",
91
+ "magic-string": "1.1.0",
92
+ "oxc-parser": "0.143.0",
93
+ "@spotpatch/compiler": "^0.1.0",
94
+ "@spotpatch/dev-server": "^0.1.0",
95
+ "@spotpatch/runtime": "^1.4.0",
96
+ "@spotpatch/shared": "^1.5.0"
97
+ },
98
+ "peerDependencies": {
99
+ "next": ">=15.3.0 <17.0.0",
100
+ "react": "^18.2.0 || ^19.0.0",
101
+ "react-dom": "^18.2.0 || ^19.0.0"
102
+ },
103
+ "devDependencies": {
104
+ "next": "16.3.0",
105
+ "react": "19.2.8",
106
+ "react-dom": "19.2.8"
107
+ },
108
+ "publishConfig": {
109
+ "access": "public",
110
+ "registry": "https://registry.npmjs.org/"
111
+ },
112
+ "scripts": {
113
+ "build": "tsup src/index.ts --format esm,cjs --dts --sourcemap --clean && tsup --config tsup.cli.config.ts && tsup --config tsup.loader.config.ts && tsup --config tsup.client.config.ts && pnpm verify:loader",
114
+ "clean": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\"",
115
+ "typecheck": "tsc --noEmit -p tsconfig.json",
116
+ "verify:loader": "node scripts/verify-loader.cjs"
117
+ }
118
+ }