@animus-ui/next-plugin 0.1.11 → 0.1.13
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 +58 -152
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +60 -153
- package/dist/loader-core-BthLSJQF.cjs +47 -0
- package/dist/loader-core-x6cOzF9v.mjs +42 -0
- package/dist/loader-core.d.ts +6 -13
- package/dist/loader-core.d.ts.map +1 -1
- package/dist/loader-path.d.ts +0 -13
- package/dist/loader-path.d.ts.map +1 -1
- package/dist/loader.cjs +2 -25
- package/dist/loader.d.ts +2 -24
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.mjs +2 -24
- package/dist/plugin.d.ts +17 -69
- package/dist/plugin.d.ts.map +1 -1
- package/dist/turbopack-config.d.ts +8 -35
- package/dist/turbopack-config.d.ts.map +1 -1
- package/dist/turbopack-loader.cjs +34 -54
- package/dist/turbopack-loader.d.ts +12 -24
- package/dist/turbopack-loader.d.ts.map +1 -1
- package/dist/turbopack-loader.mjs +35 -55
- package/dist/types.d.ts +24 -90
- package/dist/types.d.ts.map +1 -1
- package/dist/with-animus.d.ts +39 -24
- package/dist/with-animus.d.ts.map +1 -1
- package/package.json +5 -2
- package/dist/loader-core-D2rh--tX.cjs +0 -71
- package/dist/loader-core-DwiidYBi.mjs +0 -66
package/dist/index.mjs
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import { ENGINE_TRANSFORM_EXTENSIONS, assembleStylesheet, assertKnownOptionKeys, assertNoRetiredEngineSelection, buildPathAliasesJson, isPathWithinRoot, readTsconfigAliasPairs, resolveMode } from "@animus-ui/extract/pipeline";
|
|
2
|
-
import { ANIMUS_CSS_MODULE_ID, ANIMUS_CSS_MODULE_ID as ANIMUS_CSS_MODULE_ID$1, ExtractionSession, STYLES_ARTIFACT, SYSTEM_PROPS_ARTIFACT, TURBOPACK_SYSTEM_PROPS_ID,
|
|
1
|
+
import { ENGINE_TRANSFORM_EXTENSIONS, assembleStylesheet, assertKnownOptionKeys, assertNoRetiredEngineSelection, buildPathAliasesJson, isEngineTransformExtension, isPathWithinRoot, readTsconfigAliasPairs, resolveMode } from "@animus-ui/extract/pipeline";
|
|
2
|
+
import { ANIMUS_CSS_MODULE_ID, ANIMUS_CSS_MODULE_ID as ANIMUS_CSS_MODULE_ID$1, ExtractionSession, STYLES_ARTIFACT, SYSTEM_PROPS_ARTIFACT, TURBOPACK_SYSTEM_PROPS_ID, getAnalysisStartedPromise, getReplacementEpoch, getSharedCss, getSharedExternalDirs, getSharedExternalEntries, replacementEpochPath, runSessionPipeline, sessionArtifactDir, setAnalysisStartedPromise, setSharedEngine, startTurbopackWatcher, stylesPath, systemPropsPath } from "@animus-ui/extract/session";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4
4
|
import { dirname, join, relative, resolve } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
//#region src/loader-path.ts
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
* The one loader-path derivation: first existing dist candidate under the
|
|
10
|
-
* plugin dir, else the in-repo source fallback. Both loader resolvers below
|
|
11
|
-
* are thin wrappers, so rule registration and any loader-chain predicate
|
|
12
|
-
* can never drift (openspec: next-webpack-served-transform-coherence,
|
|
13
|
-
* design D1).
|
|
14
|
-
*/
|
|
7
|
+
const __filename$1 = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname$1 = dirname(__filename$1);
|
|
15
9
|
function resolveLoaderPath(pluginDir, distCandidates, sourceFallback) {
|
|
16
10
|
for (const candidate of distCandidates) {
|
|
17
11
|
const distPath = resolve(pluginDir, candidate);
|
|
@@ -19,69 +13,38 @@ function resolveLoaderPath(pluginDir, distCandidates, sourceFallback) {
|
|
|
19
13
|
}
|
|
20
14
|
return resolve(pluginDir, sourceFallback);
|
|
21
15
|
}
|
|
22
|
-
/**
|
|
23
|
-
* This package's webpack loader path, shared by the rule registration
|
|
24
|
-
* (with-animus) and the needBuild loader-chain predicate (plugin). Compiled
|
|
25
|
-
* dist ships `loader.mjs` next to this module; running from source falls
|
|
26
|
-
* back to the TypeScript loader.
|
|
27
|
-
*/
|
|
28
16
|
function resolveAnimusLoaderPath() {
|
|
29
17
|
return resolveLoaderPath(__dirname$1, ["loader.mjs"], "loader.ts");
|
|
30
18
|
}
|
|
31
19
|
//#endregion
|
|
32
20
|
//#region src/plugin.ts
|
|
33
|
-
/**
|
|
34
|
-
*
|
|
35
|
-
|
|
36
|
-
const
|
|
21
|
+
/** The value arrives from a consumer's `next.config`, so the union above is a
|
|
22
|
+
* model of what webpack accepts, not a proof about the value in hand. */
|
|
23
|
+
const isWatchIgnoreString = (ignored) => Object.prototype.toString.call(ignored) === "[object String]";
|
|
24
|
+
const isWatchIgnoreMatcher = (ignored) => Object.prototype.toString.call(ignored) === "[object Function]";
|
|
25
|
+
const UNSUPPORTED_WEBPACK_MESSAGE = "[animus-extract] Unsupported webpack: NormalModule.getCompilationHooks(compilation).needBuild is required for dev transform coherence and this webpack does not expose it. Use a Next.js version whose webpack exposes this hook.";
|
|
37
26
|
const PLUGIN_NAME = "AnimusWebpackPlugin";
|
|
38
|
-
/**
|
|
39
|
-
* Webpack adapter for the extraction pipeline. All pipeline logic lives in
|
|
40
|
-
* the bundler-agnostic ExtractionSession — this class owns only the webpack
|
|
41
|
-
* wiring: hook registration, cross-compiler analysis dedup, alias
|
|
42
|
-
* harvesting from the compiler config, watch-event translation, and
|
|
43
|
-
* in-memory CSS asset replacement.
|
|
44
|
-
*/
|
|
45
27
|
var AnimusWebpackPlugin = class {
|
|
46
28
|
options;
|
|
47
29
|
session;
|
|
48
30
|
initialized = false;
|
|
49
31
|
aliasesExtracted = false;
|
|
50
|
-
/** Loader paths counting as "the animus loader" in a module's chain —
|
|
51
|
-
* this package's own loader plus an optional harness override. */
|
|
52
32
|
animusLoaderPaths;
|
|
53
|
-
/** Epoch THIS compiler last proceeded with (set after every awaited
|
|
54
|
-
* watchRun transaction — including joined ones). Null until the
|
|
55
|
-
* initialization pipeline publishes. */
|
|
56
33
|
lastBuiltEpoch = null;
|
|
57
|
-
/** Armed by watchRun when the transaction moved the epoch; captured and
|
|
58
|
-
* disarmed by the next compilation's needBuild wiring (design D1). */
|
|
59
34
|
epochMovedForNextCompilation = false;
|
|
60
35
|
constructor(options) {
|
|
61
36
|
this.options = options;
|
|
62
37
|
assertNoRetiredEngineSelection(options.engine);
|
|
63
38
|
setSharedEngine(options.engine ?? "v2");
|
|
64
39
|
this.session = new ExtractionSession(options);
|
|
65
|
-
this.animusLoaderPaths = new Set([resolveAnimusLoaderPath()]);
|
|
40
|
+
this.animusLoaderPaths = /* @__PURE__ */ new Set([resolveAnimusLoaderPath()]);
|
|
66
41
|
if (options.loaderPath) this.animusLoaderPaths.add(options.loaderPath);
|
|
67
42
|
}
|
|
68
|
-
/** True when the module's loader chain contains the animus loader — the
|
|
69
|
-
* needBuild fan-out predicate (design D1: no historical records; covers
|
|
70
|
-
* restored persistent-cache modules and raw passthroughs alike). */
|
|
71
43
|
moduleUsesAnimusLoader(module) {
|
|
72
44
|
const loaders = module?.loaders;
|
|
73
45
|
if (!Array.isArray(loaders)) return false;
|
|
74
|
-
return loaders.some((entry) =>
|
|
46
|
+
return loaders.some((entry) => entry?.loader !== void 0 && this.animusLoaderPaths.has(entry.loader));
|
|
75
47
|
}
|
|
76
|
-
/** Append the exact epoch artifact path to `watchOptions.ignored`,
|
|
77
|
-
* preserving the user's shape (design D2: the artifact participates in
|
|
78
|
-
* module snapshots via addDependency but never triggers live watch
|
|
79
|
-
* turns — no echo compilations). Session identity is process-claimed,
|
|
80
|
-
* so every compiler's plugin instance derives the SAME session-scoped
|
|
81
|
-
* path here regardless of which instance ends up owning the pipeline.
|
|
82
|
-
* Derived from the ONE root (session.rootDir, set at config time by
|
|
83
|
-
* with-animus); compiler.context is the fallback for bare-apply
|
|
84
|
-
* harnesses — identical when compiler.context === cwd. */
|
|
85
48
|
appendEpochWatchIgnore(compiler) {
|
|
86
49
|
const options = compiler.options;
|
|
87
50
|
if (!options) return;
|
|
@@ -92,25 +55,22 @@ var AnimusWebpackPlugin = class {
|
|
|
92
55
|
if (ignored === void 0 || ignored === null) watchOptions.ignored = [epochPath];
|
|
93
56
|
else if (Array.isArray(ignored)) {
|
|
94
57
|
if (!ignored.includes(epochPath)) ignored.push(epochPath);
|
|
95
|
-
} else if (
|
|
58
|
+
} else if (isWatchIgnoreString(ignored)) watchOptions.ignored = [ignored, epochPath];
|
|
96
59
|
else if (ignored instanceof RegExp) watchOptions.ignored = (path) => path === epochPath || ignored.test(path);
|
|
97
|
-
else if (
|
|
98
|
-
const original = ignored;
|
|
99
|
-
watchOptions.ignored = (path) => path === epochPath || Boolean(original(path));
|
|
100
|
-
}
|
|
60
|
+
else if (isWatchIgnoreMatcher(ignored)) watchOptions.ignored = (path) => path === epochPath || Boolean(ignored(path));
|
|
101
61
|
}
|
|
102
|
-
/** Extract path aliases from webpack's resolve.alias config. Runs once per
|
|
103
|
-
* plugin instance — the resolve config is immutable after apply. */
|
|
104
62
|
extractAliases(compiler) {
|
|
105
63
|
if (this.aliasesExtracted) return;
|
|
106
64
|
this.aliasesExtracted = true;
|
|
107
65
|
const rootDir = compiler.context;
|
|
108
66
|
const rawAlias = compiler.options?.resolve?.alias;
|
|
109
|
-
if (
|
|
67
|
+
if (rawAlias === void 0) return;
|
|
68
|
+
if (Object.prototype.toString.call(rawAlias) !== "[object Object]") return;
|
|
110
69
|
const pairs = [];
|
|
111
70
|
for (const [key, value] of Object.entries(rawAlias)) {
|
|
112
|
-
|
|
113
|
-
|
|
71
|
+
if (value === false) continue;
|
|
72
|
+
const target = Array.isArray(value) ? value.at(0) : value;
|
|
73
|
+
if (target === void 0) continue;
|
|
114
74
|
if (key === ANIMUS_CSS_MODULE_ID) continue;
|
|
115
75
|
pairs.push({
|
|
116
76
|
pattern: key,
|
|
@@ -123,13 +83,13 @@ var AnimusWebpackPlugin = class {
|
|
|
123
83
|
apply(compiler) {
|
|
124
84
|
if (compiler.options?.name === "edge-server") return;
|
|
125
85
|
const NormalModule = compiler.webpack?.NormalModule;
|
|
126
|
-
if (
|
|
86
|
+
if (NormalModule?.getCompilationHooks === void 0) throw new Error(UNSUPPORTED_WEBPACK_MESSAGE);
|
|
127
87
|
this.appendEpochWatchIgnore(compiler);
|
|
128
88
|
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
|
|
129
89
|
const epochMoved = this.epochMovedForNextCompilation;
|
|
130
90
|
this.epochMovedForNextCompilation = false;
|
|
131
91
|
const needBuild = NormalModule.getCompilationHooks(compilation).needBuild;
|
|
132
|
-
if (
|
|
92
|
+
if (needBuild === void 0) throw new Error(UNSUPPORTED_WEBPACK_MESSAGE);
|
|
133
93
|
needBuild.tapAsync(PLUGIN_NAME, (module, _context, callback) => {
|
|
134
94
|
if (epochMoved && this.moduleUsesAnimusLoader(module)) {
|
|
135
95
|
callback(null, true);
|
|
@@ -156,7 +116,8 @@ var AnimusWebpackPlugin = class {
|
|
|
156
116
|
registerSystemDependencies();
|
|
157
117
|
const css = getSharedCss();
|
|
158
118
|
if (!css || !RawSource) return;
|
|
159
|
-
const
|
|
119
|
+
const rootDir = this.session.rootDir || compiler.context;
|
|
120
|
+
const cssPath = stylesPath(sessionArtifactDir(rootDir, this.session.sessionId));
|
|
160
121
|
if (compilation.getAsset(cssPath)) {
|
|
161
122
|
compilation.updateAsset(cssPath, new RawSource(css));
|
|
162
123
|
return;
|
|
@@ -167,24 +128,24 @@ var AnimusWebpackPlugin = class {
|
|
|
167
128
|
compiler.hooks.run.tapPromise(PLUGIN_NAME, async (_compiler) => {
|
|
168
129
|
this.adoptCompilerContext(_compiler);
|
|
169
130
|
this.extractAliases(_compiler);
|
|
170
|
-
const existing =
|
|
131
|
+
const existing = getAnalysisStartedPromise();
|
|
171
132
|
if (existing) {
|
|
172
133
|
await existing;
|
|
173
134
|
return;
|
|
174
135
|
}
|
|
175
136
|
const promise = this.session.runFullPipeline();
|
|
176
|
-
|
|
137
|
+
setAnalysisStartedPromise(promise);
|
|
177
138
|
await promise;
|
|
178
139
|
});
|
|
179
140
|
compiler.hooks.watchRun.tapPromise(PLUGIN_NAME, async (_compiler) => {
|
|
180
141
|
this.adoptCompilerContext(_compiler);
|
|
181
142
|
this.extractAliases(_compiler);
|
|
182
143
|
if (!this.initialized) {
|
|
183
|
-
const existing =
|
|
144
|
+
const existing = getAnalysisStartedPromise();
|
|
184
145
|
if (existing) await existing;
|
|
185
146
|
else {
|
|
186
147
|
const promise = this.session.runFullPipeline();
|
|
187
|
-
|
|
148
|
+
setAnalysisStartedPromise(promise);
|
|
188
149
|
await promise;
|
|
189
150
|
}
|
|
190
151
|
this.initialized = true;
|
|
@@ -200,35 +161,20 @@ var AnimusWebpackPlugin = class {
|
|
|
200
161
|
if (epoch !== null) this.lastBuiltEpoch = epoch;
|
|
201
162
|
});
|
|
202
163
|
}
|
|
203
|
-
/**
|
|
204
|
-
* Reset analysis state for HMR geological reset.
|
|
205
|
-
*/
|
|
206
164
|
resetForHmr() {
|
|
207
165
|
this.session.resetForHmr();
|
|
208
166
|
}
|
|
209
|
-
/** Session identity (process-claimed) — with-animus derives the
|
|
210
|
-
* session-scoped alias/stub paths from it (design D2). */
|
|
211
167
|
get sessionId() {
|
|
212
168
|
return this.session.sessionId;
|
|
213
169
|
}
|
|
214
|
-
/** Set the project root at CONFIG time (with-animus) — the ONE root all
|
|
215
|
-
* session-path derivations use. The compiler hooks ADOPT
|
|
216
|
-
* compiler.context only when no root was published (bare-apply
|
|
217
|
-
* harnesses); they never overwrite this. */
|
|
218
170
|
setRootDir(rootDir) {
|
|
219
171
|
this.session.rootDir = rootDir;
|
|
220
172
|
}
|
|
221
|
-
/** One warning per plugin instance for a context/root mismatch. */
|
|
222
173
|
warnedRootDivergence = false;
|
|
223
|
-
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* silent overwrite re-keys sessionDir so the pipeline publishes
|
|
228
|
-
* artifacts where none of those consumers look. A disagreement is
|
|
229
|
-
* surfaced loudly instead (with-animus derives the root from Next's own
|
|
230
|
-
* `dir`, which equals compiler.context in real Next runs — a mismatch
|
|
231
|
-
* means a custom-webpack setup wired the plugin differently). */
|
|
174
|
+
/** Adopts `compiler.context` only when no config-time root exists: every
|
|
175
|
+
* frozen derivation came from that root, so an overwrite re-keys it.
|
|
176
|
+
* Stub path, css alias, virtual system-props target and watch-ignore are
|
|
177
|
+
* all frozen from it, so a disagreement is warned, never reconciled. */
|
|
232
178
|
adoptCompilerContext(compiler) {
|
|
233
179
|
const context = compiler.context;
|
|
234
180
|
if (!this.session.rootDir) {
|
|
@@ -240,73 +186,47 @@ var AnimusWebpackPlugin = class {
|
|
|
240
186
|
console.warn(`[animus-extract] compiler.context (${context}) differs from the configured project root (${this.session.rootDir}); keeping the configured root — run next against the app directory (or align your custom webpack context) so both agree`);
|
|
241
187
|
}
|
|
242
188
|
}
|
|
243
|
-
/** This session's artifact directory, derived from the one root. */
|
|
244
189
|
get sessionDir() {
|
|
245
190
|
return this.session.sessionDir;
|
|
246
191
|
}
|
|
247
|
-
/** Expose options for the loader */
|
|
248
192
|
getOptions() {
|
|
249
193
|
return this.options;
|
|
250
194
|
}
|
|
251
|
-
/** Expose external package directories for webpack loader allowlisting.
|
|
252
|
-
* Falls back to shared globalThis state for non-owning compiler instances. */
|
|
253
195
|
getExternalPackageDirs() {
|
|
254
196
|
return this.session.externalPackageDirs.length > 0 ? this.session.externalPackageDirs : getSharedExternalDirs();
|
|
255
197
|
}
|
|
256
|
-
/** Expose external package source entries for webpack resolve alias.
|
|
257
|
-
* Falls back to shared globalThis state for non-owning compiler instances. */
|
|
258
198
|
getExternalSourceEntries() {
|
|
259
199
|
return this.session.externalSourceEntries.size > 0 ? this.session.externalSourceEntries : getSharedExternalEntries();
|
|
260
200
|
}
|
|
261
201
|
};
|
|
262
202
|
//#endregion
|
|
263
203
|
//#region src/turbopack-config.ts
|
|
264
|
-
/** The
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* via its resolved dist entry (often `dist/index.mjs`) and must still
|
|
269
|
-
* reach the loader — manifest lookup remains the file-level gate. */
|
|
204
|
+
/** The one glob the loader registers under, derived from the shared engine
|
|
205
|
+
* extension set so the bundler families cannot drift. `.mjs` belongs in that
|
|
206
|
+
* set: an external package with no src/ is ingested through its dist entry
|
|
207
|
+
* and must still reach the loader, so do not trim it. */
|
|
270
208
|
const ANIMUS_TURBOPACK_RULE_GLOB = `*.{${ENGINE_TRANSFORM_EXTENSIONS.join(",")}}`;
|
|
271
|
-
/**
|
|
272
|
-
* Resolve whether Turbopack wiring is active for this process. Default is
|
|
273
|
-
* `'auto'`: active exactly when the TURBOPACK environment variable is set
|
|
274
|
-
* (Next sets it for every Turbopack dev/build). The stable `turbopack`
|
|
275
|
-
* option wins over the deprecated `unstable_turbopack` alias.
|
|
276
|
-
*/
|
|
277
209
|
function resolveTurbopackMode(options, env = process.env) {
|
|
278
210
|
const mode = options.turbopack?.mode ?? options.unstable_turbopack?.mode ?? "auto";
|
|
279
211
|
if (mode === "on") return true;
|
|
280
212
|
if (mode === "auto") return env.TURBOPACK !== void 0;
|
|
281
213
|
return false;
|
|
282
214
|
}
|
|
283
|
-
/** rootDir-relative module request for an absolute path — always forward
|
|
284
|
-
* slashes, even when path.relative produced Windows separators. */
|
|
285
215
|
function rootRelativeRequest(rootDir, absPath) {
|
|
286
216
|
return `./${relative(rootDir, absPath).replace(/\\/g, "/")}`;
|
|
287
217
|
}
|
|
288
|
-
/**
|
|
289
|
-
* Build the `turbopack` config fragment: one glob-keyed loader rule
|
|
290
|
-
* (file-level allowlisting lives in the loader via manifest lookup — Next 15
|
|
291
|
-
* rules have no condition algebra) plus resolve aliases for the virtual
|
|
292
|
-
* system-props id, the emitter's stylesheet id, and each collected external
|
|
293
|
-
* package specifier redirected to its source entry. Loader options carry
|
|
294
|
-
* the session identity (design D2: an options-borne, JSON-serializable
|
|
295
|
-
* Turbopack task input — restart-cold by construction), and the artifact
|
|
296
|
-
* aliases point into the session-scoped tree.
|
|
297
|
-
*/
|
|
298
218
|
function buildTurbopackConfig(args) {
|
|
299
219
|
const { rootDir, loaderPath, options, externalSourceEntries, sessionId, sessionDir } = args;
|
|
300
220
|
const loaderOptions = {
|
|
301
221
|
rootDir,
|
|
302
222
|
sessionId,
|
|
303
|
-
sessionDir
|
|
304
|
-
...options.strict !== void 0 ? { strict: options.strict } : {},
|
|
305
|
-
...options.cssImportTarget !== void 0 ? { cssImportTarget: options.cssImportTarget } : {}
|
|
223
|
+
sessionDir
|
|
306
224
|
};
|
|
225
|
+
if (options.strict !== void 0) loaderOptions.strict = options.strict;
|
|
226
|
+
if (options.cssImportTarget !== void 0) loaderOptions.cssImportTarget = options.cssImportTarget;
|
|
307
227
|
const resolveAlias = {
|
|
308
228
|
[TURBOPACK_SYSTEM_PROPS_ID]: rootRelativeRequest(rootDir, join(sessionDir, SYSTEM_PROPS_ARTIFACT)),
|
|
309
|
-
|
|
229
|
+
[ANIMUS_CSS_MODULE_ID]: rootRelativeRequest(rootDir, join(sessionDir, STYLES_ARTIFACT))
|
|
310
230
|
};
|
|
311
231
|
for (const [specifier, srcEntry] of externalSourceEntries) resolveAlias[specifier] = rootRelativeRequest(rootDir, srcEntry);
|
|
312
232
|
return {
|
|
@@ -317,40 +237,25 @@ function buildTurbopackConfig(args) {
|
|
|
317
237
|
resolveAlias
|
|
318
238
|
};
|
|
319
239
|
}
|
|
320
|
-
/**
|
|
321
|
-
* Locate the Turbopack loader module: built dist first, source fallback for
|
|
322
|
-
* in-repo development. CJS preferred — Turbopack's loader-runner follows
|
|
323
|
-
* the webpack loader contract (`module.exports = fn`), and the .cjs build
|
|
324
|
-
* is loadable by every runner version; ESM default-export acceptance is
|
|
325
|
-
* not guaranteed.
|
|
326
|
-
*/
|
|
327
240
|
function resolveTurbopackLoaderPath(pluginDir) {
|
|
328
241
|
return resolveLoaderPath(pluginDir, ["turbopack-loader.cjs", "turbopack-loader.mjs"], "turbopack-loader.ts");
|
|
329
242
|
}
|
|
330
243
|
//#endregion
|
|
331
244
|
//#region src/with-animus.ts
|
|
332
|
-
const
|
|
245
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
246
|
+
const __dirname = dirname(__filename);
|
|
333
247
|
let warnedGitignore = false;
|
|
334
248
|
let warnedUnstableTurbopack = false;
|
|
335
|
-
/**
|
|
336
|
-
* Wrap a Next.js config to enable Animus static CSS extraction.
|
|
337
|
-
*
|
|
338
|
-
* ```ts
|
|
339
|
-
* // next.config.ts
|
|
340
|
-
* import { withAnimus } from '@animus-ui/next-plugin';
|
|
341
|
-
* export default withAnimus({ system: './src/ds.ts' })({});
|
|
342
|
-
* ```
|
|
343
|
-
*/
|
|
344
249
|
function withAnimus(options) {
|
|
345
250
|
if (!options.system) throw new Error("[animus-extract] Missing required option `system`. Provide the path to your SystemInstance module: withAnimus({ system: \"./src/ds.ts\" })");
|
|
346
|
-
assertKnownOptionKeys(options, [
|
|
251
|
+
assertKnownOptionKeys({ ...options }, [
|
|
347
252
|
"cssImportTarget",
|
|
348
253
|
"turbopack",
|
|
349
254
|
"unstable_turbopack",
|
|
350
255
|
"loaderPath"
|
|
351
256
|
], [{
|
|
352
257
|
key: "root",
|
|
353
|
-
reason: "
|
|
258
|
+
reason: "this driver derives its own root — Next's `dir` under webpack, `process.cwd()` under Turbopack (Next passes no dir to a config module)"
|
|
354
259
|
}], {
|
|
355
260
|
onUnknownKey: "warn",
|
|
356
261
|
warn: (message) => console.warn(`[animus-extract] ${message}`)
|
|
@@ -365,8 +270,8 @@ function withAnimus(options) {
|
|
|
365
270
|
return {
|
|
366
271
|
...nextConfig,
|
|
367
272
|
webpack(config, context) {
|
|
368
|
-
if (
|
|
369
|
-
const rootDir =
|
|
273
|
+
if (existingWebpack) config = existingWebpack(config, context);
|
|
274
|
+
const rootDir = context.dir?.length ? context.dir : process.cwd();
|
|
370
275
|
const plugin = new AnimusWebpackPlugin(options);
|
|
371
276
|
plugin.setRootDir(rootDir);
|
|
372
277
|
const sessionDir = plugin.sessionDir;
|
|
@@ -393,8 +298,8 @@ function withAnimus(options) {
|
|
|
393
298
|
const isExternalPackageFile = (filePath) => plugin.getExternalPackageDirs().some((dir) => isPathWithinRoot(dir, filePath));
|
|
394
299
|
config.plugins = config.plugins || [];
|
|
395
300
|
config.plugins.push(plugin);
|
|
396
|
-
const
|
|
397
|
-
if (
|
|
301
|
+
const DefinePlugin = context.webpack?.DefinePlugin;
|
|
302
|
+
if (DefinePlugin) config.plugins.push(new DefinePlugin({ __ANIMUS_DEV__: JSON.stringify(resolveMode(options.mode, () => context.dev === true ? "development" : "production").mode === "development") }));
|
|
398
303
|
config.resolve = config.resolve || {};
|
|
399
304
|
config.resolve.alias = config.resolve.alias || {};
|
|
400
305
|
config.resolve.alias[ANIMUS_CSS_MODULE_ID$1] = stylesPath(sessionDir);
|
|
@@ -413,10 +318,7 @@ function withAnimus(options) {
|
|
|
413
318
|
config.module = config.module || {};
|
|
414
319
|
config.module.rules = config.module.rules || [];
|
|
415
320
|
config.module.rules.push({
|
|
416
|
-
test: (filePath) =>
|
|
417
|
-
if (/\.[jt]sx?$/.test(filePath)) return true;
|
|
418
|
-
return /\.mjs$/.test(filePath) && isExternalPackageFile(filePath);
|
|
419
|
-
},
|
|
321
|
+
test: (filePath) => isEngineTransformExtension(filePath),
|
|
420
322
|
exclude: (filePath) => {
|
|
421
323
|
if (!filePath.includes("node_modules")) return false;
|
|
422
324
|
return !isExternalPackageFile(filePath);
|
|
@@ -435,20 +337,25 @@ function withAnimus(options) {
|
|
|
435
337
|
};
|
|
436
338
|
};
|
|
437
339
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
340
|
+
function bindTurbopackWatchDeathReport(outcome, rootDir) {
|
|
341
|
+
if (outcome.kind !== "started") return;
|
|
342
|
+
const handle = outcome.handle;
|
|
343
|
+
handle.onDied = () => {
|
|
344
|
+
console.error(`[animus-extract] dev watcher for ${rootDir} died — source edits are no longer extracted; restart the dev server`);
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
let liveTurbopackSession = null;
|
|
444
348
|
async function wireTurbopack(nextConfig, options) {
|
|
445
349
|
const rootDir = process.cwd();
|
|
446
350
|
const session = new ExtractionSession(options);
|
|
351
|
+
liveTurbopackSession?.close();
|
|
352
|
+
liveTurbopackSession = session;
|
|
447
353
|
session.rootDir = rootDir;
|
|
448
|
-
const
|
|
354
|
+
const aliasPairs = readTsconfigAliasPairs(rootDir);
|
|
355
|
+
const builtAliases = buildPathAliasesJson(aliasPairs, rootDir);
|
|
449
356
|
if (builtAliases) session.pathAliasesJson = builtAliases.json;
|
|
450
357
|
await runSessionPipeline(session);
|
|
451
|
-
if (process.env.NODE_ENV === "development") startTurbopackWatcher(session, rootDir);
|
|
358
|
+
if (process.env.NODE_ENV === "development") bindTurbopackWatchDeathReport(startTurbopackWatcher(session, rootDir), rootDir);
|
|
452
359
|
const fragment = buildTurbopackConfig({
|
|
453
360
|
rootDir,
|
|
454
361
|
loaderPath: resolveTurbopackLoaderPath(__dirname),
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
let _animus_ui_extract_session = require("@animus-ui/extract/session");
|
|
2
|
+
//#region src/loader-core.ts
|
|
3
|
+
/** Matches every already-emitted stylesheet import — arbitrary relative
|
|
4
|
+
* prefixes and the Vite emitter's virtual id — not this bundler's id.
|
|
5
|
+
* Never derive it from the shared module-id constant: this reads foreign
|
|
6
|
+
* output, and deriving it silently stops matching the other forms. */
|
|
7
|
+
const CSS_IMPORT_RE = /import\s+['"](?:[^'"]*\.animus\/styles\.css|virtual:animus\/styles\.css)['"];\n?/g;
|
|
8
|
+
const CSS_IMPORT_STATEMENT = `import '${_animus_ui_extract_session.ANIMUS_CSS_MODULE_ID}';\n`;
|
|
9
|
+
const ROOT_ENTRY_RE = /^(src\/)?(?:app\/layout|pages\/_app)\.[tj]sx?$/;
|
|
10
|
+
function normalizePath(p) {
|
|
11
|
+
return p.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
12
|
+
}
|
|
13
|
+
function isCssImportTarget(filename, cssImportTarget) {
|
|
14
|
+
const normalized = normalizePath(filename);
|
|
15
|
+
if (cssImportTarget) return normalized === normalizePath(cssImportTarget);
|
|
16
|
+
return ROOT_ENTRY_RE.test(normalized);
|
|
17
|
+
}
|
|
18
|
+
function transformWithManifest(args) {
|
|
19
|
+
const { source, filename, manifestJson, engineApi, opts } = args;
|
|
20
|
+
const isRootEntry = isCssImportTarget(filename, opts.cssImportTarget);
|
|
21
|
+
try {
|
|
22
|
+
const { transformFile } = engineApi();
|
|
23
|
+
const result = transformFile(source, filename, manifestJson);
|
|
24
|
+
let code = result.hasComponents ? result.code : source;
|
|
25
|
+
code = code.replace(CSS_IMPORT_RE, "");
|
|
26
|
+
if (isRootEntry && !code.includes(_animus_ui_extract_session.ANIMUS_CSS_MODULE_ID)) {
|
|
27
|
+
if (code.startsWith("'use client'") || code.startsWith("\"use client\"")) {
|
|
28
|
+
const nl = code.indexOf("\n");
|
|
29
|
+
if (nl === -1) code = `${code}\n${CSS_IMPORT_STATEMENT}`;
|
|
30
|
+
else code = `${code.slice(0, nl + 1)}${CSS_IMPORT_STATEMENT}${code.slice(nl + 1)}`;
|
|
31
|
+
} else code = `${CSS_IMPORT_STATEMENT}${code}`;
|
|
32
|
+
}
|
|
33
|
+
return code;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
36
|
+
if (opts.strict) throw new Error(`[animus-extract] Transform failed for ${filename}: ${msg}`, { cause: e });
|
|
37
|
+
console.warn(`[animus-extract] Transform failed for ${filename}:`, msg);
|
|
38
|
+
return source;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
Object.defineProperty(exports, "transformWithManifest", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function() {
|
|
45
|
+
return transformWithManifest;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ANIMUS_CSS_MODULE_ID } from "@animus-ui/extract/session";
|
|
2
|
+
//#region src/loader-core.ts
|
|
3
|
+
/** Matches every already-emitted stylesheet import — arbitrary relative
|
|
4
|
+
* prefixes and the Vite emitter's virtual id — not this bundler's id.
|
|
5
|
+
* Never derive it from the shared module-id constant: this reads foreign
|
|
6
|
+
* output, and deriving it silently stops matching the other forms. */
|
|
7
|
+
const CSS_IMPORT_RE = /import\s+['"](?:[^'"]*\.animus\/styles\.css|virtual:animus\/styles\.css)['"];\n?/g;
|
|
8
|
+
const CSS_IMPORT_STATEMENT = `import '${ANIMUS_CSS_MODULE_ID}';\n`;
|
|
9
|
+
const ROOT_ENTRY_RE = /^(src\/)?(?:app\/layout|pages\/_app)\.[tj]sx?$/;
|
|
10
|
+
function normalizePath(p) {
|
|
11
|
+
return p.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
12
|
+
}
|
|
13
|
+
function isCssImportTarget(filename, cssImportTarget) {
|
|
14
|
+
const normalized = normalizePath(filename);
|
|
15
|
+
if (cssImportTarget) return normalized === normalizePath(cssImportTarget);
|
|
16
|
+
return ROOT_ENTRY_RE.test(normalized);
|
|
17
|
+
}
|
|
18
|
+
function transformWithManifest(args) {
|
|
19
|
+
const { source, filename, manifestJson, engineApi, opts } = args;
|
|
20
|
+
const isRootEntry = isCssImportTarget(filename, opts.cssImportTarget);
|
|
21
|
+
try {
|
|
22
|
+
const { transformFile } = engineApi();
|
|
23
|
+
const result = transformFile(source, filename, manifestJson);
|
|
24
|
+
let code = result.hasComponents ? result.code : source;
|
|
25
|
+
code = code.replace(CSS_IMPORT_RE, "");
|
|
26
|
+
if (isRootEntry && !code.includes(ANIMUS_CSS_MODULE_ID)) {
|
|
27
|
+
if (code.startsWith("'use client'") || code.startsWith("\"use client\"")) {
|
|
28
|
+
const nl = code.indexOf("\n");
|
|
29
|
+
if (nl === -1) code = `${code}\n${CSS_IMPORT_STATEMENT}`;
|
|
30
|
+
else code = `${code.slice(0, nl + 1)}${CSS_IMPORT_STATEMENT}${code.slice(nl + 1)}`;
|
|
31
|
+
} else code = `${CSS_IMPORT_STATEMENT}${code}`;
|
|
32
|
+
}
|
|
33
|
+
return code;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
36
|
+
if (opts.strict) throw new Error(`[animus-extract] Transform failed for ${filename}: ${msg}`, { cause: e });
|
|
37
|
+
console.warn(`[animus-extract] Transform failed for ${filename}:`, msg);
|
|
38
|
+
return source;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { transformWithManifest as t };
|
package/dist/loader-core.d.ts
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bundler-neutral loader policy shared by the webpack loader (manifest from
|
|
3
|
-
* the process singleton) and the Turbopack loader (manifest hydrated from
|
|
4
|
-
* disk artifacts). Owns the transform invocation, strict-mode error
|
|
5
|
-
* handling, and the single-stylesheet-import policy.
|
|
6
|
-
*/
|
|
7
1
|
export interface LoaderPolicyOptions {
|
|
8
2
|
strict?: boolean;
|
|
9
3
|
cssImportTarget?: string;
|
|
10
4
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*/
|
|
5
|
+
export interface LoaderContextBase<O extends LoaderPolicyOptions = LoaderPolicyOptions> {
|
|
6
|
+
resourcePath: string;
|
|
7
|
+
rootContext: string;
|
|
8
|
+
getOptions: () => O;
|
|
9
|
+
addDependency?: (file: string) => void;
|
|
10
|
+
}
|
|
18
11
|
export declare function transformWithManifest(args: {
|
|
19
12
|
source: string;
|
|
20
13
|
/** Project-root-relative path of the file being transformed. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader-core.d.ts","sourceRoot":"","sources":["../src/loader-core.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loader-core.d.ts","sourceRoot":"","sources":["../src/loader-core.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB,CAChC,CAAC,SAAS,mBAAmB,GAAG,mBAAmB;IAEnD,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AA4BD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IAErB,SAAS,EAAE,MAAM,GAAG,CAAC;IACrB,IAAI,EAAE,mBAAmB,CAAC;CAC3B,GAAG,MAAM,CAwCT"}
|
package/dist/loader-path.d.ts
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The one loader-path derivation: first existing dist candidate under the
|
|
3
|
-
* plugin dir, else the in-repo source fallback. Both loader resolvers below
|
|
4
|
-
* are thin wrappers, so rule registration and any loader-chain predicate
|
|
5
|
-
* can never drift (openspec: next-webpack-served-transform-coherence,
|
|
6
|
-
* design D1).
|
|
7
|
-
*/
|
|
8
1
|
export declare function resolveLoaderPath(pluginDir: string, distCandidates: string[], sourceFallback: string): string;
|
|
9
|
-
/**
|
|
10
|
-
* This package's webpack loader path, shared by the rule registration
|
|
11
|
-
* (with-animus) and the needBuild loader-chain predicate (plugin). Compiled
|
|
12
|
-
* dist ships `loader.mjs` next to this module; running from source falls
|
|
13
|
-
* back to the TypeScript loader.
|
|
14
|
-
*/
|
|
15
2
|
export declare function resolveAnimusLoaderPath(): string;
|
|
16
3
|
//# sourceMappingURL=loader-path.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader-path.d.ts","sourceRoot":"","sources":["../src/loader-path.ts"],"names":[],"mappings":"AAOA
|
|
1
|
+
{"version":3,"file":"loader-path.d.ts","sourceRoot":"","sources":["../src/loader-path.ts"],"names":[],"mappings":"AAOA,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EAAE,EACxB,cAAc,EAAE,MAAM,GACrB,MAAM,CAMR;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD"}
|
package/dist/loader.cjs
CHANGED
|
@@ -1,35 +1,12 @@
|
|
|
1
|
-
const require_loader_core = require("./loader-core-
|
|
2
|
-
require("./turbopack-loader.cjs");
|
|
1
|
+
const require_loader_core = require("./loader-core-BthLSJQF.cjs");
|
|
3
2
|
let _animus_ui_extract_pipeline = require("@animus-ui/extract/pipeline");
|
|
4
3
|
let _animus_ui_extract_session = require("@animus-ui/extract/session");
|
|
5
4
|
let fs = require("fs");
|
|
6
5
|
let path = require("path");
|
|
7
6
|
//#region src/loader.ts
|
|
8
|
-
/** Session dirs whose epoch artifact has been SEEN on disk. A sibling
|
|
9
|
-
* session's reconciliation may delete the artifact, but the owning
|
|
10
|
-
* session self-heals it on its next publish, so a positive existsSync
|
|
11
|
-
* stays a sound basis for registering the dependency: a module built
|
|
12
|
-
* during the missing window records a missing-file witness that the
|
|
13
|
-
* recreation then invalidates (over-invalidation, never under).
|
|
14
|
-
* Negatives always re-probe. */
|
|
15
7
|
const epochSeenForSessionDir = /* @__PURE__ */ new Set();
|
|
16
|
-
/**
|
|
17
|
-
* Webpack loader for Animus source transformation.
|
|
18
|
-
* Runs with enforce: 'pre' to see original source before Babel/SWC.
|
|
19
|
-
* The manifest arrives via the process singleton (the webpack pipeline and
|
|
20
|
-
* this loader share one process); the transform + CSS-import policy lives
|
|
21
|
-
* in the shared loader-core.
|
|
22
|
-
*
|
|
23
|
-
* Coherence duties (openspec: next-webpack-served-transform-coherence):
|
|
24
|
-
* every dev invocation registers the replacement-epoch artifact as a file
|
|
25
|
-
* dependency (design D2 — restored persistent-cache modules snapshot it, so
|
|
26
|
-
* offline epoch moves invalidate them), and an analyzed file whose current
|
|
27
|
-
* source hash mismatches its analyzed hash fails with the stable diagnostic
|
|
28
|
-
* `ANIMUS_ANALYSIS_CATCHING_UP` after one refreshed re-check (design D4 —
|
|
29
|
-
* unconditional: a zero-entry stale manifest must never publish raw bytes).
|
|
30
|
-
*/
|
|
31
8
|
function animusLoader(source) {
|
|
32
|
-
if (this.mode !== "production" &&
|
|
9
|
+
if (this.mode !== "production" && this.addDependency !== void 0) {
|
|
33
10
|
const sessionDir = (0, _animus_ui_extract_session.getSessionArtifactDir)();
|
|
34
11
|
if (sessionDir) {
|
|
35
12
|
const epochPath = (0, _animus_ui_extract_session.replacementEpochPath)(sessionDir);
|
package/dist/loader.d.ts
CHANGED
|
@@ -1,29 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
type LoaderContext = {
|
|
3
|
-
resourcePath: string;
|
|
4
|
-
rootContext: string;
|
|
5
|
-
getOptions: () => LoaderPolicyOptions;
|
|
6
|
-
/** webpack file-dependency registration — optional so bare policy tests
|
|
7
|
-
* can drive the loader without a full context. */
|
|
8
|
-
addDependency?: (file: string) => void;
|
|
9
|
-
/** webpack build mode; production invocations stay engine-verbatim. */
|
|
1
|
+
import type { LoaderContextBase } from './loader-core';
|
|
2
|
+
type LoaderContext = LoaderContextBase & {
|
|
10
3
|
mode?: 'development' | 'production' | 'none';
|
|
11
4
|
};
|
|
12
|
-
/**
|
|
13
|
-
* Webpack loader for Animus source transformation.
|
|
14
|
-
* Runs with enforce: 'pre' to see original source before Babel/SWC.
|
|
15
|
-
* The manifest arrives via the process singleton (the webpack pipeline and
|
|
16
|
-
* this loader share one process); the transform + CSS-import policy lives
|
|
17
|
-
* in the shared loader-core.
|
|
18
|
-
*
|
|
19
|
-
* Coherence duties (openspec: next-webpack-served-transform-coherence):
|
|
20
|
-
* every dev invocation registers the replacement-epoch artifact as a file
|
|
21
|
-
* dependency (design D2 — restored persistent-cache modules snapshot it, so
|
|
22
|
-
* offline epoch moves invalidate them), and an analyzed file whose current
|
|
23
|
-
* source hash mismatches its analyzed hash fails with the stable diagnostic
|
|
24
|
-
* `ANIMUS_ANALYSIS_CATCHING_UP` after one refreshed re-check (design D4 —
|
|
25
|
-
* unconditional: a zero-entry stale manifest must never publish raw bytes).
|
|
26
|
-
*/
|
|
27
5
|
export default function animusLoader(this: LoaderContext, source: string): string;
|
|
28
6
|
export {};
|
|
29
7
|
//# sourceMappingURL=loader.d.ts.map
|
package/dist/loader.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAIvD,KAAK,aAAa,GAAG,iBAAiB,GAAG;IACvC,IAAI,CAAC,EAAE,aAAa,GAAG,YAAY,GAAG,MAAM,CAAC;CAC9C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,MAAM,GACb,MAAM,CAsCR"}
|