@beechcms/core 0.8.1 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/antivirus/noop-antivirus.provider.d.ts.map +1 -1
- package/dist/antivirus/virustotal-antivirus.provider.d.ts.map +1 -1
- package/dist/auth/account-email.d.ts +3 -0
- package/dist/auth/account-email.d.ts.map +1 -0
- package/dist/auth/account-email.js +9 -0
- package/dist/auth/password-reset-token.repository.d.ts +13 -2
- package/dist/auth/password-reset-token.repository.d.ts.map +1 -1
- package/dist/auth/user.repository.d.ts +69 -4
- package/dist/auth/user.repository.d.ts.map +1 -1
- package/dist/common/canonical-json.d.ts +2 -1
- package/dist/common/canonical-json.d.ts.map +1 -1
- package/dist/common/canonical-json.js +5 -3
- package/dist/content/content-scan.repository.d.ts +1 -1
- package/dist/content/content.repository.d.ts +156 -5
- package/dist/content/content.repository.d.ts.map +1 -1
- package/dist/content/content.repository.js +62 -0
- package/dist/content/seed-media-purge.repository.d.ts +34 -0
- package/dist/content/seed-media-purge.repository.d.ts.map +1 -0
- package/dist/content/seed.repository.d.ts +14 -0
- package/dist/content/seed.repository.d.ts.map +1 -1
- package/dist/dashboard-layout/content-view.d.ts +757 -0
- package/dist/dashboard-layout/content-view.d.ts.map +1 -0
- package/dist/dashboard-layout/content-view.js +285 -0
- package/dist/dashboard-layout/content-view.repository.d.ts +39 -0
- package/dist/dashboard-layout/content-view.repository.d.ts.map +1 -0
- package/dist/dashboard-layout/dashboard-layout.d.ts +5 -0
- package/dist/dashboard-layout/dashboard-layout.d.ts.map +1 -1
- package/dist/dashboard-layout/dashboard-layout.js +17 -9
- package/dist/dashboard-layout/kanban/kanban.d.ts +32 -18
- package/dist/dashboard-layout/kanban/kanban.d.ts.map +1 -1
- package/dist/dashboard-layout/kanban/kanban.js +45 -21
- package/dist/dashboard-layout/seed-layout.d.ts +22 -31
- package/dist/dashboard-layout/seed-layout.d.ts.map +1 -1
- package/dist/dashboard-layout/seed-layout.js +93 -18
- package/dist/dashboard-layout/seed-layout.repository.d.ts +1 -5
- package/dist/dashboard-layout/seed-layout.repository.d.ts.map +1 -1
- package/dist/engine/ddl/ddl.d.ts +31 -0
- package/dist/engine/ddl/ddl.d.ts.map +1 -1
- package/dist/engine/ddl/ddl.js +92 -13
- package/dist/engine/ddl/schema-mutator.d.ts +3 -0
- package/dist/engine/ddl/schema-mutator.d.ts.map +1 -1
- package/dist/engine/ddl/seed-purge-guards.d.ts +7 -0
- package/dist/engine/ddl/seed-purge-guards.d.ts.map +1 -0
- package/dist/engine/ddl/seed-purge-guards.js +19 -0
- package/dist/engine/engine.d.ts +4 -3
- package/dist/engine/engine.d.ts.map +1 -1
- package/dist/engine/engine.js +4 -3
- package/dist/engine/introspection/relation-audit.d.ts +46 -0
- package/dist/engine/introspection/relation-audit.d.ts.map +1 -0
- package/dist/engine/introspection/relation-audit.js +103 -0
- package/dist/engine/introspection/schema-fingerprint.d.ts +2 -1
- package/dist/engine/introspection/schema-fingerprint.d.ts.map +1 -1
- package/dist/engine/introspection/schema-fingerprint.js +8 -3
- package/dist/engine/privacy/policies.d.ts +1 -1
- package/dist/engine/privacy/policies.d.ts.map +1 -1
- package/dist/engine/privacy/policies.js +12 -6
- package/dist/engine/privacy/privacy.service.d.ts +13 -0
- package/dist/engine/privacy/privacy.service.d.ts.map +1 -1
- package/dist/engine/privacy/privacy.service.js +24 -0
- package/dist/engine/query/active-clause.d.ts +19 -0
- package/dist/engine/query/active-clause.d.ts.map +1 -0
- package/dist/engine/query/active-clause.js +27 -0
- package/dist/engine/query/query.d.ts +14 -1
- package/dist/engine/query/query.d.ts.map +1 -1
- package/dist/engine/query/query.js +105 -13
- package/dist/engine/seeds/candidate-ids.d.ts +14 -0
- package/dist/engine/seeds/candidate-ids.d.ts.map +1 -0
- package/dist/engine/seeds/candidate-ids.js +40 -0
- package/dist/engine/seeds/seed-definition-diff.d.ts +38 -0
- package/dist/engine/seeds/seed-definition-diff.d.ts.map +1 -0
- package/dist/engine/seeds/seed-definition-diff.js +51 -0
- package/dist/engine/seeds/seed-registry.d.ts +17 -0
- package/dist/engine/seeds/seed-registry.d.ts.map +1 -1
- package/dist/engine/seeds/seed-registry.js +27 -0
- package/dist/engine/seeds/seed-types-generator.d.ts.map +1 -1
- package/dist/engine/seeds/seed-types-generator.js +4 -5
- package/dist/engine/seeds/seed-validation.d.ts +5 -0
- package/dist/engine/seeds/seed-validation.d.ts.map +1 -1
- package/dist/engine/seeds/seed-validation.js +39 -19
- package/dist/engine/seeds/tag-migration.d.ts +73 -0
- package/dist/engine/seeds/tag-migration.d.ts.map +1 -0
- package/dist/engine/seeds/tag-migration.js +212 -0
- package/dist/engine/seeds/tag-options.d.ts +15 -0
- package/dist/engine/seeds/tag-options.d.ts.map +1 -0
- package/dist/engine/seeds/tag-options.js +111 -0
- package/dist/engine/seeds/tag-value.d.ts +31 -0
- package/dist/engine/seeds/tag-value.d.ts.map +1 -0
- package/dist/engine/seeds/tag-value.js +51 -0
- package/dist/engine/types.d.ts +59 -7
- package/dist/engine/types.d.ts.map +1 -1
- package/dist/engine/validation/cache.d.ts.map +1 -1
- package/dist/engine/validation/cache.js +20 -4
- package/dist/engine/validation/index.d.ts +12 -1
- package/dist/engine/validation/index.d.ts.map +1 -1
- package/dist/engine/validation/index.js +29 -33
- package/dist/engine/validation/primitives.d.ts +12 -0
- package/dist/engine/validation/primitives.d.ts.map +1 -1
- package/dist/engine/validation/primitives.js +22 -0
- package/dist/engine/validation/richtext-sanitizer.d.ts +9 -1
- package/dist/engine/validation/richtext-sanitizer.d.ts.map +1 -1
- package/dist/engine/validation/richtext-sanitizer.js +36 -7
- package/dist/engine/validation/schema-builders.d.ts +16 -0
- package/dist/engine/validation/schema-builders.d.ts.map +1 -1
- package/dist/engine/validation/schema-builders.js +125 -18
- package/dist/index.d.ts +34 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -11
- package/dist/media/file-types.d.ts +12 -0
- package/dist/media/file-types.d.ts.map +1 -1
- package/dist/media/file-types.js +24 -4
- package/dist/media/magic-bytes.d.ts.map +1 -1
- package/dist/media/magic-bytes.js +19 -9
- package/dist/media/media-transform.d.ts +8 -4
- package/dist/media/media-transform.d.ts.map +1 -1
- package/dist/media/media-transform.js +10 -6
- package/dist/media/media.repository.d.ts +5 -0
- package/dist/media/media.repository.d.ts.map +1 -1
- package/dist/notifications/notification-service.d.ts +1 -1
- package/dist/notifications/notification.repository.d.ts +11 -2
- package/dist/notifications/notification.repository.d.ts.map +1 -1
- package/dist/oauth/authorization-code.repository.d.ts +10 -5
- package/dist/oauth/authorization-code.repository.d.ts.map +1 -1
- package/dist/oauth/pkce.d.ts +1 -1
- package/dist/oauth/role-guard.d.ts +30 -11
- package/dist/oauth/role-guard.d.ts.map +1 -1
- package/dist/oauth/role-guard.js +27 -5
- package/dist/oauth/scopes.d.ts +1 -1
- package/dist/oauth/scopes.d.ts.map +1 -1
- package/dist/oauth/token.repository.d.ts +2 -0
- package/dist/oauth/token.repository.d.ts.map +1 -1
- package/dist/queue/queue.interface.d.ts +9 -1
- package/dist/queue/queue.interface.d.ts.map +1 -1
- package/dist/queue/queue.stub.d.ts +1 -1
- package/dist/queue/queue.stub.d.ts.map +1 -1
- package/dist/queue/queue.stub.js +2 -3
- package/dist/queue/scheduler.stub.d.ts.map +1 -1
- package/dist/rate-limit/token-bucket-rate-limiter.d.ts +7 -0
- package/dist/rate-limit/token-bucket-rate-limiter.d.ts.map +1 -1
- package/dist/rate-limit/token-bucket-rate-limiter.js +66 -0
- package/dist/rbac/invitation.repository.d.ts +28 -10
- package/dist/rbac/invitation.repository.d.ts.map +1 -1
- package/dist/rbac/types.d.ts +40 -28
- package/dist/rbac/types.d.ts.map +1 -1
- package/dist/rbac/types.js +2 -1
- package/dist/schema/manifest-seeds.js +3 -3
- package/dist/search/search.repository.d.ts +5 -4
- package/dist/search/search.repository.d.ts.map +1 -1
- package/dist/search/vector-extractor.d.ts.map +1 -1
- package/dist/search/vector-extractor.js +23 -2
- package/dist/search/vector.repository.d.ts +2 -1
- package/dist/search/vector.repository.d.ts.map +1 -1
- package/dist/security/time-trap-token.repository.d.ts +5 -3
- package/dist/security/time-trap-token.repository.d.ts.map +1 -1
- package/dist/settings/site-settings.repository.d.ts +8 -0
- package/dist/settings/site-settings.repository.d.ts.map +1 -1
- package/dist/transfer/flat-seed.d.ts.map +1 -1
- package/dist/transfer/flat-seed.js +6 -1
- package/dist/transfer/row-mapping.d.ts.map +1 -1
- package/dist/transfer/row-mapping.js +9 -2
- package/package.json +9 -4
- package/dist/.tsbuildinfo +0 -1
- package/dist/automations-grammar-words.d.ts +0 -2
- package/dist/automations-grammar-words.d.ts.map +0 -1
- package/dist/automations-grammar-words.js +0 -8
- package/dist/automations.repository.interface.d.ts +0 -19
- package/dist/automations.repository.interface.d.ts.map +0 -1
- package/dist/automations.runner.interface.d.ts +0 -10
- package/dist/automations.runner.interface.d.ts.map +0 -1
- package/dist/automations.runner.stub.d.ts +0 -5
- package/dist/automations.runner.stub.d.ts.map +0 -1
- package/dist/automations.runner.stub.js +0 -7
- package/dist/automations.types.d.ts +0 -75
- package/dist/automations.types.d.ts.map +0 -1
- package/dist/automations.types.js +0 -3
- package/dist/clock.d.ts +0 -25
- package/dist/clock.d.ts.map +0 -1
- package/dist/clock.js +0 -11
- package/dist/content-scan.repository.d.ts +0 -9
- package/dist/content-scan.repository.d.ts.map +0 -1
- package/dist/content-scan.repository.js +0 -3
- package/dist/content.repository.d.ts +0 -247
- package/dist/content.repository.d.ts.map +0 -1
- package/dist/content.repository.js +0 -59
- package/dist/dashboard-layout/kanban/kanban-position.repository.d.ts +0 -19
- package/dist/dashboard-layout/kanban/kanban-position.repository.d.ts.map +0 -1
- package/dist/dashboard-layout/kanban/kanban-position.repository.js +0 -3
- package/dist/dashboard-layout.d.ts +0 -154
- package/dist/dashboard-layout.d.ts.map +0 -1
- package/dist/dashboard-layout.js +0 -186
- package/dist/dashboard-layout.repository.d.ts +0 -18
- package/dist/dashboard-layout.repository.d.ts.map +0 -1
- package/dist/dashboard-layout.repository.js +0 -3
- package/dist/dashboard-permissions.d.ts +0 -3
- package/dist/dashboard-permissions.d.ts.map +0 -1
- package/dist/dashboard-permissions.js +0 -11
- package/dist/dashboard-scopes.d.ts +0 -12
- package/dist/dashboard-scopes.d.ts.map +0 -1
- package/dist/dashboard-scopes.js +0 -30
- package/dist/define-seed.d.ts +0 -3
- package/dist/define-seed.d.ts.map +0 -1
- package/dist/define-seed.js +0 -5
- package/dist/demo-data.repository.d.ts +0 -5
- package/dist/demo-data.repository.d.ts.map +0 -1
- package/dist/demo-data.repository.js +0 -3
- package/dist/email.provider.d.ts +0 -32
- package/dist/email.provider.d.ts.map +0 -1
- package/dist/email.provider.js +0 -4
- package/dist/engine/ddl/seed-ddl-destructive.d.ts +0 -40
- package/dist/engine/ddl/seed-ddl-destructive.d.ts.map +0 -1
- package/dist/engine/ddl/seed-ddl-destructive.js +0 -149
- package/dist/engine/ddl.d.ts +0 -193
- package/dist/engine/ddl.d.ts.map +0 -1
- package/dist/engine/ddl.js +0 -518
- package/dist/engine/define-seed.d.ts +0 -3
- package/dist/engine/define-seed.d.ts.map +0 -1
- package/dist/engine/define-seed.js +0 -5
- package/dist/engine/introspection.d.ts +0 -101
- package/dist/engine/introspection.d.ts.map +0 -1
- package/dist/engine/introspection.js +0 -127
- package/dist/engine/localization.d.ts +0 -127
- package/dist/engine/localization.d.ts.map +0 -1
- package/dist/engine/localization.js +0 -212
- package/dist/engine/policies.d.ts +0 -58
- package/dist/engine/policies.d.ts.map +0 -1
- package/dist/engine/policies.js +0 -168
- package/dist/engine/privacy.service.d.ts +0 -65
- package/dist/engine/privacy.service.d.ts.map +0 -1
- package/dist/engine/privacy.service.js +0 -114
- package/dist/engine/query.d.ts +0 -23
- package/dist/engine/query.d.ts.map +0 -1
- package/dist/engine/query.js +0 -236
- package/dist/engine/relations.d.ts +0 -28
- package/dist/engine/relations.d.ts.map +0 -1
- package/dist/engine/relations.js +0 -25
- package/dist/engine/schema-fingerprint.d.ts +0 -73
- package/dist/engine/schema-fingerprint.d.ts.map +0 -1
- package/dist/engine/schema-fingerprint.js +0 -97
- package/dist/engine/schema-mutator.d.ts +0 -26
- package/dist/engine/schema-mutator.d.ts.map +0 -1
- package/dist/engine/schema-mutator.js +0 -3
- package/dist/engine/seed-ddl-destructive.d.ts +0 -40
- package/dist/engine/seed-ddl-destructive.d.ts.map +0 -1
- package/dist/engine/seed-ddl-destructive.js +0 -149
- package/dist/engine/seed-ddl.d.ts +0 -40
- package/dist/engine/seed-ddl.d.ts.map +0 -1
- package/dist/engine/seed-ddl.js +0 -100
- package/dist/engine/seed-registry.d.ts +0 -71
- package/dist/engine/seed-registry.d.ts.map +0 -1
- package/dist/engine/seed-registry.js +0 -167
- package/dist/engine/seed-types-generator.d.ts +0 -10
- package/dist/engine/seed-types-generator.d.ts.map +0 -1
- package/dist/engine/seed-types-generator.js +0 -89
- package/dist/engine/seed-validation.d.ts +0 -30
- package/dist/engine/seed-validation.d.ts.map +0 -1
- package/dist/engine/seed-validation.js +0 -319
- package/dist/engine/seeds.d.ts +0 -20
- package/dist/engine/seeds.d.ts.map +0 -1
- package/dist/engine/seeds.js +0 -21
- package/dist/engine/serialize.d.ts +0 -20
- package/dist/engine/serialize.d.ts.map +0 -1
- package/dist/engine/serialize.js +0 -160
- package/dist/engine.d.ts +0 -144
- package/dist/engine.d.ts.map +0 -1
- package/dist/engine.js +0 -741
- package/dist/file-types.d.ts +0 -13
- package/dist/file-types.d.ts.map +0 -1
- package/dist/file-types.js +0 -85
- package/dist/hooks.d.ts +0 -29
- package/dist/hooks.d.ts.map +0 -1
- package/dist/hooks.js +0 -3
- package/dist/id-generator.d.ts +0 -26
- package/dist/id-generator.d.ts.map +0 -1
- package/dist/id-generator.js +0 -12
- package/dist/idempotency.repository.d.ts +0 -13
- package/dist/idempotency.repository.d.ts.map +0 -1
- package/dist/idempotency.repository.js +0 -3
- package/dist/kanban-position.repository.d.ts +0 -19
- package/dist/kanban-position.repository.d.ts.map +0 -1
- package/dist/kanban-position.repository.js +0 -3
- package/dist/kanban.d.ts +0 -75
- package/dist/kanban.d.ts.map +0 -1
- package/dist/kanban.js +0 -82
- package/dist/layout-permissions.d.ts +0 -3
- package/dist/layout-permissions.d.ts.map +0 -1
- package/dist/layout-permissions.js +0 -11
- package/dist/media.repository.d.ts +0 -61
- package/dist/media.repository.d.ts.map +0 -1
- package/dist/media.repository.js +0 -3
- package/dist/policies.d.ts +0 -10
- package/dist/policies.d.ts.map +0 -1
- package/dist/policies.js +0 -33
- package/dist/queue.interface.d.ts +0 -39
- package/dist/queue.interface.d.ts.map +0 -1
- package/dist/queue.interface.js +0 -3
- package/dist/queue.stub.d.ts +0 -6
- package/dist/queue.stub.d.ts.map +0 -1
- package/dist/queue.stub.js +0 -8
- package/dist/relations.d.ts +0 -28
- package/dist/relations.d.ts.map +0 -1
- package/dist/relations.js +0 -25
- package/dist/richtext-render.d.ts +0 -11
- package/dist/richtext-render.d.ts.map +0 -1
- package/dist/richtext-render.js +0 -87
- package/dist/richtext.d.ts +0 -11
- package/dist/richtext.d.ts.map +0 -1
- package/dist/richtext.js +0 -13
- package/dist/scheduler.interface.d.ts +0 -4
- package/dist/scheduler.interface.d.ts.map +0 -1
- package/dist/scheduler.interface.js +0 -3
- package/dist/scheduler.stub.d.ts +0 -5
- package/dist/scheduler.stub.d.ts.map +0 -1
- package/dist/scheduler.stub.js +0 -7
- package/dist/schema-mutator.d.ts +0 -26
- package/dist/schema-mutator.d.ts.map +0 -1
- package/dist/schema-mutator.js +0 -3
- package/dist/seed-ddl-destructive.d.ts +0 -40
- package/dist/seed-ddl-destructive.d.ts.map +0 -1
- package/dist/seed-ddl-destructive.js +0 -149
- package/dist/seed-ddl.d.ts +0 -40
- package/dist/seed-ddl.d.ts.map +0 -1
- package/dist/seed-ddl.js +0 -100
- package/dist/seed-layout.d.ts +0 -145
- package/dist/seed-layout.d.ts.map +0 -1
- package/dist/seed-layout.js +0 -192
- package/dist/seed-layout.repository.d.ts +0 -22
- package/dist/seed-layout.repository.d.ts.map +0 -1
- package/dist/seed-layout.repository.js +0 -3
- package/dist/seed-registry.d.ts +0 -71
- package/dist/seed-registry.d.ts.map +0 -1
- package/dist/seed-registry.js +0 -143
- package/dist/seed-types-generator.d.ts +0 -10
- package/dist/seed-types-generator.d.ts.map +0 -1
- package/dist/seed-types-generator.js +0 -86
- package/dist/seed-validation.d.ts +0 -23
- package/dist/seed-validation.d.ts.map +0 -1
- package/dist/seed-validation.js +0 -224
- package/dist/seed.repository.d.ts +0 -37
- package/dist/seed.repository.d.ts.map +0 -1
- package/dist/seed.repository.js +0 -3
- package/dist/seeds.d.ts +0 -20
- package/dist/seeds.d.ts.map +0 -1
- package/dist/seeds.js +0 -21
- package/dist/site-settings.repository.d.ts +0 -16
- package/dist/site-settings.repository.d.ts.map +0 -1
- package/dist/site-settings.repository.js +0 -3
- package/dist/slug-utils.d.ts +0 -18
- package/dist/slug-utils.d.ts.map +0 -1
- package/dist/slug-utils.js +0 -32
- package/dist/storage.d.ts +0 -46
- package/dist/storage.d.ts.map +0 -1
- package/dist/storage.js +0 -3
- package/dist/types.d.ts +0 -243
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/validation.d.ts +0 -50
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -660
- package/dist/webhook-validation.d.ts +0 -3
- package/dist/webhook-validation.d.ts.map +0 -1
- package/dist/webhook-validation.js +0 -6
- /package/dist/{automations.repository.interface.js → content/seed-media-purge.repository.js} +0 -0
- /package/dist/{automations.runner.interface.js → dashboard-layout/content-view.repository.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noop-antivirus.provider.d.ts","sourceRoot":"","sources":["../../src/antivirus/noop-antivirus.provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAEvF,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,QAAQ,CAAC,IAAI,UAAS;IAEhB,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC
|
|
1
|
+
{"version":3,"file":"noop-antivirus.provider.d.ts","sourceRoot":"","sources":["../../src/antivirus/noop-antivirus.provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAEvF,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,QAAQ,CAAC,IAAI,UAAS;IAEhB,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAGnG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virustotal-antivirus.provider.d.ts","sourceRoot":"","sources":["../../src/antivirus/virustotal-antivirus.provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAEvF,qBAAa,2BAA4B,YAAW,kBAAkB;IAExD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IADpC,QAAQ,CAAC,IAAI,gBAAe;
|
|
1
|
+
{"version":3,"file":"virustotal-antivirus.provider.d.ts","sourceRoot":"","sources":["../../src/antivirus/virustotal-antivirus.provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAEvF,qBAAa,2BAA4B,YAAW,kBAAkB;IAExD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IADpC,QAAQ,CAAC,IAAI,gBAAe;gBACC,MAAM,CAAC,EAAE,MAAM,YAAA;IAEtC,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA2CjG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-email.d.ts","sourceRoot":"","sources":["../../src/auth/account-email.ts"],"names":[],"mappings":"AAMA,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG1D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2024–2026 Flavio De Musso
|
|
3
|
+
const ACCOUNT_EMAIL_REGEX = /^[^\s@]+@[^\s@.]+(?:\.[^\s@.]+)+$/;
|
|
4
|
+
const MAX_ACCOUNT_EMAIL_LENGTH = 254;
|
|
5
|
+
/** Validates the trimmed, lowercased account identifier used by login and account writes. */
|
|
6
|
+
export function isValidAccountEmail(email) {
|
|
7
|
+
const normalizedEmail = email.trim().toLowerCase();
|
|
8
|
+
return normalizedEmail.length <= MAX_ACCOUNT_EMAIL_LENGTH && ACCOUNT_EMAIL_REGEX.test(normalizedEmail);
|
|
9
|
+
}
|
|
@@ -8,6 +8,12 @@ export interface ValidatedResetToken {
|
|
|
8
8
|
userId: string;
|
|
9
9
|
email: string;
|
|
10
10
|
}
|
|
11
|
+
export interface RedeemPasswordResetInput {
|
|
12
|
+
tokenId: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
newPasswordHash: string;
|
|
15
|
+
nowTimestamp: number;
|
|
16
|
+
}
|
|
11
17
|
export interface IPasswordResetTokenRepository {
|
|
12
18
|
/**
|
|
13
19
|
* Marks all pending (unused) tokens for the user as consumed before issuing a new one.
|
|
@@ -22,7 +28,12 @@ export interface IPasswordResetTokenRepository {
|
|
|
22
28
|
* Returns null if the token is expired, already used, or not found.
|
|
23
29
|
*/
|
|
24
30
|
findValidByHashWithEmail(tokenHash: string, nowTimestamp: number): Promise<ValidatedResetToken | null>;
|
|
25
|
-
/**
|
|
26
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Redeems a token in one atomic unit: burns it, replaces the user's password hash and revokes
|
|
33
|
+
* every refresh token. Either all three land or none do.
|
|
34
|
+
* Returns `true` for the single caller that burned the token, `false` (writing nothing) when it
|
|
35
|
+
* was already redeemed by a concurrent request.
|
|
36
|
+
*/
|
|
37
|
+
redeem(input: RedeemPasswordResetInput): Promise<boolean>;
|
|
27
38
|
}
|
|
28
39
|
//# sourceMappingURL=password-reset-token.repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-reset-token.repository.d.ts","sourceRoot":"","sources":["../../src/auth/password-reset-token.repository.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEtE,0FAA0F;IAC1F,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEpD;;;;OAIG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAA;IAEtG
|
|
1
|
+
{"version":3,"file":"password-reset-token.repository.d.ts","sourceRoot":"","sources":["../../src/auth/password-reset-token.repository.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEtE,0FAA0F;IAC1F,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEpD;;;;OAIG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAA;IAEtG;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC1D"}
|
|
@@ -1,12 +1,43 @@
|
|
|
1
|
+
import type { AdminGuardedResult, PageRequest } from '../rbac/types.js';
|
|
1
2
|
export interface UserRecord {
|
|
2
3
|
id: string;
|
|
3
4
|
email: string;
|
|
4
5
|
name: string | null;
|
|
5
6
|
surname: string | null;
|
|
6
7
|
passwordHash: string;
|
|
8
|
+
/**
|
|
9
|
+
* System-level account type ('admin' | 'editor').
|
|
10
|
+
* - 'admin': Developer / instance owner with full system access and Seed Builder control.
|
|
11
|
+
* - 'editor': Generic Beech CMS user whose permissions are managed via RBAC assignments.
|
|
12
|
+
* (Note: 'editor' is retained as technical debt for DB CHECK constraint and backwards compatibility).
|
|
13
|
+
*/
|
|
7
14
|
role: string;
|
|
8
15
|
avatarUrl: string | null;
|
|
9
16
|
notificationPreferences: string;
|
|
17
|
+
/**
|
|
18
|
+
* Reversible deactivation (`users.is_active`). A deactivated account keeps its rows,
|
|
19
|
+
* its assignments and its refresh tokens, but is refused at every authorization
|
|
20
|
+
* boundary — which is what makes revocation instant despite 15-minute access JWTs.
|
|
21
|
+
*/
|
|
22
|
+
isActive: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Administrative projection of an account. Deliberately carries NO `passwordHash`:
|
|
26
|
+
* account listings must never put credential material on the wire.
|
|
27
|
+
*/
|
|
28
|
+
export interface AccountSummary {
|
|
29
|
+
id: string;
|
|
30
|
+
email: string;
|
|
31
|
+
name: string | null;
|
|
32
|
+
surname: string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Developer/owner axis ('admin' | 'editor'), orthogonal to RBAC permissions.
|
|
35
|
+
* - 'admin' = Developer / Owner
|
|
36
|
+
* - 'editor' = Generic Beech user (RBAC-gated)
|
|
37
|
+
*/
|
|
38
|
+
role: string;
|
|
39
|
+
isActive: boolean;
|
|
40
|
+
createdAt: number;
|
|
10
41
|
}
|
|
11
42
|
export interface NewUserInput {
|
|
12
43
|
id: string;
|
|
@@ -16,6 +47,15 @@ export interface NewUserInput {
|
|
|
16
47
|
name: string | null;
|
|
17
48
|
surname: string | null;
|
|
18
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* The (role, scope) grant `createInitialAdmin` writes in the same transaction as the
|
|
52
|
+
* account itself, so the first administrator can never exist without one.
|
|
53
|
+
*/
|
|
54
|
+
export interface InitialRoleGrant {
|
|
55
|
+
id: string;
|
|
56
|
+
roleId: string;
|
|
57
|
+
scope: string;
|
|
58
|
+
}
|
|
19
59
|
export interface IUserRepository {
|
|
20
60
|
/**
|
|
21
61
|
* Returns the total number of registered users.
|
|
@@ -29,11 +69,15 @@ export interface IUserRepository {
|
|
|
29
69
|
/** Inserts a new user record. */
|
|
30
70
|
create(user: NewUserInput): Promise<void>;
|
|
31
71
|
/**
|
|
32
|
-
* Atomically creates the first administrator account
|
|
33
|
-
* setup-completed marker row inserted in the same transaction.
|
|
34
|
-
*
|
|
72
|
+
* Atomically creates the first administrator account AND its `roleGrant`,
|
|
73
|
+
* guarded by a setup-completed marker row inserted in the same transaction.
|
|
74
|
+
* The account can never exist without its role: callers must resolve the
|
|
75
|
+
* grant before calling this, so a missing or unresolvable role aborts setup
|
|
76
|
+
* with nothing written instead of leaving a stranded, unrecoverable admin.
|
|
77
|
+
* Returns false instead of throwing when setup was already completed
|
|
78
|
+
* concurrently.
|
|
35
79
|
*/
|
|
36
|
-
createInitialAdmin(user: NewUserInput): Promise<boolean>;
|
|
80
|
+
createInitialAdmin(user: NewUserInput, roleGrant: InitialRoleGrant): Promise<boolean>;
|
|
37
81
|
/** Updates the user's display name, surname, and/or email address. */
|
|
38
82
|
updateProfile(userId: string, fields: {
|
|
39
83
|
name?: string;
|
|
@@ -42,6 +86,11 @@ export interface IUserRepository {
|
|
|
42
86
|
}): Promise<void>;
|
|
43
87
|
/** Replaces the user's stored password hash after a successful password change. */
|
|
44
88
|
updatePasswordHash(userId: string, newPasswordHash: string): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Replaces the password hash and revokes every active refresh token of the user in one
|
|
91
|
+
* atomic write, so a password change can never leave old sessions valid.
|
|
92
|
+
*/
|
|
93
|
+
changePasswordAndRevokeSessions(userId: string, newPasswordHash: string, nowTimestamp: number): Promise<void>;
|
|
45
94
|
/** Sets or clears the user's avatar URL. */
|
|
46
95
|
updateAvatarUrl(userId: string, avatarUrl: string | null): Promise<void>;
|
|
47
96
|
/** Persists the user's notification preferences as a JSON string. */
|
|
@@ -52,5 +101,21 @@ export interface IUserRepository {
|
|
|
52
101
|
* an unrelated account exists.
|
|
53
102
|
*/
|
|
54
103
|
emailBelongsToAnotherUser(email: string, currentUserId: string): Promise<boolean>;
|
|
104
|
+
/** One page of accounts, oldest first, without credential material. */
|
|
105
|
+
listAccounts(page: PageRequest): Promise<AccountSummary[]>;
|
|
106
|
+
/** One account by id, without credential material. Null when absent. */
|
|
107
|
+
findAccountById(userId: string): Promise<AccountSummary | null>;
|
|
108
|
+
/**
|
|
109
|
+
* Flips `users.is_active`. `not-found` when the user does not exist.
|
|
110
|
+
* Reversible by design (brief §4): rows, assignments and tokens are all preserved.
|
|
111
|
+
* Deactivation returns `last-global-admin` and changes nothing when the account is the
|
|
112
|
+
* last active global administrator.
|
|
113
|
+
*/
|
|
114
|
+
setActive(userId: string, isActive: boolean): Promise<AdminGuardedResult>;
|
|
115
|
+
/**
|
|
116
|
+
* Read-only twin of the deactivation guard in {@link setActive}: is this account the last
|
|
117
|
+
* active global administrator? ADVISORY — see `IRoleAssignmentRepository.isLastGlobalAdminAssignment`.
|
|
118
|
+
*/
|
|
119
|
+
isLastGlobalAdmin(userId: string): Promise<boolean>;
|
|
55
120
|
}
|
|
56
121
|
//# sourceMappingURL=user.repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.repository.d.ts","sourceRoot":"","sources":["../../src/auth/user.repository.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,uBAAuB,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"user.repository.d.ts","sourceRoot":"","sources":["../../src/auth/user.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* @module common/canonical-json
|
|
3
3
|
* Deterministic JSON serialization, shared by two callers that must never disagree:
|
|
4
4
|
* the manifest writer (`schema/canonical.ts`, authoring-side) and the schema fingerprint
|
|
5
|
-
* (`engine/schema-fingerprint.ts`, runtime-side).
|
|
5
|
+
* (`engine/schema-fingerprint.ts`, runtime-side). The public API's Idempotency-Key request
|
|
6
|
+
* fingerprint also hashes it, so equivalent payloads with reordered JSON keys match.
|
|
6
7
|
*
|
|
7
8
|
* Moved here in sprint 2 because the fingerprint runs inside the Worker and `schema/` is the one
|
|
8
9
|
* module the Worker must never import. The BYTES ARE FROZEN — sprint 1 declared this format a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical-json.d.ts","sourceRoot":"","sources":["../../src/common/canonical-json.ts"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"canonical-json.d.ts","sourceRoot":"","sources":["../../src/common/canonical-json.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AAEH,4DAA4D;AAC5D,qBAAa,2BAA4B,SAAQ,KAAK;IAElD,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM;;IAHtB,gFAAgF;IACvE,IAAI,EAAE,MAAM;IACrB,6CAA6C;IACpC,KAAK,EAAE,MAAM;CAQzB;AA+CD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEzD"}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* @module common/canonical-json
|
|
5
5
|
* Deterministic JSON serialization, shared by two callers that must never disagree:
|
|
6
6
|
* the manifest writer (`schema/canonical.ts`, authoring-side) and the schema fingerprint
|
|
7
|
-
* (`engine/schema-fingerprint.ts`, runtime-side).
|
|
7
|
+
* (`engine/schema-fingerprint.ts`, runtime-side). The public API's Idempotency-Key request
|
|
8
|
+
* fingerprint also hashes it, so equivalent payloads with reordered JSON keys match.
|
|
8
9
|
*
|
|
9
10
|
* Moved here in sprint 2 because the fingerprint runs inside the Worker and `schema/` is the one
|
|
10
11
|
* module the Worker must never import. The BYTES ARE FROZEN — sprint 1 declared this format a
|
|
@@ -62,14 +63,15 @@ function canonicalize(value, path) {
|
|
|
62
63
|
if (value === null)
|
|
63
64
|
return null;
|
|
64
65
|
if (Array.isArray(value)) {
|
|
65
|
-
return value.
|
|
66
|
+
return Array.from({ length: value.length }, (_, index) => {
|
|
67
|
+
const item = Object.hasOwn(value, index) ? value[index] : undefined;
|
|
66
68
|
if (item === undefined)
|
|
67
69
|
throw new CanonicalSerializationError(`${path}[${index}]`, 'undefined');
|
|
68
70
|
return canonicalize(item, `${path}[${index}]`);
|
|
69
71
|
});
|
|
70
72
|
}
|
|
71
73
|
if (typeof value === 'object') {
|
|
72
|
-
const out =
|
|
74
|
+
const out = Object.create(null);
|
|
73
75
|
for (const key of Object.keys(value).sort()) {
|
|
74
76
|
const child = value[key];
|
|
75
77
|
if (child === undefined)
|
|
@@ -2,7 +2,7 @@ import type { Seed } from '../engine/types.js';
|
|
|
2
2
|
export interface IContentScanRepository {
|
|
3
3
|
/**
|
|
4
4
|
* Scans across all registered seeds to identify media keys that are currently referenced
|
|
5
|
-
* by any content entry. Used for orphaned media detection and storage analytics.
|
|
5
|
+
* by any content entry, live or draft. Used for orphaned media detection and storage analytics.
|
|
6
6
|
*/
|
|
7
7
|
getReferencedMediaKeys(seeds: Seed[]): Promise<Set<string>>;
|
|
8
8
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Seed, SelectOptions } from '../engine/types.js';
|
|
1
|
+
import { Seed, SelectOptions, TrashedMode } from '../engine/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* One row of the cross-seed pending-drafts overview. Aggregates the minimum a
|
|
4
4
|
* reviewer needs to triage a draft without opening it: which seed it belongs to,
|
|
@@ -19,8 +19,8 @@ export interface DraftSummary {
|
|
|
19
19
|
* Base Repository Error
|
|
20
20
|
*/
|
|
21
21
|
export declare class RepositoryError extends Error {
|
|
22
|
-
cause?: unknown;
|
|
23
|
-
constructor(message: string, cause?: unknown);
|
|
22
|
+
cause?: unknown | undefined;
|
|
23
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Thrown when an entry is not found by ID or Slug
|
|
@@ -62,6 +62,59 @@ export declare class HookValidationError extends RepositoryError {
|
|
|
62
62
|
message: string;
|
|
63
63
|
}>);
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Thrown by `publishDraft` when the live entry was written after the draft captured its
|
|
67
|
+
* `live_snapshot_at`. Publishing would overwrite that write, so the repository refuses and the
|
|
68
|
+
* caller must discard the draft or re-create it from the current live version.
|
|
69
|
+
* Mapped to 409 Conflict by the API problem-mapper.
|
|
70
|
+
*/
|
|
71
|
+
export declare class DraftConflictError extends RepositoryError {
|
|
72
|
+
readonly seedSlug: string;
|
|
73
|
+
readonly entryId: string;
|
|
74
|
+
readonly snapshotAt: number | null;
|
|
75
|
+
readonly liveUpdatedAt: number;
|
|
76
|
+
constructor(params: {
|
|
77
|
+
seedSlug: string;
|
|
78
|
+
entryId: string;
|
|
79
|
+
snapshotAt: number | null;
|
|
80
|
+
liveUpdatedAt: number;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Thrown by `update` when the caller supplied `options.ifMatch` and the live row's
|
|
85
|
+
* `updated_at` no longer matches it — another writer committed in between.
|
|
86
|
+
* Mapped to 409 Conflict by the API problem-mapper.
|
|
87
|
+
*/
|
|
88
|
+
export declare class EntryConflictError extends RepositoryError {
|
|
89
|
+
readonly seedSlug: string;
|
|
90
|
+
readonly entryId: string;
|
|
91
|
+
readonly expectedUpdatedAt: number;
|
|
92
|
+
readonly actualUpdatedAt: number;
|
|
93
|
+
constructor(params: {
|
|
94
|
+
seedSlug: string;
|
|
95
|
+
entryId: string;
|
|
96
|
+
expectedUpdatedAt: number;
|
|
97
|
+
actualUpdatedAt: number;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Thrown by `saveDraft` when the caller supplied `options.ifMatch` and the pending draft
|
|
102
|
+
* row's `updated_at` no longer matches it — another writer saved a draft in between, and
|
|
103
|
+
* blindly merging on top of it would silently drop that writer's fields.
|
|
104
|
+
* Mapped to 409 Conflict by the API problem-mapper.
|
|
105
|
+
*/
|
|
106
|
+
export declare class DraftSaveConflictError extends RepositoryError {
|
|
107
|
+
readonly seedSlug: string;
|
|
108
|
+
readonly entryId: string;
|
|
109
|
+
readonly expectedUpdatedAt: number;
|
|
110
|
+
readonly actualUpdatedAt: number;
|
|
111
|
+
constructor(params: {
|
|
112
|
+
seedSlug: string;
|
|
113
|
+
entryId: string;
|
|
114
|
+
expectedUpdatedAt: number;
|
|
115
|
+
actualUpdatedAt: number;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
65
118
|
export type BulkFieldUpdate = {
|
|
66
119
|
kind: 'set';
|
|
67
120
|
value: unknown;
|
|
@@ -85,6 +138,12 @@ export interface RepositoryOptions {
|
|
|
85
138
|
role?: string;
|
|
86
139
|
email?: string;
|
|
87
140
|
};
|
|
141
|
+
/**
|
|
142
|
+
* Optimistic concurrency guard for `update`: the `updated_at` the caller last read.
|
|
143
|
+
* When set, the write only applies if the live row's `updated_at` still matches;
|
|
144
|
+
* otherwise `update` throws {@link EntryConflictError}.
|
|
145
|
+
*/
|
|
146
|
+
ifMatch?: number;
|
|
88
147
|
}
|
|
89
148
|
/**
|
|
90
149
|
* Declarative multi-write operation translated into a single `db.batch` call.
|
|
@@ -121,6 +180,21 @@ export type BatchWrite = {
|
|
|
121
180
|
max?: number;
|
|
122
181
|
};
|
|
123
182
|
};
|
|
183
|
+
/** Everything a purge caller needs to finish cleanup outside the database. */
|
|
184
|
+
export interface PurgeResult {
|
|
185
|
+
/** The row as it existed immediately before erasure — the source of the R2 media keys. */
|
|
186
|
+
row: Record<string, any>;
|
|
187
|
+
/** True when a ledger event was appended. False only for a seed without `softDelete`. */
|
|
188
|
+
ledgerWritten: boolean;
|
|
189
|
+
}
|
|
190
|
+
/** Per-id outcome of a bulk trash operation, mirroring `bulkUpdate`'s shape. */
|
|
191
|
+
export interface BulkDeleteResult {
|
|
192
|
+
succeeded: string[];
|
|
193
|
+
failed: Array<{
|
|
194
|
+
id: string;
|
|
195
|
+
reason: string;
|
|
196
|
+
}>;
|
|
197
|
+
}
|
|
124
198
|
/**
|
|
125
199
|
* Interface defining the standard operations for content persistence.
|
|
126
200
|
* This is platform-agnostic and should be implemented for specific databases (e.g., D1).
|
|
@@ -135,14 +209,28 @@ export interface ContentRepository {
|
|
|
135
209
|
}>;
|
|
136
210
|
/**
|
|
137
211
|
* Finds a single entry by its unique ID.
|
|
212
|
+
* Trashed rows are invisible unless `options.trashed` says otherwise.
|
|
138
213
|
* Throws EntryNotFoundError if not found.
|
|
139
214
|
*/
|
|
140
|
-
findById(seed: Seed, id: string
|
|
215
|
+
findById(seed: Seed, id: string, options?: {
|
|
216
|
+
trashed?: TrashedMode;
|
|
217
|
+
}): Promise<Record<string, any>>;
|
|
141
218
|
/**
|
|
142
219
|
* Finds a single entry by its unique slug.
|
|
143
220
|
* Throws EntryNotFoundError if not found.
|
|
144
221
|
*/
|
|
145
222
|
findBySlug(seed: Seed, slug: string): Promise<Record<string, any>>;
|
|
223
|
+
/**
|
|
224
|
+
* Resolves the parent entry ids that reference any of `targetIds` through a MULTI relation
|
|
225
|
+
* branch (junction table). Single-value relations need no lookup — their target id lives in a
|
|
226
|
+
* column on the parent row and is filterable directly.
|
|
227
|
+
*
|
|
228
|
+
* Returns at most `limit` distinct parent ids, in no guaranteed order. Callers that must
|
|
229
|
+
* distinguish "complete" from "truncated" pass `limit = cap + 1` and compare the length.
|
|
230
|
+
*
|
|
231
|
+
* @throws RepositoryError if `branchAlias` is not a `multiple: true` relation branch of `seed`.
|
|
232
|
+
*/
|
|
233
|
+
findParentIdsByRelation(seed: Seed, branchAlias: string, targetIds: string[], limit: number): Promise<string[]>;
|
|
146
234
|
/**
|
|
147
235
|
* Computes facets (status counts and distinct tags) for a content type.
|
|
148
236
|
*/
|
|
@@ -158,6 +246,7 @@ export interface ContentRepository {
|
|
|
158
246
|
/**
|
|
159
247
|
* Partially updates an existing entry in the live table.
|
|
160
248
|
* Throws EntryNotFoundError if the ID does not exist.
|
|
249
|
+
* Throws EntryConflictError if `options.ifMatch` is set and no longer matches the live row's `updated_at`.
|
|
161
250
|
*/
|
|
162
251
|
update(seed: Seed, id: string, data: Record<string, any>, status?: string, options?: RepositoryOptions): Promise<void>;
|
|
163
252
|
/**
|
|
@@ -187,9 +276,17 @@ export interface ContentRepository {
|
|
|
187
276
|
/**
|
|
188
277
|
* Atomically applies an axis-value patch AND a kanban_positions upsert in one DB batch (KB-S04e).
|
|
189
278
|
* `patch` is null for same-column reorders (position only).
|
|
279
|
+
*
|
|
280
|
+
* @param ctx.ifMatch Optimistic concurrency guard for the axis-value patch: the `updated_at`
|
|
281
|
+
* the caller last read. When set and `patch` is non-null, the write only applies if the live
|
|
282
|
+
* row's `updated_at` still matches; otherwise throws {@link EntryConflictError}. Ignored when
|
|
283
|
+
* `patch` is null, since a position-only reorder does not read-modify-write column data.
|
|
284
|
+
* @throws EntryConflictError if `ctx.ifMatch` is set, `patch` is non-null, and the live row's
|
|
285
|
+
* `updated_at` no longer matches it.
|
|
190
286
|
*/
|
|
191
287
|
updateWithKanbanPosition(seed: Seed, id: string, patch: Record<string, unknown> | null, position: string, axisBranchId: string, ctx: {
|
|
192
288
|
actor: string;
|
|
289
|
+
ifMatch?: number;
|
|
193
290
|
}): Promise<{
|
|
194
291
|
success: boolean;
|
|
195
292
|
}>;
|
|
@@ -200,13 +297,21 @@ export interface ContentRepository {
|
|
|
200
297
|
runBatch(operations: BatchWrite[]): Promise<void>;
|
|
201
298
|
/**
|
|
202
299
|
* Saves or updates a pending draft in the mirror table.
|
|
300
|
+
* Throws DraftSaveConflictError if `options.ifMatch` is set and no longer matches the
|
|
301
|
+
* pending draft row's `updated_at`.
|
|
203
302
|
*/
|
|
204
|
-
saveDraft(seed: Seed, entryId: string, data: Record<string, any
|
|
303
|
+
saveDraft(seed: Seed, entryId: string, data: Record<string, any>, options?: RepositoryOptions): Promise<void>;
|
|
205
304
|
/**
|
|
206
305
|
* Retrieves the pending draft for a given entry.
|
|
207
306
|
* Returns null if no draft exists.
|
|
208
307
|
*/
|
|
209
308
|
getDraft(seed: Seed, entryId: string): Promise<Record<string, any> | null>;
|
|
309
|
+
/**
|
|
310
|
+
* Retrieves the pending draft row's `updated_at`, for use as an optimistic-concurrency
|
|
311
|
+
* guard by callers that read the draft before merging into it.
|
|
312
|
+
* Returns null if no draft exists (or drafts are disallowed for the seed).
|
|
313
|
+
*/
|
|
314
|
+
getDraftUpdatedAt(seed: Seed, entryId: string): Promise<number | null>;
|
|
210
315
|
/**
|
|
211
316
|
* Atomic promotion of a draft to the live table.
|
|
212
317
|
* Must use a transaction (db.batch) to update live and delete draft.
|
|
@@ -243,5 +348,51 @@ export interface ContentRepository {
|
|
|
243
348
|
reason: string;
|
|
244
349
|
}>;
|
|
245
350
|
}>;
|
|
351
|
+
/**
|
|
352
|
+
* Reversible delete: stamps `deleted_at` and returns the row as it was.
|
|
353
|
+
* Runs `beforeDelete`/`afterDelete`, exactly like `delete`.
|
|
354
|
+
* Leaves junction rows, `_drafts` rows and R2 media untouched — a trashed entry must be
|
|
355
|
+
* restorable whole.
|
|
356
|
+
* @throws RepositoryError if `seed.softDelete` is not true.
|
|
357
|
+
* @throws EntryNotFoundError if no live row with `id` exists.
|
|
358
|
+
*/
|
|
359
|
+
softDelete(seed: Seed, id: string, options?: RepositoryOptions): Promise<{
|
|
360
|
+
row: Record<string, any>;
|
|
361
|
+
}>;
|
|
362
|
+
/**
|
|
363
|
+
* Clears `deleted_at`. When the entry's slug was taken by a live entry in the meantime the
|
|
364
|
+
* UNIQUE constraint rejects the update; the implementation catches it and restores under an
|
|
365
|
+
* auto-renamed slug rather than failing the operation (feature brief §4).
|
|
366
|
+
* @returns The restored row, carrying the slug it actually ended up with.
|
|
367
|
+
* @throws EntryNotFoundError if no TRASHED row with `id` exists.
|
|
368
|
+
*/
|
|
369
|
+
restore(seed: Seed, id: string, options?: RepositoryOptions): Promise<{
|
|
370
|
+
row: Record<string, any>;
|
|
371
|
+
}>;
|
|
372
|
+
/**
|
|
373
|
+
* Irreversible erasure: runs `beforeDelete`, reads the row, deletes it (junction and
|
|
374
|
+
* `_drafts` rows follow via ON DELETE CASCADE), appends the ledger event, runs `afterDelete`.
|
|
375
|
+
* Works on a live row and on a trashed one.
|
|
376
|
+
* R2 media deletion is NOT performed here — the caller owns it (VSA: no external I/O in the
|
|
377
|
+
* repository beyond the ledger port).
|
|
378
|
+
* @throws EntryNotFoundError if no row with `id` exists.
|
|
379
|
+
*/
|
|
380
|
+
purge(seed: Seed, id: string, options?: RepositoryOptions): Promise<PurgeResult>;
|
|
381
|
+
/** `restore` applied per id. Never partially fails the batch: each id reports its own outcome. */
|
|
382
|
+
bulkRestore(seed: Seed, ids: string[], options?: RepositoryOptions): Promise<BulkDeleteResult>;
|
|
383
|
+
/**
|
|
384
|
+
* `purge` applied per id. Returns the purged rows so the caller can collect R2 media keys.
|
|
385
|
+
*/
|
|
386
|
+
bulkPurge(seed: Seed, ids: string[], options?: RepositoryOptions): Promise<BulkDeleteResult & {
|
|
387
|
+
rows: Record<string, any>[];
|
|
388
|
+
}>;
|
|
389
|
+
/**
|
|
390
|
+
* Pure query, no side effects: ids of trashed entries whose retention window has elapsed
|
|
391
|
+
* (`deleted_at + seed.retentionDays * 86400 <= now`).
|
|
392
|
+
* Returns [] when the seed has no `retentionDays` or no `softDelete`.
|
|
393
|
+
* Deliberately NOT wired to any scheduler — the recurring-automation adapter is future work
|
|
394
|
+
* (feature brief §2). `now` is supplied by the caller's `IClock`; never read the clock here.
|
|
395
|
+
*/
|
|
396
|
+
findExpiredByRetention(seed: Seed, now: number, limit: number): Promise<string[]>;
|
|
246
397
|
}
|
|
247
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":"AAGA,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"content.repository.d.ts","sourceRoot":"","sources":["../../src/content/content.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -57,3 +57,65 @@ export class HookValidationError extends RepositoryError {
|
|
|
57
57
|
this.fields = fields;
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Thrown by `publishDraft` when the live entry was written after the draft captured its
|
|
62
|
+
* `live_snapshot_at`. Publishing would overwrite that write, so the repository refuses and the
|
|
63
|
+
* caller must discard the draft or re-create it from the current live version.
|
|
64
|
+
* Mapped to 409 Conflict by the API problem-mapper.
|
|
65
|
+
*/
|
|
66
|
+
export class DraftConflictError extends RepositoryError {
|
|
67
|
+
seedSlug;
|
|
68
|
+
entryId;
|
|
69
|
+
snapshotAt;
|
|
70
|
+
liveUpdatedAt;
|
|
71
|
+
constructor(params) {
|
|
72
|
+
super(`Draft conflict: entry '${params.entryId}' in '${params.seedSlug}' was modified at ` +
|
|
73
|
+
`${params.liveUpdatedAt}, after the draft snapshot ${params.snapshotAt}`);
|
|
74
|
+
this.name = 'DraftConflictError';
|
|
75
|
+
this.seedSlug = params.seedSlug;
|
|
76
|
+
this.entryId = params.entryId;
|
|
77
|
+
this.snapshotAt = params.snapshotAt;
|
|
78
|
+
this.liveUpdatedAt = params.liveUpdatedAt;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Thrown by `update` when the caller supplied `options.ifMatch` and the live row's
|
|
83
|
+
* `updated_at` no longer matches it — another writer committed in between.
|
|
84
|
+
* Mapped to 409 Conflict by the API problem-mapper.
|
|
85
|
+
*/
|
|
86
|
+
export class EntryConflictError extends RepositoryError {
|
|
87
|
+
seedSlug;
|
|
88
|
+
entryId;
|
|
89
|
+
expectedUpdatedAt;
|
|
90
|
+
actualUpdatedAt;
|
|
91
|
+
constructor(params) {
|
|
92
|
+
super(`Entry conflict: entry '${params.entryId}' in '${params.seedSlug}' was modified at ` +
|
|
93
|
+
`${params.actualUpdatedAt}, expected ${params.expectedUpdatedAt}`);
|
|
94
|
+
this.name = 'EntryConflictError';
|
|
95
|
+
this.seedSlug = params.seedSlug;
|
|
96
|
+
this.entryId = params.entryId;
|
|
97
|
+
this.expectedUpdatedAt = params.expectedUpdatedAt;
|
|
98
|
+
this.actualUpdatedAt = params.actualUpdatedAt;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Thrown by `saveDraft` when the caller supplied `options.ifMatch` and the pending draft
|
|
103
|
+
* row's `updated_at` no longer matches it — another writer saved a draft in between, and
|
|
104
|
+
* blindly merging on top of it would silently drop that writer's fields.
|
|
105
|
+
* Mapped to 409 Conflict by the API problem-mapper.
|
|
106
|
+
*/
|
|
107
|
+
export class DraftSaveConflictError extends RepositoryError {
|
|
108
|
+
seedSlug;
|
|
109
|
+
entryId;
|
|
110
|
+
expectedUpdatedAt;
|
|
111
|
+
actualUpdatedAt;
|
|
112
|
+
constructor(params) {
|
|
113
|
+
super(`Draft save conflict: draft for entry '${params.entryId}' in '${params.seedSlug}' was saved at ` +
|
|
114
|
+
`${params.actualUpdatedAt}, expected ${params.expectedUpdatedAt}`);
|
|
115
|
+
this.name = 'DraftSaveConflictError';
|
|
116
|
+
this.seedSlug = params.seedSlug;
|
|
117
|
+
this.entryId = params.entryId;
|
|
118
|
+
this.expectedUpdatedAt = params.expectedUpdatedAt;
|
|
119
|
+
this.actualUpdatedAt = params.actualUpdatedAt;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Seed } from '../engine/types.js';
|
|
2
|
+
export type SeedPurgePhase = 'live' | 'drafts' | 'purging' | 'done' | 'failed';
|
|
3
|
+
export interface SeedPurgeJob {
|
|
4
|
+
id: string;
|
|
5
|
+
slug: string;
|
|
6
|
+
definition: Seed;
|
|
7
|
+
phase: SeedPurgePhase;
|
|
8
|
+
cursor: number;
|
|
9
|
+
stagedCount: number;
|
|
10
|
+
purgedCount: number;
|
|
11
|
+
}
|
|
12
|
+
export interface SeedPurgeRow {
|
|
13
|
+
rowid: number;
|
|
14
|
+
data: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
/** Durable, bounded staging and acknowledgement of media references during seed deletion. */
|
|
17
|
+
export interface ISeedMediaPurgeRepository {
|
|
18
|
+
begin(id: string, seed: Seed, now: number): Promise<void>;
|
|
19
|
+
get(id: string): Promise<SeedPurgeJob | null>;
|
|
20
|
+
getActiveBySlug(slug: string): Promise<SeedPurgeJob | null>;
|
|
21
|
+
listPendingIds(limit: number): Promise<string[]>;
|
|
22
|
+
claim(id: string, token: string, now: number, leaseSeconds: number): Promise<SeedPurgeJob | null>;
|
|
23
|
+
release(id: string, token: string): Promise<void>;
|
|
24
|
+
getColumns(table: string): Promise<Set<string> | null>;
|
|
25
|
+
readPage(table: string, columns: string[], cursor: number, limit: number): Promise<SeedPurgeRow[]>;
|
|
26
|
+
stagePage(id: string, token: string, cursor: number, keys: string[], now: number): Promise<void>;
|
|
27
|
+
moveToDrafts(id: string, token: string, now: number): Promise<void>;
|
|
28
|
+
dropAndStartPurge(id: string, token: string, statements: string[], now: number): Promise<void>;
|
|
29
|
+
abortDrop(id: string, token: string, now: number): Promise<void>;
|
|
30
|
+
listKeys(id: string, limit: number): Promise<string[]>;
|
|
31
|
+
completeKey(id: string, token: string, key: string, now: number): Promise<void>;
|
|
32
|
+
finish(id: string, token: string, now: number): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=seed-media-purge.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-media-purge.repository.d.ts","sourceRoot":"","sources":["../../src/content/seed-media-purge.repository.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAE9C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAE9E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,IAAI,CAAA;IAChB,KAAK,EAAE,cAAc,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED,6FAA6F;AAC7F,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC7C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC3D,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAChD,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IACjG,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAA;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAClG,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9F,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACtD,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/E,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9D"}
|