astro-indexnow 2.3.1 โ 2.3.3
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 +38 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -16
- package/package.json +1 -1
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.
|
|
9
|
+
> **Current release:** v2.3.3
|
|
10
10
|
> **Stateful by design. `changed` by default, `all` available. Batch-safe. CI-aware.**
|
|
11
11
|
|
|
12
12
|
---
|
|
@@ -28,6 +28,8 @@ Instead of waiting for crawlers, your site tells search engines exactly which UR
|
|
|
28
28
|
- ๐ง Stores a small on-disk cache to avoid re-submitting unchanged URLs
|
|
29
29
|
- ๐ฆ **Batches submissions** safely (IndexNow 10,000 URL limit)
|
|
30
30
|
- ๐ Optional `submissionMode` lets you choose `changed` or `all`
|
|
31
|
+
- ๐งช Optional `dryRun` plans submissions without sending requests
|
|
32
|
+
- ๐ฃ Optional `logMode` controls verbosity with `quiet`, `normal`, and `verbose`
|
|
31
33
|
- ๐งช Fully **CI/CD and Docker safe**
|
|
32
34
|
- ๐ No secrets prompted, stored, or mutated
|
|
33
35
|
- ๐งฉ No client-side or runtime code added
|
|
@@ -221,6 +223,41 @@ indexnow({ enabled: false })
|
|
|
221
223
|
|
|
222
224
|
---
|
|
223
225
|
|
|
226
|
+
### `dryRun` (optional)
|
|
227
|
+
|
|
228
|
+
Type: `boolean`
|
|
229
|
+
Default: `false`
|
|
230
|
+
|
|
231
|
+
When `true`, the integration performs discovery, diffing, and batching, then logs the plan without sending any IndexNow requests.
|
|
232
|
+
Dry runs do not mutate the cache file.
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
indexnow({
|
|
236
|
+
dryRun: true,
|
|
237
|
+
})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
### `logMode` (optional)
|
|
243
|
+
|
|
244
|
+
Type: `"quiet" | "normal" | "verbose"`
|
|
245
|
+
Default: `"normal"`
|
|
246
|
+
|
|
247
|
+
Controls how much the integration logs:
|
|
248
|
+
|
|
249
|
+
- `quiet` suppresses info and warning logs
|
|
250
|
+
- `normal` keeps high-level info and warnings, but not URL lists
|
|
251
|
+
- `verbose` includes cache, diff, and the full planned URL list
|
|
252
|
+
|
|
253
|
+
```js
|
|
254
|
+
indexnow({
|
|
255
|
+
logMode: "verbose",
|
|
256
|
+
})
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
224
261
|
### `cacheDir` (optional)
|
|
225
262
|
|
|
226
263
|
Type: `string`
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export interface IndexNowOptions {
|
|
|
4
4
|
siteUrl?: string;
|
|
5
5
|
enabled?: boolean;
|
|
6
6
|
cacheDir?: string;
|
|
7
|
+
dryRun?: boolean;
|
|
8
|
+
logMode?: "quiet" | "normal" | "verbose";
|
|
7
9
|
submissionMode?: "changed" | "all";
|
|
8
10
|
}
|
|
9
11
|
export default function indexNow(options?: IndexNowOptions): AstroIntegration;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,cAAc,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;CACpC;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC9B,OAAO,GAAE,eAAoB,GAC5B,gBAAgB,
|
|
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;CACpC;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC9B,OAAO,GAAE,eAAoB,GAC5B,gBAAgB,CAsPlB"}
|
package/dist/index.js
CHANGED
|
@@ -17,13 +17,13 @@ export default function indexNow(options = {}) {
|
|
|
17
17
|
function ensureCacheFile(logger) {
|
|
18
18
|
const dir = path.dirname(cachePath);
|
|
19
19
|
if (!fs.existsSync(dir)) {
|
|
20
|
-
logger.debug(`
|
|
20
|
+
logger.debug(`creating cache directory: ${dir}`);
|
|
21
21
|
fs.mkdirSync(dir, { recursive: true });
|
|
22
22
|
}
|
|
23
23
|
const exists = fs.existsSync(cachePath);
|
|
24
|
-
logger.debug(`
|
|
24
|
+
logger.debug(`cache exists: ${exists} (${cachePath})`);
|
|
25
25
|
if (!exists) {
|
|
26
|
-
logger.debug("
|
|
26
|
+
logger.debug("creating cache file");
|
|
27
27
|
fs.writeFileSync(cachePath, "{}", "utf8");
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -34,17 +34,17 @@ export default function indexNow(options = {}) {
|
|
|
34
34
|
return `sha256:${hash.digest("hex")}`;
|
|
35
35
|
}
|
|
36
36
|
function loadCache(logger) {
|
|
37
|
-
logger.debug("
|
|
37
|
+
logger.debug("loading cache file");
|
|
38
38
|
try {
|
|
39
39
|
return JSON.parse(fs.readFileSync(cachePath, "utf8"));
|
|
40
40
|
}
|
|
41
41
|
catch {
|
|
42
|
-
logger.warn("
|
|
42
|
+
logger.warn("cache file unreadable, resetting");
|
|
43
43
|
return {};
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
function saveCache(logger, data) {
|
|
47
|
-
logger.debug("
|
|
47
|
+
logger.debug("writing cache file");
|
|
48
48
|
fs.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf8");
|
|
49
49
|
}
|
|
50
50
|
function chunk(array, size) {
|
|
@@ -54,6 +54,24 @@ export default function indexNow(options = {}) {
|
|
|
54
54
|
}
|
|
55
55
|
return chunks;
|
|
56
56
|
}
|
|
57
|
+
function isQuiet() {
|
|
58
|
+
return options.logMode === "quiet";
|
|
59
|
+
}
|
|
60
|
+
function isVerbose() {
|
|
61
|
+
return options.logMode === "verbose";
|
|
62
|
+
}
|
|
63
|
+
function logInfo(logger, message) {
|
|
64
|
+
if (!isQuiet())
|
|
65
|
+
logger.info(message);
|
|
66
|
+
}
|
|
67
|
+
function logWarn(logger, message) {
|
|
68
|
+
if (!isQuiet())
|
|
69
|
+
logger.warn(message);
|
|
70
|
+
}
|
|
71
|
+
function logVerbose(logger, message) {
|
|
72
|
+
if (isVerbose())
|
|
73
|
+
logger.info(message);
|
|
74
|
+
}
|
|
57
75
|
/* =========================================================
|
|
58
76
|
Integration
|
|
59
77
|
========================================================= */
|
|
@@ -67,7 +85,7 @@ export default function indexNow(options = {}) {
|
|
|
67
85
|
site =
|
|
68
86
|
options.siteUrl ??
|
|
69
87
|
(config.site ? config.site.replace(/\/$/, "") : null);
|
|
70
|
-
logger
|
|
88
|
+
logVerbose(logger, `project root: ${projectRoot}`);
|
|
71
89
|
ensureCacheFile(logger);
|
|
72
90
|
},
|
|
73
91
|
/* -----------------------------------------------
|
|
@@ -75,7 +93,7 @@ export default function indexNow(options = {}) {
|
|
|
75
93
|
----------------------------------------------- */
|
|
76
94
|
"astro:build:done": async ({ dir, logger }) => {
|
|
77
95
|
if (options.enabled === false) {
|
|
78
|
-
logger
|
|
96
|
+
logInfo(logger, "disabled");
|
|
79
97
|
return;
|
|
80
98
|
}
|
|
81
99
|
if (!options.key) {
|
|
@@ -109,26 +127,38 @@ export default function indexNow(options = {}) {
|
|
|
109
127
|
}
|
|
110
128
|
}
|
|
111
129
|
walk(outDir);
|
|
112
|
-
logger
|
|
130
|
+
logVerbose(logger, "page diff:");
|
|
113
131
|
for (const url of Object.keys(nextCache)) {
|
|
114
132
|
const state = previousCache[url] === nextCache[url]
|
|
115
133
|
? "unchanged"
|
|
116
134
|
: "new/changed";
|
|
117
|
-
|
|
135
|
+
if (isVerbose()) {
|
|
136
|
+
logVerbose(logger, ` - ${url} (${state})`);
|
|
137
|
+
}
|
|
118
138
|
}
|
|
119
139
|
const urlsToSubmit = options.submissionMode === "all"
|
|
120
140
|
? Object.keys(nextCache)
|
|
121
141
|
: changedUrls;
|
|
122
142
|
if (urlsToSubmit.length === 0) {
|
|
123
|
-
logger
|
|
143
|
+
logInfo(logger, "no changed URLs detected, skipping submission");
|
|
124
144
|
saveCache(logger, nextCache);
|
|
125
145
|
return;
|
|
126
146
|
}
|
|
127
147
|
const batches = chunk(urlsToSubmit, INDEXNOW_BATCH_SIZE);
|
|
128
|
-
logger
|
|
148
|
+
logInfo(logger, `submitting ${urlsToSubmit.length} URL(s) in ${batches.length} batch(es) [mode=${options.submissionMode ?? "changed"}]`);
|
|
149
|
+
if (isVerbose()) {
|
|
150
|
+
logVerbose(logger, "planned URL list:");
|
|
151
|
+
for (const url of urlsToSubmit) {
|
|
152
|
+
logVerbose(logger, ` - ${url}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (options.dryRun) {
|
|
156
|
+
logInfo(logger, "dry run enabled, skipping submission");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
129
159
|
for (let i = 0; i < batches.length; i++) {
|
|
130
160
|
const batch = batches[i];
|
|
131
|
-
logger
|
|
161
|
+
logVerbose(logger, `submitting batch ${i + 1}/${batches.length} (${batch.length} URLs)`);
|
|
132
162
|
try {
|
|
133
163
|
const response = await fetch(INDEXNOW_ENDPOINT, {
|
|
134
164
|
method: "POST",
|
|
@@ -141,15 +171,15 @@ export default function indexNow(options = {}) {
|
|
|
141
171
|
}),
|
|
142
172
|
});
|
|
143
173
|
if (!response.ok) {
|
|
144
|
-
logger
|
|
174
|
+
logWarn(logger, `batch ${i + 1} failed (${response.status})`);
|
|
145
175
|
}
|
|
146
176
|
}
|
|
147
177
|
catch {
|
|
148
|
-
logger
|
|
178
|
+
logWarn(logger, `batch ${i + 1} submission failed (network error)`);
|
|
149
179
|
}
|
|
150
180
|
}
|
|
151
181
|
saveCache(logger, nextCache);
|
|
152
|
-
logger
|
|
182
|
+
logInfo(logger, `IndexNow submission complete`);
|
|
153
183
|
},
|
|
154
184
|
},
|
|
155
185
|
};
|