@cogenta/schema 0.2.0 → 0.4.1
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/define-collection.d.ts.map +1 -1
- package/dist/define-collection.js +53 -3
- package/dist/define-collection.js.map +1 -1
- package/dist/generate-types.d.ts.map +1 -1
- package/dist/generate-types.js +6 -1
- package/dist/generate-types.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/media-usage.d.ts +56 -0
- package/dist/media-usage.d.ts.map +1 -0
- package/dist/media-usage.js +89 -0
- package/dist/media-usage.js.map +1 -0
- package/dist/rich-text.d.ts +28 -2
- package/dist/rich-text.d.ts.map +1 -1
- package/dist/rich-text.js +26 -3
- package/dist/rich-text.js.map +1 -1
- package/dist/routing/index.d.ts +5 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +2 -0
- package/dist/routing/index.js.map +1 -1
- package/dist/routing/not-found-log.d.ts +78 -0
- package/dist/routing/not-found-log.d.ts.map +1 -0
- package/dist/routing/not-found-log.js +153 -0
- package/dist/routing/not-found-log.js.map +1 -0
- package/dist/routing/redirect-patterns.d.ts +61 -0
- package/dist/routing/redirect-patterns.d.ts.map +1 -0
- package/dist/routing/redirect-patterns.js +173 -0
- package/dist/routing/redirect-patterns.js.map +1 -0
- package/dist/routing/redirects.d.ts +27 -4
- package/dist/routing/redirects.d.ts.map +1 -1
- package/dist/routing/redirects.js +160 -48
- package/dist/routing/redirects.js.map +1 -1
- package/dist/scheduling/index.d.ts +2 -0
- package/dist/scheduling/index.d.ts.map +1 -1
- package/dist/scheduling/index.js +1 -0
- package/dist/scheduling/index.js.map +1 -1
- package/dist/scheduling/registry.d.ts +147 -0
- package/dist/scheduling/registry.d.ts.map +1 -0
- package/dist/scheduling/registry.js +318 -0
- package/dist/scheduling/registry.js.map +1 -0
- package/dist/search/extract.d.ts +24 -0
- package/dist/search/extract.d.ts.map +1 -1
- package/dist/search/extract.js +63 -8
- package/dist/search/extract.js.map +1 -1
- package/dist/search/index.d.ts +2 -1
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -9
- package/dist/search/index.js.map +1 -1
- package/dist/store/admin-theme-store.d.ts +26 -0
- package/dist/store/admin-theme-store.d.ts.map +1 -0
- package/dist/store/admin-theme-store.js +81 -0
- package/dist/store/admin-theme-store.js.map +1 -0
- package/dist/store/admin-theme-tables.d.ts +24 -0
- package/dist/store/admin-theme-tables.d.ts.map +1 -0
- package/dist/store/admin-theme-tables.js +41 -0
- package/dist/store/admin-theme-tables.js.map +1 -0
- package/dist/store/admin-theme-templates.d.ts +135 -0
- package/dist/store/admin-theme-templates.d.ts.map +1 -0
- package/dist/store/admin-theme-templates.js +217 -0
- package/dist/store/admin-theme-templates.js.map +1 -0
- package/dist/store/columns.d.ts.map +1 -1
- package/dist/store/columns.js +8 -2
- package/dist/store/columns.js.map +1 -1
- package/dist/store/diff.d.ts +40 -0
- package/dist/store/diff.d.ts.map +1 -1
- package/dist/store/diff.js +148 -0
- package/dist/store/diff.js.map +1 -1
- package/dist/store/index.d.ts +47 -4
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +26 -2
- package/dist/store/index.js.map +1 -1
- package/dist/store/maintenance-store.d.ts +34 -0
- package/dist/store/maintenance-store.d.ts.map +1 -0
- package/dist/store/maintenance-store.js +92 -0
- package/dist/store/maintenance-store.js.map +1 -0
- package/dist/store/menu-store.d.ts +146 -0
- package/dist/store/menu-store.d.ts.map +1 -0
- package/dist/store/menu-store.js +565 -0
- package/dist/store/menu-store.js.map +1 -0
- package/dist/store/menu-tables.d.ts +38 -0
- package/dist/store/menu-tables.d.ts.map +1 -0
- package/dist/store/menu-tables.js +117 -0
- package/dist/store/menu-tables.js.map +1 -0
- package/dist/store/naming.d.ts +1 -1
- package/dist/store/naming.d.ts.map +1 -1
- package/dist/store/naming.js +2 -0
- package/dist/store/naming.js.map +1 -1
- package/dist/store/pattern-store.d.ts +75 -0
- package/dist/store/pattern-store.d.ts.map +1 -0
- package/dist/store/pattern-store.js +118 -0
- package/dist/store/pattern-store.js.map +1 -0
- package/dist/store/pattern-tables.d.ts +29 -0
- package/dist/store/pattern-tables.d.ts.map +1 -0
- package/dist/store/pattern-tables.js +53 -0
- package/dist/store/pattern-tables.js.map +1 -0
- package/dist/store/read-only.d.ts +3 -3
- package/dist/store/read-only.d.ts.map +1 -1
- package/dist/store/read-only.js +4 -3
- package/dist/store/read-only.js.map +1 -1
- package/dist/store/redirect-tracking.d.ts +50 -0
- package/dist/store/redirect-tracking.d.ts.map +1 -0
- package/dist/store/redirect-tracking.js +91 -0
- package/dist/store/redirect-tracking.js.map +1 -0
- package/dist/store/review-transitions.d.ts +34 -0
- package/dist/store/review-transitions.d.ts.map +1 -0
- package/dist/store/review-transitions.js +51 -0
- package/dist/store/review-transitions.js.map +1 -0
- package/dist/store/role-permission-export.d.ts +22 -0
- package/dist/store/role-permission-export.d.ts.map +1 -0
- package/dist/store/role-permission-export.js +0 -0
- package/dist/store/role-permission-export.js.map +1 -0
- package/dist/store/role-permission-overlay.d.ts +27 -0
- package/dist/store/role-permission-overlay.d.ts.map +1 -0
- package/dist/store/role-permission-overlay.js +0 -0
- package/dist/store/role-permission-overlay.js.map +1 -0
- package/dist/store/role-permission-store.d.ts +72 -0
- package/dist/store/role-permission-store.d.ts.map +1 -0
- package/dist/store/role-permission-store.js +148 -0
- package/dist/store/role-permission-store.js.map +1 -0
- package/dist/store/role-permission-tables.d.ts +27 -0
- package/dist/store/role-permission-tables.d.ts.map +1 -0
- package/dist/store/role-permission-tables.js +52 -0
- package/dist/store/role-permission-tables.js.map +1 -0
- package/dist/store/scheduled-publish-enqueue.d.ts +37 -0
- package/dist/store/scheduled-publish-enqueue.d.ts.map +1 -0
- package/dist/store/scheduled-publish-enqueue.js +51 -0
- package/dist/store/scheduled-publish-enqueue.js.map +1 -0
- package/dist/store/scheduled-publish-failures.d.ts +36 -0
- package/dist/store/scheduled-publish-failures.d.ts.map +1 -0
- package/dist/store/scheduled-publish-failures.js +67 -0
- package/dist/store/scheduled-publish-failures.js.map +1 -0
- package/dist/store/schema-2-1-migration.d.ts +29 -0
- package/dist/store/schema-2-1-migration.d.ts.map +1 -0
- package/dist/store/schema-2-1-migration.js +71 -0
- package/dist/store/schema-2-1-migration.js.map +1 -0
- package/dist/store/search-console-store.d.ts +44 -0
- package/dist/store/search-console-store.d.ts.map +1 -0
- package/dist/store/search-console-store.js +90 -0
- package/dist/store/search-console-store.js.map +1 -0
- package/dist/store/search-console-tables.d.ts +14 -0
- package/dist/store/search-console-tables.d.ts.map +1 -0
- package/dist/store/search-console-tables.js +29 -0
- package/dist/store/search-console-tables.js.map +1 -0
- package/dist/store/search-indexing.d.ts +36 -0
- package/dist/store/search-indexing.d.ts.map +1 -1
- package/dist/store/search-indexing.js +33 -0
- package/dist/store/search-indexing.js.map +1 -1
- package/dist/store/site-settings-registry.d.ts +164 -0
- package/dist/store/site-settings-registry.d.ts.map +1 -0
- package/dist/store/site-settings-registry.js +1160 -0
- package/dist/store/site-settings-registry.js.map +1 -0
- package/dist/store/site-settings-store.d.ts +42 -0
- package/dist/store/site-settings-store.d.ts.map +1 -0
- package/dist/store/site-settings-store.js +97 -0
- package/dist/store/site-settings-store.js.map +1 -0
- package/dist/store/site-settings-tables.d.ts +29 -0
- package/dist/store/site-settings-tables.d.ts.map +1 -0
- package/dist/store/site-settings-tables.js +48 -0
- package/dist/store/site-settings-tables.js.map +1 -0
- package/dist/store/store.d.ts +57 -2
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +278 -37
- package/dist/store/store.js.map +1 -1
- package/dist/store/tables.d.ts.map +1 -1
- package/dist/store/tables.js +11 -0
- package/dist/store/tables.js.map +1 -1
- package/dist/store/taxonomy-store.d.ts.map +1 -1
- package/dist/store/taxonomy-store.js +90 -39
- package/dist/store/taxonomy-store.js.map +1 -1
- package/dist/store/taxonomy-usage.d.ts +47 -0
- package/dist/store/taxonomy-usage.d.ts.map +1 -0
- package/dist/store/taxonomy-usage.js +101 -0
- package/dist/store/taxonomy-usage.js.map +1 -0
- package/dist/store/theme-store.d.ts +73 -0
- package/dist/store/theme-store.d.ts.map +1 -0
- package/dist/store/theme-store.js +193 -0
- package/dist/store/theme-store.js.map +1 -0
- package/dist/store/types.d.ts +36 -1
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/values.d.ts.map +1 -1
- package/dist/store/values.js +28 -1
- package/dist/store/values.js.map +1 -1
- package/dist/system-fields.d.ts +8 -1
- package/dist/system-fields.d.ts.map +1 -1
- package/dist/system-fields.js +14 -1
- package/dist/system-fields.js.map +1 -1
- package/dist/types.d.ts +54 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -31,7 +31,26 @@ const MAX_PATH_LENGTH = 512;
|
|
|
31
31
|
* this code never wrote.
|
|
32
32
|
*/
|
|
33
33
|
const MAX_HOPS = 10;
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* `'agent'` (L22 task 3) marks a redirect an agent created itself —
|
|
36
|
+
* `redirects.create` (`@cogenta/agents`) always writes this reason, never
|
|
37
|
+
* `'manual'`, so an admin looking at `/seo?tab=redirects` can tell which
|
|
38
|
+
* rows a human typed and which one a monitoring agent proposed and had
|
|
39
|
+
* applied under `autopilot` autonomy. Additive to a stored, open list (not a
|
|
40
|
+
* versioned contract enum): `toRecord` below already falls back to
|
|
41
|
+
* `'manual'` for any string it does not recognise, so a row written by an
|
|
42
|
+
* older build still reads back fine.
|
|
43
|
+
*/
|
|
44
|
+
export const REDIRECT_REASONS = ['slug-change', 'manual', 'import', 'agent'];
|
|
45
|
+
/** 301 and 308 are the two search engines and browsers may cache. */
|
|
46
|
+
function isPermanent(status) {
|
|
47
|
+
return status === 301 || status === 308;
|
|
48
|
+
}
|
|
49
|
+
const REDIRECT_STATUSES = [301, 302, 307, 308, 410];
|
|
50
|
+
/** Falls back to 301 for anything a hand-edited table might hold that this version does not know. */
|
|
51
|
+
function asStatus(value) {
|
|
52
|
+
return REDIRECT_STATUSES.includes(value) ? value : 301;
|
|
53
|
+
}
|
|
35
54
|
export function createRedirectStore(options) {
|
|
36
55
|
const { db } = options;
|
|
37
56
|
const now = options.now ?? Date.now;
|
|
@@ -80,9 +99,15 @@ export function createRedirectStore(options) {
|
|
|
80
99
|
}
|
|
81
100
|
return normalised;
|
|
82
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* A 410 row is excluded on purpose: its `to_path` is only ever itself
|
|
104
|
+
* (see `add`), and chasing it would make `flattenTarget` see a path that
|
|
105
|
+
* "leads back to itself" and refuse a perfectly ordinary redirect *into*
|
|
106
|
+
* a page that happens to be marked Gone.
|
|
107
|
+
*/
|
|
83
108
|
async function targetOf(tx, path) {
|
|
84
109
|
const found = await tx.query(sql `
|
|
85
|
-
select to_path from ${table} where from_path = ${path} limit ${limit(1)}`);
|
|
110
|
+
select to_path from ${table} where from_path = ${path} and status != ${410} limit ${limit(1)}`);
|
|
86
111
|
return found.rows[0]?.to_path;
|
|
87
112
|
}
|
|
88
113
|
/**
|
|
@@ -122,55 +147,129 @@ export function createRedirectStore(options) {
|
|
|
122
147
|
delete from ${table} where from_path = ${normalisePath(path)}`);
|
|
123
148
|
return result.rowsAffected > 0;
|
|
124
149
|
}
|
|
125
|
-
|
|
126
|
-
ensureTable
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
150
|
+
const performAdd = async (input) => {
|
|
151
|
+
await ensureTable();
|
|
152
|
+
const from = checkPath(input.from, 'from');
|
|
153
|
+
const status = input.status ?? 301;
|
|
154
|
+
const reason = input.reason ?? 'manual';
|
|
155
|
+
const createdAt = now();
|
|
156
|
+
// 410 (Gone) is not a redirect: there is nothing to chase or flatten,
|
|
157
|
+
// and nothing else in the table should be rewritten because of it —
|
|
158
|
+
// an existing rule that happened to point here keeps pointing here,
|
|
159
|
+
// exactly as it would if any other ordinary page appeared at `from`.
|
|
160
|
+
// `to` is stored equal to `from` so every reader of this table can
|
|
161
|
+
// keep treating the column as a plain, non-null string.
|
|
162
|
+
if (status === 410) {
|
|
163
|
+
const record = {
|
|
164
|
+
id: nextId(),
|
|
165
|
+
from,
|
|
166
|
+
to: from,
|
|
167
|
+
status,
|
|
168
|
+
collection: input.collection ?? null,
|
|
169
|
+
entryId: input.entryId ?? null,
|
|
170
|
+
locale: input.locale ?? null,
|
|
171
|
+
reason,
|
|
172
|
+
createdAt,
|
|
173
|
+
};
|
|
144
174
|
return db.transaction(async (tx) => {
|
|
145
|
-
|
|
146
|
-
//
|
|
147
|
-
// This is what keeps the table one hop deep however often an entry is
|
|
148
|
-
// renamed.
|
|
149
|
-
await tx.query(sql `
|
|
150
|
-
update ${table} set to_path = ${target} where to_path = ${from}`);
|
|
151
|
-
// Delete-then-insert rather than an upsert: `ON CONFLICT`, `ON
|
|
152
|
-
// DUPLICATE KEY` and `INSERT OR REPLACE` are three different
|
|
153
|
-
// statements, and this layer owes callers one behaviour.
|
|
175
|
+
// Same delete-then-insert as below, for the same reason: one
|
|
176
|
+
// behaviour across three dialects that each spell "replace" differently.
|
|
154
177
|
await tx.query(sql `delete from ${table} where from_path = ${from}`);
|
|
155
|
-
const record = {
|
|
156
|
-
id: nextId(),
|
|
157
|
-
from,
|
|
158
|
-
to: target,
|
|
159
|
-
status,
|
|
160
|
-
collection: input.collection ?? null,
|
|
161
|
-
entryId: input.entryId ?? null,
|
|
162
|
-
locale: input.locale ?? null,
|
|
163
|
-
reason,
|
|
164
|
-
createdAt,
|
|
165
|
-
};
|
|
166
178
|
await tx.query(sql `
|
|
179
|
+
insert into ${table}
|
|
180
|
+
(id, from_path, to_path, status, collection, entry_id, locale, reason, created_at)
|
|
181
|
+
values (${record.id}, ${record.from}, ${record.to}, ${record.status},
|
|
182
|
+
${record.collection}, ${record.entryId}, ${record.locale},
|
|
183
|
+
${record.reason}, ${record.createdAt})`);
|
|
184
|
+
return record;
|
|
185
|
+
}, { immediate: true });
|
|
186
|
+
}
|
|
187
|
+
if (input.to === undefined || input.to.length === 0) {
|
|
188
|
+
throw new CogentaError({
|
|
189
|
+
code: 'CONTENT_ROUTE_INVALID',
|
|
190
|
+
message: 'A redirect needs a destination unless its status is 410 (Gone).',
|
|
191
|
+
hint: 'Pass "to", or set status to 410 for a page that is gone rather than moved.',
|
|
192
|
+
details: { from },
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
const to = checkPath(input.to, 'to');
|
|
196
|
+
if (from === to) {
|
|
197
|
+
throw new CogentaError({
|
|
198
|
+
code: 'CONTENT_REDIRECT_LOOP',
|
|
199
|
+
message: `${from} cannot redirect to itself.`,
|
|
200
|
+
hint: 'Nothing needs a redirect here: the path did not change.',
|
|
201
|
+
details: { from },
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// One transaction: the chain is read, rewritten and extended together, so
|
|
205
|
+
// a second rename running at the same time cannot slot a hop in between.
|
|
206
|
+
return db.transaction(async (tx) => {
|
|
207
|
+
const target = await flattenTarget(tx, from, to);
|
|
208
|
+
// Everything that pointed at the old path now points at the new one.
|
|
209
|
+
// This is what keeps the table one hop deep however often an entry is
|
|
210
|
+
// renamed. Rows already marked 410 are left alone (see `flattenTarget`
|
|
211
|
+
// and `targetOf`, which never treat a Gone row as a link in a chain).
|
|
212
|
+
await tx.query(sql `
|
|
213
|
+
update ${table} set to_path = ${target}
|
|
214
|
+
where to_path = ${from} and status != ${410}`);
|
|
215
|
+
// Delete-then-insert rather than an upsert: `ON CONFLICT`, `ON
|
|
216
|
+
// DUPLICATE KEY` and `INSERT OR REPLACE` are three different
|
|
217
|
+
// statements, and this layer owes callers one behaviour.
|
|
218
|
+
await tx.query(sql `delete from ${table} where from_path = ${from}`);
|
|
219
|
+
const record = {
|
|
220
|
+
id: nextId(),
|
|
221
|
+
from,
|
|
222
|
+
to: target,
|
|
223
|
+
status,
|
|
224
|
+
collection: input.collection ?? null,
|
|
225
|
+
entryId: input.entryId ?? null,
|
|
226
|
+
locale: input.locale ?? null,
|
|
227
|
+
reason,
|
|
228
|
+
createdAt,
|
|
229
|
+
};
|
|
230
|
+
await tx.query(sql `
|
|
167
231
|
insert into ${table}
|
|
168
232
|
(id, from_path, to_path, status, collection, entry_id, locale, reason, created_at)
|
|
169
233
|
values (${record.id}, ${record.from}, ${record.to}, ${record.status},
|
|
170
234
|
${record.collection}, ${record.entryId}, ${record.locale},
|
|
171
235
|
${record.reason}, ${record.createdAt})`);
|
|
172
|
-
|
|
173
|
-
|
|
236
|
+
return record;
|
|
237
|
+
}, { immediate: true });
|
|
238
|
+
};
|
|
239
|
+
return {
|
|
240
|
+
ensureTable,
|
|
241
|
+
add: performAdd,
|
|
242
|
+
// A PATCH by another name: `to` and/or `status` change, everything else
|
|
243
|
+
// — `collection`, `entryId`, `locale`, `reason` — stays what it was,
|
|
244
|
+
// because none of those describe *where this redirect points*, only
|
|
245
|
+
// *why it exists*. Routed through `performAdd` rather than a second copy
|
|
246
|
+
// of its chain-flattening and loop-refusal logic, for the same reason
|
|
247
|
+
// `add()` already treats "add at an existing `from`" as a replace: they
|
|
248
|
+
// are the same operation with a different name at the call site.
|
|
249
|
+
update: async (from, input) => {
|
|
250
|
+
await ensureTable();
|
|
251
|
+
const normalisedFrom = normalisePath(from);
|
|
252
|
+
const found = await db.query(sql `
|
|
253
|
+
select * from ${table} where from_path = ${normalisedFrom} limit ${limit(1)}`);
|
|
254
|
+
const row = found.rows[0];
|
|
255
|
+
if (row === undefined) {
|
|
256
|
+
throw new CogentaError({
|
|
257
|
+
code: 'REDIRECT_UNKNOWN',
|
|
258
|
+
message: `No redirect leaves "${normalisedFrom}".`,
|
|
259
|
+
hint: 'Check the path — it may already have been removed, or never existed.',
|
|
260
|
+
details: { from: normalisedFrom },
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
const existing = toRecord(row);
|
|
264
|
+
return performAdd({
|
|
265
|
+
from: normalisedFrom,
|
|
266
|
+
to: input.to ?? existing.to,
|
|
267
|
+
status: input.status ?? existing.status,
|
|
268
|
+
reason: existing.reason,
|
|
269
|
+
...(existing.collection === null ? {} : { collection: existing.collection }),
|
|
270
|
+
...(existing.entryId === null ? {} : { entryId: existing.entryId }),
|
|
271
|
+
...(existing.locale === null ? {} : { locale: existing.locale }),
|
|
272
|
+
});
|
|
174
273
|
},
|
|
175
274
|
resolve: async (path) => {
|
|
176
275
|
await ensureTable();
|
|
@@ -178,16 +277,29 @@ export function createRedirectStore(options) {
|
|
|
178
277
|
const seen = new Set([start]);
|
|
179
278
|
let current = start;
|
|
180
279
|
let status = 301;
|
|
280
|
+
// Once true, a later permanent hop must not paper back over an earlier
|
|
281
|
+
// temporary one — the chain as a whole must not be cached as permanent
|
|
282
|
+
// by a browser that never sees the hop that made it temporary.
|
|
283
|
+
let sawTemporary = false;
|
|
181
284
|
for (let hop = 0; hop < MAX_HOPS; hop += 1) {
|
|
182
285
|
const found = await db.query(sql `
|
|
183
286
|
select to_path, status from ${table} where from_path = ${current} limit ${limit(1)}`);
|
|
184
287
|
const row = found.rows[0];
|
|
185
288
|
if (row === undefined)
|
|
186
289
|
break;
|
|
187
|
-
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
290
|
+
const rowStatus = asStatus(Number(row.status));
|
|
291
|
+
// 410 is terminal: there is nothing further to chase, and `to_path`
|
|
292
|
+
// is only ever `current` itself for a Gone row (see `add`).
|
|
293
|
+
if (rowStatus === 410)
|
|
294
|
+
return { to: current, status: 410 };
|
|
295
|
+
if (isPermanent(rowStatus)) {
|
|
296
|
+
if (!sawTemporary)
|
|
297
|
+
status = rowStatus;
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
status = rowStatus;
|
|
301
|
+
sawTemporary = true;
|
|
302
|
+
}
|
|
191
303
|
current = row.to_path;
|
|
192
304
|
// A cycle in imported data resolves to the last path before the loop
|
|
193
305
|
// closes rather than throwing: serving one redirect is better than
|
|
@@ -224,7 +336,7 @@ function toRecord(row) {
|
|
|
224
336
|
id: row.id,
|
|
225
337
|
from: row.from_path,
|
|
226
338
|
to: row.to_path,
|
|
227
|
-
status: Number(row.status)
|
|
339
|
+
status: asStatus(Number(row.status)),
|
|
228
340
|
collection: row.collection,
|
|
229
341
|
entryId: row.entry_id,
|
|
230
342
|
locale: row.locale,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirects.js","sourceRoot":"","sources":["../../src/routing/redirects.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,UAAU,EACV,KAAK,EAEL,GAAG,GACJ,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAA;AAElD;;;;;;GAMG;AACH,MAAM,eAAe,GAAG,GAAG,CAAA;AAE3B;;;;;;GAMG;AACH,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"redirects.js","sourceRoot":"","sources":["../../src/routing/redirects.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,UAAU,EACV,KAAK,EAEL,GAAG,GACJ,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAA;AAElD;;;;;;GAMG;AACH,MAAM,eAAe,GAAG,GAAG,CAAA;AAE3B;;;;;;GAMG;AACH,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAA;AAWrF,qEAAqE;AACrE,SAAS,WAAW,CAAC,MAAsB;IACzC,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,CAAA;AACzC,CAAC;AAED,MAAM,iBAAiB,GAA8B,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAE9E,qGAAqG;AACrG,SAAS,QAAQ,CAAC,KAAa;IAC7B,OAAQ,iBAAuC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAwB,CAAC,CAAC,CAAC,GAAG,CAAA;AACnG,CAAC;AAqFD,MAAM,UAAU,mBAAmB,CAAC,OAA6B;IAC/D,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAA;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAA;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAA;IACrC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,IAAI,eAAe,EAAE,EAAE,CAAC,OAAO,CAAC,CAAA;IACtE,IAAI,KAAK,GAAG,KAAK,CAAA;IAEjB,KAAK,UAAU,WAAW;QACxB,IAAI,KAAK;YAAE,OAAM;QAEjB,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;mCACa,KAAK;;;;;;;;;;QAUhC,CAAC,CAAA;QAEL,2EAA2E;QAC3E,2EAA2E;QAC3E,MAAM,EAAE;aACL,KAAK,CACJ,GAAG,CAAA,uBAAuB,UAAU,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI,eAAe,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC;iBACnF,KAAK,cAAc,CAC7B;aACA,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA,CAAC,iEAAiE;QAE3F,KAAK,GAAG,IAAI,CAAA;IACd,CAAC;IAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAoB;QACnD,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;QAEtC,IAAI,UAAU,KAAK,GAAG,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC3C,MAAM,IAAI,YAAY,CAAC;gBACrB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,gCAAgC;gBACzC,IAAI,EAAE,4DAA4D;aACnE,CAAC,CAAA;QACJ,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;YACxC,MAAM,IAAI,YAAY,CAAC;gBACrB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,0BAA0B,eAAe,sBAAsB;gBACxE,IAAI,EAAE,+DAA+D;gBACrE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE;aAC9C,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,UAAU,CAAA;IACnB,CAAC;IAED;;;;;OAKG;IACH,KAAK,UAAU,QAAQ,CAAC,EAAe,EAAE,IAAY;QACnD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAsB,GAAG,CAAA;4BAC7B,KAAK,sBAAsB,IAAI,kBAAkB,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACjG,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAA;IAC/B,CAAC;IAED;;;;;OAKG;IACH,KAAK,UAAU,aAAa,CAAC,EAAe,EAAE,IAAY,EAAE,EAAU;QACpE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QACpC,IAAI,MAAM,GAAG,EAAE,CAAA;QAEf,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;YAC5C,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,YAAY,CAAC;oBACrB,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,yCAAyC;oBAC9E,IAAI,EAAE,GAAG,MAAM,0BAA0B,IAAI,4DAA4D;oBACzG,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE;iBAClC,CAAC,CAAA;YACJ,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAEhB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;YACvC,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAA;YACrC,MAAM,GAAG,IAAI,CAAA;QACf,CAAC;QAED,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,kCAAkC,EAAE,iBAAiB,QAAQ,aAAa;YACnF,IAAI,EAAE,4EAA4E;YAClF,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;SACtB,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,UAAU,UAAU,CAAC,IAAY;QACpC,MAAM,WAAW,EAAE,CAAA;QACnB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;oBACjB,KAAK,sBAAsB,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACjE,OAAO,MAAM,CAAC,YAAY,GAAG,CAAC,CAAA;IAChC,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,EAAE,KAAuB,EAA2B,EAAE;QAC5E,MAAM,WAAW,EAAE,CAAA;QAEnB,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,CAAA;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAA;QACvC,MAAM,SAAS,GAAG,GAAG,EAAE,CAAA;QAEvB,sEAAsE;QACtE,oEAAoE;QACpE,oEAAoE;QACpE,qEAAqE;QACrE,mEAAmE;QACnE,wDAAwD;QACxD,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,MAAM,MAAM,GAAmB;gBAC7B,EAAE,EAAE,MAAM,EAAE;gBACZ,IAAI;gBACJ,EAAE,EAAE,IAAI;gBACR,MAAM;gBACN,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,IAAI;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;gBAC9B,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;gBAC5B,MAAM;gBACN,SAAS;aACV,CAAA;YACD,OAAO,EAAE,CAAC,WAAW,CACnB,KAAK,EAAE,EAAE,EAAE,EAAE;gBACX,6DAA6D;gBAC7D,yEAAyE;gBACzE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA,eAAe,KAAK,sBAAsB,IAAI,EAAE,CAAC,CAAA;gBACnE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;4BACA,KAAK;;wBAET,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,MAAM;wBACzD,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,MAAM;wBACtD,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,SAAS,GAAG,CAAC,CAAA;gBACpD,OAAO,MAAM,CAAA;YACf,CAAC,EACD,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAA;QACH,CAAC;QAED,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,YAAY,CAAC;gBACrB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,iEAAiE;gBAC1E,IAAI,EAAE,4EAA4E;gBAClF,OAAO,EAAE,EAAE,IAAI,EAAE;aAClB,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;QAEpC,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,YAAY,CAAC;gBACrB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,GAAG,IAAI,6BAA6B;gBAC7C,IAAI,EAAE,yDAAyD;gBAC/D,OAAO,EAAE,EAAE,IAAI,EAAE;aAClB,CAAC,CAAA;QACJ,CAAC;QAED,0EAA0E;QAC1E,yEAAyE;QACzE,OAAO,EAAE,CAAC,WAAW,CACnB,KAAK,EAAE,EAAE,EAAE,EAAE;YACX,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAAA;YAEhD,qEAAqE;YACrE,sEAAsE;YACtE,uEAAuE;YACvE,sEAAsE;YACtE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;qBACL,KAAK,kBAAkB,MAAM;8BACpB,IAAI,kBAAkB,GAAG,EAAE,CAAC,CAAA;YAElD,+DAA+D;YAC/D,6DAA6D;YAC7D,yDAAyD;YACzD,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA,eAAe,KAAK,sBAAsB,IAAI,EAAE,CAAC,CAAA;YAEnE,MAAM,MAAM,GAAmB;gBAC7B,EAAE,EAAE,MAAM,EAAE;gBACZ,IAAI;gBACJ,EAAE,EAAE,MAAM;gBACV,MAAM;gBACN,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,IAAI;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;gBAC9B,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;gBAC5B,MAAM;gBACN,SAAS;aACV,CAAA;YAED,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA;0BACA,KAAK;;sBAET,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,MAAM;sBACzD,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,MAAM;sBACtD,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,SAAS,GAAG,CAAC,CAAA;YAEpD,OAAO,MAAM,CAAA;QACf,CAAC,EACD,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAA;IACH,CAAC,CAAA;IAED,OAAO;QACL,WAAW;QACX,GAAG,EAAE,UAAU;QAEf,wEAAwE;QACxE,qEAAqE;QACrE,oEAAoE;QACpE,yEAAyE;QACzE,sEAAsE;QACtE,wEAAwE;QACxE,iEAAiE;QACjE,MAAM,EAAE,KAAK,EAAE,IAAY,EAAE,KAA0B,EAA2B,EAAE;YAClF,MAAM,WAAW,EAAE,CAAA;YACnB,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;YAE1C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAc,GAAG,CAAA;wBAC3B,KAAK,sBAAsB,cAAc,UAAU,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YAChF,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACzB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,MAAM,IAAI,YAAY,CAAC;oBACrB,IAAI,EAAE,kBAAkB;oBACxB,OAAO,EAAE,uBAAuB,cAAc,IAAI;oBAClD,IAAI,EAAE,sEAAsE;oBAC5E,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE;iBAClC,CAAC,CAAA;YACJ,CAAC;YACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;YAE9B,OAAO,UAAU,CAAC;gBAChB,IAAI,EAAE,cAAc;gBACpB,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,QAAQ,CAAC,EAAE;gBAC3B,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM;gBACvC,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,GAAG,CAAC,QAAQ,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC5E,GAAG,CAAC,QAAQ,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACnE,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;aACjE,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAY,EAAsC,EAAE;YAClE,MAAM,WAAW,EAAE,CAAA;YAEnB,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,KAAK,CAAC,CAAC,CAAA;YACrC,IAAI,OAAO,GAAG,KAAK,CAAA;YACnB,IAAI,MAAM,GAAmB,GAAG,CAAA;YAChC,uEAAuE;YACvE,uEAAuE;YACvE,+DAA+D;YAC/D,IAAI,YAAY,GAAG,KAAK,CAAA;YAExB,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAsC,GAAG,CAAA;wCACrC,KAAK,sBAAsB,OAAO,UAAU,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;gBAEvF,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBACzB,IAAI,GAAG,KAAK,SAAS;oBAAE,MAAK;gBAE5B,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;gBAE9C,oEAAoE;gBACpE,4DAA4D;gBAC5D,IAAI,SAAS,KAAK,GAAG;oBAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;gBAE1D,IAAI,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC3B,IAAI,CAAC,YAAY;wBAAE,MAAM,GAAG,SAAS,CAAA;gBACvC,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,SAAS,CAAA;oBAClB,YAAY,GAAG,IAAI,CAAA;gBACrB,CAAC;gBACD,OAAO,GAAG,GAAG,CAAC,OAAO,CAAA;gBAErB,qEAAqE;gBACrE,mEAAmE;gBACnE,uDAAuD;gBACvD,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;oBAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;gBACrD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACnB,CAAC;YAED,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;QAC3D,CAAC;QAED,IAAI,EAAE,KAAK,EAAE,WAAW,GAAyB,EAAE,EAA6B,EAAE;YAChF,MAAM,WAAW,EAAE,CAAA;YAEnB,MAAM,YAAY,GAChB,WAAW,CAAC,UAAU,KAAK,SAAS;gBAClC,CAAC,CAAC,GAAG,CAAA,EAAE;gBACP,CAAC,CAAC,GAAG,CAAA,qBAAqB,WAAW,CAAC,UAAU,EAAE,CAAA;YACtD,MAAM,QAAQ,GACZ,WAAW,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAA,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA,iBAAiB,WAAW,CAAC,MAAM,EAAE,CAAA;YAErF,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAc,GAAG,CAAA;;eAEpC,KAAK;qBACC,YAAY,GAAG,QAAQ;;gBAE5B,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;YAE7C,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACjC,CAAC;QAED,MAAM,EAAE,UAAU;QAClB,2EAA2E;QAC3E,uEAAuE;QACvE,gEAAgE;QAChE,OAAO,EAAE,UAAU;KACpB,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,GAAgB;IAChC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,SAAS;QACnB,EAAE,EAAE,GAAG,CAAC,OAAO;QACf,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,OAAO,EAAE,GAAG,CAAC,QAAQ;QACrB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,MAAM,EAAG,gBAAsC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;YAClE,CAAC,CAAE,GAAG,CAAC,MAAyB;YAChC,CAAC,CAAC,QAAQ;QACZ,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;KAClC,CAAA;AACH,CAAC"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export type { PublishHandler, ScheduledPublication, ScheduledPublishingOptions, SchedulePublicationInput, } from './publish.js';
|
|
2
2
|
export { cancelPublication, parsePayload, registerScheduledPublishing, reschedulePublication, SCHEDULED_PUBLISH_JOB, schedulePublication, } from './publish.js';
|
|
3
|
+
export type { CreateScheduledTaskRegistryOptions, ScheduledTaskDefinition, ScheduledTaskOutcome, ScheduledTaskRegistry, ScheduledTaskRun, ScheduledTaskState, TaskOutcome, TaskTrigger, } from './registry.js';
|
|
4
|
+
export { createScheduledTaskRegistry, SCHEDULED_TASK_RUNS_TABLE } from './registry.js';
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scheduling/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scheduling/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,kCAAkC,EAClC,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,WAAW,GACZ,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/scheduling/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { cancelPublication, parsePayload, registerScheduledPublishing, reschedulePublication, SCHEDULED_PUBLISH_JOB, schedulePublication, } from './publish.js';
|
|
2
|
+
export { createScheduledTaskRegistry, SCHEDULED_TASK_RUNS_TABLE } from './registry.js';
|
|
2
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scheduling/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scheduling/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,cAAc,CAAA;AAWrB,OAAO,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { type DatabaseHandle, type Logger } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* The scheduled-task registry (fiche 28 task 1).
|
|
4
|
+
*
|
|
5
|
+
* Before this, `cogenta serve` registered four unrelated pieces of recurring
|
|
6
|
+
* work — scheduled publication, the 404 log purge, the audit-integrity
|
|
7
|
+
* check, the trash sweep — each on its own bare `setInterval`, with no shared
|
|
8
|
+
* bookkeeping. Nothing recorded whether a run had happened, how long it took,
|
|
9
|
+
* or whether it had failed; the only way to know a scheduled publication had
|
|
10
|
+
* stopped working was a reader noticing a page never went live.
|
|
11
|
+
*
|
|
12
|
+
* A registered task declares a name, a description, an interval and a
|
|
13
|
+
* function. This module owns everything else: running due tasks, recording
|
|
14
|
+
* every run, and answering "what is scheduled, and did it work" for the
|
|
15
|
+
* admin screen fiche 28 task 2 builds over it.
|
|
16
|
+
*
|
|
17
|
+
* **Persistence is the point of task 3.** A task's "last run" is a row in
|
|
18
|
+
* this table, not a variable in the process — a `setInterval` handle dies
|
|
19
|
+
* with the process, and a site restarted after being down all night must be
|
|
20
|
+
* able to say, immediately, "the trash sweep has not run in fourteen hours"
|
|
21
|
+
* rather than resetting the clock the moment it comes back up. `tick()`
|
|
22
|
+
* itself is equally indifferent to *why* it is being called: `cogenta
|
|
23
|
+
* serve`'s own loop and the one-shot `cogenta cron` command both just call
|
|
24
|
+
* it, which is what makes the second a real alternative to the first rather
|
|
25
|
+
* than a separate reimplementation (fiche 28 task 5).
|
|
26
|
+
*/
|
|
27
|
+
export declare const SCHEDULED_TASK_RUNS_TABLE = "cogenta_scheduled_task_runs";
|
|
28
|
+
/**
|
|
29
|
+
* One row per task: the compare-and-set lock `tick()` claims before running a
|
|
30
|
+
* task (L22 task 6). Kept separate from the run-history table above —
|
|
31
|
+
* history answers "what happened", this answers "is anyone already doing
|
|
32
|
+
* this right now", and conflating the two would make every read of the
|
|
33
|
+
* admin history screen reason about lock state.
|
|
34
|
+
*
|
|
35
|
+
* Before this table existed, `tick()` read the last run from the history
|
|
36
|
+
* table, decided a task was due, and only recorded the new run *after* it
|
|
37
|
+
* finished — nothing made that read-then-act atomic. With more than one
|
|
38
|
+
* `cogenta serve` replica (or a replica racing a `cogenta cron` invocation)
|
|
39
|
+
* against the same database, two processes could both read "due" and both
|
|
40
|
+
* start executing the same task, including the destructive trash-purge
|
|
41
|
+
* sweep. The fix is the same shape as `takeOne`'s guarded stock `UPDATE` in
|
|
42
|
+
* `@cogenta/commerce` and `claimOnce`'s guarded job `UPDATE` in
|
|
43
|
+
* `@cogenta/core`'s database queue: read `last_claim`, then issue a single
|
|
44
|
+
* `UPDATE ... WHERE last_claim = <the value just read>`. Only one of two
|
|
45
|
+
* racing `UPDATE`s can match that `WHERE` — the loser sees
|
|
46
|
+
* `rowsAffected === 0` and skips the task entirely. No dialect-specific
|
|
47
|
+
* locking primitive is needed: a single `UPDATE` with an equality `WHERE` is
|
|
48
|
+
* atomic per row on SQLite, Postgres and MySQL/MariaDB alike, so the exact
|
|
49
|
+
* same query runs unmodified on all three.
|
|
50
|
+
*/
|
|
51
|
+
export declare const SCHEDULED_TASK_CLAIMS_TABLE = "cogenta_scheduled_task_claims";
|
|
52
|
+
export type TaskTrigger = 'schedule' | 'manual' | 'cron';
|
|
53
|
+
export type TaskOutcome = 'success' | 'error';
|
|
54
|
+
export interface ScheduledTaskRun {
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly taskName: string;
|
|
57
|
+
/** Epoch milliseconds. */
|
|
58
|
+
readonly startedAt: number;
|
|
59
|
+
/** Epoch milliseconds. */
|
|
60
|
+
readonly finishedAt: number;
|
|
61
|
+
readonly durationMs: number;
|
|
62
|
+
readonly outcome: TaskOutcome;
|
|
63
|
+
readonly summary: string | null;
|
|
64
|
+
readonly error: string | null;
|
|
65
|
+
readonly triggeredBy: TaskTrigger;
|
|
66
|
+
/** Who clicked "run now", when `triggeredBy` is `'manual'`. Never set otherwise. */
|
|
67
|
+
readonly actor: string | null;
|
|
68
|
+
}
|
|
69
|
+
export interface ScheduledTaskOutcome {
|
|
70
|
+
/** A short, human-readable result — "3 published", "12 purged". Shown next to the run in the admin screen. */
|
|
71
|
+
readonly summary?: string;
|
|
72
|
+
}
|
|
73
|
+
export interface ScheduledTaskDefinition {
|
|
74
|
+
/** Stable, used as the id everywhere — in the run table, in the admin screen's URL, in `runNow`. Never shown untranslated as the only label (`description` is). */
|
|
75
|
+
readonly name: string;
|
|
76
|
+
readonly description: string;
|
|
77
|
+
readonly intervalMs: number;
|
|
78
|
+
/**
|
|
79
|
+
* True for a task whose manual run destroys something irrecoverable (the
|
|
80
|
+
* trash sweep, most of all) — the admin screen's "run now" button asks for
|
|
81
|
+
* confirmation before calling it (fiche 28 task 2/piège: "«Exécuter
|
|
82
|
+
* maintenant» sur une purge est destructif").
|
|
83
|
+
*/
|
|
84
|
+
readonly destructive?: boolean;
|
|
85
|
+
readonly run: () => Promise<ScheduledTaskOutcome | undefined>;
|
|
86
|
+
}
|
|
87
|
+
export interface ScheduledTaskState {
|
|
88
|
+
readonly name: string;
|
|
89
|
+
readonly description: string;
|
|
90
|
+
readonly intervalMs: number;
|
|
91
|
+
readonly destructive: boolean;
|
|
92
|
+
readonly lastRun: ScheduledTaskRun | null;
|
|
93
|
+
/** Epoch milliseconds: when this task next becomes due. `lastRun`'s instant plus its interval, or "now" if it has never run. */
|
|
94
|
+
readonly nextRunAt: number;
|
|
95
|
+
/**
|
|
96
|
+
* True once a task is more than twice its own interval past due (fiche 28
|
|
97
|
+
* task 3) — including a task that has never run at all, which is the state
|
|
98
|
+
* an external cron that was configured but never actually invoked leaves
|
|
99
|
+
* every task in forever.
|
|
100
|
+
*/
|
|
101
|
+
readonly overdue: boolean;
|
|
102
|
+
/** Most recent first, bounded to `keepRuns`. */
|
|
103
|
+
readonly recentRuns: readonly ScheduledTaskRun[];
|
|
104
|
+
}
|
|
105
|
+
export interface ScheduledTaskRegistry {
|
|
106
|
+
/** Declares a task. Registering the same name twice is a configuration bug, refused loudly rather than silently overwriting the first. */
|
|
107
|
+
register(definition: ScheduledTaskDefinition): void;
|
|
108
|
+
/** Every registered task's current state, in registration order. */
|
|
109
|
+
list(): Promise<readonly ScheduledTaskState[]>;
|
|
110
|
+
get(name: string): Promise<ScheduledTaskState | null>;
|
|
111
|
+
/**
|
|
112
|
+
* Runs one task regardless of whether it is due, and records the run.
|
|
113
|
+
* Never rejects on the task's own failure — the run is recorded with
|
|
114
|
+
* `outcome: 'error'` and returned, not thrown, so a caller (the admin
|
|
115
|
+
* "run now" route, `tick()` itself) never needs a second error path for
|
|
116
|
+
* "the task ran and failed" versus "calling it failed".
|
|
117
|
+
*/
|
|
118
|
+
runNow(name: string, options?: {
|
|
119
|
+
readonly actor?: string | null;
|
|
120
|
+
}): Promise<ScheduledTaskRun>;
|
|
121
|
+
/**
|
|
122
|
+
* Runs every task whose interval has elapsed since its last run, in
|
|
123
|
+
* registration order and one at a time — never concurrently, so two tasks
|
|
124
|
+
* sharing one SQLite connection never open overlapping transactions.
|
|
125
|
+
*
|
|
126
|
+
* Each due task is first claimed with a compare-and-set `UPDATE` against
|
|
127
|
+
* `SCHEDULED_TASK_CLAIMS_TABLE`. Losing that race (another replica already
|
|
128
|
+
* claimed the same task) is not an error — the task is silently skipped
|
|
129
|
+
* for this tick, exactly as if it had not been due.
|
|
130
|
+
*/
|
|
131
|
+
tick(now?: number): Promise<{
|
|
132
|
+
readonly ran: readonly string[];
|
|
133
|
+
}>;
|
|
134
|
+
ensureTable(): Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
export interface CreateScheduledTaskRegistryOptions {
|
|
137
|
+
readonly db: DatabaseHandle;
|
|
138
|
+
readonly logger?: Logger;
|
|
139
|
+
readonly now?: () => number;
|
|
140
|
+
/** Runs kept per task before older ones are pruned. Defaults to 50. */
|
|
141
|
+
readonly keepRuns?: number;
|
|
142
|
+
readonly table?: string;
|
|
143
|
+
/** Defaults to `SCHEDULED_TASK_CLAIMS_TABLE`. */
|
|
144
|
+
readonly claimsTable?: string;
|
|
145
|
+
}
|
|
146
|
+
export declare function createScheduledTaskRegistry(options: CreateScheduledTaskRegistryOptions): ScheduledTaskRegistry;
|
|
147
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/scheduling/registry.ts"],"names":[],"mappings":"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"}
|