@nuxtseo/protocol 0.1.3 → 0.1.4

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,517 @@
1
+ import type { z } from 'zod';
2
+ export declare const timelineSiteParamsSchema: z.ZodObject<{
3
+ siteId: z.ZodString;
4
+ }, z.core.$strict>;
5
+ export declare const timelineEntrySeveritySchema: z.ZodEnum<{
6
+ high: "high";
7
+ info: "info";
8
+ notable: "notable";
9
+ }>;
10
+ export declare const timelineEntriesQuerySchema: z.ZodObject<{
11
+ kinds: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string[] | undefined, string | undefined>>;
12
+ feature: z.ZodOptional<z.ZodString>;
13
+ severity: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<("high" | "info" | "notable")[] | undefined, string | undefined>>;
14
+ since: z.ZodOptional<z.ZodString>;
15
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
16
+ cursor: z.ZodOptional<z.ZodString>;
17
+ includeClosed: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
18
+ false: "false";
19
+ true: "true";
20
+ }>]>>, z.ZodTransform<boolean, "false" | "true" | boolean>>;
21
+ }, z.core.$strict>;
22
+ export declare const timelineEntrySchema: import("./core.js").CompatibleResponseSchema<z.ZodObject<{
23
+ readonly id: z.ZodString;
24
+ readonly kind: z.ZodString;
25
+ readonly severity: z.ZodNullable<z.ZodEnum<{
26
+ high: "high";
27
+ info: "info";
28
+ notable: "notable";
29
+ }>>;
30
+ readonly occurredAt: z.ZodString;
31
+ readonly rendered: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
32
+ readonly payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
33
+ }, z.core.$strip>, z.ZodObject<{
34
+ readonly id: z.ZodString;
35
+ readonly kind: z.ZodString;
36
+ readonly severity: z.ZodNullable<z.ZodEnum<{
37
+ high: "high";
38
+ info: "info";
39
+ notable: "notable";
40
+ }>>;
41
+ readonly occurredAt: z.ZodString;
42
+ readonly rendered: z.ZodNullable<z.ZodObject<{}, z.core.$loose>>;
43
+ readonly payload: z.ZodObject<{}, z.core.$loose>;
44
+ }, z.core.$strip>>;
45
+ export declare const timelineEntriesDataSchema: import("./core.js").CompatibleResponseSchema<z.ZodObject<{
46
+ readonly entries: z.ZodArray<z.ZodObject<{
47
+ readonly id: z.ZodString;
48
+ readonly kind: z.ZodString;
49
+ readonly severity: z.ZodNullable<z.ZodEnum<{
50
+ high: "high";
51
+ info: "info";
52
+ notable: "notable";
53
+ }>>;
54
+ readonly occurredAt: z.ZodString;
55
+ readonly rendered: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
56
+ readonly payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
57
+ }, z.core.$strip>>;
58
+ readonly nextCursor: z.ZodNullable<z.ZodString>;
59
+ readonly counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
60
+ }, z.core.$strip>, z.ZodObject<{
61
+ readonly entries: z.ZodArray<z.ZodObject<{
62
+ readonly id: z.ZodString;
63
+ readonly kind: z.ZodString;
64
+ readonly severity: z.ZodNullable<z.ZodEnum<{
65
+ high: "high";
66
+ info: "info";
67
+ notable: "notable";
68
+ }>>;
69
+ readonly occurredAt: z.ZodString;
70
+ readonly rendered: z.ZodNullable<z.ZodObject<{}, z.core.$loose>>;
71
+ readonly payload: z.ZodObject<{}, z.core.$loose>;
72
+ }, z.core.$strip>>;
73
+ readonly nextCursor: z.ZodNullable<z.ZodString>;
74
+ readonly counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
75
+ }, z.core.$strip>>;
76
+ export declare const timelineEntriesResponseSchema: import("./core.js").CompatibleResponseSchema<z.ZodObject<{
77
+ data: z.ZodObject<{
78
+ readonly entries: z.ZodArray<z.ZodObject<{
79
+ readonly id: z.ZodString;
80
+ readonly kind: z.ZodString;
81
+ readonly severity: z.ZodNullable<z.ZodEnum<{
82
+ high: "high";
83
+ info: "info";
84
+ notable: "notable";
85
+ }>>;
86
+ readonly occurredAt: z.ZodString;
87
+ readonly rendered: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
88
+ readonly payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
89
+ }, z.core.$strip>>;
90
+ readonly nextCursor: z.ZodNullable<z.ZodString>;
91
+ readonly counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
92
+ }, z.core.$strip>;
93
+ meta: z.ZodObject<{
94
+ requestId: z.ZodString;
95
+ version: z.ZodLiteral<"1.0">;
96
+ }, z.core.$strict>;
97
+ }, z.core.$strip>, z.ZodObject<{
98
+ data: z.ZodObject<{
99
+ readonly entries: z.ZodArray<z.ZodObject<{
100
+ readonly id: z.ZodString;
101
+ readonly kind: z.ZodString;
102
+ readonly severity: z.ZodNullable<z.ZodEnum<{
103
+ high: "high";
104
+ info: "info";
105
+ notable: "notable";
106
+ }>>;
107
+ readonly occurredAt: z.ZodString;
108
+ readonly rendered: z.ZodNullable<z.ZodObject<{}, z.core.$loose>>;
109
+ readonly payload: z.ZodObject<{}, z.core.$loose>;
110
+ }, z.core.$strip>>;
111
+ readonly nextCursor: z.ZodNullable<z.ZodString>;
112
+ readonly counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
113
+ }, z.core.$strip>;
114
+ meta: z.ZodObject<{
115
+ requestId: z.ZodString;
116
+ version: z.ZodLiteral<"1.0">;
117
+ }, z.core.$loose>;
118
+ }, z.core.$strip>>;
119
+ export type TimelineSiteParams = z.input<typeof timelineSiteParamsSchema>;
120
+ export type TimelineEntriesQuery = z.input<typeof timelineEntriesQuerySchema>;
121
+ export type TimelineEntry = z.output<typeof timelineEntrySchema.client>;
122
+ export type TimelineEntries = z.output<typeof timelineEntriesDataSchema.client>;
123
+ export type TimelineEntriesResponse = z.output<typeof timelineEntriesResponseSchema.client>;
124
+ export declare const timelineEntriesOperation: {
125
+ readonly id: 'timeline.entries';
126
+ readonly method: 'GET';
127
+ readonly path: '/api/v1/sites/{siteId}/timeline';
128
+ readonly visibility: 'public';
129
+ readonly semantics: {
130
+ readonly kind: 'query';
131
+ readonly sideEffects: 'none';
132
+ readonly retry: 'idempotent';
133
+ readonly readConsistency: 'primary';
134
+ };
135
+ readonly auth: {
136
+ readonly credentials: readonly ['session', 'api_token'];
137
+ readonly scopes: readonly ['timeline:read'];
138
+ readonly minimumRole: 'viewer';
139
+ readonly ownership: 'site';
140
+ };
141
+ readonly request: {
142
+ readonly params: z.ZodObject<{
143
+ siteId: z.ZodString;
144
+ }, z.core.$strict>;
145
+ readonly query: z.ZodObject<{
146
+ kinds: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string[] | undefined, string | undefined>>;
147
+ feature: z.ZodOptional<z.ZodString>;
148
+ severity: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<("high" | "info" | "notable")[] | undefined, string | undefined>>;
149
+ since: z.ZodOptional<z.ZodString>;
150
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
151
+ cursor: z.ZodOptional<z.ZodString>;
152
+ includeClosed: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
153
+ false: "false";
154
+ true: "true";
155
+ }>]>>, z.ZodTransform<boolean, "false" | "true" | boolean>>;
156
+ }, z.core.$strict>;
157
+ readonly headers: null;
158
+ readonly body: null;
159
+ };
160
+ readonly responses: {
161
+ readonly 200: import("./core.js").CompatibleResponseSchema<z.ZodObject<{
162
+ data: z.ZodObject<{
163
+ readonly entries: z.ZodArray<z.ZodObject<{
164
+ readonly id: z.ZodString;
165
+ readonly kind: z.ZodString;
166
+ readonly severity: z.ZodNullable<z.ZodEnum<{
167
+ high: "high";
168
+ info: "info";
169
+ notable: "notable";
170
+ }>>;
171
+ readonly occurredAt: z.ZodString;
172
+ readonly rendered: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
173
+ readonly payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
174
+ }, z.core.$strip>>;
175
+ readonly nextCursor: z.ZodNullable<z.ZodString>;
176
+ readonly counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
177
+ }, z.core.$strip>;
178
+ meta: z.ZodObject<{
179
+ requestId: z.ZodString;
180
+ version: z.ZodLiteral<"1.0">;
181
+ }, z.core.$strict>;
182
+ }, z.core.$strip>, z.ZodObject<{
183
+ data: z.ZodObject<{
184
+ readonly entries: z.ZodArray<z.ZodObject<{
185
+ readonly id: z.ZodString;
186
+ readonly kind: z.ZodString;
187
+ readonly severity: z.ZodNullable<z.ZodEnum<{
188
+ high: "high";
189
+ info: "info";
190
+ notable: "notable";
191
+ }>>;
192
+ readonly occurredAt: z.ZodString;
193
+ readonly rendered: z.ZodNullable<z.ZodObject<{}, z.core.$loose>>;
194
+ readonly payload: z.ZodObject<{}, z.core.$loose>;
195
+ }, z.core.$strip>>;
196
+ readonly nextCursor: z.ZodNullable<z.ZodString>;
197
+ readonly counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
198
+ }, z.core.$strip>;
199
+ meta: z.ZodObject<{
200
+ requestId: z.ZodString;
201
+ version: z.ZodLiteral<"1.0">;
202
+ }, z.core.$loose>;
203
+ }, z.core.$strip>>;
204
+ };
205
+ readonly errors: readonly ["invalid_request", "unauthorized", "auth_expired", "forbidden", "not_found", "rate_limited", "provider_unavailable", "contract_violation", "internal_error"];
206
+ readonly errorResponse: import("./core.js").CompatibleResponseSchema<z.ZodObject<{
207
+ readonly error: z.ZodObject<{
208
+ code: z.ZodEnum<{
209
+ auth_expired: "auth_expired";
210
+ conflict: "conflict";
211
+ contract_violation: "contract_violation";
212
+ entitlement_required: "entitlement_required";
213
+ forbidden: "forbidden";
214
+ internal_error: "internal_error";
215
+ invalid_request: "invalid_request";
216
+ not_found: "not_found";
217
+ provider_unavailable: "provider_unavailable";
218
+ quota_exhausted: "quota_exhausted";
219
+ rate_limited: "rate_limited";
220
+ site_ambiguous: "site_ambiguous";
221
+ stale_evidence: "stale_evidence";
222
+ unauthorized: "unauthorized";
223
+ }>;
224
+ message: z.ZodString;
225
+ requestId: z.ZodString;
226
+ retryable: z.ZodBoolean;
227
+ details: z.ZodRecord<z.ZodString, z.ZodUnknown>;
228
+ }, z.core.$strict>;
229
+ }, z.core.$strip>, z.ZodObject<{
230
+ readonly error: z.ZodObject<{
231
+ code: z.ZodEnum<{
232
+ auth_expired: "auth_expired";
233
+ conflict: "conflict";
234
+ contract_violation: "contract_violation";
235
+ entitlement_required: "entitlement_required";
236
+ forbidden: "forbidden";
237
+ internal_error: "internal_error";
238
+ invalid_request: "invalid_request";
239
+ not_found: "not_found";
240
+ provider_unavailable: "provider_unavailable";
241
+ quota_exhausted: "quota_exhausted";
242
+ rate_limited: "rate_limited";
243
+ site_ambiguous: "site_ambiguous";
244
+ stale_evidence: "stale_evidence";
245
+ unauthorized: "unauthorized";
246
+ }>;
247
+ message: z.ZodString;
248
+ requestId: z.ZodString;
249
+ retryable: z.ZodBoolean;
250
+ details: z.ZodRecord<z.ZodString, z.ZodUnknown>;
251
+ }, z.core.$loose>;
252
+ }, z.core.$strip>>;
253
+ readonly resources: {
254
+ readonly reads: readonly [{
255
+ readonly type: 'site.timeline';
256
+ readonly idFrom: 'params.siteId';
257
+ }];
258
+ readonly changes: readonly [];
259
+ };
260
+ readonly policy: {
261
+ readonly rate: {
262
+ readonly name: 'public-v1-fixed-window';
263
+ readonly limit: 50;
264
+ readonly windowSeconds: 60;
265
+ };
266
+ readonly idempotency: {
267
+ readonly _tag: 'none';
268
+ };
269
+ readonly entitlement: null;
270
+ readonly meter: null;
271
+ };
272
+ readonly lifecycle: {
273
+ readonly introduced: '1.0.0';
274
+ };
275
+ readonly docs: {
276
+ readonly summary: 'Read the Timeline';
277
+ readonly description: 'What changed on this Site — Timeline Entries such as traffic drops, indexing changes, sitemap changes, rank shifts and deploys. Filter by kind, feature, severity and since; paginated with an opaque cursor.';
278
+ readonly tags: readonly ["Timeline"];
279
+ readonly examples: readonly [{
280
+ readonly request: {
281
+ readonly params: {
282
+ readonly siteId: 'site_01JXYZ';
283
+ };
284
+ readonly query: {
285
+ readonly severity: 'high';
286
+ };
287
+ };
288
+ readonly response: {
289
+ readonly status: 200;
290
+ readonly body: {
291
+ readonly data: {
292
+ readonly entries: readonly [{
293
+ readonly id: 'timeline_01JXYZ';
294
+ readonly kind: 'traffic.dropped';
295
+ readonly severity: 'high';
296
+ readonly occurredAt: '2026-08-10T01:30:00.000Z';
297
+ readonly rendered: {
298
+ readonly label: 'Clicks dropped 42%';
299
+ readonly value: -0.42;
300
+ readonly direction: 'down';
301
+ };
302
+ readonly payload: {
303
+ readonly clicksDelta: -180;
304
+ };
305
+ }];
306
+ readonly nextCursor: null;
307
+ readonly counts: {
308
+ readonly 'traffic.dropped': 1;
309
+ };
310
+ };
311
+ readonly meta: {
312
+ readonly requestId: 'req_01JXYZ';
313
+ readonly version: '1.0';
314
+ };
315
+ };
316
+ };
317
+ }];
318
+ };
319
+ };
320
+ export declare const timelineV1Registry: import("./core.js").PublicV1Registry<{
321
+ readonly entries: {
322
+ readonly id: 'timeline.entries';
323
+ readonly method: 'GET';
324
+ readonly path: '/api/v1/sites/{siteId}/timeline';
325
+ readonly visibility: 'public';
326
+ readonly semantics: {
327
+ readonly kind: 'query';
328
+ readonly sideEffects: 'none';
329
+ readonly retry: 'idempotent';
330
+ readonly readConsistency: 'primary';
331
+ };
332
+ readonly auth: {
333
+ readonly credentials: readonly ['session', 'api_token'];
334
+ readonly scopes: readonly ['timeline:read'];
335
+ readonly minimumRole: 'viewer';
336
+ readonly ownership: 'site';
337
+ };
338
+ readonly request: {
339
+ readonly params: z.ZodObject<{
340
+ siteId: z.ZodString;
341
+ }, z.core.$strict>;
342
+ readonly query: z.ZodObject<{
343
+ kinds: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string[] | undefined, string | undefined>>;
344
+ feature: z.ZodOptional<z.ZodString>;
345
+ severity: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<("high" | "info" | "notable")[] | undefined, string | undefined>>;
346
+ since: z.ZodOptional<z.ZodString>;
347
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
348
+ cursor: z.ZodOptional<z.ZodString>;
349
+ includeClosed: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
350
+ false: "false";
351
+ true: "true";
352
+ }>]>>, z.ZodTransform<boolean, "false" | "true" | boolean>>;
353
+ }, z.core.$strict>;
354
+ readonly headers: null;
355
+ readonly body: null;
356
+ };
357
+ readonly responses: {
358
+ readonly 200: import("./core.js").CompatibleResponseSchema<z.ZodObject<{
359
+ data: z.ZodObject<{
360
+ readonly entries: z.ZodArray<z.ZodObject<{
361
+ readonly id: z.ZodString;
362
+ readonly kind: z.ZodString;
363
+ readonly severity: z.ZodNullable<z.ZodEnum<{
364
+ high: "high";
365
+ info: "info";
366
+ notable: "notable";
367
+ }>>;
368
+ readonly occurredAt: z.ZodString;
369
+ readonly rendered: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
370
+ readonly payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
371
+ }, z.core.$strip>>;
372
+ readonly nextCursor: z.ZodNullable<z.ZodString>;
373
+ readonly counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
374
+ }, z.core.$strip>;
375
+ meta: z.ZodObject<{
376
+ requestId: z.ZodString;
377
+ version: z.ZodLiteral<"1.0">;
378
+ }, z.core.$strict>;
379
+ }, z.core.$strip>, z.ZodObject<{
380
+ data: z.ZodObject<{
381
+ readonly entries: z.ZodArray<z.ZodObject<{
382
+ readonly id: z.ZodString;
383
+ readonly kind: z.ZodString;
384
+ readonly severity: z.ZodNullable<z.ZodEnum<{
385
+ high: "high";
386
+ info: "info";
387
+ notable: "notable";
388
+ }>>;
389
+ readonly occurredAt: z.ZodString;
390
+ readonly rendered: z.ZodNullable<z.ZodObject<{}, z.core.$loose>>;
391
+ readonly payload: z.ZodObject<{}, z.core.$loose>;
392
+ }, z.core.$strip>>;
393
+ readonly nextCursor: z.ZodNullable<z.ZodString>;
394
+ readonly counts: z.ZodRecord<z.ZodString, z.ZodNumber>;
395
+ }, z.core.$strip>;
396
+ meta: z.ZodObject<{
397
+ requestId: z.ZodString;
398
+ version: z.ZodLiteral<"1.0">;
399
+ }, z.core.$loose>;
400
+ }, z.core.$strip>>;
401
+ };
402
+ readonly errors: readonly ["invalid_request", "unauthorized", "auth_expired", "forbidden", "not_found", "rate_limited", "provider_unavailable", "contract_violation", "internal_error"];
403
+ readonly errorResponse: import("./core.js").CompatibleResponseSchema<z.ZodObject<{
404
+ readonly error: z.ZodObject<{
405
+ code: z.ZodEnum<{
406
+ auth_expired: "auth_expired";
407
+ conflict: "conflict";
408
+ contract_violation: "contract_violation";
409
+ entitlement_required: "entitlement_required";
410
+ forbidden: "forbidden";
411
+ internal_error: "internal_error";
412
+ invalid_request: "invalid_request";
413
+ not_found: "not_found";
414
+ provider_unavailable: "provider_unavailable";
415
+ quota_exhausted: "quota_exhausted";
416
+ rate_limited: "rate_limited";
417
+ site_ambiguous: "site_ambiguous";
418
+ stale_evidence: "stale_evidence";
419
+ unauthorized: "unauthorized";
420
+ }>;
421
+ message: z.ZodString;
422
+ requestId: z.ZodString;
423
+ retryable: z.ZodBoolean;
424
+ details: z.ZodRecord<z.ZodString, z.ZodUnknown>;
425
+ }, z.core.$strict>;
426
+ }, z.core.$strip>, z.ZodObject<{
427
+ readonly error: z.ZodObject<{
428
+ code: z.ZodEnum<{
429
+ auth_expired: "auth_expired";
430
+ conflict: "conflict";
431
+ contract_violation: "contract_violation";
432
+ entitlement_required: "entitlement_required";
433
+ forbidden: "forbidden";
434
+ internal_error: "internal_error";
435
+ invalid_request: "invalid_request";
436
+ not_found: "not_found";
437
+ provider_unavailable: "provider_unavailable";
438
+ quota_exhausted: "quota_exhausted";
439
+ rate_limited: "rate_limited";
440
+ site_ambiguous: "site_ambiguous";
441
+ stale_evidence: "stale_evidence";
442
+ unauthorized: "unauthorized";
443
+ }>;
444
+ message: z.ZodString;
445
+ requestId: z.ZodString;
446
+ retryable: z.ZodBoolean;
447
+ details: z.ZodRecord<z.ZodString, z.ZodUnknown>;
448
+ }, z.core.$loose>;
449
+ }, z.core.$strip>>;
450
+ readonly resources: {
451
+ readonly reads: readonly [{
452
+ readonly type: 'site.timeline';
453
+ readonly idFrom: 'params.siteId';
454
+ }];
455
+ readonly changes: readonly [];
456
+ };
457
+ readonly policy: {
458
+ readonly rate: {
459
+ readonly name: 'public-v1-fixed-window';
460
+ readonly limit: 50;
461
+ readonly windowSeconds: 60;
462
+ };
463
+ readonly idempotency: {
464
+ readonly _tag: 'none';
465
+ };
466
+ readonly entitlement: null;
467
+ readonly meter: null;
468
+ };
469
+ readonly lifecycle: {
470
+ readonly introduced: '1.0.0';
471
+ };
472
+ readonly docs: {
473
+ readonly summary: 'Read the Timeline';
474
+ readonly description: 'What changed on this Site — Timeline Entries such as traffic drops, indexing changes, sitemap changes, rank shifts and deploys. Filter by kind, feature, severity and since; paginated with an opaque cursor.';
475
+ readonly tags: readonly ["Timeline"];
476
+ readonly examples: readonly [{
477
+ readonly request: {
478
+ readonly params: {
479
+ readonly siteId: 'site_01JXYZ';
480
+ };
481
+ readonly query: {
482
+ readonly severity: 'high';
483
+ };
484
+ };
485
+ readonly response: {
486
+ readonly status: 200;
487
+ readonly body: {
488
+ readonly data: {
489
+ readonly entries: readonly [{
490
+ readonly id: 'timeline_01JXYZ';
491
+ readonly kind: 'traffic.dropped';
492
+ readonly severity: 'high';
493
+ readonly occurredAt: '2026-08-10T01:30:00.000Z';
494
+ readonly rendered: {
495
+ readonly label: 'Clicks dropped 42%';
496
+ readonly value: -0.42;
497
+ readonly direction: 'down';
498
+ };
499
+ readonly payload: {
500
+ readonly clicksDelta: -180;
501
+ };
502
+ }];
503
+ readonly nextCursor: null;
504
+ readonly counts: {
505
+ readonly 'traffic.dropped': 1;
506
+ };
507
+ };
508
+ readonly meta: {
509
+ readonly requestId: 'req_01JXYZ';
510
+ readonly version: '1.0';
511
+ };
512
+ };
513
+ };
514
+ }];
515
+ };
516
+ };
517
+ }>;
@@ -0,0 +1,150 @@
1
+ import { z as schema } from 'zod';
2
+ import { defineOperation, defineRegistry, defineResponseObject, defineSuccessEnvelope, publicV1ErrorEnvelope, publicV1StandardRatePolicy, } from './core.js';
3
+ export const timelineSiteParamsSchema = schema.strictObject({
4
+ siteId: schema.string().min(1),
5
+ });
6
+ // Mirrors `timelineSeverityEnum` owned by `layers/pro/timeline` (GLOSSARY:
7
+ // Timeline Entry). Duplicated by value, not imported — the protocol package
8
+ // never depends on a Nuxt layer.
9
+ export const timelineEntrySeveritySchema = schema.enum(['info', 'notable', 'high']);
10
+ /** A GET query value repeated as a comma-separated list, e.g. `?kinds=a,b`. */
11
+ function commaListQuerySchema(item) {
12
+ return schema.string().optional().transform((raw, context) => {
13
+ if (!raw)
14
+ return undefined;
15
+ const parsed = schema.array(item).safeParse(raw.split(',').map(part => part.trim()).filter(Boolean));
16
+ if (!parsed.success) {
17
+ context.addIssue({ code: 'custom', message: parsed.error.issues.map(issue => issue.message).join(', ') });
18
+ return schema.NEVER;
19
+ }
20
+ return parsed.data;
21
+ });
22
+ }
23
+ // Query strings are never real booleans, and coerce.boolean() turns `'false'`
24
+ // into `true`. Parse the two spellings explicitly instead (same pattern as the
25
+ // analytics queries).
26
+ function booleanQuerySchema(fallback) {
27
+ return schema
28
+ .union([schema.boolean(), schema.enum(['true', 'false'])])
29
+ .default(fallback)
30
+ .transform(value => value === true || value === 'true');
31
+ }
32
+ export const timelineEntriesQuerySchema = schema.strictObject({
33
+ kinds: commaListQuerySchema(schema.string().min(1)),
34
+ feature: schema.string().min(1).optional(),
35
+ severity: commaListQuerySchema(timelineEntrySeveritySchema),
36
+ since: schema.string().datetime({ offset: true }).optional(),
37
+ limit: schema.coerce.number().int().min(1).max(100).default(25),
38
+ cursor: schema.string().min(1).optional(),
39
+ includeClosed: booleanQuerySchema(false),
40
+ });
41
+ export const timelineEntrySchema = defineResponseObject({
42
+ id: schema.string(),
43
+ kind: schema.string(),
44
+ severity: timelineEntrySeveritySchema.nullable(),
45
+ occurredAt: schema.string(),
46
+ rendered: schema.record(schema.string(), schema.unknown()).nullable(),
47
+ payload: schema.record(schema.string(), schema.unknown()),
48
+ }, {
49
+ id: schema.string(),
50
+ kind: schema.string(),
51
+ severity: timelineEntrySeveritySchema.nullable(),
52
+ occurredAt: schema.string(),
53
+ rendered: schema.looseObject({}).nullable(),
54
+ payload: schema.looseObject({}),
55
+ });
56
+ export const timelineEntriesDataSchema = defineResponseObject({
57
+ entries: schema.array(timelineEntrySchema.producer),
58
+ nextCursor: schema.string().nullable(),
59
+ counts: schema.record(schema.string(), schema.number()),
60
+ }, {
61
+ entries: schema.array(timelineEntrySchema.client),
62
+ nextCursor: schema.string().nullable(),
63
+ counts: schema.record(schema.string(), schema.number()),
64
+ });
65
+ export const timelineEntriesResponseSchema = defineSuccessEnvelope(timelineEntriesDataSchema);
66
+ const timelineReadSemantics = {
67
+ kind: 'query',
68
+ sideEffects: 'none',
69
+ retry: 'idempotent',
70
+ readConsistency: 'primary',
71
+ };
72
+ const timelineReadAuth = {
73
+ credentials: ['session', 'api_token'],
74
+ scopes: ['timeline:read'],
75
+ minimumRole: 'viewer',
76
+ ownership: 'site',
77
+ };
78
+ const timelineReadErrors = [
79
+ 'invalid_request',
80
+ 'unauthorized',
81
+ 'auth_expired',
82
+ 'forbidden',
83
+ 'not_found',
84
+ 'rate_limited',
85
+ 'provider_unavailable',
86
+ 'contract_violation',
87
+ 'internal_error',
88
+ ];
89
+ const timelineReadResources = {
90
+ reads: [{ type: 'site.timeline', idFrom: 'params.siteId' }],
91
+ changes: [],
92
+ };
93
+ const timelineReadPolicy = {
94
+ rate: publicV1StandardRatePolicy,
95
+ idempotency: { _tag: 'none' },
96
+ entitlement: null,
97
+ meter: null,
98
+ };
99
+ export const timelineEntriesOperation = defineOperation({
100
+ id: 'timeline.entries',
101
+ method: 'GET',
102
+ path: '/api/v1/sites/{siteId}/timeline',
103
+ visibility: 'public',
104
+ semantics: timelineReadSemantics,
105
+ auth: timelineReadAuth,
106
+ request: {
107
+ params: timelineSiteParamsSchema,
108
+ query: timelineEntriesQuerySchema,
109
+ headers: null,
110
+ body: null,
111
+ },
112
+ responses: { 200: timelineEntriesResponseSchema },
113
+ errors: timelineReadErrors,
114
+ errorResponse: publicV1ErrorEnvelope,
115
+ resources: timelineReadResources,
116
+ policy: timelineReadPolicy,
117
+ lifecycle: { introduced: '1.0.0' },
118
+ docs: {
119
+ summary: 'Read the Timeline',
120
+ description: 'What changed on this Site — Timeline Entries such as traffic drops, indexing changes, sitemap changes, rank shifts and deploys. Filter by kind, feature, severity and since; paginated with an opaque cursor.',
121
+ tags: ['Timeline'],
122
+ examples: [{
123
+ request: { params: { siteId: 'site_01JXYZ' }, query: { severity: 'high' } },
124
+ response: {
125
+ status: 200,
126
+ body: {
127
+ data: {
128
+ entries: [{
129
+ id: 'timeline_01JXYZ',
130
+ kind: 'traffic.dropped',
131
+ severity: 'high',
132
+ occurredAt: '2026-08-10T01:30:00.000Z',
133
+ rendered: { label: 'Clicks dropped 42%', value: -0.42, direction: 'down' },
134
+ payload: { clicksDelta: -180 },
135
+ }],
136
+ nextCursor: null,
137
+ counts: { 'traffic.dropped': 1 },
138
+ },
139
+ meta: { requestId: 'req_01JXYZ', version: '1.0' },
140
+ },
141
+ },
142
+ }],
143
+ },
144
+ });
145
+ export const timelineV1Registry = defineRegistry({
146
+ feature: 'timeline',
147
+ operations: {
148
+ entries: timelineEntriesOperation,
149
+ },
150
+ });