astro-indexnow 2.3.7 → 2.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.MD CHANGED
@@ -6,7 +6,7 @@ to **IndexNow** after each build.
6
6
  This package is designed for **modern CI/CD pipelines**, **Docker-based deployments**, and
7
7
  **large static sites**, while remaining fully deterministic and explicit.
8
8
 
9
- > **Current release:** v2.3.7
9
+ > **Current release:** v2.3.9
10
10
  > **Stateful by design. `changed` by default, `all` available. Batch-safe. CI-aware.**
11
11
 
12
12
  ---
@@ -137,6 +137,15 @@ Using environment variables is **strongly recommended** for CI/CD.
137
137
  This release is backwards compatible with earlier supported package versions.
138
138
  Older npm versions are not deprecated by default; they remain supported until a future major release introduces a breaking change.
139
139
 
140
+ ## Release Rollback Policy
141
+
142
+ If a published version is found to be broken:
143
+
144
+ - Prefer `npm deprecate` for the affected version if users should avoid it.
145
+ - Publish a patch release with the fix rather than rewriting the bad version.
146
+ - Create a new git tag and GitHub release for the patched version.
147
+ - Keep the changelog explicit about which version is bad and which version supersedes it.
148
+
140
149
  ## Migration Notes
141
150
 
142
151
  ### From v1
@@ -204,7 +213,23 @@ This file:
204
213
 
205
214
  Older flat cache files are still read automatically and will be upgraded on the next write.
206
215
 
207
- Deleting the file simply causes the next build to treat all pages as new.
216
+ ### When should you commit it?
217
+
218
+ - Commit the cache when your site builds in an ephemeral environment such as GitHub Actions, GitLab CI, Vercel, Netlify, or a container recreated for each build.
219
+ - Do not commit it when your deploy process reuses the same working directory and the file persists between builds.
220
+ - If you are unsure, commit it for Git-based deploys and leave it out for long-lived servers.
221
+
222
+ ### What happens if you delete it?
223
+
224
+ - The next build treats every generated page as new.
225
+ - That usually means a full re-submission on the next successful build.
226
+ - The cache is rebuilt automatically after the next successful submission run.
227
+
228
+ ### How does this affect CI/CD and branch builds?
229
+
230
+ - In CI/CD, the cache should usually be checked in so each run can compare against the previous state.
231
+ - For branch builds and preview environments, keep the cache separate per branch if you want branch-local change tracking.
232
+ - If a branch does not have a prior cache, the first build behaves like a fresh site and submits every generated page.
208
233
 
209
234
  ---
210
235
 
@@ -314,6 +339,38 @@ The directory where the `.astro-indexnow-cache.json` file will be stored. Can be
314
339
 
315
340
  Example: `./node_modules/.astro`
316
341
 
342
+ The `site` value in Astro config may include a path prefix, such as `https://example.com/blog`. The integration preserves that base path when building submission URLs.
343
+
344
+ Submitted URLs use the canonical no-trailing-slash form for generated pages, except for the site root itself.
345
+
346
+ ### Monorepo note
347
+
348
+ - The cache path is resolved from `process.cwd()` unless you override `cacheDir`.
349
+ - In a monorepo, that means the cache is written relative to the package you run `astro build` from, not the repository root.
350
+ - If your Astro app lives in a nested workspace, set `cacheDir` explicitly so the cache lands where you expect it.
351
+
352
+ ---
353
+
354
+ ### `buildOutputDir` (optional)
355
+
356
+ Type: `string`
357
+ Default: Astro's build output directory
358
+
359
+ Overrides the directory the integration scans for generated HTML.
360
+
361
+ Use this if:
362
+ - your build output lives somewhere other than Astro's default `dist`
363
+ - you want to point the integration at a custom generated output directory
364
+ - you need to scan a fixture or alternate build target in CI
365
+
366
+ The path is resolved from the project root when relative.
367
+
368
+ ```js
369
+ indexnow({
370
+ buildOutputDir: "./fixtures/site-dist",
371
+ })
372
+ ```
373
+
317
374
  ---
318
375
 
319
376
  ### `submissionMode` (optional)
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export interface IndexNowOptions {
4
4
  siteUrl?: string;
5
5
  enabled?: boolean;
6
6
  cacheDir?: string;
7
+ buildOutputDir?: string;
7
8
  dryRun?: boolean;
8
9
  logMode?: "quiet" | "normal" | "verbose";
9
10
  submissionMode?: "changed" | "all";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAM9C,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzC,cAAc,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAOD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC9B,OAAO,GAAE,eAAoB,GAC5B,gBAAgB,CAsVlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAM9C,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzC,cAAc,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAOD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC9B,OAAO,GAAE,eAAoB,GAC5B,gBAAgB,CAmXlB"}
package/dist/index.js CHANGED
@@ -82,6 +82,19 @@ export default function indexNow(options = {}) {
82
82
  function sleep(ms) {
83
83
  return new Promise((resolve) => setTimeout(resolve, ms));
84
84
  }
85
+ function normalizeSiteUrl(value) {
86
+ const url = new URL(value);
87
+ const normalizedPath = url.pathname.replace(/\/+$/, "").replace(/\/+/g, "/");
88
+ url.pathname = normalizedPath || "/";
89
+ return url.toString().replace(/\/$/, "");
90
+ }
91
+ function normalizeSubmittedUrl(value) {
92
+ const url = new URL(value);
93
+ if (url.pathname !== "/") {
94
+ url.pathname = url.pathname.replace(/\/+$/, "");
95
+ }
96
+ return url.toString();
97
+ }
85
98
  function isQuiet() {
86
99
  return options.logMode === "quiet";
87
100
  }
@@ -152,8 +165,11 @@ export default function indexNow(options = {}) {
152
165
  ----------------------------------------------- */
153
166
  "astro:config:setup": ({ config, logger }) => {
154
167
  site =
155
- options.siteUrl ??
156
- (config.site ? config.site.replace(/\/$/, "") : null);
168
+ options.siteUrl
169
+ ? normalizeSiteUrl(options.siteUrl)
170
+ : config.site
171
+ ? normalizeSiteUrl(config.site)
172
+ : null;
157
173
  logVerbose(logger, `project root: ${projectRoot}`);
158
174
  ensureCacheFile(logger);
159
175
  },
@@ -172,7 +188,12 @@ export default function indexNow(options = {}) {
172
188
  throw new Error("[astro-indexnow] Missing site URL");
173
189
  }
174
190
  ensureCacheFile(logger);
175
- const outDir = fileURLToPath(dir instanceof URL ? dir : new URL(dir));
191
+ const outDir = options.buildOutputDir
192
+ ? path.resolve(projectRoot, options.buildOutputDir)
193
+ : fileURLToPath(dir instanceof URL ? dir : new URL(dir));
194
+ if (!fs.existsSync(outDir)) {
195
+ throw new Error(`[astro-indexnow] Build output directory not found: ${outDir}`);
196
+ }
176
197
  const previousCache = loadCache(logger);
177
198
  const nextCache = {};
178
199
  const changedUrls = [];
@@ -188,7 +209,7 @@ export default function indexNow(options = {}) {
188
209
  .relative(outDir, fullPath)
189
210
  .replace(/index\.html$/, "")
190
211
  .replace(/\\/g, "/");
191
- const url = site + "/" + relativePath.replace(/^\/+/, "");
212
+ const url = normalizeSubmittedUrl(new URL(relativePath.replace(/^\/+/, ""), `${site}/`).toString());
192
213
  const hash = hashFile(fullPath);
193
214
  // Cache by URL because IndexNow submits URLs, not filesystem paths.
194
215
  nextCache[url] = hash;
@@ -241,13 +262,13 @@ export default function indexNow(options = {}) {
241
262
  anyBatchFailed = true;
242
263
  }
243
264
  }
244
- saveCache(logger, nextCache);
245
265
  if (anyBatchFailed) {
246
266
  logWarn(logger, `IndexNow submission failed`);
267
+ logWarn(logger, "cache left unchanged because one or more submissions failed");
268
+ return;
247
269
  }
248
- else {
249
- logInfo(logger, `IndexNow submission complete`);
250
- }
270
+ saveCache(logger, nextCache);
271
+ logInfo(logger, `IndexNow submission complete`);
251
272
  },
252
273
  },
253
274
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-indexnow",
3
- "version": "2.3.7",
3
+ "version": "2.3.9",
4
4
  "description": "Astro integration to submit pages to IndexNow automatically after build",
5
5
  "type": "module",
6
6
  "exports": {