@murumets-ee/yhikas-sync 0.41.0 → 0.43.0
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/index.d.mts +121 -88
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{jobs-DrMLTUFm.mjs → jobs-CvSKn8C5.mjs} +2 -2
- package/dist/{jobs-DrMLTUFm.mjs.map → jobs-CvSKn8C5.mjs.map} +1 -1
- package/dist/plugin.mjs +1 -1
- package/dist/{sync-state-table-CM6eL5W9.mjs → sync-state-table-CNkHbvbV.mjs} +2 -2
- package/dist/{sync-state-table-CM6eL5W9.mjs.map → sync-state-table-CNkHbvbV.mjs.map} +1 -1
- package/dist/watchdog-Dy3ExN2p.mjs +2 -0
- package/dist/watchdog-Dy3ExN2p.mjs.map +1 -0
- package/package.json +7 -7
- package/dist/watchdog-BVf1F4sR.mjs +0 -2
- package/dist/watchdog-BVf1F4sR.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -175,16 +175,49 @@ declare function planDiff<T>(input: PlanDiffInput<T>): DiffPlan<T>;
|
|
|
175
175
|
* NOT `.strict()`: unknown keys are stripped rather than rejected, so adding a
|
|
176
176
|
* third language upstream degrades to "the sync ignores it" instead of "every
|
|
177
177
|
* run fails".
|
|
178
|
+
*
|
|
179
|
+
* 🔴 **Each locale key is nullable AND optional, and that is the load-bearing
|
|
180
|
+
* clause** (F058, cross-referenced to upstream F031). The column is declared
|
|
181
|
+
* `json(...).notNull()` — and **notNull covers the OBJECT, not its keys**. There
|
|
182
|
+
* is no CHECK constraint, and two of the four public columns
|
|
183
|
+
* (`room_type.name`, `legal_document.title`) have no upstream validation at all:
|
|
184
|
+
* the write is a raw `formData.get(…) as string`, which is `null` the moment a
|
|
185
|
+
* field is absent. So `{"et":"Tuba","en":null}` — and `{"et":"Tuba"}` — are rows
|
|
186
|
+
* yhikas-admin accepts today, through its ordinary admin UI.
|
|
187
|
+
*
|
|
188
|
+
* Requiring both keys would fail the ENTIRE response for one such row, so 32
|
|
189
|
+
* room types would stop syncing because one lacks an English name — every six
|
|
190
|
+
* hours, until somebody edited it upstream. That is exactly the blast-radius
|
|
191
|
+
* mistake `legalDocumentRowSchema.slug` documents below and deliberately
|
|
192
|
+
* avoided; a missing translation belongs at one row, and `projection.ts` is
|
|
193
|
+
* where it is decided (the locale is suppressed, or the row is skipped with a
|
|
194
|
+
* reason).
|
|
195
|
+
*
|
|
196
|
+
* What is NOT relaxed, on purpose:
|
|
197
|
+
*
|
|
198
|
+
* - **The object itself stays required.** A missing translation is DATA; a
|
|
199
|
+
* missing FIELD is a renamed column or a changed envelope. The consequence of
|
|
200
|
+
* tolerating one is caught either way — `assertSomethingSurvived` refuses a
|
|
201
|
+
* snapshot in which no row survived — but refusing here NAMES it
|
|
202
|
+
* (`title: Required`) instead of reporting 32 identical "no 'et' title
|
|
203
|
+
* upstream" skips and leaving the reader to infer the cause.
|
|
204
|
+
* - **A non-string value is still a shape violation.** `{"en":42}` would
|
|
205
|
+
* otherwise be written as a name.
|
|
206
|
+
*
|
|
207
|
+
* Note the asymmetry this leaves, deliberately: a RENAMED key (`et_EE`) is
|
|
208
|
+
* indistinguishable from two absent ones, because unknown keys are stripped by
|
|
209
|
+
* design so a third language degrades gracefully. That case falls through to
|
|
210
|
+
* `assertSomethingSurvived`, which is exactly what it is for.
|
|
178
211
|
*/
|
|
179
212
|
declare const multilingualTextSchema: z.ZodObject<{
|
|
180
|
-
et: z.ZodString
|
|
181
|
-
en: z.ZodString
|
|
213
|
+
et: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
214
|
+
en: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
182
215
|
}, "strip", z.ZodTypeAny, {
|
|
183
|
-
et
|
|
184
|
-
en
|
|
216
|
+
et?: string | null | undefined;
|
|
217
|
+
en?: string | null | undefined;
|
|
185
218
|
}, {
|
|
186
|
-
et
|
|
187
|
-
en
|
|
219
|
+
et?: string | null | undefined;
|
|
220
|
+
en?: string | null | undefined;
|
|
188
221
|
}>;
|
|
189
222
|
type MultilingualText = z.infer<typeof multilingualTextSchema>;
|
|
190
223
|
/**
|
|
@@ -199,14 +232,14 @@ type MultilingualText = z.infer<typeof multilingualTextSchema>;
|
|
|
199
232
|
declare const roomTypeRowSchema: z.ZodObject<{
|
|
200
233
|
code: z.ZodString;
|
|
201
234
|
name: z.ZodObject<{
|
|
202
|
-
et: z.ZodString
|
|
203
|
-
en: z.ZodString
|
|
235
|
+
et: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
236
|
+
en: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
204
237
|
}, "strip", z.ZodTypeAny, {
|
|
205
|
-
et
|
|
206
|
-
en
|
|
238
|
+
et?: string | null | undefined;
|
|
239
|
+
en?: string | null | undefined;
|
|
207
240
|
}, {
|
|
208
|
-
et
|
|
209
|
-
en
|
|
241
|
+
et?: string | null | undefined;
|
|
242
|
+
en?: string | null | undefined;
|
|
210
243
|
}>;
|
|
211
244
|
totalArea: z.ZodNullable<z.ZodString>;
|
|
212
245
|
livingArea: z.ZodNullable<z.ZodString>;
|
|
@@ -219,8 +252,8 @@ declare const roomTypeRowSchema: z.ZodObject<{
|
|
|
219
252
|
}, "strip", z.ZodTypeAny, {
|
|
220
253
|
code: string;
|
|
221
254
|
name: {
|
|
222
|
-
et
|
|
223
|
-
en
|
|
255
|
+
et?: string | null | undefined;
|
|
256
|
+
en?: string | null | undefined;
|
|
224
257
|
};
|
|
225
258
|
totalArea: string | null;
|
|
226
259
|
livingArea: string | null;
|
|
@@ -233,8 +266,8 @@ declare const roomTypeRowSchema: z.ZodObject<{
|
|
|
233
266
|
}, {
|
|
234
267
|
code: string;
|
|
235
268
|
name: {
|
|
236
|
-
et
|
|
237
|
-
en
|
|
269
|
+
et?: string | null | undefined;
|
|
270
|
+
en?: string | null | undefined;
|
|
238
271
|
};
|
|
239
272
|
totalArea: string | null;
|
|
240
273
|
livingArea: string | null;
|
|
@@ -258,14 +291,14 @@ type RoomTypeRow = z.infer<typeof roomTypeRowSchema>;
|
|
|
258
291
|
declare const legalDocumentRowSchema: z.ZodObject<{
|
|
259
292
|
type: z.ZodString;
|
|
260
293
|
title: z.ZodObject<{
|
|
261
|
-
et: z.ZodString
|
|
262
|
-
en: z.ZodString
|
|
294
|
+
et: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
295
|
+
en: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
263
296
|
}, "strip", z.ZodTypeAny, {
|
|
264
|
-
et
|
|
265
|
-
en
|
|
297
|
+
et?: string | null | undefined;
|
|
298
|
+
en?: string | null | undefined;
|
|
266
299
|
}, {
|
|
267
|
-
et
|
|
268
|
-
en
|
|
300
|
+
et?: string | null | undefined;
|
|
301
|
+
en?: string | null | undefined;
|
|
269
302
|
}>;
|
|
270
303
|
/**
|
|
271
304
|
* Accepted as free text HERE, and screened per-row in the projection.
|
|
@@ -286,8 +319,8 @@ declare const legalDocumentRowSchema: z.ZodObject<{
|
|
|
286
319
|
type: string;
|
|
287
320
|
slug: string;
|
|
288
321
|
title: {
|
|
289
|
-
et
|
|
290
|
-
en
|
|
322
|
+
et?: string | null | undefined;
|
|
323
|
+
en?: string | null | undefined;
|
|
291
324
|
};
|
|
292
325
|
order: number;
|
|
293
326
|
htmlContentEt: string;
|
|
@@ -296,8 +329,8 @@ declare const legalDocumentRowSchema: z.ZodObject<{
|
|
|
296
329
|
type: string;
|
|
297
330
|
slug: string;
|
|
298
331
|
title: {
|
|
299
|
-
et
|
|
300
|
-
en
|
|
332
|
+
et?: string | null | undefined;
|
|
333
|
+
en?: string | null | undefined;
|
|
301
334
|
};
|
|
302
335
|
order: number;
|
|
303
336
|
htmlContentEt: string;
|
|
@@ -319,14 +352,14 @@ declare const roomTypesResponseSchema: z.ZodObject<{
|
|
|
319
352
|
roomTypes: z.ZodArray<z.ZodObject<{
|
|
320
353
|
code: z.ZodString;
|
|
321
354
|
name: z.ZodObject<{
|
|
322
|
-
et: z.ZodString
|
|
323
|
-
en: z.ZodString
|
|
355
|
+
et: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
356
|
+
en: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
324
357
|
}, "strip", z.ZodTypeAny, {
|
|
325
|
-
et
|
|
326
|
-
en
|
|
358
|
+
et?: string | null | undefined;
|
|
359
|
+
en?: string | null | undefined;
|
|
327
360
|
}, {
|
|
328
|
-
et
|
|
329
|
-
en
|
|
361
|
+
et?: string | null | undefined;
|
|
362
|
+
en?: string | null | undefined;
|
|
330
363
|
}>;
|
|
331
364
|
totalArea: z.ZodNullable<z.ZodString>;
|
|
332
365
|
livingArea: z.ZodNullable<z.ZodString>;
|
|
@@ -339,8 +372,8 @@ declare const roomTypesResponseSchema: z.ZodObject<{
|
|
|
339
372
|
}, "strip", z.ZodTypeAny, {
|
|
340
373
|
code: string;
|
|
341
374
|
name: {
|
|
342
|
-
et
|
|
343
|
-
en
|
|
375
|
+
et?: string | null | undefined;
|
|
376
|
+
en?: string | null | undefined;
|
|
344
377
|
};
|
|
345
378
|
totalArea: string | null;
|
|
346
379
|
livingArea: string | null;
|
|
@@ -353,8 +386,8 @@ declare const roomTypesResponseSchema: z.ZodObject<{
|
|
|
353
386
|
}, {
|
|
354
387
|
code: string;
|
|
355
388
|
name: {
|
|
356
|
-
et
|
|
357
|
-
en
|
|
389
|
+
et?: string | null | undefined;
|
|
390
|
+
en?: string | null | undefined;
|
|
358
391
|
};
|
|
359
392
|
totalArea: string | null;
|
|
360
393
|
livingArea: string | null;
|
|
@@ -370,8 +403,8 @@ declare const roomTypesResponseSchema: z.ZodObject<{
|
|
|
370
403
|
roomTypes: {
|
|
371
404
|
code: string;
|
|
372
405
|
name: {
|
|
373
|
-
et
|
|
374
|
-
en
|
|
406
|
+
et?: string | null | undefined;
|
|
407
|
+
en?: string | null | undefined;
|
|
375
408
|
};
|
|
376
409
|
totalArea: string | null;
|
|
377
410
|
livingArea: string | null;
|
|
@@ -387,8 +420,8 @@ declare const roomTypesResponseSchema: z.ZodObject<{
|
|
|
387
420
|
roomTypes: {
|
|
388
421
|
code: string;
|
|
389
422
|
name: {
|
|
390
|
-
et
|
|
391
|
-
en
|
|
423
|
+
et?: string | null | undefined;
|
|
424
|
+
en?: string | null | undefined;
|
|
392
425
|
};
|
|
393
426
|
totalArea: string | null;
|
|
394
427
|
livingArea: string | null;
|
|
@@ -405,14 +438,14 @@ declare const legalDocumentsResponseSchema: z.ZodObject<{
|
|
|
405
438
|
documents: z.ZodArray<z.ZodObject<{
|
|
406
439
|
type: z.ZodString;
|
|
407
440
|
title: z.ZodObject<{
|
|
408
|
-
et: z.ZodString
|
|
409
|
-
en: z.ZodString
|
|
441
|
+
et: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
442
|
+
en: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
410
443
|
}, "strip", z.ZodTypeAny, {
|
|
411
|
-
et
|
|
412
|
-
en
|
|
444
|
+
et?: string | null | undefined;
|
|
445
|
+
en?: string | null | undefined;
|
|
413
446
|
}, {
|
|
414
|
-
et
|
|
415
|
-
en
|
|
447
|
+
et?: string | null | undefined;
|
|
448
|
+
en?: string | null | undefined;
|
|
416
449
|
}>;
|
|
417
450
|
/**
|
|
418
451
|
* Accepted as free text HERE, and screened per-row in the projection.
|
|
@@ -433,8 +466,8 @@ declare const legalDocumentsResponseSchema: z.ZodObject<{
|
|
|
433
466
|
type: string;
|
|
434
467
|
slug: string;
|
|
435
468
|
title: {
|
|
436
|
-
et
|
|
437
|
-
en
|
|
469
|
+
et?: string | null | undefined;
|
|
470
|
+
en?: string | null | undefined;
|
|
438
471
|
};
|
|
439
472
|
order: number;
|
|
440
473
|
htmlContentEt: string;
|
|
@@ -443,8 +476,8 @@ declare const legalDocumentsResponseSchema: z.ZodObject<{
|
|
|
443
476
|
type: string;
|
|
444
477
|
slug: string;
|
|
445
478
|
title: {
|
|
446
|
-
et
|
|
447
|
-
en
|
|
479
|
+
et?: string | null | undefined;
|
|
480
|
+
en?: string | null | undefined;
|
|
448
481
|
};
|
|
449
482
|
order: number;
|
|
450
483
|
htmlContentEt: string;
|
|
@@ -456,8 +489,8 @@ declare const legalDocumentsResponseSchema: z.ZodObject<{
|
|
|
456
489
|
type: string;
|
|
457
490
|
slug: string;
|
|
458
491
|
title: {
|
|
459
|
-
et
|
|
460
|
-
en
|
|
492
|
+
et?: string | null | undefined;
|
|
493
|
+
en?: string | null | undefined;
|
|
461
494
|
};
|
|
462
495
|
order: number;
|
|
463
496
|
htmlContentEt: string;
|
|
@@ -469,8 +502,8 @@ declare const legalDocumentsResponseSchema: z.ZodObject<{
|
|
|
469
502
|
type: string;
|
|
470
503
|
slug: string;
|
|
471
504
|
title: {
|
|
472
|
-
et
|
|
473
|
-
en
|
|
505
|
+
et?: string | null | undefined;
|
|
506
|
+
en?: string | null | undefined;
|
|
474
507
|
};
|
|
475
508
|
order: number;
|
|
476
509
|
htmlContentEt: string;
|
|
@@ -491,28 +524,28 @@ declare const legalDocumentsResponseSchema: z.ZodObject<{
|
|
|
491
524
|
*/
|
|
492
525
|
declare const siteNoticeRowSchema: z.ZodObject<{
|
|
493
526
|
text: z.ZodObject<{
|
|
494
|
-
et: z.ZodString
|
|
495
|
-
en: z.ZodString
|
|
527
|
+
et: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
528
|
+
en: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
496
529
|
}, "strip", z.ZodTypeAny, {
|
|
497
|
-
et
|
|
498
|
-
en
|
|
530
|
+
et?: string | null | undefined;
|
|
531
|
+
en?: string | null | undefined;
|
|
499
532
|
}, {
|
|
500
|
-
et
|
|
501
|
-
en
|
|
533
|
+
et?: string | null | undefined;
|
|
534
|
+
en?: string | null | undefined;
|
|
502
535
|
}>;
|
|
503
536
|
isActive: z.ZodBoolean;
|
|
504
537
|
order: z.ZodNumber;
|
|
505
538
|
}, "strip", z.ZodTypeAny, {
|
|
506
539
|
text: {
|
|
507
|
-
et
|
|
508
|
-
en
|
|
540
|
+
et?: string | null | undefined;
|
|
541
|
+
en?: string | null | undefined;
|
|
509
542
|
};
|
|
510
543
|
order: number;
|
|
511
544
|
isActive: boolean;
|
|
512
545
|
}, {
|
|
513
546
|
text: {
|
|
514
|
-
et
|
|
515
|
-
en
|
|
547
|
+
et?: string | null | undefined;
|
|
548
|
+
en?: string | null | undefined;
|
|
516
549
|
};
|
|
517
550
|
order: number;
|
|
518
551
|
isActive: boolean;
|
|
@@ -536,52 +569,52 @@ type SiteNoticeRow = z.infer<typeof siteNoticeRowSchema>;
|
|
|
536
569
|
declare const siteInfoResponseSchema: z.ZodObject<{
|
|
537
570
|
success: z.ZodLiteral<true>;
|
|
538
571
|
receptionHours: z.ZodObject<{
|
|
539
|
-
et: z.ZodString
|
|
540
|
-
en: z.ZodString
|
|
572
|
+
et: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
573
|
+
en: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
541
574
|
}, "strip", z.ZodTypeAny, {
|
|
542
|
-
et
|
|
543
|
-
en
|
|
575
|
+
et?: string | null | undefined;
|
|
576
|
+
en?: string | null | undefined;
|
|
544
577
|
}, {
|
|
545
|
-
et
|
|
546
|
-
en
|
|
578
|
+
et?: string | null | undefined;
|
|
579
|
+
en?: string | null | undefined;
|
|
547
580
|
}>;
|
|
548
581
|
notices: z.ZodArray<z.ZodObject<{
|
|
549
582
|
text: z.ZodObject<{
|
|
550
|
-
et: z.ZodString
|
|
551
|
-
en: z.ZodString
|
|
583
|
+
et: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
584
|
+
en: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
552
585
|
}, "strip", z.ZodTypeAny, {
|
|
553
|
-
et
|
|
554
|
-
en
|
|
586
|
+
et?: string | null | undefined;
|
|
587
|
+
en?: string | null | undefined;
|
|
555
588
|
}, {
|
|
556
|
-
et
|
|
557
|
-
en
|
|
589
|
+
et?: string | null | undefined;
|
|
590
|
+
en?: string | null | undefined;
|
|
558
591
|
}>;
|
|
559
592
|
isActive: z.ZodBoolean;
|
|
560
593
|
order: z.ZodNumber;
|
|
561
594
|
}, "strip", z.ZodTypeAny, {
|
|
562
595
|
text: {
|
|
563
|
-
et
|
|
564
|
-
en
|
|
596
|
+
et?: string | null | undefined;
|
|
597
|
+
en?: string | null | undefined;
|
|
565
598
|
};
|
|
566
599
|
order: number;
|
|
567
600
|
isActive: boolean;
|
|
568
601
|
}, {
|
|
569
602
|
text: {
|
|
570
|
-
et
|
|
571
|
-
en
|
|
603
|
+
et?: string | null | undefined;
|
|
604
|
+
en?: string | null | undefined;
|
|
572
605
|
};
|
|
573
606
|
order: number;
|
|
574
607
|
isActive: boolean;
|
|
575
608
|
}>, "many">;
|
|
576
609
|
}, "strip", z.ZodTypeAny, {
|
|
577
610
|
receptionHours: {
|
|
578
|
-
et
|
|
579
|
-
en
|
|
611
|
+
et?: string | null | undefined;
|
|
612
|
+
en?: string | null | undefined;
|
|
580
613
|
};
|
|
581
614
|
notices: {
|
|
582
615
|
text: {
|
|
583
|
-
et
|
|
584
|
-
en
|
|
616
|
+
et?: string | null | undefined;
|
|
617
|
+
en?: string | null | undefined;
|
|
585
618
|
};
|
|
586
619
|
order: number;
|
|
587
620
|
isActive: boolean;
|
|
@@ -589,13 +622,13 @@ declare const siteInfoResponseSchema: z.ZodObject<{
|
|
|
589
622
|
success: true;
|
|
590
623
|
}, {
|
|
591
624
|
receptionHours: {
|
|
592
|
-
et
|
|
593
|
-
en
|
|
625
|
+
et?: string | null | undefined;
|
|
626
|
+
en?: string | null | undefined;
|
|
594
627
|
};
|
|
595
628
|
notices: {
|
|
596
629
|
text: {
|
|
597
|
-
et
|
|
598
|
-
en
|
|
630
|
+
et?: string | null | undefined;
|
|
631
|
+
en?: string | null | undefined;
|
|
599
632
|
};
|
|
600
633
|
order: number;
|
|
601
634
|
isActive: boolean;
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/constants.ts","../src/diff.ts","../src/upstream/wire.ts","../src/projection.ts","../src/apply.ts","../src/entities/guard.ts","../src/entities/index.ts","../src/entities/legal-document.ts","../src/entities/room-type.ts","../src/entities/site-info.ts","../src/entity-client.ts","../src/sync-state-table.ts","../src/sync-state.ts","../src/upstream/client.ts","../src/run-sync.ts","../src/upstream/errors.ts","../src/watchdog.ts"],"mappings":";;;;;;;;;;;;AASA;;cAAa,uBAAA;;AAAuB;AAWpC;;;;AAAiC;AAOjC;;cAPa,oBAAA;;AAOa;AAC1B;;;cADa,aAAA;AAAA,cACA,iBAAA;AAgBb;;;;AAAgC;AAChC;;;;AAAqC;AACrC;;;;AAFA,cAAa,mBAAA;AAAA,cACA,wBAAA;AAAA,cACA,kBAAA;AAAA,cAEA,cAAA;AAAA,KAKD,YAAA,WAAuB,cAAc;AADvC;AACV;;;;AAAiD;AAYjD;;;;AAbU,cAaG,aAAA;AAOb;;;;AAAsB;AAAtB,cAAa,SAAA;AAAA,cACA,SAAA;;;AAAS;AAatB;;;;AAA8B;AAE9B;;;cAFa,iBAAA;AAEsB;AAAA,cAAtB,sBAAA;;ACxDe;AAG5B;;;cD4Fa,gBAAA;;;;;;;;cASA,eAAA;AAAA,cACA,gBAAA;;;AArHoB;AAAA,UCAhB,QAAA;EAAA,SACN,EAAA;;WAEA,GAAA;EAAA,SACA,MAAA;EDIE;;;;AAAiB;EAAjB,SCEF,UAAA;EDcqB;EAAA,SCZrB,WAAA,EAAa,IAAI;AAAA;AAAA,UAGX,QAAA;EDUJ;EAAA,SCRF,MAAA,WAAiB,CAAA;;WAEjB,MAAA;IAAA,SAA4B,KAAA,EAAO,QAAA;IAAA,SAAmB,GAAA,EAAK,CAAA;EAAA;;WAE3D,SAAA,WAAoB,QAAA;EDKA;EAAA,SCHpB,MAAA,WAAiB,QAAA;AAAA;AAAA,UAGX,WAAA;EDMP;EAAA,SCJC,OAAA;EDKC;EAAA,SCHD,iBAAA;;WAEA,kBAAA;AAAA;AAAA,UAGM,aAAA;EAAA,SACN,QAAA,EAAU,YAAA;EAAA,SACV,QAAA,WAAmB,CAAA;EAAA,SACnB,KAAA,WAAgB,QAAA;EAAA,SAChB,KAAA,GAAQ,GAAA,EAAK,CAAA;EAAA,SACb,MAAA,GAAS,GAAA,EAAK,CAAA;EAAA,SACd,KAAA,EAAO,WAAA;AAAA;;ADWI;AACtB;;;;AAAsB;iBCFN,UAAA,CAAW,KAAc;;;;ADeX;AAE9B;;;;AAAmC;AAuCnC;;;;AAA6B;AAS7B;iBChCgB,QAAA,GAAA,CAAY,KAAA,EAAO,aAAA,CAAc,CAAA,IAAK,QAAA,CAAS,CAAA;;;AD5E/D;;;;AAA8B;AAgB9B
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/constants.ts","../src/diff.ts","../src/upstream/wire.ts","../src/projection.ts","../src/apply.ts","../src/entities/guard.ts","../src/entities/index.ts","../src/entities/legal-document.ts","../src/entities/room-type.ts","../src/entities/site-info.ts","../src/entity-client.ts","../src/sync-state-table.ts","../src/sync-state.ts","../src/upstream/client.ts","../src/run-sync.ts","../src/upstream/errors.ts","../src/watchdog.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,D as t,E as n,O as r,S as i,T as a,_ as o,a as s,b as c,c as l,d as u,f as d,h as f,i as p,l as m,m as h,n as g,o as _,p as v,r as y,s as b,t as x,u as S,v as C,w,x as T,y as E}from"./watchdog-
|
|
1
|
+
import{C as e,D as t,E as n,O as r,S as i,T as a,_ as o,a as s,b as c,c as l,d as u,f as d,h as f,i as p,l as m,m as h,n as g,o as _,p as v,r as y,s as b,t as x,u as S,v as C,w,x as T,y as E}from"./watchdog-Dy3ExN2p.mjs";import{A as D,D as O,M as k,O as A,S as j,T as M,_ as N,a as P,c as F,d as I,f as L,g as R,h as z,i as B,j as V,k as H,l as U,m as W,n as G,o as K,p as q,r as J,s as Y,t as X,u as Z,v as Q,w as $,x as ee,y as te}from"./sync-state-table-CNkHbvbV.mjs";export{W as API_KEY_ENV_VAR,z as BASE_URL_ENV_VAR,R as DECLARED_CURRENCY,N as DECLARED_VAT_TREATMENT,Q as EN_LOCALE,te as ET_LOCALE,ee as LEGAL_DOCUMENTS_RESOURCE,j as MAX_SITE_NOTICES,$ as ROOM_TYPES_RESOURCE,M as SITE_INFO_KEY,O as SITE_INFO_RESOURCE,G as SYNCED_ENTITIES,A as SYNC_JOB_NAME,H as SYNC_RESOURCES,P as VAT_TREATMENTS,D as WATCHDOG_JOB_NAME,F as YHIKAS_LEGAL_DOCUMENT_ENTITY,K as YHIKAS_ROOM_TYPE_ENTITY,J as YHIKAS_SITE_INFO_ENTITY,V as YHIKAS_SYNC_ACTOR_ID,k as YHIKAS_SYNC_PLUGIN_NAME,n as YhikasApplyPartialError,U as YhikasLegalDocument,Y as YhikasRoomType,B as YhikasSiteInfo,L as YhikasSyncConfigError,w as YhikasSyncRefusedError,h as YhikasSyncRunError,x as YhikasSyncStaleError,Z as YhikasSyncedContentReadOnlyError,p as YhikasUpstreamClient,a as YhikasUpstreamError,t as applyPlan,g as assertNotStale,y as assessStaleness,d as createSyncStateStore,s as legalDocumentRowSchema,_ as legalDocumentsResponseSchema,I as machineWritten,b as multilingualTextSchema,i as planDiff,o as projectLegalDocuments,C as projectRoomTypes,E as projectSiteInfo,r as readLocalRows,q as resolveYhikasSyncConfig,l as roomTypeRowSchema,m as roomTypesResponseSchema,f as runYhikasSync,c as secondaryLocaleOf,S as siteInfoResponseSchema,u as siteNoticeRowSchema,e as stableHash,T as toSyncEntityClient,v as truncateError,X as yhikasSyncStateTable};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{b as e,f as t,g as n,h as r,i,n as a,x as o}from"./watchdog-
|
|
2
|
-
//# sourceMappingURL=jobs-
|
|
1
|
+
import{b as e,f as t,g as n,h as r,i,n as a,x as o}from"./watchdog-Dy3ExN2p.mjs";import{h as s,i as c,j as l,k as u,l as d,m as f,s as p,t as m}from"./sync-state-table-CNkHbvbV.mjs";import{elevateRequestContext as h,runWithContextAsync as g}from"@murumets-ee/core";var _=class extends Error{constructor(e){super(`yhikas-sync is enabled but ${e.join(` and `)} ${e.length===1?`is`:`are`} not set. Failing loudly rather than skipping quietly: an unconfigured sync is a broken sync, and a broken sync must be visibly broken. Set the variable, or pass \`enabled: false\` to yhikasSync() if this install has no yhikas-admin.`),this.name=`YhikasSyncNotConfiguredError`}};function v(){return h({user:{id:l,groups:[`admin`]}})}function y(e){return e.logger}async function b(t){let{resolveI18nConfig:r}=await import(`@murumets-ee/content`),{defaultLocale:i}=await r(t);if(!n.includes(i))throw new x(`The app's default locale is '${i}', but yhikas-admin carries content in 'et' and 'en' only. The sync has nothing to write to the base row, so it refuses rather than publishing one language under another's name.`);return{defaultLocale:i,secondaryLocale:e(i)}}var x=class extends Error{constructor(e){super(e),this.name=`YhikasSyncLocaleError`}};function S(e,t){let n=t[f],r=[];if(e.baseUrl||r.push(s),n||r.push(f),!e.baseUrl||!n)throw new _(r);return{baseUrl:e.baseUrl,apiKey:n}}async function C(e,n,a=process.env){let{baseUrl:s,apiKey:l}=S(n,a),{sanitizeHtml:u}=await import(`@murumets-ee/blocks`);return g(v(),async()=>{let{defaultLocale:a}=await b(e);return r({upstream:new i({baseUrl:s,apiKey:l,timeoutMs:n.requestTimeoutMs}),roomTypeClient:o(e.getClient(p),a),legalDocumentClient:o(e.getClient(d),a),siteInfoClient:o(e.getClient(c),a),state:t(m.makeClient(e.db.readWrite)),sanitizeHtml:u,logger:y(e),defaultLocale:a,floor:{maxRows:n.maxRowsPerResource,maxRetireFraction:n.maxRetireFraction,minRowsForFraction:n.minRowsForRetireFloor}})})}async function w(e,n,r=new Date){let i=t(m.makeClient(e.db.readWrite));await T(e,r);let o=a(await i.readAll(),r,n.staleAfterMs);return e.logger.debug({window:n.staleAfterMs,resources:o.map(e=>({resource:e.resource,lastSuccessAt:e.lastSuccessAt}))},`yhikas-sync: staleness check passed`),o}async function T(e,n=new Date){let r=t(m.makeClient(e.db.readWrite));for(let e of u)await r.ensure(e,n)}export{C as runSyncJob,w as runWatchdogJob};
|
|
2
|
+
//# sourceMappingURL=jobs-CvSKn8C5.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jobs-DrMLTUFm.mjs","names":[],"sources":["../src/jobs.ts"],"sourcesContent":["/**\n * The two job handlers, bound to a live `ToolkitApp`.\n *\n * This module is reached ONLY through a dynamic `import()` from the plugin's\n * `init` (see `plugin.ts`). It statically imports `@murumets-ee/core` and\n * `@murumets-ee/blocks`, either of which would be evaluated at\n * `lumi.config.ts`-load time under the CLI's jiti loader if the plugin entry\n * reached it statically — and `@murumets-ee/blocks`' root export evaluates\n * React's `createContext` at module scope.\n */\n\nimport { elevateRequestContext, runWithContextAsync, type ToolkitApp } from '@murumets-ee/core'\nimport type { SyncLogger } from './apply.js'\nimport type { ResolvedYhikasSyncConfig } from './config.js'\nimport {\n API_KEY_ENV_VAR,\n BASE_URL_ENV_VAR,\n EN_LOCALE,\n ET_LOCALE,\n LEGAL_DOCUMENTS_RESOURCE,\n ROOM_TYPES_RESOURCE,\n SYNC_RESOURCES,\n YHIKAS_SYNC_ACTOR_ID,\n} from './constants.js'\nimport { YhikasLegalDocument } from './entities/legal-document.js'\nimport { YhikasRoomType } from './entities/room-type.js'\nimport { YhikasSiteInfo } from './entities/site-info.js'\nimport { toSyncEntityClient } from './entity-client.js'\nimport { SUPPORTED_LOCALES, secondaryLocaleOf } from './projection.js'\nimport { runYhikasSync, type SyncRunSummary } from './run-sync.js'\nimport { createSyncStateStore } from './sync-state.js'\nimport { yhikasSyncStateTable } from './sync-state-table.js'\nimport { YhikasUpstreamClient } from './upstream/client.js'\nimport { assertNotStale, type ResourceStaleness } from './watchdog.js'\n\n/** Thrown when the sync is enabled but has no credential or no origin to talk to. */\nexport class YhikasSyncNotConfiguredError extends Error {\n constructor(missing: readonly string[]) {\n super(\n `yhikas-sync is enabled but ${missing.join(' and ')} ${missing.length === 1 ? 'is' : 'are'} ` +\n `not set. Failing loudly rather than skipping quietly: an unconfigured sync is a broken ` +\n `sync, and a broken sync must be visibly broken. Set the variable, or pass ` +\n `\\`enabled: false\\` to yhikasSync() if this install has no yhikas-admin.`,\n )\n this.name = 'YhikasSyncNotConfiguredError'\n }\n}\n\n/**\n * Every entity write runs as this identity.\n *\n * `elevateRequestContext` rather than `runAsCli`: both replace the permission\n * checker, but this one carries a NAMED actor, so `auditable()` records\n * `yhikas-sync` in `created_by`/`updated_by` instead of a generic `cli`. That\n * makes the sync's writes attributable — worth having precisely because the\n * upstream writes are not (F006) — and it is what the machine-written guard\n * recognises when it refuses every other writer.\n *\n * Built per run rather than at module scope: `elevateRequestContext` reads the\n * ambient context at CALL time, and a module-scope constant would bake in\n * whatever context happened to exist when the module first loaded.\n */\nfunction syncContext() {\n return elevateRequestContext({\n user: { id: YHIKAS_SYNC_ACTOR_ID, groups: ['admin'] },\n })\n}\n\n/** Narrow `app.logger` to the shape the sync uses, without importing a logger type. */\nfunction toSyncLogger(app: ToolkitApp): SyncLogger {\n return app.logger\n}\n\n/**\n * The app's REAL default locale, read from the content plugin rather than\n * configured here.\n *\n * A configured copy could disagree with the app's actual default, and the\n * failure would be silent in both directions: `updateForLocale` would take its\n * `isDefault` branch for what this package thought was the secondary locale\n * and overwrite the base row with the wrong language, while no translation was\n * ever written for the real secondary. `resolveI18nConfig` is the authoritative\n * answer — it merges the runtime `i18n` override over the shipped config — so\n * there is nothing to keep in sync.\n */\nasync function resolveLocales(\n app: ToolkitApp,\n): Promise<{ defaultLocale: string; secondaryLocale: string }> {\n const { resolveI18nConfig } = await import('@murumets-ee/content')\n const { defaultLocale } = await resolveI18nConfig(app)\n\n if (!SUPPORTED_LOCALES.includes(defaultLocale)) {\n throw new YhikasSyncLocaleError(\n `The app's default locale is '${defaultLocale}', but yhikas-admin carries content in ` +\n `'${ET_LOCALE}' and '${EN_LOCALE}' only. The sync has nothing to write to the base row, ` +\n `so it refuses rather than publishing one language under another's name.`,\n )\n }\n // `secondaryLocaleOf` asserts the same thing, so the two can never disagree.\n return { defaultLocale, secondaryLocale: secondaryLocaleOf(defaultLocale) }\n}\n\n/** Thrown when the app's locale configuration cannot carry the synced content. */\nexport class YhikasSyncLocaleError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'YhikasSyncLocaleError'\n }\n}\n\n/**\n * Resolve the bearer credential at RUN time, from the environment.\n *\n * Deliberately not part of the plugin's declared config: resolved config lands\n * in the framework's `PluginConfigRegistry`, a process-global any plugin can\n * read, and a secret does not belong there (mirroring `@murumets-ee/merit`'s\n * D003). Reading it here also means rotating the key needs a restart rather\n * than a rebuild.\n */\nfunction resolveCredentials(\n config: ResolvedYhikasSyncConfig,\n env: NodeJS.ProcessEnv,\n): { baseUrl: string; apiKey: string } {\n const apiKey = env[API_KEY_ENV_VAR]\n const missing: string[] = []\n if (!config.baseUrl) missing.push(BASE_URL_ENV_VAR)\n if (!apiKey) missing.push(API_KEY_ENV_VAR)\n if (!config.baseUrl || !apiKey) throw new YhikasSyncNotConfiguredError(missing)\n return { baseUrl: config.baseUrl, apiKey }\n}\n\n/** One full sync run. Throws on any resource failure, so the queue retries and alerts. */\nexport async function runSyncJob(\n app: ToolkitApp,\n config: ResolvedYhikasSyncConfig,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<SyncRunSummary> {\n const { baseUrl, apiKey } = resolveCredentials(config, env)\n const { sanitizeHtml } = await import('@murumets-ee/blocks')\n\n return runWithContextAsync(syncContext(), async () => {\n const { defaultLocale } = await resolveLocales(app)\n return runYhikasSync({\n upstream: new YhikasUpstreamClient({\n baseUrl,\n apiKey,\n timeoutMs: config.requestTimeoutMs,\n }),\n // The clients are built HERE, inside the job, not in the plugin's\n // `init`. That is load-bearing and easy to \"tidy\" into a bug:\n // `createAdminClient` reads the locale-status writer ONCE at\n // construction, and `@murumets-ee/content` installs that writer from its\n // own `init`. `Plugin.requires` guarantees content is CONFIGURED, not\n // that it initialised first — so a client constructed during init could\n // capture no writer, and `updateForLocale` would then silently assign\n // the requested status to the BASE row. Constructing at job-run time is\n // after every plugin's init, unconditionally.\n roomTypeClient: toSyncEntityClient(app.getClient(YhikasRoomType), defaultLocale),\n legalDocumentClient: toSyncEntityClient(app.getClient(YhikasLegalDocument), defaultLocale),\n siteInfoClient: toSyncEntityClient(app.getClient(YhikasSiteInfo), defaultLocale),\n state: createSyncStateStore(yhikasSyncStateTable.makeClient(app.db.readWrite)),\n sanitizeHtml,\n logger: toSyncLogger(app),\n defaultLocale,\n floor: {\n maxRows: config.maxRowsPerResource,\n maxRetireFraction: config.maxRetireFraction,\n minRowsForFraction: config.minRowsForRetireFloor,\n },\n })\n })\n}\n\n/**\n * The staleness check. Throws when any resource is past the window, which is\n * how it reaches the queue's dead-letter alerting — the detection is new, the\n * delivery is not.\n */\nexport async function runWatchdogJob(\n app: ToolkitApp,\n config: ResolvedYhikasSyncConfig,\n now: Date = new Date(),\n): Promise<ResourceStaleness[]> {\n const store = createSyncStateStore(yhikasSyncStateTable.makeClient(app.db.readWrite))\n // Seed before assessing, so a fresh install gets a `firstSeenAt` to be\n // measured from rather than reading as \"no tracking row at all\" — which is\n // correct but alarming on an app that simply has not reached its first sync\n // tick yet.\n //\n // The cost, stated: `assessStaleness`'s missing-row branch is therefore\n // unreachable from here, so a tracking row DELETED by hand while the sync is\n // broken resets the clock instead of alerting. That needs deliberate DB\n // surgery to reach, and the alternative — alerting on every fresh install's\n // first tick — trains people to ignore the one channel that has to stay\n // trustworthy.\n await ensureSyncState(app, now)\n const records = await store.readAll()\n const assessed = assertNotStale(records, now, config.staleAfterMs)\n app.logger.debug(\n {\n window: config.staleAfterMs,\n resources: assessed.map((entry) => ({\n resource: entry.resource,\n lastSuccessAt: entry.lastSuccessAt,\n })),\n },\n 'yhikas-sync: staleness check passed',\n )\n return assessed\n}\n\n/**\n * Seed a tracking row per resource, so a fresh install has a clock to be\n * measured against before its first sync tick.\n *\n * Called from the WATCHDOG, not from the plugin's `init`. Doing DB I/O during\n * `init` runs it in every process that builds a `ToolkitApp` — web included —\n * and would fail app boot outright on a database blip, or on any boot that\n * precedes `lumi migrate` creating the table, in exchange for two bookkeeping\n * rows.\n */\nexport async function ensureSyncState(app: ToolkitApp, now: Date = new Date()): Promise<void> {\n const store = createSyncStateStore(yhikasSyncStateTable.makeClient(app.db.readWrite))\n for (const resource of SYNC_RESOURCES) {\n await store.ensure(resource, now)\n }\n}\n\nexport { LEGAL_DOCUMENTS_RESOURCE, ROOM_TYPES_RESOURCE }\n"],"mappings":"yQAoCA,IAAa,EAAb,cAAkD,KAAM,CACtD,YAAY,EAA4B,CACtC,MACE,8BAA8B,EAAQ,KAAK,OAAO,EAAE,GAAG,EAAQ,SAAW,EAAI,KAAO,MAAM,0OAI7F,EACA,KAAK,KAAO,8BACd,CACF,EAgBA,SAAS,GAAc,CACrB,OAAO,EAAsB,CAC3B,KAAM,CAAE,GAAI,EAAsB,OAAQ,CAAC,OAAO,CAAE,CACtD,CAAC,CACH,CAGA,SAAS,EAAa,EAA6B,CACjD,OAAO,EAAI,MACb,CAcA,eAAe,EACb,EAC6D,CAC7D,GAAM,CAAE,qBAAsB,MAAM,OAAO,wBACrC,CAAE,iBAAkB,MAAM,EAAkB,CAAG,EAErD,GAAI,CAAC,EAAkB,SAAS,CAAa,EAC3C,MAAM,IAAI,EACR,gCAAgC,EAAc,kLAGhD,EAGF,MAAO,CAAE,gBAAe,gBAAiB,EAAkB,CAAa,CAAE,CAC5E,CAGA,IAAa,EAAb,cAA2C,KAAM,CAC/C,YAAY,EAAiB,CAC3B,MAAM,CAAO,EACb,KAAK,KAAO,uBACd,CACF,EAWA,SAAS,EACP,EACA,EACqC,CACrC,IAAM,EAAS,EAAI,GACb,EAAoB,CAAC,EAG3B,GAFK,EAAO,SAAS,EAAQ,KAAK,CAAgB,EAC7C,GAAQ,EAAQ,KAAK,CAAe,EACrC,CAAC,EAAO,SAAW,CAAC,EAAQ,MAAM,IAAI,EAA6B,CAAO,EAC9E,MAAO,CAAE,QAAS,EAAO,QAAS,QAAO,CAC3C,CAGA,eAAsB,EACpB,EACA,EACA,EAAyB,QAAQ,IACR,CACzB,GAAM,CAAE,UAAS,UAAW,EAAmB,EAAQ,CAAG,EACpD,CAAE,gBAAiB,MAAM,OAAO,uBAEtC,OAAO,EAAoB,EAAY,EAAG,SAAY,CACpD,GAAM,CAAE,iBAAkB,MAAM,EAAe,CAAG,EAClD,OAAO,EAAc,CACnB,SAAU,IAAI,EAAqB,CACjC,UACA,SACA,UAAW,EAAO,gBACpB,CAAC,EAUD,eAAgB,EAAmB,EAAI,UAAU,CAAc,EAAG,CAAa,EAC/E,oBAAqB,EAAmB,EAAI,UAAU,CAAmB,EAAG,CAAa,EACzF,eAAgB,EAAmB,EAAI,UAAU,CAAc,EAAG,CAAa,EAC/E,MAAO,EAAqB,EAAqB,WAAW,EAAI,GAAG,SAAS,CAAC,EAC7E,eACA,OAAQ,EAAa,CAAG,EACxB,gBACA,MAAO,CACL,QAAS,EAAO,mBAChB,kBAAmB,EAAO,kBAC1B,mBAAoB,EAAO,qBAC7B,CACF,CAAC,CACH,CAAC,CACH,CAOA,eAAsB,EACpB,EACA,EACA,EAAY,IAAI,KACc,CAC9B,IAAM,EAAQ,EAAqB,EAAqB,WAAW,EAAI,GAAG,SAAS,CAAC,EAYpF,MAAM,EAAgB,EAAK,CAAG,EAE9B,IAAM,EAAW,EAAe,MADV,EAAM,QAAQ,EACK,EAAK,EAAO,YAAY,EAWjE,OAVA,EAAI,OAAO,MACT,CACE,OAAQ,EAAO,aACf,UAAW,EAAS,IAAK,IAAW,CAClC,SAAU,EAAM,SAChB,cAAe,EAAM,aACvB,EAAE,CACJ,EACA,qCACF,EACO,CACT,CAYA,eAAsB,EAAgB,EAAiB,EAAY,IAAI,KAAuB,CAC5F,IAAM,EAAQ,EAAqB,EAAqB,WAAW,EAAI,GAAG,SAAS,CAAC,EACpF,IAAK,IAAM,KAAY,EACrB,MAAM,EAAM,OAAO,EAAU,CAAG,CAEpC"}
|
|
1
|
+
{"version":3,"file":"jobs-CvSKn8C5.mjs","names":[],"sources":["../src/jobs.ts"],"sourcesContent":["/**\n * The two job handlers, bound to a live `ToolkitApp`.\n *\n * This module is reached ONLY through a dynamic `import()` from the plugin's\n * `init` (see `plugin.ts`). It statically imports `@murumets-ee/core` and\n * `@murumets-ee/blocks`, either of which would be evaluated at\n * `lumi.config.ts`-load time under the CLI's jiti loader if the plugin entry\n * reached it statically — and `@murumets-ee/blocks`' root export evaluates\n * React's `createContext` at module scope.\n */\n\nimport { elevateRequestContext, runWithContextAsync, type ToolkitApp } from '@murumets-ee/core'\nimport type { SyncLogger } from './apply.js'\nimport type { ResolvedYhikasSyncConfig } from './config.js'\nimport {\n API_KEY_ENV_VAR,\n BASE_URL_ENV_VAR,\n EN_LOCALE,\n ET_LOCALE,\n LEGAL_DOCUMENTS_RESOURCE,\n ROOM_TYPES_RESOURCE,\n SYNC_RESOURCES,\n YHIKAS_SYNC_ACTOR_ID,\n} from './constants.js'\nimport { YhikasLegalDocument } from './entities/legal-document.js'\nimport { YhikasRoomType } from './entities/room-type.js'\nimport { YhikasSiteInfo } from './entities/site-info.js'\nimport { toSyncEntityClient } from './entity-client.js'\nimport { SUPPORTED_LOCALES, secondaryLocaleOf } from './projection.js'\nimport { runYhikasSync, type SyncRunSummary } from './run-sync.js'\nimport { createSyncStateStore } from './sync-state.js'\nimport { yhikasSyncStateTable } from './sync-state-table.js'\nimport { YhikasUpstreamClient } from './upstream/client.js'\nimport { assertNotStale, type ResourceStaleness } from './watchdog.js'\n\n/** Thrown when the sync is enabled but has no credential or no origin to talk to. */\nexport class YhikasSyncNotConfiguredError extends Error {\n constructor(missing: readonly string[]) {\n super(\n `yhikas-sync is enabled but ${missing.join(' and ')} ${missing.length === 1 ? 'is' : 'are'} ` +\n `not set. Failing loudly rather than skipping quietly: an unconfigured sync is a broken ` +\n `sync, and a broken sync must be visibly broken. Set the variable, or pass ` +\n `\\`enabled: false\\` to yhikasSync() if this install has no yhikas-admin.`,\n )\n this.name = 'YhikasSyncNotConfiguredError'\n }\n}\n\n/**\n * Every entity write runs as this identity.\n *\n * `elevateRequestContext` rather than `runAsCli`: both replace the permission\n * checker, but this one carries a NAMED actor, so `auditable()` records\n * `yhikas-sync` in `created_by`/`updated_by` instead of a generic `cli`. That\n * makes the sync's writes attributable — worth having precisely because the\n * upstream writes are not (F006) — and it is what the machine-written guard\n * recognises when it refuses every other writer.\n *\n * Built per run rather than at module scope: `elevateRequestContext` reads the\n * ambient context at CALL time, and a module-scope constant would bake in\n * whatever context happened to exist when the module first loaded.\n */\nfunction syncContext() {\n return elevateRequestContext({\n user: { id: YHIKAS_SYNC_ACTOR_ID, groups: ['admin'] },\n })\n}\n\n/** Narrow `app.logger` to the shape the sync uses, without importing a logger type. */\nfunction toSyncLogger(app: ToolkitApp): SyncLogger {\n return app.logger\n}\n\n/**\n * The app's REAL default locale, read from the content plugin rather than\n * configured here.\n *\n * A configured copy could disagree with the app's actual default, and the\n * failure would be silent in both directions: `updateForLocale` would take its\n * `isDefault` branch for what this package thought was the secondary locale\n * and overwrite the base row with the wrong language, while no translation was\n * ever written for the real secondary. `resolveI18nConfig` is the authoritative\n * answer — it merges the runtime `i18n` override over the shipped config — so\n * there is nothing to keep in sync.\n */\nasync function resolveLocales(\n app: ToolkitApp,\n): Promise<{ defaultLocale: string; secondaryLocale: string }> {\n const { resolveI18nConfig } = await import('@murumets-ee/content')\n const { defaultLocale } = await resolveI18nConfig(app)\n\n if (!SUPPORTED_LOCALES.includes(defaultLocale)) {\n throw new YhikasSyncLocaleError(\n `The app's default locale is '${defaultLocale}', but yhikas-admin carries content in ` +\n `'${ET_LOCALE}' and '${EN_LOCALE}' only. The sync has nothing to write to the base row, ` +\n `so it refuses rather than publishing one language under another's name.`,\n )\n }\n // `secondaryLocaleOf` asserts the same thing, so the two can never disagree.\n return { defaultLocale, secondaryLocale: secondaryLocaleOf(defaultLocale) }\n}\n\n/** Thrown when the app's locale configuration cannot carry the synced content. */\nexport class YhikasSyncLocaleError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'YhikasSyncLocaleError'\n }\n}\n\n/**\n * Resolve the bearer credential at RUN time, from the environment.\n *\n * Deliberately not part of the plugin's declared config: resolved config lands\n * in the framework's `PluginConfigRegistry`, a process-global any plugin can\n * read, and a secret does not belong there (mirroring `@murumets-ee/merit`'s\n * D003). Reading it here also means rotating the key needs a restart rather\n * than a rebuild.\n */\nfunction resolveCredentials(\n config: ResolvedYhikasSyncConfig,\n env: NodeJS.ProcessEnv,\n): { baseUrl: string; apiKey: string } {\n const apiKey = env[API_KEY_ENV_VAR]\n const missing: string[] = []\n if (!config.baseUrl) missing.push(BASE_URL_ENV_VAR)\n if (!apiKey) missing.push(API_KEY_ENV_VAR)\n if (!config.baseUrl || !apiKey) throw new YhikasSyncNotConfiguredError(missing)\n return { baseUrl: config.baseUrl, apiKey }\n}\n\n/** One full sync run. Throws on any resource failure, so the queue retries and alerts. */\nexport async function runSyncJob(\n app: ToolkitApp,\n config: ResolvedYhikasSyncConfig,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<SyncRunSummary> {\n const { baseUrl, apiKey } = resolveCredentials(config, env)\n const { sanitizeHtml } = await import('@murumets-ee/blocks')\n\n return runWithContextAsync(syncContext(), async () => {\n const { defaultLocale } = await resolveLocales(app)\n return runYhikasSync({\n upstream: new YhikasUpstreamClient({\n baseUrl,\n apiKey,\n timeoutMs: config.requestTimeoutMs,\n }),\n // The clients are built HERE, inside the job, not in the plugin's\n // `init`. That is load-bearing and easy to \"tidy\" into a bug:\n // `createAdminClient` reads the locale-status writer ONCE at\n // construction, and `@murumets-ee/content` installs that writer from its\n // own `init`. `Plugin.requires` guarantees content is CONFIGURED, not\n // that it initialised first — so a client constructed during init could\n // capture no writer, and `updateForLocale` would then silently assign\n // the requested status to the BASE row. Constructing at job-run time is\n // after every plugin's init, unconditionally.\n roomTypeClient: toSyncEntityClient(app.getClient(YhikasRoomType), defaultLocale),\n legalDocumentClient: toSyncEntityClient(app.getClient(YhikasLegalDocument), defaultLocale),\n siteInfoClient: toSyncEntityClient(app.getClient(YhikasSiteInfo), defaultLocale),\n state: createSyncStateStore(yhikasSyncStateTable.makeClient(app.db.readWrite)),\n sanitizeHtml,\n logger: toSyncLogger(app),\n defaultLocale,\n floor: {\n maxRows: config.maxRowsPerResource,\n maxRetireFraction: config.maxRetireFraction,\n minRowsForFraction: config.minRowsForRetireFloor,\n },\n })\n })\n}\n\n/**\n * The staleness check. Throws when any resource is past the window, which is\n * how it reaches the queue's dead-letter alerting — the detection is new, the\n * delivery is not.\n */\nexport async function runWatchdogJob(\n app: ToolkitApp,\n config: ResolvedYhikasSyncConfig,\n now: Date = new Date(),\n): Promise<ResourceStaleness[]> {\n const store = createSyncStateStore(yhikasSyncStateTable.makeClient(app.db.readWrite))\n // Seed before assessing, so a fresh install gets a `firstSeenAt` to be\n // measured from rather than reading as \"no tracking row at all\" — which is\n // correct but alarming on an app that simply has not reached its first sync\n // tick yet.\n //\n // The cost, stated: `assessStaleness`'s missing-row branch is therefore\n // unreachable from here, so a tracking row DELETED by hand while the sync is\n // broken resets the clock instead of alerting. That needs deliberate DB\n // surgery to reach, and the alternative — alerting on every fresh install's\n // first tick — trains people to ignore the one channel that has to stay\n // trustworthy.\n await ensureSyncState(app, now)\n const records = await store.readAll()\n const assessed = assertNotStale(records, now, config.staleAfterMs)\n app.logger.debug(\n {\n window: config.staleAfterMs,\n resources: assessed.map((entry) => ({\n resource: entry.resource,\n lastSuccessAt: entry.lastSuccessAt,\n })),\n },\n 'yhikas-sync: staleness check passed',\n )\n return assessed\n}\n\n/**\n * Seed a tracking row per resource, so a fresh install has a clock to be\n * measured against before its first sync tick.\n *\n * Called from the WATCHDOG, not from the plugin's `init`. Doing DB I/O during\n * `init` runs it in every process that builds a `ToolkitApp` — web included —\n * and would fail app boot outright on a database blip, or on any boot that\n * precedes `lumi migrate` creating the table, in exchange for two bookkeeping\n * rows.\n */\nexport async function ensureSyncState(app: ToolkitApp, now: Date = new Date()): Promise<void> {\n const store = createSyncStateStore(yhikasSyncStateTable.makeClient(app.db.readWrite))\n for (const resource of SYNC_RESOURCES) {\n await store.ensure(resource, now)\n }\n}\n\nexport { LEGAL_DOCUMENTS_RESOURCE, ROOM_TYPES_RESOURCE }\n"],"mappings":"yQAoCA,IAAa,EAAb,cAAkD,KAAM,CACtD,YAAY,EAA4B,CACtC,MACE,8BAA8B,EAAQ,KAAK,OAAO,EAAE,GAAG,EAAQ,SAAW,EAAI,KAAO,MAAM,0OAI7F,EACA,KAAK,KAAO,8BACd,CACF,EAgBA,SAAS,GAAc,CACrB,OAAO,EAAsB,CAC3B,KAAM,CAAE,GAAI,EAAsB,OAAQ,CAAC,OAAO,CAAE,CACtD,CAAC,CACH,CAGA,SAAS,EAAa,EAA6B,CACjD,OAAO,EAAI,MACb,CAcA,eAAe,EACb,EAC6D,CAC7D,GAAM,CAAE,qBAAsB,MAAM,OAAO,wBACrC,CAAE,iBAAkB,MAAM,EAAkB,CAAG,EAErD,GAAI,CAAC,EAAkB,SAAS,CAAa,EAC3C,MAAM,IAAI,EACR,gCAAgC,EAAc,kLAGhD,EAGF,MAAO,CAAE,gBAAe,gBAAiB,EAAkB,CAAa,CAAE,CAC5E,CAGA,IAAa,EAAb,cAA2C,KAAM,CAC/C,YAAY,EAAiB,CAC3B,MAAM,CAAO,EACb,KAAK,KAAO,uBACd,CACF,EAWA,SAAS,EACP,EACA,EACqC,CACrC,IAAM,EAAS,EAAI,GACb,EAAoB,CAAC,EAG3B,GAFK,EAAO,SAAS,EAAQ,KAAK,CAAgB,EAC7C,GAAQ,EAAQ,KAAK,CAAe,EACrC,CAAC,EAAO,SAAW,CAAC,EAAQ,MAAM,IAAI,EAA6B,CAAO,EAC9E,MAAO,CAAE,QAAS,EAAO,QAAS,QAAO,CAC3C,CAGA,eAAsB,EACpB,EACA,EACA,EAAyB,QAAQ,IACR,CACzB,GAAM,CAAE,UAAS,UAAW,EAAmB,EAAQ,CAAG,EACpD,CAAE,gBAAiB,MAAM,OAAO,uBAEtC,OAAO,EAAoB,EAAY,EAAG,SAAY,CACpD,GAAM,CAAE,iBAAkB,MAAM,EAAe,CAAG,EAClD,OAAO,EAAc,CACnB,SAAU,IAAI,EAAqB,CACjC,UACA,SACA,UAAW,EAAO,gBACpB,CAAC,EAUD,eAAgB,EAAmB,EAAI,UAAU,CAAc,EAAG,CAAa,EAC/E,oBAAqB,EAAmB,EAAI,UAAU,CAAmB,EAAG,CAAa,EACzF,eAAgB,EAAmB,EAAI,UAAU,CAAc,EAAG,CAAa,EAC/E,MAAO,EAAqB,EAAqB,WAAW,EAAI,GAAG,SAAS,CAAC,EAC7E,eACA,OAAQ,EAAa,CAAG,EACxB,gBACA,MAAO,CACL,QAAS,EAAO,mBAChB,kBAAmB,EAAO,kBAC1B,mBAAoB,EAAO,qBAC7B,CACF,CAAC,CACH,CAAC,CACH,CAOA,eAAsB,EACpB,EACA,EACA,EAAY,IAAI,KACc,CAC9B,IAAM,EAAQ,EAAqB,EAAqB,WAAW,EAAI,GAAG,SAAS,CAAC,EAYpF,MAAM,EAAgB,EAAK,CAAG,EAE9B,IAAM,EAAW,EAAe,MADV,EAAM,QAAQ,EACK,EAAK,EAAO,YAAY,EAWjE,OAVA,EAAI,OAAO,MACT,CACE,OAAQ,EAAO,aACf,UAAW,EAAS,IAAK,IAAW,CAClC,SAAU,EAAM,SAChB,cAAe,EAAM,aACvB,EAAE,CACJ,EACA,qCACF,EACO,CACT,CAYA,eAAsB,EAAgB,EAAiB,EAAY,IAAI,KAAuB,CAC5F,IAAM,EAAQ,EAAqB,EAAqB,WAAW,EAAI,GAAG,SAAS,CAAC,EACpF,IAAK,IAAM,KAAY,EACrB,MAAM,EAAM,OAAO,EAAU,CAAG,CAEpC"}
|
package/dist/plugin.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{A as e,M as t,O as n,n as r,p as i,t as a}from"./sync-state-table-
|
|
1
|
+
import{A as e,M as t,O as n,n as r,p as i,t as a}from"./sync-state-table-CNkHbvbV.mjs";import{definePlugin as o}from"@murumets-ee/core";function s(s){let c=i(s);return o({name:t,requires:[`@murumets-ee/content`,`@murumets-ee/queue`],server:{config:c,entities:[...r],tables:{yhikas_sync_state:a.table},init:async r=>{if(!c.enabled){r.logger.warn({plugin:t},`yhikas-sync is disabled by config — no scheduled pull, and no staleness alerting`);return}let{defineJob:i,registerJob:a}=await import(`@murumets-ee/queue/client`);a(i({name:n,description:`Pull room types and legal documents from yhikas-admin and apply a full-snapshot diff.`,schedule:c.schedule}),async()=>{let{runSyncJob:e}=await import(`./jobs-CvSKn8C5.mjs`);await e(r,c)}),a(i({name:e,description:`Alert when the newest successful yhikas-admin sync is older than the staleness window.`,schedule:c.watchdogSchedule}),async()=>{let{runWatchdogJob:e}=await import(`./jobs-CvSKn8C5.mjs`);await e(r,c)})}}})}export{s as yhikasSync};
|
|
2
2
|
//# sourceMappingURL=plugin.mjs.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{auditable as e,defineEntity as t,field as n,publishable as r}from"@murumets-ee/entity";import{column as i,defineTable as a}from"@murumets-ee/db";const o=`@murumets-ee/yhikas-sync`,s=`yhikas-sync`,c=`yhikas-sync:pull`,l=`yhikas-sync:staleness-watchdog`,u=`room_types`,d=`legal_documents`,f=`site_info`,p=[u,d,f],m=`default`,h=`et`,g=`en`,_=`EUR`,v=`net`,y=`/api/public/room-types`,b=`/api/public/legal-documents`,x=`/api/public/site-info`,S=25,C=`YHIKAS_SYNC_API_KEY`,w=`YHIKAS_ADMIN_BASE_URL`;var T=class extends Error{constructor(e){super(e),this.name=`YhikasSyncConfigError`}};function E(e,t){if(!Number.isSafeInteger(e)||e<=0)throw new T(`${t} must be a positive integer, got ${e}`);return e}function D(e,t){if(!Number.isFinite(e)||e<=0)throw new T(`${t} must be a finite positive number, got ${e}`);return e}function O(e={},t=process.env){let n=e.maxRetireFraction??.5;if(!Number.isFinite(n)||n<=0||n>1)throw new T(`maxRetireFraction must be in (0, 1], got ${n}. A value of 1 disables the fraction rule; the empty-snapshot rule still applies.`);let r=e.baseUrl??t.YHIKAS_ADMIN_BASE_URL;return Object.freeze({baseUrl:r&&r.length>0?r:void 0,schedule:e.schedule??`@every 6h`,watchdogSchedule:e.watchdogSchedule??`@every 1h`,staleAfterMs:D(e.staleAfterMs??864e5,`staleAfterMs`),requestTimeoutMs:D(e.requestTimeoutMs??15e3,`requestTimeoutMs`),maxRowsPerResource:E(e.maxRowsPerResource??500,`maxRowsPerResource`),maxRetireFraction:n,minRowsForRetireFloor:E(e.minRowsForRetireFloor??3,`minRowsForRetireFloor`),enabled:e.enabled??!0})}var k=class extends Error{constructor(e,t,n){super(`'${e}' is written only by the yhikas-admin sync. Refusing ${t} by '${n}': ${t===`translation write`||t===`locale publish change`?`a change here would NOT be reverted on the next sync run — it does not alter sourceHash, so the differ reports the row unchanged and the divergence from yhikas-admin stands permanently, with no alert and no staleness`:`an edit here would be silently reverted on the next sync run, which is worse than no editor at all`}. Change the value in yhikas-admin instead.`),this.name=`YhikasSyncedContentReadOnlyError`}};function A(e,t,n){let r=n?.user?.id;if(r!==`yhikas-sync`)throw new k(e,t,r??`<unattributed>`)}function j(e){return{name:`yhikas-sync:machine-written:${e}`,hooks:{beforeCreate:async(t,n)=>(A(e,`create`,n),t),beforeUpdate:async(t,n,r)=>(A(e,`update`,r),n),beforeDelete:async(t,n)=>{A(e,`delete`,n)}},assertBulkUpdate:()=>{throw new k(e,`bulk update`,`<bulk>`)},assertTranslationWrite:(t,n)=>{A(e,t.action===`locale-status`?`locale publish change`:`translation write`,n)}}}const M=`yhikas_legal_document`,N=t({name:M,scope:`global`,fields:{type:n.text({required:!0,unique:!0,indexed:!0,maxLength:190}),title:n.text({required:!0,translatable:!0}),sourceSlug:n.text({required:!0,indexed:!0,maxLength:190}),body:n.richtext({required:!0,translatable:!0}),order:n.number({integer:!0,required:!0,default:0}),hasEnglish:n.boolean({required:!0,default:!1}),sourceHash:n.text({maxLength:64})},behaviors:[e(),r(),j(M)],access:{view:`group.admin`,create:`group.admin`,update:`group.admin`,delete:`group.admin`},admin:{group:`yhikas`,label:`Legal documents`,labelSingular:`Legal document`,titleField:`type`,icon:`file-text`,description:`Synced from yhikas-admin every 6 hours. Read-only here — an edit would be reverted on the next run. Change the text in yhikas-admin.`,defaultSort:`order`,defaultSortDirection:`asc`,disableCreate:!0,hideFromDashboard:!0,hiddenFields:[`sourceHash`],hiddenColumns:[`sourceHash`]}}),P=`yhikas_room_type`,F=[`net`,`gross`],I=t({name:P,scope:`global`,fields:{code:n.text({required:!0,unique:!0,indexed:!0,maxLength:190}),name:n.text({required:!0,translatable:!0}),totalArea:n.text({maxLength:32}),livingArea:n.text({maxLength:32}),commonArea:n.text({maxLength:32}),capacity:n.number({integer:!0}),placesOccupied:n.number({integer:!0}),monthlyRent:n.text({maxLength:32}),discountedMonthlyRent:n.text({maxLength:32}),dailyRent:n.text({maxLength:32}),currency:n.text({required:!0,maxLength:3,default:`EUR`}),vatTreatment:n.select({options:F,required:!0,default:`net`}),hasEnglish:n.boolean({required:!0,default:!1}),sourceHash:n.text({maxLength:64})},behaviors:[e(),r(),j(P)],access:{view:`group.admin`,create:`group.admin`,update:`group.admin`,delete:`group.admin`},admin:{group:`yhikas`,label:`Room types`,labelSingular:`Room type`,titleField:`code`,icon:`bed-double`,description:`Synced from yhikas-admin every 6 hours. Read-only here — an edit would be reverted on the next run. Change prices in yhikas-admin.`,defaultSort:`code`,defaultSortDirection:`asc`,disableCreate:!0,hideFromDashboard:!0,hiddenFields:[`sourceHash`],hiddenColumns:[`sourceHash`]}}),L=`yhikas_site_info`,R=t({name:L,scope:`global`,fields:{key:n.text({required:!0,unique:!0,indexed:!0,maxLength:32}),receptionHours:n.text({translatable:!0,maxLength:500}),notices:n.json({translatable:!0}),hasEnglish:n.boolean({default:!1,required:!0}),sourceHash:n.text({maxLength:64})},behaviors:[e(),r(),j(L)],access:{view:`group.admin`,create:`group.admin`,update:`group.admin`,delete:`group.admin`},admin:{group:`yhikas`,label:`Site info`,titleField:`key`,disableCreate:!0,hideFromDashboard:!0,hiddenFields:[`sourceHash`],hiddenColumns:[`sourceHash`]}}),z=[I,N,R],B=a({name:`yhikas_sync_state`,columns:{resource:i.varchar({length:64,notNull:!0}),firstSeenAt:i.timestamp({notNull:!0,withTimezone:!0,defaultNow:!0,pgName:`first_seen_at`}),lastAttemptAt:i.timestamp({withTimezone:!0,pgName:`last_attempt_at`}),lastSuccessAt:i.timestamp({withTimezone:!0,pgName:`last_success_at`}),lastError:i.varchar({length:1024,pgName:`last_error`}),lastCreated:i.integer({notNull:!0,default:0,pgName:`last_created`}),lastUpdated:i.integer({notNull:!0,default:0,pgName:`last_updated`}),lastRetired:i.integer({notNull:!0,default:0,pgName:`last_retired`}),lastUnchanged:i.integer({notNull:!0,default:0,pgName:`last_unchanged`})},primaryKey:`resource`});export{l as A,y as C,f as D,x as E,o as M,c as O,S,m as T,v as _,F as a,b,M as c,j as d,T as f,_ as g,w as h,R as i,s as j,p as k,N as l,C as m,z as n,P as o,O as p,L as r,I as s,B as t,k as u,g as v,u as w,d as x,h as y};
|
|
2
|
-
//# sourceMappingURL=sync-state-table-
|
|
1
|
+
import{auditable as e,defineEntity as t,field as n,publishable as r}from"@murumets-ee/entity";import{column as i,defineTable as a}from"@murumets-ee/db";const o=`@murumets-ee/yhikas-sync`,s=`yhikas-sync`,c=`yhikas-sync:pull`,l=`yhikas-sync:staleness-watchdog`,u=`room_types`,d=`legal_documents`,f=`site_info`,p=[u,d,f],m=`default`,h=`et`,g=`en`,_=`EUR`,v=`net`,y=`/api/public/room-types`,b=`/api/public/legal-documents`,x=`/api/public/site-info`,S=25,C=`YHIKAS_SYNC_API_KEY`,w=`YHIKAS_ADMIN_BASE_URL`;var T=class extends Error{constructor(e){super(e),this.name=`YhikasSyncConfigError`}};function E(e,t){if(!Number.isSafeInteger(e)||e<=0)throw new T(`${t} must be a positive integer, got ${e}`);return e}function D(e,t){if(!Number.isFinite(e)||e<=0)throw new T(`${t} must be a finite positive number, got ${e}`);return e}function O(e={},t=process.env){let n=e.maxRetireFraction??.5;if(!Number.isFinite(n)||n<=0||n>1)throw new T(`maxRetireFraction must be in (0, 1], got ${n}. A value of 1 disables the fraction rule; the empty-snapshot rule still applies.`);let r=e.baseUrl??t.YHIKAS_ADMIN_BASE_URL;return Object.freeze({baseUrl:r&&r.length>0?r:void 0,schedule:e.schedule??`@every 6h`,watchdogSchedule:e.watchdogSchedule??`@every 1h`,staleAfterMs:D(e.staleAfterMs??864e5,`staleAfterMs`),requestTimeoutMs:D(e.requestTimeoutMs??15e3,`requestTimeoutMs`),maxRowsPerResource:E(e.maxRowsPerResource??500,`maxRowsPerResource`),maxRetireFraction:n,minRowsForRetireFloor:E(e.minRowsForRetireFloor??3,`minRowsForRetireFloor`),enabled:e.enabled??!0})}var k=class extends Error{constructor(e,t,n){super(`'${e}' is written only by the yhikas-admin sync. Refusing ${t} by '${n}': ${t===`translation write`||t===`locale publish change`?`a change here would NOT be reverted on the next sync run — it does not alter sourceHash, so the differ reports the row unchanged and the divergence from yhikas-admin stands permanently, with no alert and no staleness`:`an edit here would be silently reverted on the next sync run, which is worse than no editor at all`}. Change the value in yhikas-admin instead.`),this.name=`YhikasSyncedContentReadOnlyError`}};function A(e,t,n){let r=n?.user?.id;if(r!==`yhikas-sync`)throw new k(e,t,r??`<unattributed>`)}function j(e){return{name:`yhikas-sync:machine-written:${e}`,hooks:{beforeCreate:async(t,n)=>(A(e,`create`,n),t),beforeUpdate:async(t,n,r)=>(A(e,`update`,r),n),beforeDelete:async(t,n)=>{A(e,`delete`,n)}},assertBulkUpdate:()=>{throw new k(e,`bulk update`,`<bulk>`)},assertTranslationWrite:(t,n)=>{A(e,t.action===`locale-status`?`locale publish change`:`translation write`,n)}}}const M=`yhikas_legal_document`,N=t({name:M,scope:`global`,fields:{type:n.text({required:!0,unique:!0,indexed:!0,maxLength:190}),title:n.text({required:!0,translatable:!0}),sourceSlug:n.text({required:!0,indexed:!0,maxLength:190}),body:n.richtext({required:!0,translatable:!0}),order:n.number({integer:!0,required:!0,default:0}),hasEnglish:n.boolean({required:!0,default:!1}),sourceHash:n.text({maxLength:64})},behaviors:[e(),r(),j(M)],access:{view:`group.admin`,create:`group.admin`,update:`group.admin`,delete:`group.admin`},admin:{group:`yhikas`,label:`Legal documents`,labelSingular:`Legal document`,titleField:`type`,icon:`file-text`,description:`Synced from yhikas-admin every 6 hours. Read-only here — an edit would be reverted on the next run. Change the text in yhikas-admin.`,defaultSort:`order`,defaultSortDirection:`asc`,disableCreate:!0,hideFromDashboard:!0,hiddenFields:[`sourceHash`],hiddenColumns:[`sourceHash`]}}),P=`yhikas_room_type`,F=[`net`,`gross`],I=t({name:P,scope:`global`,fields:{code:n.text({required:!0,unique:!0,indexed:!0,maxLength:190}),name:n.text({required:!0,translatable:!0}),totalArea:n.text({maxLength:32}),livingArea:n.text({maxLength:32}),commonArea:n.text({maxLength:32}),capacity:n.number({integer:!0}),placesOccupied:n.number({integer:!0}),monthlyRent:n.text({maxLength:32}),discountedMonthlyRent:n.text({maxLength:32}),dailyRent:n.text({maxLength:32}),currency:n.text({required:!0,maxLength:3,default:`EUR`}),vatTreatment:n.select({options:F,required:!0,default:`net`}),hasEnglish:n.boolean({required:!0,default:!1}),sourceHash:n.text({maxLength:64})},behaviors:[e(),r(),j(P)],access:{view:`group.admin`,create:`group.admin`,update:`group.admin`,delete:`group.admin`},admin:{group:`yhikas`,label:`Room types`,labelSingular:`Room type`,titleField:`code`,icon:`bed-double`,description:`Synced from yhikas-admin every 6 hours. Read-only here — an edit would be reverted on the next run. Change prices in yhikas-admin.`,defaultSort:`code`,defaultSortDirection:`asc`,disableCreate:!0,hideFromDashboard:!0,hiddenFields:[`sourceHash`],hiddenColumns:[`sourceHash`]}}),L=`yhikas_site_info`,R=t({name:L,kind:`singleton`,scope:`global`,fields:{key:n.text({required:!0,unique:!0,indexed:!0,maxLength:32}),receptionHours:n.text({translatable:!0,maxLength:500}),notices:n.json({translatable:!0}),hasEnglish:n.boolean({default:!1,required:!0}),sourceHash:n.text({maxLength:64})},behaviors:[e(),r(),j(L)],access:{view:`group.admin`,create:`group.admin`,update:`group.admin`,delete:`group.admin`},admin:{group:`yhikas`,label:`Site info`,titleField:`key`,disableCreate:!0,hideFromDashboard:!0,hiddenFields:[`sourceHash`],hiddenColumns:[`sourceHash`]}}),z=[I,N,R],B=a({name:`yhikas_sync_state`,columns:{resource:i.varchar({length:64,notNull:!0}),firstSeenAt:i.timestamp({notNull:!0,withTimezone:!0,defaultNow:!0,pgName:`first_seen_at`}),lastAttemptAt:i.timestamp({withTimezone:!0,pgName:`last_attempt_at`}),lastSuccessAt:i.timestamp({withTimezone:!0,pgName:`last_success_at`}),lastError:i.varchar({length:1024,pgName:`last_error`}),lastCreated:i.integer({notNull:!0,default:0,pgName:`last_created`}),lastUpdated:i.integer({notNull:!0,default:0,pgName:`last_updated`}),lastRetired:i.integer({notNull:!0,default:0,pgName:`last_retired`}),lastUnchanged:i.integer({notNull:!0,default:0,pgName:`last_unchanged`})},primaryKey:`resource`});export{l as A,y as C,f as D,x as E,o as M,c as O,S,m as T,v as _,F as a,b,M as c,j as d,T as f,_ as g,w as h,R as i,s as j,p as k,N as l,C as m,z as n,P as o,O as p,L as r,I as s,B as t,k as u,g as v,u as w,d as x,h as y};
|
|
2
|
+
//# sourceMappingURL=sync-state-table-CNkHbvbV.mjs.map
|