@karibsen/eponyme 0.7.0 → 0.8.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/README.md +59 -7
- package/dist/module.d.mts +15 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +5 -0
- package/dist/runtime/components/fields/FieldRenderer.vue +11 -0
- package/dist/runtime/components/fields/RichTextField.vue +37 -1
- package/dist/runtime/components/fields/TagsField.d.vue.ts +21 -0
- package/dist/runtime/components/fields/TagsField.vue +55 -0
- package/dist/runtime/components/fields/TagsField.vue.d.ts +21 -0
- package/dist/runtime/components/ui/EPAlertDialog.d.vue.ts +37 -0
- package/dist/runtime/components/ui/EPAlertDialog.vue +66 -0
- package/dist/runtime/components/ui/EPAlertDialog.vue.d.ts +37 -0
- package/dist/runtime/components/ui/EPDialog.d.vue.ts +1 -0
- package/dist/runtime/components/ui/EPDialog.vue +6 -2
- package/dist/runtime/components/ui/EPDialog.vue.d.ts +1 -0
- package/dist/runtime/components/ui/EPTagsInput.d.vue.ts +27 -0
- package/dist/runtime/components/ui/EPTagsInput.vue +101 -0
- package/dist/runtime/components/ui/EPTagsInput.vue.d.ts +27 -0
- package/dist/runtime/composables/useEponymeCollection.d.ts +13 -1
- package/dist/runtime/composables/useEponymeCollection.js +29 -4
- package/dist/runtime/fields/index.d.ts +2 -0
- package/dist/runtime/fields/index.js +2 -1
- package/dist/runtime/fields/tags.d.ts +6 -0
- package/dist/runtime/fields/tags.js +3 -0
- package/dist/runtime/pages/EponymeIndexPage.vue +0 -3
- package/dist/runtime/server/api/eponyme-collections/[path].get.js +40 -1
- package/dist/runtime/server/plugins/eponyme-sync.js +11 -1
- package/dist/runtime/server/services/eponyme-form-store.js +2 -2
- package/dist/runtime/server/services/eponyme-store.d.ts +278 -30
- package/dist/runtime/server/services/eponyme-store.js +373 -71
- package/dist/runtime/server/utils/eponyme-reindex.d.ts +13 -0
- package/dist/runtime/server/utils/eponyme-reindex.js +4 -0
- package/dist/runtime/types/eponyme.d.ts +53 -2
- package/dist/runtime/types/field.d.ts +35 -2
- package/dist/runtime/utils/eponyme-entry-index.d.ts +39 -0
- package/dist/runtime/utils/eponyme-entry-index.js +51 -0
- package/dist/runtime/utils/get-field-default-value.js +2 -0
- package/dist/runtime/utils/normalize-eponyme-values.d.ts +13 -0
- package/dist/runtime/utils/{normalize-eponyme-phones.js → normalize-eponyme-values.js} +4 -2
- package/dist/runtime/utils/normalize-tags.d.ts +10 -0
- package/dist/runtime/utils/normalize-tags.js +17 -0
- package/dist/runtime/utils/validate-eponyme-data.js +16 -0
- package/dist/runtime/utils/variables.d.ts +4 -0
- package/dist/runtime/utils/variables.js +8 -1
- package/package.json +3 -2
- package/dist/runtime/utils/normalize-eponyme-phones.d.ts +0 -9
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EponymeCollectionDefinitionBase, EponymeConfig, EponymeSchema } from '../../types/index.js';
|
|
2
2
|
import { type ValidationErrors } from '../../utils/validate-eponyme-data.js';
|
|
3
|
+
import { type EponymeIndexRow } from '../../utils/eponyme-entry-index.js';
|
|
3
4
|
export type EponymeAction = 'draft' | 'publish';
|
|
4
5
|
export type EponymeVersion = 'draft' | 'published';
|
|
5
6
|
/** Either the live draft/published content, or a numeric id from the version history. */
|
|
@@ -75,11 +76,31 @@ export interface EponymeImportRejection {
|
|
|
75
76
|
schemaMismatch?: string[];
|
|
76
77
|
}
|
|
77
78
|
export type EponymeSortDirection = 'asc' | 'desc';
|
|
79
|
+
/** Comparisons a filter may ask for. Only fields stored in a sortable text form accept one. */
|
|
80
|
+
export interface EponymeFilterRange {
|
|
81
|
+
gte?: string;
|
|
82
|
+
lte?: string;
|
|
83
|
+
gt?: string;
|
|
84
|
+
lt?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface EponymeFilterOperators extends EponymeFilterRange {
|
|
87
|
+
in?: string[];
|
|
88
|
+
/** Excluded values. Resolved by subtraction: the index only records what is there. */
|
|
89
|
+
not?: string[];
|
|
90
|
+
contains?: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* One condition of a `where`. A list means "any of these", so the values of one key are
|
|
94
|
+
* ORed together while the keys themselves are ANDed.
|
|
95
|
+
*/
|
|
96
|
+
export type EponymeFilterCondition = string | string[] | EponymeFilterOperators;
|
|
78
97
|
export interface EponymeCollectionQuery {
|
|
79
98
|
take?: number;
|
|
80
99
|
skip?: number;
|
|
81
100
|
orderBy?: string;
|
|
82
101
|
order?: EponymeSortDirection;
|
|
102
|
+
/** Keyed by field name. Only the keys `collectionFilterKeys` reports can be used. */
|
|
103
|
+
where?: Record<string, EponymeFilterCondition>;
|
|
83
104
|
}
|
|
84
105
|
export interface EponymeCollectionPage<Data extends Record<string, unknown> = Record<string, unknown>> {
|
|
85
106
|
entries: EponymeCollectionEntry<Data>[];
|
|
@@ -87,12 +108,65 @@ export interface EponymeCollectionPage<Data extends Record<string, unknown> = Re
|
|
|
87
108
|
total: number;
|
|
88
109
|
}
|
|
89
110
|
export declare const COLLECTION_METADATA_KEYS: readonly ["updatedAt", "publishedAt", "title", "slug"];
|
|
111
|
+
/**
|
|
112
|
+
* A content row. Everything but the name is optional because a query narrows what it reads —
|
|
113
|
+
* a public listing selects `published` and never `draft` — and a narrowed row has to satisfy
|
|
114
|
+
* this type as it is, without an overload per shape.
|
|
115
|
+
*/
|
|
90
116
|
export type PrismaEponymeRow = {
|
|
91
117
|
name: string;
|
|
92
|
-
|
|
118
|
+
draft?: unknown;
|
|
119
|
+
published?: unknown;
|
|
120
|
+
status?: string;
|
|
121
|
+
publishedAt?: Date | string | null;
|
|
93
122
|
updatedAt?: Date | string;
|
|
94
123
|
deletedAt?: Date | string | null;
|
|
95
124
|
};
|
|
125
|
+
export type EponymeRowWrite = {
|
|
126
|
+
draft: Record<string, unknown>;
|
|
127
|
+
published: Record<string, unknown>;
|
|
128
|
+
status: EponymeStatus;
|
|
129
|
+
publishedAt: Date | null;
|
|
130
|
+
};
|
|
131
|
+
export type PrismaEponymeSelect = {
|
|
132
|
+
name?: true;
|
|
133
|
+
draft?: true;
|
|
134
|
+
published?: true;
|
|
135
|
+
status?: true;
|
|
136
|
+
publishedAt?: true;
|
|
137
|
+
updatedAt?: true;
|
|
138
|
+
};
|
|
139
|
+
export type PrismaEponymeQuery = {
|
|
140
|
+
where: {
|
|
141
|
+
/** `in` is what a filtered listing uses: the index resolves the names first. */
|
|
142
|
+
name: {
|
|
143
|
+
startsWith: string;
|
|
144
|
+
} | {
|
|
145
|
+
in: string[];
|
|
146
|
+
};
|
|
147
|
+
deletedAt?: PrismaDeletedAtFilter;
|
|
148
|
+
publishedAt?: {
|
|
149
|
+
not: null;
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
orderBy?: PrismaEponymeOrderBy[];
|
|
153
|
+
take?: number;
|
|
154
|
+
skip?: number;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* `nulls` appears on `publishedAt` alone: Prisma refuses it on a column that cannot be null,
|
|
158
|
+
* and `updatedAt` never is. A test double cannot catch that — only the real client does.
|
|
159
|
+
*/
|
|
160
|
+
export type PrismaEponymeOrderBy = {
|
|
161
|
+
name: 'asc';
|
|
162
|
+
} | {
|
|
163
|
+
updatedAt: EponymeSortDirection;
|
|
164
|
+
} | {
|
|
165
|
+
publishedAt: {
|
|
166
|
+
sort: EponymeSortDirection;
|
|
167
|
+
nulls: 'last';
|
|
168
|
+
};
|
|
169
|
+
};
|
|
96
170
|
/** `null` keeps the live rows, `{ not: null }` the trashed ones. */
|
|
97
171
|
export type PrismaDeletedAtFilter = null | {
|
|
98
172
|
not: null;
|
|
@@ -110,27 +184,27 @@ export type PrismaEponymeVersionRow = {
|
|
|
110
184
|
username: string;
|
|
111
185
|
} | null;
|
|
112
186
|
};
|
|
113
|
-
|
|
187
|
+
/**
|
|
188
|
+
* The model delegates, which a transaction exposes just like the client does.
|
|
189
|
+
* They are named on their own because Prisma hands an interactive transaction a client
|
|
190
|
+
* stripped of `$transaction`, so the callback cannot be typed as the full client.
|
|
191
|
+
*/
|
|
192
|
+
export type PrismaEponymeDelegates = {
|
|
114
193
|
eponyme: {
|
|
115
194
|
upsert(args: {
|
|
116
195
|
where: {
|
|
117
196
|
name: string;
|
|
118
197
|
};
|
|
119
|
-
create: {
|
|
198
|
+
create: EponymeRowWrite & {
|
|
120
199
|
name: string;
|
|
121
|
-
data: Record<string, unknown>;
|
|
122
|
-
};
|
|
123
|
-
update: {
|
|
124
|
-
data?: Record<string, unknown>;
|
|
125
200
|
};
|
|
201
|
+
update: Partial<EponymeRowWrite>;
|
|
126
202
|
}): Promise<PrismaEponymeRow>;
|
|
127
203
|
update(args: {
|
|
128
204
|
where: {
|
|
129
205
|
name: string;
|
|
130
206
|
};
|
|
131
|
-
data:
|
|
132
|
-
data: Record<string, unknown>;
|
|
133
|
-
};
|
|
207
|
+
data: EponymeRowWrite;
|
|
134
208
|
}): Promise<PrismaEponymeRow>;
|
|
135
209
|
/** Used as a compare-and-swap: the `updatedAt` guard makes concurrent writes fail instead of overwriting. */
|
|
136
210
|
updateMany(args: {
|
|
@@ -139,17 +213,15 @@ export type PrismaEponymeClient = {
|
|
|
139
213
|
updatedAt?: Date | string;
|
|
140
214
|
deletedAt?: PrismaDeletedAtFilter;
|
|
141
215
|
};
|
|
142
|
-
data: {
|
|
143
|
-
data?: Record<string, unknown>;
|
|
216
|
+
data: Partial<EponymeRowWrite> & {
|
|
144
217
|
deletedAt?: Date | null;
|
|
145
218
|
};
|
|
146
219
|
}): Promise<{
|
|
147
220
|
count: number;
|
|
148
221
|
}>;
|
|
149
222
|
create(args: {
|
|
150
|
-
data: {
|
|
223
|
+
data: EponymeRowWrite & {
|
|
151
224
|
name: string;
|
|
152
|
-
data: Record<string, unknown>;
|
|
153
225
|
};
|
|
154
226
|
}): Promise<PrismaEponymeRow>;
|
|
155
227
|
findUnique(args: {
|
|
@@ -157,19 +229,14 @@ export type PrismaEponymeClient = {
|
|
|
157
229
|
name: string;
|
|
158
230
|
};
|
|
159
231
|
}): Promise<PrismaEponymeRow | null>;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
};
|
|
167
|
-
orderBy: Array<{
|
|
168
|
-
updatedAt: 'desc';
|
|
169
|
-
} | {
|
|
170
|
-
name: 'asc';
|
|
171
|
-
}>;
|
|
232
|
+
/**
|
|
233
|
+
* One signature rather than an overload per `select`: every column of
|
|
234
|
+
* `PrismaEponymeRow` but `name` is optional, so a narrowed row satisfies it as it is.
|
|
235
|
+
*/
|
|
236
|
+
findMany(args: PrismaEponymeQuery & {
|
|
237
|
+
select?: PrismaEponymeSelect;
|
|
172
238
|
}): Promise<PrismaEponymeRow[]>;
|
|
239
|
+
count(args: PrismaEponymeQuery): Promise<number>;
|
|
173
240
|
delete(args: {
|
|
174
241
|
where: {
|
|
175
242
|
name: string;
|
|
@@ -204,6 +271,94 @@ export type PrismaEponymeClient = {
|
|
|
204
271
|
};
|
|
205
272
|
}): Promise<PrismaEponymeVersionRow | null>;
|
|
206
273
|
};
|
|
274
|
+
eponymeEntryIndex: {
|
|
275
|
+
/** The rows of an entry are replaced as a whole, so a removed value cannot survive. */
|
|
276
|
+
deleteMany(args: {
|
|
277
|
+
where: {
|
|
278
|
+
entryName: string | {
|
|
279
|
+
startsWith: string;
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
}): Promise<{
|
|
283
|
+
count: number;
|
|
284
|
+
}>;
|
|
285
|
+
createMany(args: {
|
|
286
|
+
data: EponymeIndexRow[];
|
|
287
|
+
}): Promise<{
|
|
288
|
+
count: number;
|
|
289
|
+
}>;
|
|
290
|
+
findMany(args: {
|
|
291
|
+
where: {
|
|
292
|
+
entryName: {
|
|
293
|
+
startsWith: string;
|
|
294
|
+
};
|
|
295
|
+
version: 'draft' | 'published';
|
|
296
|
+
key: string;
|
|
297
|
+
value: PrismaStringFilter;
|
|
298
|
+
};
|
|
299
|
+
select: {
|
|
300
|
+
entryName: true;
|
|
301
|
+
};
|
|
302
|
+
}): Promise<Array<{
|
|
303
|
+
entryName: string;
|
|
304
|
+
}>>;
|
|
305
|
+
};
|
|
306
|
+
eponymeIndexState: {
|
|
307
|
+
findMany(): Promise<Array<{
|
|
308
|
+
name: string;
|
|
309
|
+
fingerprint: string;
|
|
310
|
+
}>>;
|
|
311
|
+
upsert(args: {
|
|
312
|
+
where: {
|
|
313
|
+
name: string;
|
|
314
|
+
};
|
|
315
|
+
create: {
|
|
316
|
+
name: string;
|
|
317
|
+
fingerprint: string;
|
|
318
|
+
};
|
|
319
|
+
update: {
|
|
320
|
+
fingerprint: string;
|
|
321
|
+
};
|
|
322
|
+
}): Promise<{
|
|
323
|
+
name: string;
|
|
324
|
+
fingerprint: string;
|
|
325
|
+
}>;
|
|
326
|
+
deleteMany(args: {
|
|
327
|
+
where: {
|
|
328
|
+
name: {
|
|
329
|
+
in: string[];
|
|
330
|
+
};
|
|
331
|
+
};
|
|
332
|
+
}): Promise<{
|
|
333
|
+
count: number;
|
|
334
|
+
}>;
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
/**
|
|
338
|
+
* What one condition asks the index for. Text order is the point: a range only makes sense
|
|
339
|
+
* because every indexed value is stored in a form whose alphabetical order is its natural
|
|
340
|
+
* one — see `buildEponymeIndexRows`.
|
|
341
|
+
*/
|
|
342
|
+
export type PrismaStringFilter = string | {
|
|
343
|
+
in?: string[];
|
|
344
|
+
/** Substring match. A leading wildcard cannot use the index's ordering, so this scans. */
|
|
345
|
+
contains?: string;
|
|
346
|
+
gte?: string;
|
|
347
|
+
lte?: string;
|
|
348
|
+
gt?: string;
|
|
349
|
+
lt?: string;
|
|
350
|
+
};
|
|
351
|
+
export type PrismaEponymeClient = PrismaEponymeDelegates & {
|
|
352
|
+
/**
|
|
353
|
+
* Prisma's interactive transaction. Writes that only make sense together — an entry and
|
|
354
|
+
* its history version, an import and every version it writes — run inside one, so a
|
|
355
|
+
* failure between the two rolls back instead of leaving the history disagreeing with
|
|
356
|
+
* the content it describes.
|
|
357
|
+
*/
|
|
358
|
+
$transaction<T>(fn: (tx: PrismaEponymeDelegates) => Promise<T>, options?: {
|
|
359
|
+
maxWait?: number;
|
|
360
|
+
timeout?: number;
|
|
361
|
+
}): Promise<T>;
|
|
207
362
|
};
|
|
208
363
|
export declare class EponymeService {
|
|
209
364
|
private readonly client;
|
|
@@ -228,6 +383,55 @@ export declare class EponymeService {
|
|
|
228
383
|
* collection that contains it, whose row set just changed.
|
|
229
384
|
*/
|
|
230
385
|
private invalidate;
|
|
386
|
+
/**
|
|
387
|
+
* Replaces an entry's filterable values, in the same transaction as the write that
|
|
388
|
+
* changed them.
|
|
389
|
+
*
|
|
390
|
+
* Deleting before inserting rather than diffing: an entry carries a handful of rows, the
|
|
391
|
+
* two statements are cheap, and a diff is one more place for the index to drift from the
|
|
392
|
+
* content it describes — a failure mode that returns wrong listings without erroring.
|
|
393
|
+
*/
|
|
394
|
+
private reindexEntry;
|
|
395
|
+
collectionFilterKeys(name: string): string[] | undefined;
|
|
396
|
+
/**
|
|
397
|
+
* One transaction per entry rather than one for the whole collection: a collection has no
|
|
398
|
+
* bound, and a single transaction over it would exceed Prisma's timeout on anything real.
|
|
399
|
+
* The unit that has to be atomic is the entry, and it is.
|
|
400
|
+
*/
|
|
401
|
+
private reindexName;
|
|
402
|
+
private indexedNames;
|
|
403
|
+
/**
|
|
404
|
+
* The unconditional rebuild, for a first backfill or a manual repair. It refreshes the
|
|
405
|
+
* recorded fingerprints too, so a repair does not leave the next boot with work to redo.
|
|
406
|
+
*/
|
|
407
|
+
reindexAll(): Promise<{
|
|
408
|
+
entries: number;
|
|
409
|
+
}>;
|
|
410
|
+
/**
|
|
411
|
+
* Rebuilds only what a configuration change invalidated, and nothing when nothing changed.
|
|
412
|
+
*
|
|
413
|
+
* This is what makes the index self-maintaining. Ordinary writes keep it current, but a
|
|
414
|
+
* newly filterable field leaves the entries already stored without any row for that key —
|
|
415
|
+
* and a filter on them then answers "none" rather than failing, which is the worst way for
|
|
416
|
+
* this to break.
|
|
417
|
+
*
|
|
418
|
+
* Unchanged configuration costs one read of a table with one row per collection.
|
|
419
|
+
*/
|
|
420
|
+
syncIndexState(): Promise<{
|
|
421
|
+
reindexed: string[];
|
|
422
|
+
}>;
|
|
423
|
+
private indexFingerprint;
|
|
424
|
+
private writeIndexState;
|
|
425
|
+
/**
|
|
426
|
+
* Runs writes that have to land together, then drops what they invalidated.
|
|
427
|
+
*
|
|
428
|
+
* The callback reports the entries it touched rather than invalidating them itself:
|
|
429
|
+
* inside the transaction the write has not landed yet, and a read racing an
|
|
430
|
+
* uncommitted change would re-cache the old row and hold it for the whole TTL. The
|
|
431
|
+
* drop is deliberate on a rollback too — losing a cache entry costs one query, while
|
|
432
|
+
* keeping a wrong one costs the TTL.
|
|
433
|
+
*/
|
|
434
|
+
private transaction;
|
|
231
435
|
getSchema(name: string): EponymeSchema | undefined;
|
|
232
436
|
getCollection(name: string): EponymeCollectionDefinitionBase | undefined;
|
|
233
437
|
private getCollectionEntry;
|
|
@@ -246,7 +450,14 @@ export declare class EponymeService {
|
|
|
246
450
|
/** Descends into the containers; a leaf is returned untouched for `reconcile` to judge. */
|
|
247
451
|
private reconcileField;
|
|
248
452
|
private createState;
|
|
453
|
+
/**
|
|
454
|
+
* Reads a state out of an envelope. Live content is in columns now, so this serves the two
|
|
455
|
+
* places an envelope still exists: a history row, which deliberately keeps the old shape so
|
|
456
|
+
* that versions written before this change stay restorable, and an import, which rebuilds
|
|
457
|
+
* one from the portable file.
|
|
458
|
+
*/
|
|
249
459
|
private normalizeState;
|
|
460
|
+
private rowToState;
|
|
250
461
|
/**
|
|
251
462
|
* A singleton row is created on first read, but only when it is genuinely missing.
|
|
252
463
|
* An `upsert` would send a write on every read instead, and each one costs a database
|
|
@@ -270,14 +481,33 @@ export declare class EponymeService {
|
|
|
270
481
|
* Writes a new state only if the row still carries the `updatedAt` we read.
|
|
271
482
|
* Returns false when a concurrent editor won the race, so the caller can report a conflict
|
|
272
483
|
* instead of silently discarding their changes.
|
|
484
|
+
*
|
|
485
|
+
* Dropping the cached row is left to `transaction`, which does it once the write has
|
|
486
|
+
* actually committed rather than while it is still in flight.
|
|
273
487
|
*/
|
|
274
488
|
private writeState;
|
|
275
489
|
/**
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
490
|
+
* Every live row of a collection, payload included. The reindex needs both versions of the
|
|
491
|
+
* content, so this is the one read that still selects everything; a listing goes through
|
|
492
|
+
* `collectionRows` with a narrower select.
|
|
279
493
|
*/
|
|
280
494
|
private liveCollectionRows;
|
|
495
|
+
/**
|
|
496
|
+
* The names a `where` keeps, resolved from the index table before a single row of content
|
|
497
|
+
* is read. This is the point of the index: a filtered listing loads and normalizes the
|
|
498
|
+
* entries it returns, not the whole collection.
|
|
499
|
+
*
|
|
500
|
+
* One query per key, intersected: the values of a key are ORed by the query itself, and
|
|
501
|
+
* the keys are ANDed by narrowing the set. An empty set short-circuits the whole listing.
|
|
502
|
+
*/
|
|
503
|
+
private resolveFilter;
|
|
504
|
+
private indexNames;
|
|
505
|
+
private collectionEntryNames;
|
|
506
|
+
/**
|
|
507
|
+
* The rows a filter selected. Never cached: the shared `rows:` key holds the whole
|
|
508
|
+
* collection, and one key per filter combination would evict it for no reuse.
|
|
509
|
+
*/
|
|
510
|
+
private filteredCollectionRows;
|
|
281
511
|
get(name: string, version?: EponymeVersionSelector): Promise<Record<string, unknown> | undefined>;
|
|
282
512
|
getResult(name: string, version?: EponymeVersionSelector): Promise<EponymeResult | undefined>;
|
|
283
513
|
/** Content as it was in a given version, for previewing without restoring it. */
|
|
@@ -286,6 +516,17 @@ export declare class EponymeService {
|
|
|
286
516
|
/** Metadata keys that can be sorted on, alongside every field of the collection. */
|
|
287
517
|
collectionSortKeys(name: string): string[] | undefined;
|
|
288
518
|
listCollection(name: string, version?: EponymeVersion, query?: EponymeCollectionQuery): Promise<EponymeCollectionPage | undefined>;
|
|
519
|
+
/**
|
|
520
|
+
* The unpaginated read, still cached: an unfiltered listing of one collection is what a
|
|
521
|
+
* page hits repeatedly, and the key carries the version so a draft view cannot answer a
|
|
522
|
+
* public one.
|
|
523
|
+
*/
|
|
524
|
+
private collectionRows;
|
|
525
|
+
/**
|
|
526
|
+
* `findMany` already carries every payload, so the state is built here rather than re-read
|
|
527
|
+
* one entry at a time: a listing costs one query, not N+1.
|
|
528
|
+
*/
|
|
529
|
+
private toCollectionEntries;
|
|
289
530
|
/**
|
|
290
531
|
* Builds the public URL list configured by `previewPaths`.
|
|
291
532
|
* Collections are resolved directly from their stored rows so this performs
|
|
@@ -302,12 +543,19 @@ export declare class EponymeService {
|
|
|
302
543
|
* upserted, everything else is left alone. Nothing is ever deleted.
|
|
303
544
|
*
|
|
304
545
|
* The schema check runs first and refuses the whole file, so an import can never
|
|
305
|
-
* land half of its entries into a configuration that no longer matches.
|
|
546
|
+
* land half of its entries into a configuration that no longer matches. The writes then
|
|
547
|
+
* run in one transaction, so a failure partway through leaves nothing behind either —
|
|
548
|
+
* an interrupted import can simply be replayed.
|
|
306
549
|
*/
|
|
307
550
|
importContent(file: unknown, options?: {
|
|
308
551
|
dryRun?: boolean;
|
|
309
552
|
actorId?: string;
|
|
310
553
|
}): Promise<EponymeImportResult | EponymeImportRejection>;
|
|
554
|
+
/**
|
|
555
|
+
* The body of an import, over whichever client it was handed: the live one for a dry
|
|
556
|
+
* run, a transaction for the real thing.
|
|
557
|
+
*/
|
|
558
|
+
private applyImport;
|
|
311
559
|
createCollectionEntry(name: string, payload: unknown, actorId?: string): Promise<(EponymeResult & {
|
|
312
560
|
slug: string;
|
|
313
561
|
errors?: never;
|