@beechcms/core 0.9.4 → 0.9.6
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/content/content-lock.repository.d.ts +63 -0
- package/dist/content/content-lock.repository.d.ts.map +1 -0
- package/dist/content/content-lock.repository.js +15 -0
- package/dist/content/content.repository.d.ts +22 -22
- package/dist/content/content.repository.d.ts.map +1 -1
- package/dist/content/retention.d.ts +13 -0
- package/dist/content/retention.d.ts.map +1 -0
- package/dist/content/retention.js +20 -0
- package/dist/content/slug-utils.d.ts +7 -0
- package/dist/content/slug-utils.d.ts.map +1 -1
- package/dist/content/slug-utils.js +12 -0
- package/dist/dashboard-layout/content-view.d.ts +4 -4
- package/dist/dashboard-layout/dashboard-layout.d.ts +2 -2
- package/dist/dashboard-layout/dashboard-layout.d.ts.map +1 -1
- package/dist/dashboard-layout/dashboard-layout.js +3 -3
- package/dist/dashboard-layout/kanban/kanban-position.repository.d.ts +19 -0
- package/dist/dashboard-layout/kanban/kanban-position.repository.d.ts.map +1 -0
- package/dist/dashboard-layout/kanban/kanban-position.repository.js +3 -0
- package/dist/dashboard-layout/seed-layout.d.ts.map +1 -1
- package/dist/dashboard-layout/seed-layout.js +17 -1
- package/dist/engine/ddl/ddl.d.ts +4 -6
- package/dist/engine/ddl/ddl.d.ts.map +1 -1
- package/dist/engine/ddl/ddl.js +13 -27
- package/dist/engine/ddl/seed-ddl-destructive.d.ts +40 -0
- package/dist/engine/ddl/seed-ddl-destructive.d.ts.map +1 -0
- package/dist/engine/ddl/seed-ddl-destructive.js +149 -0
- package/dist/engine/ddl/seed-ddl.d.ts.map +1 -1
- package/dist/engine/ddl/seed-ddl.js +10 -2
- package/dist/engine/ddl.d.ts +216 -0
- package/dist/engine/ddl.d.ts.map +1 -0
- package/dist/engine/ddl.js +574 -0
- package/dist/engine/define-seed.d.ts +3 -0
- package/dist/engine/define-seed.d.ts.map +1 -0
- package/dist/engine/define-seed.js +5 -0
- package/dist/engine/introspection.d.ts +101 -0
- package/dist/engine/introspection.d.ts.map +1 -0
- package/dist/engine/introspection.js +127 -0
- package/dist/engine/policies.d.ts +58 -0
- package/dist/engine/policies.d.ts.map +1 -0
- package/dist/engine/policies.js +168 -0
- package/dist/engine/privacy.service.d.ts +65 -0
- package/dist/engine/privacy.service.d.ts.map +1 -0
- package/dist/engine/privacy.service.js +114 -0
- package/dist/engine/query/active-clause.d.ts +2 -3
- package/dist/engine/query/active-clause.d.ts.map +1 -1
- package/dist/engine/query/active-clause.js +3 -4
- package/dist/engine/query/query.js +8 -8
- package/dist/engine/query/relations.d.ts +15 -0
- package/dist/engine/query/relations.d.ts.map +1 -1
- package/dist/engine/query.d.ts +23 -0
- package/dist/engine/query.d.ts.map +1 -0
- package/dist/engine/query.js +248 -0
- package/dist/engine/relations.d.ts +28 -0
- package/dist/engine/relations.d.ts.map +1 -0
- package/dist/engine/relations.js +25 -0
- package/dist/engine/schema-fingerprint.d.ts +71 -0
- package/dist/engine/schema-fingerprint.d.ts.map +1 -0
- package/dist/engine/schema-fingerprint.js +95 -0
- package/dist/engine/schema-mutator.d.ts +26 -0
- package/dist/engine/schema-mutator.d.ts.map +1 -0
- package/dist/engine/schema-mutator.js +3 -0
- package/dist/engine/seed-ddl-destructive.d.ts +40 -0
- package/dist/engine/seed-ddl-destructive.d.ts.map +1 -0
- package/dist/engine/seed-ddl-destructive.js +149 -0
- package/dist/engine/seed-ddl.d.ts +43 -0
- package/dist/engine/seed-ddl.d.ts.map +1 -0
- package/dist/engine/seed-ddl.js +115 -0
- package/dist/engine/seed-registry.d.ts +71 -0
- package/dist/engine/seed-registry.d.ts.map +1 -0
- package/dist/engine/seed-registry.js +167 -0
- package/dist/engine/seed-types-generator.d.ts +25 -0
- package/dist/engine/seed-types-generator.d.ts.map +1 -0
- package/dist/engine/seed-types-generator.js +117 -0
- package/dist/engine/seed-validation.d.ts +30 -0
- package/dist/engine/seed-validation.d.ts.map +1 -0
- package/dist/engine/seed-validation.js +329 -0
- package/dist/engine/seeds/seed-definition-diff.d.ts +1 -1
- package/dist/engine/seeds/seed-definition-diff.d.ts.map +1 -1
- package/dist/engine/seeds/seed-definition-diff.js +2 -2
- package/dist/engine/seeds/seed-validation.d.ts.map +1 -1
- package/dist/engine/seeds/seed-validation.js +3 -12
- package/dist/engine/seeds.d.ts +20 -0
- package/dist/engine/seeds.d.ts.map +1 -0
- package/dist/engine/seeds.js +21 -0
- package/dist/engine/serialize.d.ts +20 -0
- package/dist/engine/serialize.d.ts.map +1 -0
- package/dist/engine/serialize.js +160 -0
- package/dist/engine/types.d.ts +7 -7
- package/dist/engine/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/notifications/notification-service.d.ts +2 -2
- package/dist/notifications/notification.repository.d.ts +6 -3
- package/dist/notifications/notification.repository.d.ts.map +1 -1
- package/dist/security/time-trap.d.ts +3 -2
- package/dist/security/time-trap.d.ts.map +1 -1
- package/dist/security/time-trap.js +5 -4
- package/dist/seed-types-generator.d.ts +10 -0
- package/dist/seed-types-generator.d.ts.map +1 -0
- package/dist/seed-types-generator.js +86 -0
- package/dist/settings/site-settings.repository.d.ts +2 -0
- package/dist/settings/site-settings.repository.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Lock lifetime in seconds. Brief §2: strictly enforced, not configurable per seed. */
|
|
2
|
+
export declare const LOCK_TTL_SECONDS = 180;
|
|
3
|
+
/** Identity persisted alongside a lock so a blocked caller can be told who holds it. */
|
|
4
|
+
export interface LockHolder {
|
|
5
|
+
userId: string;
|
|
6
|
+
/** Display name, when the account has one. Never used for authorization. */
|
|
7
|
+
name: string | null;
|
|
8
|
+
email: string | null;
|
|
9
|
+
}
|
|
10
|
+
/** A lock row as the API exposes it. All timestamps are Unix epoch SECONDS. */
|
|
11
|
+
export interface ContentLock {
|
|
12
|
+
seedSlug: string;
|
|
13
|
+
entryId: string;
|
|
14
|
+
holder: LockHolder;
|
|
15
|
+
acquiredAt: number;
|
|
16
|
+
expiresAt: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Outcome of an acquisition attempt. `ok: false` always carries the live lock that
|
|
20
|
+
* blocked it, which is what the 423 response body is built from.
|
|
21
|
+
*/
|
|
22
|
+
export type LockAcquisition = {
|
|
23
|
+
ok: true;
|
|
24
|
+
lock: ContentLock;
|
|
25
|
+
} | {
|
|
26
|
+
ok: false;
|
|
27
|
+
heldBy: ContentLock;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Storage port for pessimistic entry locks.
|
|
31
|
+
*
|
|
32
|
+
* Deliberately NOT part of `ContentRepository`: that interface is referenced by
|
|
33
|
+
* `HookContext` and `JobContext`, so widening it would break every user-authored
|
|
34
|
+
* hook and background job handler.
|
|
35
|
+
*
|
|
36
|
+
* Every `nowSeconds` argument is the caller's clock reading, never the database's:
|
|
37
|
+
* expiry must be deterministic under the test harness's `FixedClock`.
|
|
38
|
+
*/
|
|
39
|
+
export interface IContentLockRepository {
|
|
40
|
+
/**
|
|
41
|
+
* Takes the lock, or extends it when the caller already holds it. An expired row is
|
|
42
|
+
* overwritten in the same statement — this is the lazy expiration of brief §4.
|
|
43
|
+
*/
|
|
44
|
+
acquire(seedSlug: string, entryId: string, holder: LockHolder, nowSeconds: number, ttlSeconds: number): Promise<LockAcquisition>;
|
|
45
|
+
/**
|
|
46
|
+
* Extends a lock the caller currently holds. Returns null when the lock has already
|
|
47
|
+
* expired or has been taken over — the heartbeat's signal that the lock was LOST,
|
|
48
|
+
* which `acquire` would silently paper over by re-taking it.
|
|
49
|
+
*/
|
|
50
|
+
renew(seedSlug: string, entryId: string, userId: string, nowSeconds: number, ttlSeconds: number): Promise<ContentLock | null>;
|
|
51
|
+
/** Drops the lock only if `userId` holds it. Returns false when it did not. */
|
|
52
|
+
release(seedSlug: string, entryId: string, userId: string): Promise<boolean>;
|
|
53
|
+
/** The live lock, or null when none is held or the stored one has expired. */
|
|
54
|
+
find(seedSlug: string, entryId: string, nowSeconds: number): Promise<ContentLock | null>;
|
|
55
|
+
}
|
|
56
|
+
/** True when `lock` exists and has not yet expired at `nowSeconds`. */
|
|
57
|
+
export declare function isLockActive(lock: ContentLock | null, nowSeconds: number): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* True when `userId` is the live holder. A null `userId` (the Public API, which has no
|
|
60
|
+
* authenticated subject) is never a holder.
|
|
61
|
+
*/
|
|
62
|
+
export declare function isLockHeldBy(lock: ContentLock | null, userId: string | null, nowSeconds: number): boolean;
|
|
63
|
+
//# sourceMappingURL=content-lock.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-lock.repository.d.ts","sourceRoot":"","sources":["../../src/content/content-lock.repository.ts"],"names":[],"mappings":"AAGA,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAEnC,wFAAwF;AACxF,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,4EAA4E;IAC5E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,UAAU,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC/B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAA;AAEtC;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,OAAO,CACL,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAAA;IAE3B;;;;OAIG;IACH,KAAK,CACH,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAE9B,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAE5E,8EAA8E;IAC9E,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;CACzF;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAElF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAET"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2024–2026 Flavio De Musso
|
|
3
|
+
/** Lock lifetime in seconds. Brief §2: strictly enforced, not configurable per seed. */
|
|
4
|
+
export const LOCK_TTL_SECONDS = 180;
|
|
5
|
+
/** True when `lock` exists and has not yet expired at `nowSeconds`. */
|
|
6
|
+
export function isLockActive(lock, nowSeconds) {
|
|
7
|
+
return lock !== null && lock.expiresAt > nowSeconds;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* True when `userId` is the live holder. A null `userId` (the Public API, which has no
|
|
11
|
+
* authenticated subject) is never a holder.
|
|
12
|
+
*/
|
|
13
|
+
export function isLockHeldBy(lock, userId, nowSeconds) {
|
|
14
|
+
return isLockActive(lock, nowSeconds) && userId !== null && lock.holder.userId === userId;
|
|
15
|
+
}
|
|
@@ -145,6 +145,15 @@ export interface RepositoryOptions {
|
|
|
145
145
|
*/
|
|
146
146
|
ifMatch?: number;
|
|
147
147
|
}
|
|
148
|
+
/** Options for `purge`. */
|
|
149
|
+
export interface PurgeOptions extends RepositoryOptions {
|
|
150
|
+
/**
|
|
151
|
+
* Which rows the purge may erase. Default `'trashed'`: an ordinary purge only ever erases an entry
|
|
152
|
+
* already in the Trash. `'any'` is reserved for ledger reconciliation, which must re-erase a row a
|
|
153
|
+
* database restore resurrected as live.
|
|
154
|
+
*/
|
|
155
|
+
trashed?: Exclude<TrashedMode, 'active'>;
|
|
156
|
+
}
|
|
148
157
|
/**
|
|
149
158
|
* Declarative multi-write operation translated into a single `db.batch` call.
|
|
150
159
|
* Used for coordinated writes across one or more seeds when D1's lack of
|
|
@@ -184,7 +193,7 @@ export type BatchWrite = {
|
|
|
184
193
|
export interface PurgeResult {
|
|
185
194
|
/** The row as it existed immediately before erasure — the source of the R2 media keys. */
|
|
186
195
|
row: Record<string, any>;
|
|
187
|
-
/** True when a ledger event was appended. False only
|
|
196
|
+
/** True when a ledger event was appended. False only when the repository has no ledger configured. */
|
|
188
197
|
ledgerWritten: boolean;
|
|
189
198
|
}
|
|
190
199
|
/** Per-id outcome of a bulk trash operation, mirroring `bulkUpdate`'s shape. */
|
|
@@ -249,14 +258,6 @@ export interface ContentRepository {
|
|
|
249
258
|
* Throws EntryConflictError if `options.ifMatch` is set and no longer matches the live row's `updated_at`.
|
|
250
259
|
*/
|
|
251
260
|
update(seed: Seed, id: string, data: Record<string, any>, status?: string, options?: RepositoryOptions): Promise<void>;
|
|
252
|
-
/**
|
|
253
|
-
* Deletes an entry from the live table.
|
|
254
|
-
* Returns the deleted row data (useful for media cleanup).
|
|
255
|
-
* Throws EntryNotFoundError if the ID does not exist.
|
|
256
|
-
*/
|
|
257
|
-
delete(seed: Seed, id: string, options?: RepositoryOptions): Promise<{
|
|
258
|
-
row: Record<string, any>;
|
|
259
|
-
}>;
|
|
260
261
|
/**
|
|
261
262
|
* Atomically increments/decrements a numeric field with optional min/max guards.
|
|
262
263
|
* Bypasses document-level lifecycle hooks — it's a single UPDATE statement,
|
|
@@ -350,19 +351,19 @@ export interface ContentRepository {
|
|
|
350
351
|
}>;
|
|
351
352
|
/**
|
|
352
353
|
* Reversible delete: stamps `deleted_at` and returns the row as it was.
|
|
353
|
-
*
|
|
354
|
+
* Stamps `deleted_at` from the repository's `IClock` and renames the slug with `toTrashedSlug`.
|
|
355
|
+
* Runs `beforeDelete`/`afterDelete`.
|
|
354
356
|
* Leaves junction rows, `_drafts` rows and R2 media untouched — a trashed entry must be
|
|
355
357
|
* restorable whole.
|
|
356
|
-
* @throws RepositoryError if `seed.softDelete` is not true.
|
|
357
358
|
* @throws EntryNotFoundError if no live row with `id` exists.
|
|
358
359
|
*/
|
|
359
360
|
softDelete(seed: Seed, id: string, options?: RepositoryOptions): Promise<{
|
|
360
361
|
row: Record<string, any>;
|
|
361
362
|
}>;
|
|
362
363
|
/**
|
|
363
|
-
* Clears `deleted_at`. When
|
|
364
|
-
* UNIQUE constraint rejects the update; the implementation catches it
|
|
365
|
-
*
|
|
364
|
+
* Clears `deleted_at` and restores `fromTrashedSlug(slug)`. When that slug was taken by a live
|
|
365
|
+
* entry in the meantime the UNIQUE constraint rejects the update; the implementation catches it
|
|
366
|
+
* and falls back to `<original>-restored-<id8>` rather than failing the operation (feature brief §4).
|
|
366
367
|
* @returns The restored row, carrying the slug it actually ended up with.
|
|
367
368
|
* @throws EntryNotFoundError if no TRASHED row with `id` exists.
|
|
368
369
|
*/
|
|
@@ -372,12 +373,12 @@ export interface ContentRepository {
|
|
|
372
373
|
/**
|
|
373
374
|
* Irreversible erasure: runs `beforeDelete`, reads the row, deletes it (junction and
|
|
374
375
|
* `_drafts` rows follow via ON DELETE CASCADE), appends the ledger event, runs `afterDelete`.
|
|
375
|
-
*
|
|
376
|
+
* Only erases a trashed row unless `PurgeOptions.trashed` is `'any'`.
|
|
376
377
|
* R2 media deletion is NOT performed here — the caller owns it (VSA: no external I/O in the
|
|
377
378
|
* repository beyond the ledger port).
|
|
378
|
-
* @throws EntryNotFoundError if no row with `id` exists.
|
|
379
|
+
* @throws EntryNotFoundError if no row matching the `PurgeOptions.trashed` mode with `id` exists.
|
|
379
380
|
*/
|
|
380
|
-
purge(seed: Seed, id: string, options?:
|
|
381
|
+
purge(seed: Seed, id: string, options?: PurgeOptions): Promise<PurgeResult>;
|
|
381
382
|
/** `restore` applied per id. Never partially fails the batch: each id reports its own outcome. */
|
|
382
383
|
bulkRestore(seed: Seed, ids: string[], options?: RepositoryOptions): Promise<BulkDeleteResult>;
|
|
383
384
|
/**
|
|
@@ -388,11 +389,10 @@ export interface ContentRepository {
|
|
|
388
389
|
}>;
|
|
389
390
|
/**
|
|
390
391
|
* Pure query, no side effects: ids of trashed entries whose retention window has elapsed
|
|
391
|
-
* (`deleted_at +
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
* (feature brief §2). `now` is supplied by the caller's `IClock`; never read the clock here.
|
|
392
|
+
* (`deleted_at + retentionDays * 86400 <= now`), oldest deletion first, at most `limit`.
|
|
393
|
+
* `retentionDays` is the EFFECTIVE value (`resolveRetentionDays`); `0` = never purge → [] without querying.
|
|
394
|
+
* `now` is unix seconds supplied by the caller's `IClock`; never read the clock here.
|
|
395
395
|
*/
|
|
396
|
-
findExpiredByRetention(seed: Seed, now: number, limit: number): Promise<string[]>;
|
|
396
|
+
findExpiredByRetention(seed: Seed, retentionDays: number, now: number, limit: number): Promise<string[]>;
|
|
397
397
|
}
|
|
398
398
|
//# sourceMappingURL=content.repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.repository.d.ts","sourceRoot":"","sources":["../../src/content/content.repository.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"content.repository.d.ts","sourceRoot":"","sources":["../../src/content/content.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Seed } from '../engine/types.js';
|
|
2
|
+
/** Global Trash retention when the setting was never configured (feature brief §2). */
|
|
3
|
+
export declare const DEFAULT_TRASH_RETENTION_DAYS = 14;
|
|
4
|
+
/** Upper bound for any retention value: ~100 years. Keeps `days * 86400` far inside safe-integer range. */
|
|
5
|
+
export declare const MAX_RETENTION_DAYS = 36500;
|
|
6
|
+
/** True for an integer in [0, MAX_RETENTION_DAYS]. `0` means "never purge". Rejects NaN, floats, strings, null. */
|
|
7
|
+
export declare function isValidRetentionDays(value: unknown): value is number;
|
|
8
|
+
/**
|
|
9
|
+
* Effective retention for one seed: the seed's own `retentionDays` when it is a number (including 0),
|
|
10
|
+
* otherwise `globalRetentionDays`. `0` = never purge. Pure; never throws.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveRetentionDays(seed: Pick<Seed, 'retentionDays'>, globalRetentionDays: number): number;
|
|
13
|
+
//# sourceMappingURL=retention.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/content/retention.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAE9C,uFAAuF;AACvF,eAAO,MAAM,4BAA4B,KAAK,CAAA;AAE9C,2GAA2G;AAC3G,eAAO,MAAM,kBAAkB,QAAQ,CAAA;AAEvC,mHAAmH;AACnH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAKpE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,mBAAmB,EAAE,MAAM,GAAG,MAAM,CAE3G"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2024–2026 Flavio De Musso
|
|
3
|
+
/** Global Trash retention when the setting was never configured (feature brief §2). */
|
|
4
|
+
export const DEFAULT_TRASH_RETENTION_DAYS = 14;
|
|
5
|
+
/** Upper bound for any retention value: ~100 years. Keeps `days * 86400` far inside safe-integer range. */
|
|
6
|
+
export const MAX_RETENTION_DAYS = 36500;
|
|
7
|
+
/** True for an integer in [0, MAX_RETENTION_DAYS]. `0` means "never purge". Rejects NaN, floats, strings, null. */
|
|
8
|
+
export function isValidRetentionDays(value) {
|
|
9
|
+
return typeof value === 'number'
|
|
10
|
+
&& Number.isInteger(value)
|
|
11
|
+
&& value >= 0
|
|
12
|
+
&& value <= MAX_RETENTION_DAYS;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Effective retention for one seed: the seed's own `retentionDays` when it is a number (including 0),
|
|
16
|
+
* otherwise `globalRetentionDays`. `0` = never purge. Pure; never throws.
|
|
17
|
+
*/
|
|
18
|
+
export function resolveRetentionDays(seed, globalRetentionDays) {
|
|
19
|
+
return typeof seed.retentionDays === 'number' ? seed.retentionDays : globalRetentionDays;
|
|
20
|
+
}
|
|
@@ -5,8 +5,15 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* Converte una stringa in uno slug URL-safe.
|
|
7
7
|
* Limita la lunghezza a 15 caratteri come richiesto.
|
|
8
|
+
* Never emits `_`, so a live slug can never carry `TRASHED_SLUG_INFIX`.
|
|
8
9
|
*/
|
|
9
10
|
export declare function slugify(value: string): string;
|
|
11
|
+
/** Separator between an entry's slug and its deletion timestamp while it sits in the Trash. */
|
|
12
|
+
export declare const TRASHED_SLUG_INFIX = "_old_";
|
|
13
|
+
/** `<slug>_old_<deletedAtMs>`, lower-cased. Frees the slug for reuse under any UNIQUE constraint. */
|
|
14
|
+
export declare function toTrashedSlug(slug: string, deletedAtMs: number): string;
|
|
15
|
+
/** Inverse of toTrashedSlug: strips a trailing `_old_<digits>`; returns the input unchanged when absent. */
|
|
16
|
+
export declare function fromTrashedSlug(slug: string): string;
|
|
10
17
|
/**
|
|
11
18
|
* Genera uno slug da un input (es. titolo o nome) o un fallback UUID.
|
|
12
19
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slug-utils.d.ts","sourceRoot":"","sources":["../../src/content/slug-utils.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH
|
|
1
|
+
{"version":3,"file":"slug-utils.d.ts","sourceRoot":"","sources":["../../src/content/slug-utils.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAU7C;AAED,+FAA+F;AAC/F,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAIzC,qGAAqG;AACrG,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,4GAA4G;AAC5G,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CASnG"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
/**
|
|
8
8
|
* Converte una stringa in uno slug URL-safe.
|
|
9
9
|
* Limita la lunghezza a 15 caratteri come richiesto.
|
|
10
|
+
* Never emits `_`, so a live slug can never carry `TRASHED_SLUG_INFIX`.
|
|
10
11
|
*/
|
|
11
12
|
export function slugify(value) {
|
|
12
13
|
return value
|
|
@@ -19,6 +20,17 @@ export function slugify(value) {
|
|
|
19
20
|
.slice(0, 15) // Limita a 15 caratteri
|
|
20
21
|
.replace(/-+$/g, ''); // Rimuove trattini rimasti alla fine dopo il taglio
|
|
21
22
|
}
|
|
23
|
+
/** Separator between an entry's slug and its deletion timestamp while it sits in the Trash. */
|
|
24
|
+
export const TRASHED_SLUG_INFIX = '_old_';
|
|
25
|
+
const TRASHED_SLUG_SUFFIX = new RegExp(`${TRASHED_SLUG_INFIX}\\d+$`);
|
|
26
|
+
/** `<slug>_old_<deletedAtMs>`, lower-cased. Frees the slug for reuse under any UNIQUE constraint. */
|
|
27
|
+
export function toTrashedSlug(slug, deletedAtMs) {
|
|
28
|
+
return `${slug.toLowerCase()}${TRASHED_SLUG_INFIX}${deletedAtMs}`;
|
|
29
|
+
}
|
|
30
|
+
/** Inverse of toTrashedSlug: strips a trailing `_old_<digits>`; returns the input unchanged when absent. */
|
|
31
|
+
export function fromTrashedSlug(slug) {
|
|
32
|
+
return slug.replace(TRASHED_SLUG_SUFFIX, '');
|
|
33
|
+
}
|
|
22
34
|
/**
|
|
23
35
|
* Genera uno slug da un input (es. titolo o nome) o un fallback UUID.
|
|
24
36
|
*/
|
|
@@ -125,8 +125,8 @@ export declare const viewConditionalFormatSchema: z.ZodObject<{
|
|
|
125
125
|
value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
|
|
126
126
|
}, z.core.$strip>>;
|
|
127
127
|
tone: z.ZodEnum<{
|
|
128
|
-
success: "success";
|
|
129
128
|
info: "info";
|
|
129
|
+
success: "success";
|
|
130
130
|
warning: "warning";
|
|
131
131
|
neutral: "neutral";
|
|
132
132
|
danger: "danger";
|
|
@@ -275,8 +275,8 @@ export declare const contentViewConfigSchema: z.ZodObject<{
|
|
|
275
275
|
value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
|
|
276
276
|
}, z.core.$strip>>;
|
|
277
277
|
tone: z.ZodEnum<{
|
|
278
|
-
success: "success";
|
|
279
278
|
info: "info";
|
|
279
|
+
success: "success";
|
|
280
280
|
warning: "warning";
|
|
281
281
|
neutral: "neutral";
|
|
282
282
|
danger: "danger";
|
|
@@ -457,8 +457,8 @@ export declare const createContentViewInputSchema: z.ZodObject<{
|
|
|
457
457
|
value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
|
|
458
458
|
}, z.core.$strip>>;
|
|
459
459
|
tone: z.ZodEnum<{
|
|
460
|
-
success: "success";
|
|
461
460
|
info: "info";
|
|
461
|
+
success: "success";
|
|
462
462
|
warning: "warning";
|
|
463
463
|
neutral: "neutral";
|
|
464
464
|
danger: "danger";
|
|
@@ -629,8 +629,8 @@ export declare const updateContentViewInputSchema: z.ZodObject<{
|
|
|
629
629
|
value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
|
|
630
630
|
}, z.core.$strip>>;
|
|
631
631
|
tone: z.ZodEnum<{
|
|
632
|
-
success: "success";
|
|
633
632
|
info: "info";
|
|
633
|
+
success: "success";
|
|
634
634
|
warning: "warning";
|
|
635
635
|
neutral: "neutral";
|
|
636
636
|
danger: "danger";
|
|
@@ -41,8 +41,8 @@ export interface DashboardLayout {
|
|
|
41
41
|
/** Namespaced widget type — lowercase npm-name-compatible.
|
|
42
42
|
* Built-ins use the 'core/' prefix; custom widgets '@scope/name'. */
|
|
43
43
|
export declare const WIDGET_TYPE_REGEX: RegExp;
|
|
44
|
-
/** Max serialized size of a single widget `config
|
|
45
|
-
* (`JSON.stringify(widget.config)
|
|
44
|
+
/** Max serialized size of a single widget `config`, in UTF-8 bytes
|
|
45
|
+
* (`JSON.stringify(widget.config)` encoded) — guards D1 row bloat. */
|
|
46
46
|
export declare const MAX_WIDGET_CONFIG_BYTES = 8192;
|
|
47
47
|
/** Max serialized size of a whole layout. Keeps the `dashboard_layouts` row
|
|
48
48
|
* far below D1's per-row limit and bounds the per-request cost of every GET. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-layout.d.ts","sourceRoot":"","sources":["../../src/dashboard-layout/dashboard-layout.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAM9C;;sEAEsE;AACtE,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,uBAAuB,EAAE,CAAA;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,0CAA0C;IAC1C,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B;gCAC4B;IAC5B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,OAAO,EAAE,CAAC,CAAA;IACV,KAAK,EAAE,mBAAmB,EAAE,CAAA;CAC7B;AAMD;sEACsE;AACtE,eAAO,MAAM,iBAAiB,QAA6B,CAAA;AAE3D;
|
|
1
|
+
{"version":3,"file":"dashboard-layout.d.ts","sourceRoot":"","sources":["../../src/dashboard-layout/dashboard-layout.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAM9C;;sEAEsE;AACtE,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,uBAAuB,EAAE,CAAA;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,0CAA0C;IAC1C,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B;gCAC4B;IAC5B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,OAAO,EAAE,CAAC,CAAA;IACV,KAAK,EAAE,mBAAmB,EAAE,CAAA;CAC7B;AAMD;sEACsE;AACtE,eAAO,MAAM,iBAAiB,QAA6B,CAAA;AAE3D;uEACuE;AACvE,eAAO,MAAM,uBAAuB,OAAO,CAAA;AAE3C;iFACiF;AACjF,eAAO,MAAM,0BAA0B,QAAa,CAAA;AAEpD,eAAO,MAAM,qBAAqB,KAAK,CAAA;AACvC,eAAO,MAAM,sBAAsB,KAAK,CAAA;AAOxC,eAAO,MAAM,6BAA6B;;;;;iBAKxC,CAAA;AACF,eAAO,MAAM,qBAAqB;;;;;;;;iBAGhC,CAAA;AACF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;iBAOjC,CAAA;AACF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;iBAM9B,CAAA;AACF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;iBAQ/B,CAAA;AAQH;;6DAE6D;AAC7D,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,MAAM,CAAA;CAAE,GAC7B,eAAe,CA2EjB;AAMD,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC9B;uEACmE;IACnE,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CACvC;AAED,MAAM,MAAM,6BAA6B,GACrC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAEjF;;;;mDAImD;AACnD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,eAAe,EACvB,GAAG,EAAE,sBAAsB,GAC1B,6BAA6B,CA2E/B"}
|
|
@@ -7,8 +7,8 @@ import { z } from 'zod';
|
|
|
7
7
|
/** Namespaced widget type — lowercase npm-name-compatible.
|
|
8
8
|
* Built-ins use the 'core/' prefix; custom widgets '@scope/name'. */
|
|
9
9
|
export const WIDGET_TYPE_REGEX = /^[a-z0-9@][a-z0-9@/_-]*$/;
|
|
10
|
-
/** Max serialized size of a single widget `config
|
|
11
|
-
* (`JSON.stringify(widget.config)
|
|
10
|
+
/** Max serialized size of a single widget `config`, in UTF-8 bytes
|
|
11
|
+
* (`JSON.stringify(widget.config)` encoded) — guards D1 row bloat. */
|
|
12
12
|
export const MAX_WIDGET_CONFIG_BYTES = 8192;
|
|
13
13
|
/** Max serialized size of a whole layout. Keeps the `dashboard_layouts` row
|
|
14
14
|
* far below D1's per-row limit and bounds the per-request cost of every GET. */
|
|
@@ -177,7 +177,7 @@ export function validateDashboardLayout(layout, ctx) {
|
|
|
177
177
|
else {
|
|
178
178
|
seenWidgetIds.add(w.id);
|
|
179
179
|
}
|
|
180
|
-
if (JSON.stringify(w.config ?? {}).length > MAX_WIDGET_CONFIG_BYTES) {
|
|
180
|
+
if (new TextEncoder().encode(JSON.stringify(w.config ?? {})).length > MAX_WIDGET_CONFIG_BYTES) {
|
|
181
181
|
errors.push(`Widget '${w.type}' (id=${w.id}): config exceeds ${MAX_WIDGET_CONFIG_BYTES} bytes when serialized.`);
|
|
182
182
|
}
|
|
183
183
|
if (ctx.knownWidgetTypes !== undefined && !ctx.knownWidgetTypes.has(w.type)) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface KanbanPositionRecord {
|
|
2
|
+
entryId: string;
|
|
3
|
+
position: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Persistence contract for card ordering. The ONLY gateway to `kanban_positions`.
|
|
7
|
+
* Handlers and the dashboard never touch the table directly (Botanical invariant).
|
|
8
|
+
*/
|
|
9
|
+
export interface IKanbanPositionRepository {
|
|
10
|
+
/** entryId → position for one column axis (entries without a row are omitted). */
|
|
11
|
+
getColumn(seedSlug: string, axisBranchId: string): Promise<Map<string, string>>;
|
|
12
|
+
/** Single-row upsert — exactly one write per drag (KB-S04b). */
|
|
13
|
+
setPosition(seedSlug: string, entryId: string, axisBranchId: string, position: string): Promise<void>;
|
|
14
|
+
/** Remove an entry's position row (e.g. entry deleted). */
|
|
15
|
+
remove(seedSlug: string, entryId: string, axisBranchId: string): Promise<void>;
|
|
16
|
+
/** Async rebalance (KB-S04f): rewrite a whole column's positions in one batch. */
|
|
17
|
+
rebalance(seedSlug: string, axisBranchId: string, ordered: KanbanPositionRecord[]): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=kanban-position.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kanban-position.repository.d.ts","sourceRoot":"","sources":["../../../src/dashboard-layout/kanban/kanban-position.repository.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,kFAAkF;IAClF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/E,gEAAgE;IAChE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrG,2DAA2D;IAC3D,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9E,kFAAkF;IAClF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed-layout.d.ts","sourceRoot":"","sources":["../../src/dashboard-layout/seed-layout.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"seed-layout.d.ts","sourceRoot":"","sources":["../../src/dashboard-layout/seed-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -163,6 +163,22 @@ export const formLayoutSchema = z
|
|
|
163
163
|
})
|
|
164
164
|
.refine((layout) => new TextEncoder().encode(JSON.stringify(layout)).length <= MAX_LAYOUT_BYTES, {
|
|
165
165
|
message: `Layout exceeds the ${MAX_LAYOUT_BYTES / 1024} KB size limit.`,
|
|
166
|
+
})
|
|
167
|
+
.superRefine((layout, ctx) => {
|
|
168
|
+
// The builder keys tabs, sections and columns (and drag-and-drop targets) by id alone.
|
|
169
|
+
const seen = { tab: new Set(), section: new Set(), column: new Set() };
|
|
170
|
+
const claim = (kind, id, path) => {
|
|
171
|
+
if (seen[kind].has(id))
|
|
172
|
+
ctx.addIssue({ code: 'custom', path, message: `Duplicate ${kind} id '${id}'.` });
|
|
173
|
+
seen[kind].add(id);
|
|
174
|
+
};
|
|
175
|
+
layout.tabs.forEach((tab, ti) => {
|
|
176
|
+
claim('tab', tab.id, ['tabs', ti, 'id']);
|
|
177
|
+
tab.sections.forEach((section, si) => {
|
|
178
|
+
claim('section', section.id, ['tabs', ti, 'sections', si, 'id']);
|
|
179
|
+
section.columns.forEach((col, ci) => claim('column', col.id, ['tabs', ti, 'sections', si, 'columns', ci, 'id']));
|
|
180
|
+
});
|
|
181
|
+
});
|
|
166
182
|
});
|
|
167
183
|
// ---------------------------------------------------------------------------
|
|
168
184
|
// Default layout generator
|
|
@@ -267,7 +283,7 @@ export function validateLayoutAgainstSeed(layout, seed) {
|
|
|
267
283
|
const branch = findBranchById(seed, f.branchId);
|
|
268
284
|
if (!branch)
|
|
269
285
|
return false;
|
|
270
|
-
if (
|
|
286
|
+
if (!isLayoutableBranch(branch))
|
|
271
287
|
return false;
|
|
272
288
|
return true;
|
|
273
289
|
}),
|
package/dist/engine/ddl/ddl.d.ts
CHANGED
|
@@ -235,13 +235,11 @@ export declare function generateRetypeColumn(seed: Seed, branch: Branch): string
|
|
|
235
235
|
*/
|
|
236
236
|
export declare function generateRetypeIncompatibleCount(seed: Seed, branch: Branch): string[];
|
|
237
237
|
/**
|
|
238
|
-
* Additive statements that
|
|
238
|
+
* Additive statements that upgrade a table predating universal soft delete.
|
|
239
239
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* and a trashed slug stays reserved until the table is rebuilt (see ROADMAP deferral).
|
|
244
|
-
* Returns [] when the seed does not opt in.
|
|
240
|
+
* On a pre-existing table the inline `slug … UNIQUE` survives as a sqlite_autoindex that
|
|
241
|
+
* SQLite cannot drop via ALTER; there the partial index is redundant, and the `_old_<ms>`
|
|
242
|
+
* slug rename on soft delete is what frees the slug. Callers decide when to emit these.
|
|
245
243
|
*/
|
|
246
244
|
export declare function generateEnableSoftDelete(seed: Seed): string[];
|
|
247
245
|
//# sourceMappingURL=ddl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ddl.d.ts","sourceRoot":"","sources":["../../../src/engine/ddl/ddl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EACJ,MAAM,EAOP,MAAM,aAAa,CAAC;AAIrB;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGrD;AA6BD;;GAEG;AACH,eAAO,MAAM,cAAc,aAA8E,CAAA;AAGzG;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5C;AAGD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEjD;AAGD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE/C;AAGD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAElD;AAGD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"ddl.d.ts","sourceRoot":"","sources":["../../../src/engine/ddl/ddl.ts"],"names":[],"mappings":"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"}
|
package/dist/engine/ddl/ddl.js
CHANGED
|
@@ -70,8 +70,6 @@ export function vectorTableName(seed) {
|
|
|
70
70
|
* @returns True if the column is valid, false otherwise.
|
|
71
71
|
*/
|
|
72
72
|
export function isValidColumn(seed, col) {
|
|
73
|
-
if (col === 'deleted_at')
|
|
74
|
-
return seed.softDelete === true;
|
|
75
73
|
if (SYSTEM_COLUMNS.has(col))
|
|
76
74
|
return true;
|
|
77
75
|
return seed.branches.some(b => b.alias === col);
|
|
@@ -127,12 +125,9 @@ export function generateCreateTable(seed) {
|
|
|
127
125
|
const lines = [
|
|
128
126
|
`CREATE TABLE IF NOT EXISTS ${table} (`,
|
|
129
127
|
` id TEXT NOT NULL PRIMARY KEY,`,
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
seed.softDelete
|
|
134
|
-
? ` slug TEXT NOT NULL,`
|
|
135
|
-
: ` slug TEXT NOT NULL UNIQUE,`,
|
|
128
|
+
// Uniqueness lives in a PARTIAL unique index instead, so a trashed row stops reserving
|
|
129
|
+
// its slug. An inline UNIQUE would become a sqlite_autoindex that no ALTER TABLE can drop later.
|
|
130
|
+
` slug TEXT NOT NULL,`,
|
|
136
131
|
` status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'review', 'published', 'archived')),`,
|
|
137
132
|
];
|
|
138
133
|
for (const branch of seed.branches) {
|
|
@@ -151,9 +146,8 @@ export function generateCreateTable(seed) {
|
|
|
151
146
|
}
|
|
152
147
|
}
|
|
153
148
|
lines.push(` created_at INTEGER NOT NULL DEFAULT (unixepoch()),`);
|
|
154
|
-
lines.push(` updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
155
|
-
|
|
156
|
-
lines.push(` deleted_at INTEGER`);
|
|
149
|
+
lines.push(` updated_at INTEGER NOT NULL DEFAULT (unixepoch()),`);
|
|
150
|
+
lines.push(` deleted_at INTEGER`);
|
|
157
151
|
lines.push(`);`);
|
|
158
152
|
return lines.join('\n');
|
|
159
153
|
}
|
|
@@ -271,11 +265,9 @@ export function generateIndexes(seed) {
|
|
|
271
265
|
indexes.push(`CREATE INDEX IF NOT EXISTS ${name} ON ${table}(${column});`);
|
|
272
266
|
}
|
|
273
267
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
indexes.push(`CREATE UNIQUE INDEX IF NOT EXISTS idx_${slug}_slug_active ON ${table}(slug) WHERE deleted_at IS NULL;`);
|
|
278
|
-
}
|
|
268
|
+
indexes.push(`CREATE INDEX IF NOT EXISTS idx_${slug}_deleted_at ON ${table}(deleted_at);`);
|
|
269
|
+
// Active rows only: a trashed row releases its slug for reuse (feature brief §4).
|
|
270
|
+
indexes.push(`CREATE UNIQUE INDEX IF NOT EXISTS idx_${slug}_slug_active ON ${table}(slug) WHERE deleted_at IS NULL;`);
|
|
279
271
|
return indexes;
|
|
280
272
|
}
|
|
281
273
|
/**
|
|
@@ -389,9 +381,7 @@ export function getExpectedColumns(seed) {
|
|
|
389
381
|
...branchCols,
|
|
390
382
|
{ name: 'created_at', sqlType: 'INTEGER', notNull: true, isPk: false },
|
|
391
383
|
{ name: 'updated_at', sqlType: 'INTEGER', notNull: true, isPk: false },
|
|
392
|
-
|
|
393
|
-
? [{ name: 'deleted_at', sqlType: 'INTEGER', notNull: false, isPk: false }]
|
|
394
|
-
: []),
|
|
384
|
+
{ name: 'deleted_at', sqlType: 'INTEGER', notNull: false, isPk: false },
|
|
395
385
|
];
|
|
396
386
|
}
|
|
397
387
|
/**
|
|
@@ -632,17 +622,13 @@ export function generateRetypeIncompatibleCount(seed, branch) {
|
|
|
632
622
|
return stmts;
|
|
633
623
|
}
|
|
634
624
|
/**
|
|
635
|
-
* Additive statements that
|
|
625
|
+
* Additive statements that upgrade a table predating universal soft delete.
|
|
636
626
|
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
640
|
-
* and a trashed slug stays reserved until the table is rebuilt (see ROADMAP deferral).
|
|
641
|
-
* Returns [] when the seed does not opt in.
|
|
627
|
+
* On a pre-existing table the inline `slug … UNIQUE` survives as a sqlite_autoindex that
|
|
628
|
+
* SQLite cannot drop via ALTER; there the partial index is redundant, and the `_old_<ms>`
|
|
629
|
+
* slug rename on soft delete is what frees the slug. Callers decide when to emit these.
|
|
642
630
|
*/
|
|
643
631
|
export function generateEnableSoftDelete(seed) {
|
|
644
|
-
if (!seed.softDelete)
|
|
645
|
-
return [];
|
|
646
632
|
const table = tableName(seed);
|
|
647
633
|
const slug = seed.slug;
|
|
648
634
|
return [
|