@riebeckite/core 0.0.30 → 0.0.31

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.js CHANGED
@@ -826,7 +826,7 @@ function getFileName(filePath) {
826
826
  }
827
827
 
828
828
  // src/content/content_build_state.ts
829
- var CONTENT_BUILD_STATE_VERSION = 19;
829
+ var CONTENT_BUILD_STATE_VERSION = 20;
830
830
  var CONTENT_BUILD_STATE_DIRECTORY = ".riebeckite";
831
831
  var CONTENT_BUILD_STATE_EXCLUDE = `${CONTENT_BUILD_STATE_DIRECTORY}/**`;
832
832
 
@@ -834,8 +834,11 @@ var CONTENT_BUILD_STATE_EXCLUDE = `${CONTENT_BUILD_STATE_DIRECTORY}/**`;
834
834
  import { randomUUID } from "node:crypto";
835
835
  import fs from "node:fs/promises";
836
836
  import path from "node:path";
837
+ var MAX_CONTENT_BUILD_STATE_BYTES = 64 * 1024 * 1024;
837
838
  async function loadContentBuildState(statePath) {
838
839
  try {
840
+ const metadata = await fs.stat(statePath);
841
+ if (metadata.size > MAX_CONTENT_BUILD_STATE_BYTES) return void 0;
839
842
  const parsed = JSON.parse(await fs.readFile(statePath, "utf8"));
840
843
  return isContentBuildState(parsed) ? parsed : void 0;
841
844
  } catch {
@@ -922,7 +925,7 @@ function isContentBuildStateShape(value) {
922
925
  }
923
926
  function isManifestHookCache(value) {
924
927
  return Array.isArray(value) && value.every(
925
- (entry) => isRecord2(entry) && typeof entry.pluginName === "string" && typeof entry.cacheable === "boolean" && (entry.pipelineFingerprint === void 0 || typeof entry.pipelineFingerprint === "string") && typeof entry.inputFingerprint === "string" && (entry.outputFingerprint === void 0 || typeof entry.outputFingerprint === "string") && (entry.snapshot === void 0 || isManifestHookSnapshot(entry.snapshot))
928
+ (entry) => isRecord2(entry) && typeof entry.pluginName === "string" && typeof entry.cacheVersion === "string" && typeof entry.cacheable === "boolean" && (entry.pipelineFingerprint === void 0 || typeof entry.pipelineFingerprint === "string") && typeof entry.inputFingerprint === "string" && (entry.outputFingerprint === void 0 || typeof entry.outputFingerprint === "string") && (entry.snapshot === void 0 || isManifestHookSnapshot(entry.snapshot))
926
929
  );
927
930
  }
928
931
  function isManifestHookSnapshot(value) {
@@ -2991,16 +2994,18 @@ function serializeManifestEntries(entries) {
2991
2994
  serialized.set(entry.slug, JSON.stringify(entry));
2992
2995
  return serialized;
2993
2996
  }
2994
- function createManifestHookCacheEntry(pluginName, cacheable, pipelineFingerprint, inputFingerprint, manifest, beforeEntries, afterEntries) {
2997
+ function createManifestHookCacheEntry(pluginName, cacheVersion, cacheable, pipelineFingerprint, inputFingerprint, manifest, beforeEntries, afterEntries) {
2995
2998
  if (!cacheable)
2996
2999
  return {
2997
3000
  pluginName,
3001
+ cacheVersion,
2998
3002
  cacheable,
2999
3003
  pipelineFingerprint,
3000
3004
  inputFingerprint
3001
3005
  };
3002
3006
  return {
3003
3007
  pluginName,
3008
+ cacheVersion,
3004
3009
  cacheable,
3005
3010
  pipelineFingerprint,
3006
3011
  inputFingerprint,
@@ -3282,9 +3287,10 @@ var ManifestHookRunner = class {
3282
3287
  if (plugin.buildEnd) return "plugin-build-end";
3283
3288
  if (plugin.planGeneratedOutputs) return "plugin-generated-output-plan";
3284
3289
  if (!plugin.onManifestCreated) continue;
3290
+ if (!plugin.manifestHookCache) return "manifest-hook-cache-disabled";
3285
3291
  const cached = previousCache[cacheIndex];
3286
3292
  cacheIndex += 1;
3287
- if (cached?.pluginName !== plugin.name || !cached.cacheable || cached.pipelineFingerprint !== pipelineFingerprint)
3293
+ if (cached?.pluginName !== plugin.name || cached.cacheVersion !== plugin.manifestHookCache.version || !cached.cacheable || cached.pipelineFingerprint !== pipelineFingerprint)
3288
3294
  return "manifest-hook-cache-miss";
3289
3295
  }
3290
3296
  return void 0;
@@ -3298,10 +3304,14 @@ var ManifestHookRunner = class {
3298
3304
  manifest
3299
3305
  };
3300
3306
  let cacheIndex = 0;
3301
- let entriesBeforeHook = serializeManifestEntries(manifest.entries);
3302
3307
  for (const plugin of this.options.plugins()) {
3303
3308
  const hook = plugin.onManifestCreated;
3304
3309
  if (!hook) continue;
3310
+ const cacheVersion = plugin.manifestHookCache?.version;
3311
+ if (!cacheVersion) {
3312
+ await this.runManifestHook(plugin, hook, context, "cache-disabled");
3313
+ continue;
3314
+ }
3305
3315
  const inputFingerprint = fingerprintManifestHookInput(manifest);
3306
3316
  const cached = previousCache[cacheIndex];
3307
3317
  cacheIndex += 1;
@@ -3313,46 +3323,29 @@ var ManifestHookRunner = class {
3313
3323
  );
3314
3324
  let restored = false;
3315
3325
  let restorePoint;
3316
- if (cached !== void 0 && cached.pluginName === plugin.name && cached.cacheable && cached.pipelineFingerprint === pipelineFingerprint && cached.inputFingerprint === inputFingerprint && cached.snapshot !== void 0 && cached.outputFingerprint !== void 0) {
3326
+ if (cached !== void 0 && cached.pluginName === plugin.name && cached.cacheVersion === cacheVersion && cached.cacheable && cached.pipelineFingerprint === pipelineFingerprint && cached.inputFingerprint === inputFingerprint && cached.snapshot !== void 0 && cached.outputFingerprint !== void 0) {
3317
3327
  restorePoint = captureManifestHookRestorePoint(manifest);
3318
3328
  restored = applyManifestHookSnapshot(manifest, cached.snapshot);
3319
3329
  if (restored && fingerprintManifestHookSnapshot(manifest) === cached.outputFingerprint) {
3320
3330
  this.manifestHooksReused += 1;
3321
3331
  this.manifestHookCache.push(cached);
3322
3332
  this.recordManifestHookMetric(plugin.name, "reused", "cache-hit", 0);
3323
- entriesBeforeHook = serializeManifestEntries(manifest.entries);
3324
3333
  continue;
3325
3334
  }
3326
3335
  }
3327
3336
  if (restored && restorePoint)
3328
3337
  restoreManifestHookEntries(manifest, restorePoint);
3338
+ const entriesBeforeHook = serializeManifestEntries(manifest.entries);
3329
3339
  const sideEffectsBefore = fingerprintManifestHookSideEffects(manifest);
3330
3340
  const outputCountBefore = this.options.generatedOutputCount();
3331
3341
  const diagnosticCountBefore = this.options.diagnosticCount();
3332
3342
  const manifestDiagnosticCountBefore = manifest.diagnostics.length;
3333
- const started = performance.now();
3334
- this.manifestHooksExecuted += 1;
3335
- try {
3336
- await runPluginHook(
3337
- plugin,
3338
- "onManifestCreated",
3339
- this.options.createPluginContext(plugin, context),
3340
- hook
3341
- );
3342
- } finally {
3343
- const durationMs = performance.now() - started;
3344
- this.manifestHookDurationMs += durationMs;
3345
- this.recordManifestHookMetric(
3346
- plugin.name,
3347
- "executed",
3348
- reason,
3349
- durationMs
3350
- );
3351
- }
3343
+ await this.runManifestHook(plugin, hook, context, reason);
3352
3344
  const entriesAfterHook = serializeManifestEntries(manifest.entries);
3353
3345
  this.manifestHookCache.push(
3354
3346
  createManifestHookCacheEntry(
3355
3347
  plugin.name,
3348
+ cacheVersion,
3356
3349
  plugin.resolveExternalDependencies === void 0 && sideEffectsBefore === fingerprintManifestHookSideEffects(manifest) && outputCountBefore === this.options.generatedOutputCount() && diagnosticCountBefore === this.options.diagnosticCount() && manifestDiagnosticCountBefore === manifest.diagnostics.length,
3357
3350
  pipelineFingerprint,
3358
3351
  inputFingerprint,
@@ -3361,7 +3354,27 @@ var ManifestHookRunner = class {
3361
3354
  entriesAfterHook
3362
3355
  )
3363
3356
  );
3364
- entriesBeforeHook = entriesAfterHook;
3357
+ }
3358
+ }
3359
+ async runManifestHook(plugin, hook, context, reason) {
3360
+ const started = performance.now();
3361
+ this.manifestHooksExecuted += 1;
3362
+ try {
3363
+ await runPluginHook(
3364
+ plugin,
3365
+ "onManifestCreated",
3366
+ this.options.createPluginContext(plugin, context),
3367
+ hook
3368
+ );
3369
+ } finally {
3370
+ const durationMs = performance.now() - started;
3371
+ this.manifestHookDurationMs += durationMs;
3372
+ this.recordManifestHookMetric(
3373
+ plugin.name,
3374
+ "executed",
3375
+ reason,
3376
+ durationMs
3377
+ );
3365
3378
  }
3366
3379
  }
3367
3380
  recordManifestHookMetric(pluginName, outcome, reason, durationMs) {
@@ -6026,7 +6039,7 @@ var ContentManager = class {
6026
6039
  /** Resolves a page contributed by an enabled plugin. */
6027
6040
  async resolvePage(pathname) {
6028
6041
  const [manifest, contentIndex] = await Promise.all([
6029
- this.getManifest(),
6042
+ this.getManifest({ incremental: false }),
6030
6043
  this.getContentIndex()
6031
6044
  ]);
6032
6045
  return await this.pluginRuntime.resolvePage(
@@ -6089,7 +6102,7 @@ var ContentManager = class {
6089
6102
  }
6090
6103
  requestBuildStateCommit(options) {
6091
6104
  if (this.pipelineOptions.commitBuildState === false) return;
6092
- if (options?.incremental === true) this.buildStateCommitRequested = true;
6105
+ if (options?.incremental !== false) this.buildStateCommitRequested = true;
6093
6106
  }
6094
6107
  async commitBuildState() {
6095
6108
  if (this.buildStateCommitted || !this.buildStateCommitRequested || !this.manifest || !this.outputChangeSet) {
@@ -1,7 +1,7 @@
1
1
  import type { ContentManifestEntry } from "../types/content_manifest.js";
2
2
  import type { ContentSourceEntry } from "./content_source.js";
3
3
  import type { OutputDescriptor } from "./output_dependency.js";
4
- export declare const CONTENT_BUILD_STATE_VERSION = 19;
4
+ export declare const CONTENT_BUILD_STATE_VERSION = 20;
5
5
  /**
6
6
  * Build state lives under `<content directory>/.riebeckite`. That directory is
7
7
  * build-time state, not content, so content sources must exclude it from scans
@@ -33,6 +33,7 @@ export type ContentBuildState = {
33
33
  };
34
34
  export type ManifestHookCacheEntry = {
35
35
  readonly pluginName: string;
36
+ readonly cacheVersion: string;
36
37
  readonly cacheable: boolean;
37
38
  readonly pipelineFingerprint: string | undefined;
38
39
  readonly inputFingerprint: string;
@@ -2,7 +2,7 @@ import type { ContentManifest, ContentManifestEntry } from "../types/content_man
2
2
  import type { ManifestHookCacheEntry, ManifestHookSnapshot } from "./content_build_state.js";
3
3
  export declare function fingerprintManifestHookInput(manifest: ContentManifest): string;
4
4
  export declare function serializeManifestEntries(entries: readonly ContentManifestEntry[]): Map<string, string>;
5
- export declare function createManifestHookCacheEntry(pluginName: string, cacheable: boolean, pipelineFingerprint: string | undefined, inputFingerprint: string, manifest: ContentManifest, beforeEntries: ReadonlyMap<string, string>, afterEntries: ReadonlyMap<string, string>): ManifestHookCacheEntry;
5
+ export declare function createManifestHookCacheEntry(pluginName: string, cacheVersion: string, cacheable: boolean, pipelineFingerprint: string | undefined, inputFingerprint: string, manifest: ContentManifest, beforeEntries: ReadonlyMap<string, string>, afterEntries: ReadonlyMap<string, string>): ManifestHookCacheEntry;
6
6
  export declare function fingerprintManifestHookSideEffects(manifest: ContentManifest): string;
7
7
  export declare function fingerprintManifestHookSnapshot(manifest: ContentManifest): string;
8
8
  export type ManifestHookRestorePoint = {
@@ -37,6 +37,7 @@ export declare class ManifestHookRunner {
37
37
  getNoChangeFastPathBlockReason(previousCache: readonly ManifestHookCacheEntry[], pipelineFingerprint: string | undefined): string | undefined;
38
38
  getCache(): readonly ManifestHookCacheEntry[];
39
39
  runManifestCreated(manifest: ContentManifest, contentIndex: Map<string, string>, previousCache: readonly ManifestHookCacheEntry[], pipelineFingerprint: string | undefined): Promise<void>;
40
+ private runManifestHook;
40
41
  private recordManifestHookMetric;
41
42
  }
42
43
  export {};
@@ -23,13 +23,6 @@ export type ContentAsset = {
23
23
  export type ContentManifestPluginAsset = PluginAsset & {
24
24
  path: string;
25
25
  };
26
- /**
27
- * The standard `article.*` positions the article consumer recognizes.
28
- *
29
- * These constants are a convenience for Sites that prefer named references;
30
- * writing the slot string inline (for example `name="article.metadata"`) stays
31
- * the recommended, most readable form in TSX layouts.
32
- */
33
26
  /** Client entries and their explicitly public configuration. */
34
27
  export type ContentManifestPluginClientEntry = PluginClientEntry;
35
28
  export type ContentManifestEntry = {
@@ -74,6 +74,9 @@ export type RiebeckitePlugin<TOptions = unknown> = {
74
74
  extendContentLocations?(context: PluginContentLocationAugmentContext): void | Promise<void>;
75
75
  onPostParsed?(context: PluginPostContext): void | Promise<void>;
76
76
  onPostProcessed?(context: PluginPostContext): void | Promise<void>;
77
+ manifestHookCache?: {
78
+ version: string;
79
+ };
77
80
  onManifestCreated?(context: PluginManifestContext): void | Promise<void>;
78
81
  extendMarkdownPipeline?(pipeline: MarkdownPipeline, context: MarkdownPipelineContext): void;
79
82
  extendHtmlPipeline?(pipeline: HtmlPipeline): void;
@@ -36,6 +36,8 @@ export type PluginEndpoint = {
36
36
  path: string;
37
37
  /** Defaults to `GET` when omitted. */
38
38
  method?: PluginEndpointMethod;
39
+ /** Defaults to `true`; set to `false` for endpoints that only use configuration. */
40
+ requiresManifest?: boolean;
39
41
  handler(context: PluginEndpointContext): PluginEndpointResponse | Promise<PluginEndpointResponse>;
40
42
  };
41
43
  export type PluginEndpointOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/core",
3
- "version": "0.0.30",
3
+ "version": "0.0.31",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "tsx": "^4.22.4",
52
- "@riebeckite/test": "0.0.30"
52
+ "@riebeckite/test": "0.0.31"
53
53
  },
54
54
  "repository": {
55
55
  "type": "git",