@neohm/nestend 3.3.9 → 3.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -64
- package/dist/admin/admin.module.d.ts.map +1 -1
- package/dist/admin/admin.module.js.map +1 -1
- package/dist/admin/controllers/admin.api.key.controller.js +1 -1
- package/dist/admin/controllers/admin.api.key.controller.js.map +1 -1
- package/dist/admin/controllers/admin.email.template.controller.d.ts +24 -0
- package/dist/admin/controllers/admin.email.template.controller.d.ts.map +1 -0
- package/dist/admin/controllers/admin.email.template.controller.js +106 -0
- package/dist/admin/controllers/admin.email.template.controller.js.map +1 -0
- package/dist/admin/controllers/admin.pdf.template.controller.d.ts +24 -0
- package/dist/admin/controllers/admin.pdf.template.controller.d.ts.map +1 -0
- package/dist/admin/controllers/admin.pdf.template.controller.js +106 -0
- package/dist/admin/controllers/admin.pdf.template.controller.js.map +1 -0
- package/dist/admin/controllers/admin.scheduled.task.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.scheduled.task.controller.js +1 -1
- package/dist/admin/controllers/admin.scheduled.task.controller.js.map +1 -1
- package/dist/admin/controllers/admin.scope.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.scope.controller.js +1 -1
- package/dist/admin/controllers/admin.scope.controller.js.map +1 -1
- package/dist/admin/controllers/admin.system.user.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.system.user.controller.js +1 -1
- package/dist/admin/controllers/admin.system.user.controller.js.map +1 -1
- package/dist/admin/controllers/admin.tenant.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.tenant.controller.js +1 -1
- package/dist/admin/controllers/admin.tenant.controller.js.map +1 -1
- package/dist/admin/controllers/admin.tenant.user.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.tenant.user.controller.js +1 -1
- package/dist/admin/controllers/admin.tenant.user.controller.js.map +1 -1
- package/dist/admin/controllers/admin.user.controller.d.ts.map +1 -1
- package/dist/admin/controllers/admin.user.controller.js +1 -1
- package/dist/admin/controllers/admin.user.controller.js.map +1 -1
- package/dist/admin/controllers/system.role.controller.d.ts.map +1 -1
- package/dist/admin/controllers/system.role.controller.js +1 -1
- package/dist/admin/controllers/system.role.controller.js.map +1 -1
- package/dist/admin/dtos/add.email.template.dto.d.ts +9 -0
- package/dist/admin/dtos/add.email.template.dto.d.ts.map +1 -0
- package/dist/admin/dtos/add.email.template.dto.js +68 -0
- package/dist/admin/dtos/add.email.template.dto.js.map +1 -0
- package/dist/admin/dtos/add.pdf.template.dto.d.ts +8 -0
- package/dist/admin/dtos/add.pdf.template.dto.d.ts.map +1 -0
- package/dist/admin/dtos/add.pdf.template.dto.js +58 -0
- package/dist/admin/dtos/add.pdf.template.dto.js.map +1 -0
- package/dist/admin/dtos/add.tenant.dto.d.ts +1 -0
- package/dist/admin/dtos/add.tenant.dto.d.ts.map +1 -1
- package/dist/admin/dtos/add.tenant.dto.js +7 -0
- package/dist/admin/dtos/add.tenant.dto.js.map +1 -1
- package/dist/admin/dtos/email.template.list.dto.d.ts +4 -0
- package/dist/admin/dtos/email.template.list.dto.d.ts.map +1 -0
- package/dist/admin/dtos/email.template.list.dto.js +8 -0
- package/dist/admin/dtos/email.template.list.dto.js.map +1 -0
- package/dist/admin/dtos/pdf.template.list.dto.d.ts +4 -0
- package/dist/admin/dtos/pdf.template.list.dto.d.ts.map +1 -0
- package/dist/admin/dtos/pdf.template.list.dto.js +8 -0
- package/dist/admin/dtos/pdf.template.list.dto.js.map +1 -0
- package/dist/admin/es6.classes.d.ts +12 -4
- package/dist/admin/es6.classes.d.ts.map +1 -1
- package/dist/admin/es6.classes.js +22 -1
- package/dist/admin/es6.classes.js.map +1 -1
- package/dist/admin/libraries/email.template.data.processor.d.ts +13 -0
- package/dist/admin/libraries/email.template.data.processor.d.ts.map +1 -0
- package/dist/admin/libraries/email.template.data.processor.js +51 -0
- package/dist/admin/libraries/email.template.data.processor.js.map +1 -0
- package/dist/admin/libraries/email.template.list.processor.d.ts +15 -0
- package/dist/admin/libraries/email.template.list.processor.d.ts.map +1 -0
- package/dist/admin/libraries/email.template.list.processor.js +31 -0
- package/dist/admin/libraries/email.template.list.processor.js.map +1 -0
- package/dist/admin/libraries/pdf.template.data.processor.d.ts +13 -0
- package/dist/admin/libraries/pdf.template.data.processor.d.ts.map +1 -0
- package/dist/admin/libraries/pdf.template.data.processor.js +48 -0
- package/dist/admin/libraries/pdf.template.data.processor.js.map +1 -0
- package/dist/admin/libraries/pdf.template.list.processor.d.ts +15 -0
- package/dist/admin/libraries/pdf.template.list.processor.d.ts.map +1 -0
- package/dist/admin/libraries/pdf.template.list.processor.js +30 -0
- package/dist/admin/libraries/pdf.template.list.processor.js.map +1 -0
- package/dist/admin/libraries/tenant.data.processor.d.ts.map +1 -1
- package/dist/admin/libraries/tenant.data.processor.js +1 -0
- package/dist/admin/libraries/tenant.data.processor.js.map +1 -1
- package/dist/admin/services/template.service.d.ts +7 -0
- package/dist/admin/services/template.service.d.ts.map +1 -0
- package/dist/admin/services/template.service.js +34 -0
- package/dist/admin/services/template.service.js.map +1 -0
- package/dist/constants/entity.constants.d.ts +1 -0
- package/dist/constants/entity.constants.d.ts.map +1 -1
- package/dist/constants/entity.constants.js +1 -0
- package/dist/constants/entity.constants.js.map +1 -1
- package/dist/constants/entity.maps.d.ts +2 -0
- package/dist/constants/entity.maps.d.ts.map +1 -1
- package/dist/constants/entity.maps.js +2 -0
- package/dist/constants/entity.maps.js.map +1 -1
- package/dist/document/document.module.d.ts.map +1 -1
- package/dist/document/document.module.js +3 -1
- package/dist/document/document.module.js.map +1 -1
- package/dist/document/dtos/pdf.document.options.dto.d.ts +17 -0
- package/dist/document/dtos/pdf.document.options.dto.d.ts.map +1 -0
- package/dist/document/dtos/pdf.document.options.dto.js +13 -0
- package/dist/document/dtos/pdf.document.options.dto.js.map +1 -0
- package/dist/document/dtos/pdf.template.attributes.dto.d.ts +3 -0
- package/dist/document/dtos/pdf.template.attributes.dto.d.ts.map +1 -0
- package/dist/document/dtos/pdf.template.attributes.dto.js +7 -0
- package/dist/document/dtos/pdf.template.attributes.dto.js.map +1 -0
- package/dist/document/entities/document.entity.d.ts +1 -0
- package/dist/document/entities/document.entity.d.ts.map +1 -1
- package/dist/document/entities/document.entity.js +4 -0
- package/dist/document/entities/document.entity.js.map +1 -1
- package/dist/document/entities/pdf.template.entity.d.ts +9 -0
- package/dist/document/entities/pdf.template.entity.d.ts.map +1 -0
- package/dist/document/entities/pdf.template.entity.js +38 -0
- package/dist/document/entities/pdf.template.entity.js.map +1 -0
- package/dist/document/enums/pdf.default.enum.d.ts +2 -1
- package/dist/document/enums/pdf.default.enum.d.ts.map +1 -1
- package/dist/document/enums/pdf.default.enum.js +1 -0
- package/dist/document/enums/pdf.default.enum.js.map +1 -1
- package/dist/document/es6.classes.d.ts +6 -5
- package/dist/document/es6.classes.d.ts.map +1 -1
- package/dist/document/es6.classes.js +14 -2
- package/dist/document/es6.classes.js.map +1 -1
- package/dist/document/libraries/process.pdf.document.d.ts +16 -0
- package/dist/document/libraries/process.pdf.document.d.ts.map +1 -0
- package/dist/document/libraries/process.pdf.document.js +47 -0
- package/dist/document/libraries/process.pdf.document.js.map +1 -0
- package/dist/document/services/document.service.d.ts +2 -2
- package/dist/document/services/document.service.d.ts.map +1 -1
- package/dist/document/services/document.service.js +5 -2
- package/dist/document/services/document.service.js.map +1 -1
- package/dist/document/services/pdf.template.service.d.ts +12 -0
- package/dist/document/services/pdf.template.service.d.ts.map +1 -0
- package/dist/document/services/pdf.template.service.js +57 -0
- package/dist/document/services/pdf.template.service.js.map +1 -0
- package/dist/document/types/document.types.d.ts +3 -0
- package/dist/document/types/document.types.d.ts.map +1 -1
- package/dist/document/types/pdf.types.d.ts +4 -0
- package/dist/document/types/pdf.types.d.ts.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -3
- package/dist/index.js.map +1 -1
- package/dist/migrations/1749600000002.CreateSysTenantsTable.d.ts.map +1 -1
- package/dist/migrations/1749600000002.CreateSysTenantsTable.js +1 -0
- package/dist/migrations/1749600000002.CreateSysTenantsTable.js.map +1 -1
- package/dist/migrations/1749600000020.CreateSysEmailTemplatesTable.d.ts.map +1 -1
- package/dist/migrations/1749600000020.CreateSysEmailTemplatesTable.js +11 -1
- package/dist/migrations/1749600000020.CreateSysEmailTemplatesTable.js.map +1 -1
- package/dist/migrations/1749600000028.CreateSysDocumentsTable.d.ts.map +1 -1
- package/dist/migrations/1749600000028.CreateSysDocumentsTable.js +1 -0
- package/dist/migrations/1749600000028.CreateSysDocumentsTable.js.map +1 -1
- package/dist/migrations/1749600000029.CreateSysPdfTemplatesTable.d.ts +6 -0
- package/dist/migrations/1749600000029.CreateSysPdfTemplatesTable.d.ts.map +1 -0
- package/dist/migrations/1749600000029.CreateSysPdfTemplatesTable.js +33 -0
- package/dist/migrations/1749600000029.CreateSysPdfTemplatesTable.js.map +1 -0
- package/dist/notification/entities/email.template.entity.d.ts +2 -2
- package/dist/notification/entities/email.template.entity.d.ts.map +1 -1
- package/dist/notification/entities/email.template.entity.js +2 -2
- package/dist/notification/entities/email.template.entity.js.map +1 -1
- package/dist/tenant/entities/tenant.entity.d.ts +1 -0
- package/dist/tenant/entities/tenant.entity.d.ts.map +1 -1
- package/dist/tenant/entities/tenant.entity.js +5 -1
- package/dist/tenant/entities/tenant.entity.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,7 +104,7 @@ these are free to change without a breaking release.
|
|
|
104
104
|
| Area | Key exports | Notes |
|
|
105
105
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
106
106
|
| Entities | `RootEntity`, `CommonEntity`, `CommonAdminEntity`, `UserEntity`, `AdminUserEntity`, `SystemRoleEntity`, `SystemAdminRoleEntity`, ... | uuid PK, soft deletes, `created_by`/`updated_by` (+ `creator`/`updater` relations), jsonb `attributes`; entity-level `findOneOrNew`, `hardDelete`, `restore`, `paginate` statics plus a row-wise `softDelete()` |
|
|
107
|
-
| Migrations | `MigrationUtility`, `SeederUtility` (the
|
|
107
|
+
| Migrations | `MigrationUtility`, `SeederUtility` (the 29 table migrations ship in `dist/migrations` — glob them, they are not barrel exports) | fluent `this.string()`, `this.numeric()`, `addRecord()` seeding |
|
|
108
108
|
| Queue | `QueueModule`, `QueueModule.withConnection()`, `QueueService`, `CommonJob` | BullMQ `@Processor`/`WorkerHost` consumer; auto-discovered jobs, duplicate prevention, recurring schedulers, completed jobs cleared from Redis on success (1-day TTL on failures), `clearQueue()`, retries, failures persisted to `sys_failed_jobs`; connection from `BULL_REDIS_*` or supplied by the app — never register `BullModule.forRoot()` yourself, two roots race over the worker's connection |
|
|
109
109
|
| Scheduled events | `SystemScheduledTaskEntity`, `ScheduledEventEntity`, `ScheduleKind`, `ScheduleSpec`, `IsCronExpression` | schedule definitions in `sys_scheduled_tasks` → events in `sys_scheduled_events`; interval / cron / once specs with timezones, drift-free slots, horizon materialisation, catch-up + overlap policies, fire-once dispatch with backoff, cadence via `SCHEDULED_EVENT_MIN` |
|
|
110
110
|
| Auth | `AuthModule`, `AuthService.validateRole()`, `RoleTier`, `TenantRole`, `Auth`, `JwtMiddleware` | imperative auth (open by default); `<module>.<tier>` role hierarchy (manager > writer > viewer), with `global.admin` overriding every role check; JwtMiddleware resolves the user into `Auth`'s AsyncLocalStorage context per request; access + rotating refresh tokens; session-based logout invalidation (`sys_auth_sessions`); Google SSO via ID token at `POST /auth/google`; impersonation — a tenantless `has_global_access` user signs into one organization at `POST /auth/impersonation/login` |
|
|
@@ -112,15 +112,15 @@ these are free to change without a breaking release.
|
|
|
112
112
|
| API keys | `ApiKeyService`, `ApiKeyGuard` / `ApiKeyMiddleware`, `@ApiKeyScopes()`, `ApiKeyContext` | hashed keys in `sys_api_keys` (admin-owned), one tenant per key, expiry/revocation, `x-api-key` header; `validateAccess(scope)` returns the tenant the key acts for |
|
|
113
113
|
| Scopes | `ScopeService`, `AuthService.validateAccess()`, `ScopeEntity`, `TenantScopeEntity`, `ApiScopeEntity` | one feature named once in `sys_scopes`, then granted per organization (`sys_tenant_scopes`) or per API key (`sys_api_scopes`) — never an array on the principal |
|
|
114
114
|
| Multi-tenancy | `TenantModule`, `TenantEntity`, `CommonTenantEntity`, `TenantContextService`, `TenantContextMiddleware` | AsyncLocalStorage tenant context; resolve by header, slug, or domain; tenants are onboarded by admins (`TenantEntity.creator` → `AdminUserEntity`) |
|
|
115
|
-
| Admin | `AdminModule` (its controllers, DTOs and processors are internal — import the module and hit the endpoints), `GlobalAdminRoles` | back-office APIs: tenant onboarding, client/admin/system user registration (single + bulk), the `has_global_access` grant that enables impersonation, tenant + scheduled-task listing; 4-tier `GlobalAdminRoles` gate over `sys_admin_roles`; Swagger at `/docs` (hidden in production) |
|
|
115
|
+
| Admin | `AdminModule` (its controllers, DTOs and processors are internal — import the module and hit the endpoints), `GlobalAdminRoles` | back-office APIs: tenant onboarding, client/admin/system user registration (single + bulk), the `has_global_access` grant that enables impersonation, tenant + scheduled-task listing, the email/PDF template catalogues (read at content-reader, written at content-manager, deleted at global admin); 4-tier `GlobalAdminRoles` gate over `sys_admin_roles`; Swagger at `/docs` (hidden in production) |
|
|
116
116
|
| Notifications | `NotificationModule`, `NotificationService`, `FcmPushNotificationService` | in-app rows + FCM push (optional `firebase-admin`); device token registry |
|
|
117
|
-
| Email (SES) | `EmailNotificationService`, `ProcessEmailNotification`, `EmailTemplateEntity`, `EmailNotificationLogEntity` | templates in `sys_email_templates` rendered by a remote service, dispatched via SES per recipient (to/cc/bcc); logged to `sys_email_notification_logs` outside production; dispatch skipped when `AWS_SES_FROM_ADDRESS` unset |
|
|
117
|
+
| Email (SES) | `EmailNotificationService`, `ProcessEmailNotification`, `EmailTemplateEntity`, `EmailNotificationLogEntity` | templates in `sys_email_templates` (managed from the admin surface) rendered by a remote service, dispatched via SES per recipient (to/cc/bcc); logged to `sys_email_notification_logs` outside production; dispatch skipped when `AWS_SES_FROM_ADDRESS` unset |
|
|
118
118
|
| Audit | `AuditService` | `saveAuditLog(old, new)` with changed-value diffing into `sys_audit_logs` |
|
|
119
119
|
| Cache | `CacheService` | Redis, TTL objects (`{days, hours, min}`), transparent encryption |
|
|
120
120
|
| Encryption | `EncryptionService` | AES-256-GCM, scrypt-derived keys |
|
|
121
121
|
| System properties | `SystemPropertyModule`, `SystemPropertyService` | cached + optionally encrypted key/value settings in `sys_properties` |
|
|
122
|
-
| Documents | `DocumentModule`, `DocumentService`, `S3BucketDocumentService`, `MinioBucketDocumentService` | `POST /api/documents/upload` (multipart) or `uploadDocument(multerFiles) → links[]`; driver chosen via `DOCUMENT_STORAGE_DRIVER`
|
|
123
|
-
| PDF
|
|
122
|
+
| Documents | `DocumentModule`, `DocumentService`, `S3BucketDocumentService`, `MinioBucketDocumentService` | `POST /api/documents/upload` (multipart) or `uploadDocument(multerFiles) → links[]`; driver chosen via `DOCUMENT_STORAGE_DRIVER`; `sys_document_uploads` is the file, `sys_documents` the link to one of your records (`system_generated` marks the ones the backend produced itself) |
|
|
123
|
+
| PDF documents | `PdfService`, `PdfTemplateService`, `ProcessPdfDocument`, `PdfTemplateEntity`, `PdfRenderOptions` | templates in `sys_pdf_templates` rendered to HTML by a remote service, rasterized by headless Chromium (`renderHtmlToPdf(html) → Buffer`, honours the document's own `@page` rules and paginates to any length), then stored — `ProcessPdfDocument` writes both rows and flags the `sys_documents` one `system_generated`; optional peer dep `puppeteer` |
|
|
124
124
|
| HTTP | `CommonController`, `GlobalExceptionFilter`, common DTOs | health endpoint base controller, uniform error envelope |
|
|
125
125
|
| Raw SQL | `SqlService`, `SqlTarget` | named `:key` placeholders always bound as driver params, `:...key` array expansion; runs on the read replica (`DB_READ_*`) with transparent primary fallback; `fetchOne`/`fetchScalar`/`exists`/`count`/`paginate` helpers |
|
|
126
126
|
| List endpoints | `CommonListProcessor`, `CommonListFilterDto`, `FilterDto`, `CommonListFilterConfig` | allowlisted columns, parameterised operators (`eq`…`isNull`), typed value casting (`str`/`num`/`date`/`bool`/`null`), multi-sort + paginated on the read replica |
|
|
@@ -605,7 +605,7 @@ a subscriber only starts firing once something constructs it.
|
|
|
605
605
|
| `MINIO_BUCKET` | `documents` | Bucket name (auto-created if missing) |
|
|
606
606
|
| `MINIO_PUBLIC_URL` | _(empty)_ | CDN base URL when MinIO sits behind a proxy |
|
|
607
607
|
|
|
608
|
-
### PDF
|
|
608
|
+
### PDF Documents
|
|
609
609
|
|
|
610
610
|
Requires the optional peer dependency `puppeteer`.
|
|
611
611
|
|
|
@@ -694,9 +694,18 @@ Requires the optional peer dependency `firebase-admin`. Provide **one** of:
|
|
|
694
694
|
Storage is split across two tables. `sys_document_uploads` (`DocumentUploadEntity`)
|
|
695
695
|
is the stored object — name, mime type, size, driver, path, url, `is_public` — and
|
|
696
696
|
every upload writes one row automatically. `sys_documents` (`DocumentEntity`) is just
|
|
697
|
-
the link to one of your records: `upload_id` + `source_type` + `source_id
|
|
698
|
-
metadata. So one file can hang off several records, and a
|
|
699
|
-
anything owns it.
|
|
697
|
+
the link to one of your records: `upload_id` + `source_type` + `source_id` +
|
|
698
|
+
`system_generated`, no file metadata. So one file can hang off several records, and a
|
|
699
|
+
file can exist before anything owns it.
|
|
700
|
+
|
|
701
|
+
`system_generated` answers a question the two tables otherwise cannot: whether anybody
|
|
702
|
+
uploaded this file. A generated invoice and an uploaded scan of one are the same pair of
|
|
703
|
+
rows, so the flag is what lets a listing tell them apart — and what lets a regeneration
|
|
704
|
+
know which of its records it may replace. It is set through
|
|
705
|
+
`setDocument(dto, { systemGenerated: true })`, which is how
|
|
706
|
+
[`ProcessPdfDocument`](#pdf-documents-pdfservice-pdftemplateservice-processpdfdocument)
|
|
707
|
+
marks what it produces; it is deliberately absent from `SetDocumentDto`, so the HTTP
|
|
708
|
+
endpoint cannot claim it.
|
|
700
709
|
|
|
701
710
|
`DocumentModule` ships two endpoints. `POST /api/documents/upload` is multipart: it
|
|
702
711
|
takes the files in a `files` field, uploads them through the active driver and returns
|
|
@@ -752,43 +761,97 @@ that object from the bucket and soft deletes its row, so one unreachable file re
|
|
|
752
761
|
alone instead of stalling the sweep. Schedule it with a `sys_scheduled_tasks` row under
|
|
753
762
|
that identifier — the module registers the handler but never dispatches it.
|
|
754
763
|
|
|
755
|
-
## PDF
|
|
764
|
+
## PDF Documents (PdfService, PdfTemplateService, ProcessPdfDocument)
|
|
756
765
|
|
|
757
|
-
`
|
|
758
|
-
|
|
766
|
+
The `/pdfs` counterpart of [Templated Email](#templated-email-aws-ses), and it reuses
|
|
767
|
+
that pipeline's shape exactly: a catalogue row names a template, a remote service
|
|
768
|
+
renders it, a processor drives the whole thing. What differs is the last mile — mail is
|
|
769
|
+
handed to SES, a document is rasterized and stored.
|
|
759
770
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
771
|
+
Three pieces, split along the one line that matters — where the browser binary lives:
|
|
772
|
+
|
|
773
|
+
- **`PdfTemplateService`** — resolves a `sys_pdf_templates` row by `identifier` and
|
|
774
|
+
POSTs your `data` to the remote template service, returning print-ready HTML. Exactly
|
|
775
|
+
`EmailNotificationService.getEmailBody()`, for documents.
|
|
776
|
+
- **`PdfService`** — turns that HTML into PDF bytes with a headless Chromium. Knows
|
|
777
|
+
nothing about templates or storage.
|
|
778
|
+
- **`ProcessPdfDocument`** — the entry point. Validates, renders, rasterizes, stores,
|
|
779
|
+
and returns the `sys_documents` row with its `upload` relation attached.
|
|
780
|
+
|
|
781
|
+
All three are exported by `DocumentModule`.
|
|
782
|
+
|
|
783
|
+
### The whole thing in one call
|
|
765
784
|
|
|
766
785
|
```ts
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
786
|
+
const processor = new ProcessPdfDocument(
|
|
787
|
+
this.pdfTemplateService,
|
|
788
|
+
this.pdfService,
|
|
789
|
+
this.documentService,
|
|
790
|
+
);
|
|
791
|
+
|
|
792
|
+
const document = await processor.process({
|
|
793
|
+
identifier: 'purchase-order', // a sys_pdf_templates row
|
|
794
|
+
metadata: {
|
|
795
|
+
fileName: 'po-10432.pdf',
|
|
796
|
+
mimeType: 'application/pdf', // default
|
|
797
|
+
pathIdentifier: 'purchase.order', // → the document.path.purchase.order property
|
|
798
|
+
isPublic: false, // default
|
|
799
|
+
},
|
|
800
|
+
source: { // becomes the sys_documents row
|
|
801
|
+
source_type: 'purchase.order',
|
|
802
|
+
source_id: purchaseOrder.id,
|
|
803
|
+
},
|
|
804
|
+
data: { order: purchaseOrder, lines }, // payload for the remote renderer
|
|
774
805
|
});
|
|
775
806
|
|
|
776
|
-
|
|
807
|
+
const link = await this.documentService.getDocumentLink(document.upload);
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
Four steps, in order:
|
|
811
|
+
|
|
812
|
+
1. `PdfTemplateService.getPdfHtml()` — loads the template (`OperationException` if the
|
|
813
|
+
identifier is unknown), builds the URL as the `pdf.template.base.url` system
|
|
814
|
+
property + `template.path` + `identifier`, and POSTs `data` to it. The URL is a
|
|
815
|
+
plain concatenation, so the property and `path` carry their own trailing slashes —
|
|
816
|
+
same contract as `email.template.base.url`.
|
|
817
|
+
2. `PdfService.renderHtmlToUploadableFile()` — the bytes, named (`.pdf` appended when
|
|
818
|
+
the file name lacks it).
|
|
819
|
+
3. `DocumentService.uploadSingleDocument()` — the object goes to the active driver and
|
|
820
|
+
one `sys_document_uploads` row records it. `pathIdentifier` is resolved through
|
|
821
|
+
`resolvePathPrefix()` first, so the destination folder is a `document.path.*` system
|
|
822
|
+
property rather than a caller-supplied path.
|
|
823
|
+
4. `DocumentService.setDocument(…, { systemGenerated: true })` — the `sys_documents`
|
|
824
|
+
row linking that upload to your record.
|
|
825
|
+
|
|
826
|
+
The upload is deliberately made _without_ `sourceType`/`sourceId` and linked in a
|
|
827
|
+
separate call: those options attach the document as an ordinary upload, and
|
|
828
|
+
`system_generated` is only settable on the explicit `setDocument()` — never from
|
|
829
|
+
`SetDocumentDto`, so the HTTP endpoint cannot claim it.
|
|
830
|
+
|
|
831
|
+
**Seed the catalogue.** A `sys_pdf_templates` row per document, plus the
|
|
832
|
+
`pdf.template.base.url` property; without either, `getPdfHtml()` raises. Manage them
|
|
833
|
+
through [the admin surface](#admin-module) — content manager to define or edit, global
|
|
834
|
+
admin to delete. There is no `PdfTemplateIdentifier` enum: the library dispatches no
|
|
835
|
+
documents of its own, so name yours in an enum in your app rather than inline.
|
|
836
|
+
|
|
837
|
+
### Using PdfService on its own
|
|
838
|
+
|
|
839
|
+
Skip the processor when you already have the HTML, or want the bytes rather than a
|
|
840
|
+
stored document:
|
|
841
|
+
|
|
842
|
+
```ts
|
|
777
843
|
const pdf: Buffer = await this.pdfService.renderHtmlToPdf(html);
|
|
778
844
|
|
|
779
845
|
// …or go straight to bucket storage.
|
|
780
|
-
const file = await this.pdfService.renderHtmlToUploadableFile(
|
|
781
|
-
html,
|
|
782
|
-
'summary-report.pdf',
|
|
783
|
-
);
|
|
846
|
+
const file = await this.pdfService.renderHtmlToUploadableFile(html, 'report.pdf');
|
|
784
847
|
const [link] = await this.documentService.uploadDocument([file], {
|
|
785
848
|
pathPrefix: 'reports',
|
|
786
849
|
});
|
|
787
850
|
```
|
|
788
851
|
|
|
789
|
-
**Install puppeteer.** It is an _optional_ peer dependency — nothing imports it
|
|
790
|
-
|
|
791
|
-
|
|
852
|
+
**Install puppeteer.** It is an _optional_ peer dependency — nothing imports it until a
|
|
853
|
+
PDF is actually requested, so apps that never generate one skip the ~170MB Chromium
|
|
854
|
+
download entirely:
|
|
792
855
|
|
|
793
856
|
```bash
|
|
794
857
|
yarn add puppeteer
|
|
@@ -878,9 +941,15 @@ await new ProcessEmailNotification(emailNotificationService).process({
|
|
|
878
941
|
});
|
|
879
942
|
```
|
|
880
943
|
|
|
944
|
+
The catalogue is managed from [the admin surface](#admin-module) —
|
|
945
|
+
`POST /admin/email-templates` and friends — and `EmailTemplateEntity` extends
|
|
946
|
+
`CommonAdminEntity` for that reason: a row is authored from the back office, never by a
|
|
947
|
+
tenant user.
|
|
948
|
+
|
|
881
949
|
The templates the library itself dispatches are named by the
|
|
882
950
|
`EmailTemplateIdentifier` enum — seed a matching `sys_email_templates` row for each
|
|
883
|
-
one you want delivered
|
|
951
|
+
one you want delivered, and note that these two are exactly the rows a delete must not
|
|
952
|
+
reach:
|
|
884
953
|
|
|
885
954
|
| Identifier | Sent by | Recipient | `data` keys |
|
|
886
955
|
| ----------------------- | ------------------------- | ------------------ | --------------------------------------------------------------------------- |
|
|
@@ -953,7 +1022,8 @@ SQL runs. Results come back as `{ records, total, page, limit, total_pages }`.
|
|
|
953
1022
|
## Admin Module
|
|
954
1023
|
|
|
955
1024
|
`AdminModule` is the back-office surface — tenant onboarding, client/admin user
|
|
956
|
-
registration, tenant listing
|
|
1025
|
+
registration, tenant listing, scheduled-task management and the email/PDF template
|
|
1026
|
+
catalogues. It uses the same
|
|
957
1027
|
imperative auth model as the rest of the app: controllers are open by default and
|
|
958
1028
|
gate each action through `AdminAccessService` before handing the work to a
|
|
959
1029
|
processor.
|
|
@@ -979,42 +1049,73 @@ pass the actor to a processor.
|
|
|
979
1049
|
|
|
980
1050
|
### Endpoints
|
|
981
1051
|
|
|
982
|
-
| Route
|
|
983
|
-
|
|
|
984
|
-
| `POST
|
|
985
|
-
| `POST
|
|
986
|
-
| `GET
|
|
987
|
-
| `
|
|
988
|
-
| `POST
|
|
989
|
-
| `POST
|
|
990
|
-
| `POST
|
|
991
|
-
| `GET
|
|
992
|
-
| `
|
|
993
|
-
| `POST
|
|
994
|
-
| `POST
|
|
995
|
-
| `GET
|
|
996
|
-
| `
|
|
997
|
-
| `POST
|
|
998
|
-
| `POST
|
|
999
|
-
| `
|
|
1000
|
-
| `
|
|
1001
|
-
| `
|
|
1002
|
-
| `POST
|
|
1003
|
-
| `POST
|
|
1004
|
-
| `POST
|
|
1005
|
-
| `GET
|
|
1006
|
-
| `
|
|
1007
|
-
| `POST
|
|
1008
|
-
| `POST
|
|
1009
|
-
| `GET
|
|
1010
|
-
| `
|
|
1011
|
-
| `POST
|
|
1052
|
+
| Route | Min. role | Handler |
|
|
1053
|
+
| ------------------------------------ | --------------- | --------------------------------------------------------------- |
|
|
1054
|
+
| `POST /admin/tenants` | super admin | `TenantDataProcessor` (upsert — send `id` to update) |
|
|
1055
|
+
| `POST /admin/tenants/list` | content reader | `TenantListProcessor` |
|
|
1056
|
+
| `GET /admin/tenants/:id` | content reader | the row plus its `scopes` |
|
|
1057
|
+
| `DELETE /admin/tenants/:id` | super admin | `TenantDeleteProcessor` (cascades to users, keys, grants) |
|
|
1058
|
+
| `POST /admin/tenant-users` | admin | `ClientUserDataProcessor` |
|
|
1059
|
+
| `POST /admin/tenant-users/bulk` | admin | `BulkUserDataProcessor` |
|
|
1060
|
+
| `POST /admin/tenant-users/list` | content reader | `ClientUserListProcessor` |
|
|
1061
|
+
| `GET /admin/tenant-users/:id` | content reader | the row |
|
|
1062
|
+
| `DELETE /admin/tenant-users/:id` | admin | `ClientUserDeleteProcessor` |
|
|
1063
|
+
| `POST /admin/system-users` | super admin | `SystemUserDataProcessor` (upsert — send `id` to update) |
|
|
1064
|
+
| `POST /admin/system-users/list` | content reader | `SystemUserListProcessor` (scoped to `user_type = system.user`) |
|
|
1065
|
+
| `GET /admin/system-users/:id` | content reader | the row |
|
|
1066
|
+
| `DELETE /admin/system-users/:id` | super admin | `SystemUserService.delete` (revokes live sessions) |
|
|
1067
|
+
| `POST /admin/users` | super admin | `AdminUserDataProcessor` |
|
|
1068
|
+
| `POST /admin/users/list` | content reader | `AdminUserListProcessor` |
|
|
1069
|
+
| `GET /admin/users/:id` | content reader | the row |
|
|
1070
|
+
| `DELETE /admin/users/:id` | super admin | `AdminUserDeleteProcessor` |
|
|
1071
|
+
| `POST /admin/roles/list` | admin | `AdminRoleListProcessor` — picker feed (`sys_admin_roles`) |
|
|
1072
|
+
| `POST /admin/roles/tenant/list` | admin | `RoleListProcessor` — picker feed (`sys_roles`) |
|
|
1073
|
+
| `POST /admin/system-roles` | content manager | `SystemRoleDataProcessor` (upsert — send `id` to update) |
|
|
1074
|
+
| `POST /admin/system-roles/list` | content reader | `RoleListProcessor` |
|
|
1075
|
+
| `GET /admin/system-roles/:id` | content reader | the row |
|
|
1076
|
+
| `DELETE /admin/system-roles/:id` | content manager | `RoleService.deleteRole` (cascades to every grant) |
|
|
1077
|
+
| `POST /admin/scheduled-tasks` | content manager | `ScheduledTaskDataProcessor` (upsert — send `id` to update) |
|
|
1078
|
+
| `POST /admin/scheduled-tasks/list` | content reader | `ScheduledTaskListProcessor` |
|
|
1079
|
+
| `GET /admin/scheduled-tasks/:id` | content reader | the row |
|
|
1080
|
+
| `DELETE /admin/scheduled-tasks/:id` | content manager | `ScheduledTaskDeleteProcessor` |
|
|
1081
|
+
| `POST /admin/email-templates` | content manager | `EmailTemplateDataProcessor` (upsert — send `id` to update) |
|
|
1082
|
+
| `POST /admin/email-templates/list` | content reader | `EmailTemplateListProcessor` |
|
|
1083
|
+
| `GET /admin/email-templates/:id` | content reader | the row |
|
|
1084
|
+
| `DELETE /admin/email-templates/:id` | **admin** | `TemplateService.deleteEmailTemplate` |
|
|
1085
|
+
| `POST /admin/pdf-templates` | content manager | `PdfTemplateDataProcessor` (upsert — send `id` to update) |
|
|
1086
|
+
| `POST /admin/pdf-templates/list` | content reader | `PdfTemplateListProcessor` |
|
|
1087
|
+
| `GET /admin/pdf-templates/:id` | content reader | the row |
|
|
1088
|
+
| `DELETE /admin/pdf-templates/:id` | **admin** | `TemplateService.deletePdfTemplate` |
|
|
1089
|
+
| `POST /admin/scopes` | content manager | `ScopeDataProcessor` (upsert — send `id` to update) |
|
|
1090
|
+
| `POST /admin/scopes/list` | content reader | `ScopeListProcessor` |
|
|
1091
|
+
| `GET /admin/scopes/:id` | content reader | the row |
|
|
1092
|
+
| `DELETE /admin/scopes/:id` | content manager | `ScopeService.deleteScope` (cascades to every grant) |
|
|
1093
|
+
| `POST /admin/api-keys` | admin | `ApiKeyDataProcessor` — returns `{ raw_key, api_key }` |
|
|
1094
|
+
| `POST /admin/api-keys/list` | content reader | `ApiKeyListProcessor` |
|
|
1095
|
+
| `GET /admin/api-keys/:id` | content reader | the row, its `scopes`, and `key` from admin up |
|
|
1096
|
+
| `POST /admin/api-keys/:id/disable` | admin | `ApiKeyService.disableApiKey` (reversible) |
|
|
1097
|
+
| `DELETE /admin/api-keys/:id` | admin | `ApiKeyService.deleteApiKey` (soft, and revokes) |
|
|
1012
1098
|
|
|
1013
1099
|
List endpoints are `POST .../list` with the filter payload in the body (a
|
|
1014
1100
|
`CommonListFilterDto`) — see [List Endpoints & Filtering](#list-endpoints--filtering).
|
|
1015
1101
|
Deletes and the API-key disable are single-action, so they sit on the domain service
|
|
1016
1102
|
rather than in a processor; processors are for the writes that validate a payload.
|
|
1017
1103
|
|
|
1104
|
+
**Template catalogues.** `sys_email_templates` and `sys_pdf_templates` are the same
|
|
1105
|
+
surface across two controllers — same routes, same DTO, and a PDF template simply has
|
|
1106
|
+
no `subject` because a document has no envelope to address. Neither row holds markup:
|
|
1107
|
+
`path` + `identifier` are appended to a base-URL system property to reach the remote
|
|
1108
|
+
template service, so the catalogue is a table of pointers.
|
|
1109
|
+
|
|
1110
|
+
Reading is content-reader work and writing content-manager work, the same split scopes
|
|
1111
|
+
get. **Deleting sits one level higher, at global admin** — the one place these differ
|
|
1112
|
+
from every other catalogue. An identifier is named by _code_
|
|
1113
|
+
(`EmailTemplateIdentifier.TENANT_ONBOARDED`, whatever `ProcessPdfDocument` asks for),
|
|
1114
|
+
so deleting a row does not change what a flow says, it stops the flow rendering at all
|
|
1115
|
+
— and only at send/generate time, as an `OperationException`. Nothing cascades: the
|
|
1116
|
+
remote template, every mail already sent and every document already generated are left
|
|
1117
|
+
exactly as they are.
|
|
1118
|
+
|
|
1018
1119
|
**Scopes and grants.** A scope is defined once in `sys_scopes` (content manager),
|
|
1019
1120
|
then granted to the principals that hold it. `AddTenantDto.scope_ids` carries the
|
|
1020
1121
|
tenant's whole scope set — `setScopes()` grants what is new and soft-removes what is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.module.d.ts","sourceRoot":"","sources":["../../src/admin/admin.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,gBAAgB,CAAC;AAIvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"admin.module.d.ts","sourceRoot":"","sources":["../../src/admin/admin.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,gBAAgB,CAAC;AAIvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAa9D,qBAMa,WAAW;IACtB,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAE,kBAAuB,GAAG,aAAa;CAcjE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.module.js","sourceRoot":"","sources":["../../src/admin/admin.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,qDAAiD;AACjD,2DAAuD;AACvD,+CAA2C;AAE3C,6EAAyE;AACzE,6EAAwE;
|
|
1
|
+
{"version":3,"file":"admin.module.js","sourceRoot":"","sources":["../../src/admin/admin.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,qDAAiD;AACjD,2DAAuD;AACvD,+CAA2C;AAE3C,6EAAyE;AACzE,6EAAwE;AAoBjE,IAAM,WAAW,mBAAjB,MAAM,WAAW;IACtB,MAAM,CAAC,QAAQ,CAAC,UAA8B,EAAE;QAC9C,OAAO;YACL,MAAM,EAAE,aAAW;YACnB,OAAO,EAAE;gBACP,wBAAU,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAC5B,4BAAY,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAC9B,wCAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACpC,6CAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC;aACvC;YACD,WAAW,EAAE,CAAC,GAAG,wBAAU,CAAC,WAAW,CAAC;YACxC,SAAS,EAAE,CAAC,GAAG,wBAAU,CAAC,QAAQ,CAAC;YACnC,OAAO,EAAE,CAAC,GAAG,wBAAU,CAAC,QAAQ,CAAC;SAClC,CAAC;IACJ,CAAC;CACF,CAAA;AAfY,kCAAW;sBAAX,WAAW;IANvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,wBAAU,EAAE,4BAAY,EAAE,wCAAkB,EAAE,6CAAoB,CAAC;QAC7E,WAAW,EAAE,CAAC,GAAG,wBAAU,CAAC,WAAW,CAAC;QACxC,SAAS,EAAE,CAAC,GAAG,wBAAU,CAAC,QAAQ,CAAC;QACnC,OAAO,EAAE,CAAC,GAAG,wBAAU,CAAC,QAAQ,CAAC;KAClC,CAAC;GACW,WAAW,CAevB"}
|
|
@@ -98,7 +98,7 @@ __decorate([
|
|
|
98
98
|
__metadata("design:returntype", Promise)
|
|
99
99
|
], AdminApiKeyController.prototype, "disable", null);
|
|
100
100
|
__decorate([
|
|
101
|
-
(0, common_1.
|
|
101
|
+
(0, common_1.Delete)(':id'),
|
|
102
102
|
(0, swagger_1.ApiOperation)({
|
|
103
103
|
summary: 'Delete an API key.',
|
|
104
104
|
description: 'Soft delete: the row keeps its data with `deleted_at` set and drops out of every listing. It is revoked in the same transaction, along with its scope grants — key validation matches on `is_active`/`revoked_at`, so a row that only left the listings would keep authenticating requests. Requires at least the global admin role.',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.api.key.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.api.key.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"admin.api.key.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.api.key.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA4E;AAC5E,6CAAuE;AACvE,mEAA+D;AAC/D,yEAAoE;AACpE,sFAA4E;AAC5E,2EAAsE;AACtE,2EAAsE;AACtE,gFAA0E;AAC1E,gFAA0E;AAC1E,6DAAuD;AACvD,+DAAyD;AAUlD,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAChC,YACmB,kBAAsC,EACtC,aAA4B,EAC5B,UAAsB;QAFtB,uBAAkB,GAAlB,kBAAkB,CAAoB;QACtC,kBAAa,GAAb,aAAa,CAAe;QAC5B,eAAU,GAAV,UAAU,CAAY;IACtC,CAAC;IAQE,AAAN,KAAK,CAAC,KAAK,CAAS,GAAiB;QACnC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,CAAC;QAC/D,OAAO,IAAI,4CAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACxE,CAAC;IAQK,AAAN,KAAK,CAAC,IAAI,CAAS,GAAkB;QACnC,MAAM,IAAI,CAAC,kBAAkB,CAAC,qBAAqB,EAAE,CAAC;QACtD,OAAO,IAAI,4CAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/D,CAAC;IAQK,AAAN,KAAK,CAAC,MAAM,CAAU,EAAE,EAAE,EAAmB;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,qBAAqB,EAAE,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,CAAC,YAAY,CACjD,MAAM,EACN,0CAAgB,CAAC,YAAY,CAC9B,CAAC;QAEF,OAAO,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;IAQK,AAAN,KAAK,CAAC,OAAO,CAAU,EAAE,EAAE,EAAmB;QAC5C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,CAAC;QAC/D,OAAO,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IAQK,AAAN,KAAK,CAAC,MAAM,CAAU,EAAE,EAAE,EAAmB;QAC3C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,CAAC;QAC/D,OAAO,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;CACF,CAAA;AAlEY,sDAAqB;AAa1B;IANL,IAAA,aAAI,GAAE;IACN,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,gCAAgC;QACzC,WAAW,EACT,0MAA0M;KAC7M,CAAC;IACW,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,8BAAY;;kDAGpC;AAQK;IANL,IAAA,aAAI,EAAC,MAAM,CAAC;IACZ,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,mCAAmC;QAC5C,WAAW,EACT,uKAAuK;KAC1K,CAAC;IACU,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,gCAAa;;iDAGpC;AAQK;IANL,IAAA,YAAG,EAAC,KAAK,CAAC;IACV,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,uBAAuB;QAChC,WAAW,EACT,mWAAmW;KACtW,CAAC;IACY,WAAA,IAAA,cAAK,GAAE,CAAA;;qCAAS,mCAAe;;mDAQ5C;AAQK;IANL,IAAA,aAAI,EAAC,aAAa,CAAC;IACnB,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,qBAAqB;QAC9B,WAAW,EACT,sLAAsL;KACzL,CAAC;IACa,WAAA,IAAA,cAAK,GAAE,CAAA;;qCAAS,mCAAe;;oDAG7C;AAQK;IANL,IAAA,eAAM,EAAC,KAAK,CAAC;IACb,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,oBAAoB;QAC7B,WAAW,EACT,sUAAsU;KACzU,CAAC;IACY,WAAA,IAAA,cAAK,GAAE,CAAA;;qCAAS,mCAAe;;mDAG5C;gCAjEU,qBAAqB;IAHjC,IAAA,iBAAO,EAAC,kBAAkB,CAAC;IAC3B,IAAA,uBAAa,GAAE;IACf,IAAA,mBAAU,EAAC,oBAAoB,CAAC;qCAGQ,yCAAkB;QACvB,+BAAa;QAChB,wBAAU;GAJ9B,qBAAqB,CAkEjC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SqlService } from '../../common/services/sql.service';
|
|
2
|
+
import { AdminAccessService } from '../services/admin.access.service';
|
|
3
|
+
import { TemplateService } from '../services/template.service';
|
|
4
|
+
import { CommonParamsDto } from '../../common/dtos/common.params.dto';
|
|
5
|
+
import { AddEmailTemplateDto } from '../dtos/add.email.template.dto';
|
|
6
|
+
import { EmailTemplateListDto } from '../dtos/email.template.list.dto';
|
|
7
|
+
import { EmailTemplateEntity } from '../../notification/entities/email.template.entity';
|
|
8
|
+
export declare class AdminEmailTemplateController {
|
|
9
|
+
private readonly adminAccessService;
|
|
10
|
+
private readonly templateService;
|
|
11
|
+
private readonly sqlService;
|
|
12
|
+
constructor(adminAccessService: AdminAccessService, templateService: TemplateService, sqlService: SqlService);
|
|
13
|
+
save(dto: AddEmailTemplateDto): Promise<EmailTemplateEntity>;
|
|
14
|
+
list(dto: EmailTemplateListDto): Promise<{
|
|
15
|
+
records: import("../..").SqlRow[];
|
|
16
|
+
total: number;
|
|
17
|
+
page: number;
|
|
18
|
+
limit: number;
|
|
19
|
+
total_pages: number;
|
|
20
|
+
}>;
|
|
21
|
+
detail({ id }: CommonParamsDto): Promise<EmailTemplateEntity>;
|
|
22
|
+
remove({ id }: CommonParamsDto): Promise<import("../..").DeleteResult>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=admin.email.template.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.email.template.controller.d.ts","sourceRoot":"","sources":["../../../src/admin/controllers/admin.email.template.controller.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAGtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mDAAmD,CAAC;AAQxF,qBAGa,4BAA4B;IAErC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAFV,kBAAkB,EAAE,kBAAkB,EACtC,eAAe,EAAE,eAAe,EAChC,UAAU,EAAE,UAAU;IASnC,IAAI,CAAS,GAAG,EAAE,mBAAmB;IAUrC,IAAI,CAAS,GAAG,EAAE,oBAAoB;;;;;;;IAWtC,MAAM,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAgBtE,MAAM,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe;CAI9C"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.AdminEmailTemplateController = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
18
|
+
const sql_service_1 = require("../../common/services/sql.service");
|
|
19
|
+
const admin_access_service_1 = require("../services/admin.access.service");
|
|
20
|
+
const template_service_1 = require("../services/template.service");
|
|
21
|
+
const common_params_dto_1 = require("../../common/dtos/common.params.dto");
|
|
22
|
+
const email_template_data_processor_1 = require("../libraries/email.template.data.processor");
|
|
23
|
+
const email_template_list_processor_1 = require("../libraries/email.template.list.processor");
|
|
24
|
+
const add_email_template_dto_1 = require("../dtos/add.email.template.dto");
|
|
25
|
+
const email_template_list_dto_1 = require("../dtos/email.template.list.dto");
|
|
26
|
+
const email_template_entity_1 = require("../../notification/entities/email.template.entity");
|
|
27
|
+
let AdminEmailTemplateController = class AdminEmailTemplateController {
|
|
28
|
+
constructor(adminAccessService, templateService, sqlService) {
|
|
29
|
+
this.adminAccessService = adminAccessService;
|
|
30
|
+
this.templateService = templateService;
|
|
31
|
+
this.sqlService = sqlService;
|
|
32
|
+
}
|
|
33
|
+
async save(dto) {
|
|
34
|
+
const { user } = await this.adminAccessService.validateContentManager();
|
|
35
|
+
return new email_template_data_processor_1.EmailTemplateDataProcessor(user).process(dto);
|
|
36
|
+
}
|
|
37
|
+
async list(dto) {
|
|
38
|
+
await this.adminAccessService.validateContentReader();
|
|
39
|
+
return new email_template_list_processor_1.EmailTemplateListProcessor(this.sqlService).process(dto);
|
|
40
|
+
}
|
|
41
|
+
async detail({ id }) {
|
|
42
|
+
await this.adminAccessService.validateContentReader();
|
|
43
|
+
const emailTemplate = await email_template_entity_1.EmailTemplateEntity.findOne({ where: { id } });
|
|
44
|
+
if (!emailTemplate)
|
|
45
|
+
throw new common_1.NotFoundException('No email template exists for this id');
|
|
46
|
+
return emailTemplate;
|
|
47
|
+
}
|
|
48
|
+
async remove({ id }) {
|
|
49
|
+
const { user } = await this.adminAccessService.validateAdmin();
|
|
50
|
+
return this.templateService.deleteEmailTemplate(id, user);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
exports.AdminEmailTemplateController = AdminEmailTemplateController;
|
|
54
|
+
__decorate([
|
|
55
|
+
(0, common_1.Post)(),
|
|
56
|
+
(0, swagger_1.ApiOperation)({
|
|
57
|
+
summary: 'Define an email template, or update an existing one.',
|
|
58
|
+
description: 'Send an `id` to edit that template; omit it to define a new one. `identifier` is what sending code names and is unique across the catalogue. Requires at least the global content manager role.',
|
|
59
|
+
}),
|
|
60
|
+
__param(0, (0, common_1.Body)()),
|
|
61
|
+
__metadata("design:type", Function),
|
|
62
|
+
__metadata("design:paramtypes", [add_email_template_dto_1.AddEmailTemplateDto]),
|
|
63
|
+
__metadata("design:returntype", Promise)
|
|
64
|
+
], AdminEmailTemplateController.prototype, "save", null);
|
|
65
|
+
__decorate([
|
|
66
|
+
(0, common_1.Post)('list'),
|
|
67
|
+
(0, swagger_1.ApiOperation)({
|
|
68
|
+
summary: 'List, search and filter email templates.',
|
|
69
|
+
description: 'Requires at least the global content reader role.',
|
|
70
|
+
}),
|
|
71
|
+
__param(0, (0, common_1.Body)()),
|
|
72
|
+
__metadata("design:type", Function),
|
|
73
|
+
__metadata("design:paramtypes", [email_template_list_dto_1.EmailTemplateListDto]),
|
|
74
|
+
__metadata("design:returntype", Promise)
|
|
75
|
+
], AdminEmailTemplateController.prototype, "list", null);
|
|
76
|
+
__decorate([
|
|
77
|
+
(0, common_1.Get)(':id'),
|
|
78
|
+
(0, swagger_1.ApiOperation)({
|
|
79
|
+
summary: 'One email template, in full.',
|
|
80
|
+
description: 'Everything the listing leaves out — the `attributes` bag and the authoring trail. Requires at least the global content reader role.',
|
|
81
|
+
}),
|
|
82
|
+
__param(0, (0, common_1.Param)()),
|
|
83
|
+
__metadata("design:type", Function),
|
|
84
|
+
__metadata("design:paramtypes", [common_params_dto_1.CommonParamsDto]),
|
|
85
|
+
__metadata("design:returntype", Promise)
|
|
86
|
+
], AdminEmailTemplateController.prototype, "detail", null);
|
|
87
|
+
__decorate([
|
|
88
|
+
(0, common_1.Delete)(':id'),
|
|
89
|
+
(0, swagger_1.ApiOperation)({
|
|
90
|
+
summary: 'Delete an email template.',
|
|
91
|
+
description: 'Soft delete: the row keeps its data with `deleted_at` set and drops out of every listing. Nothing cascades — the remote template and every mail already sent from it are untouched — but a flow that still names the identifier stops rendering. Requires at least the global admin role.',
|
|
92
|
+
}),
|
|
93
|
+
__param(0, (0, common_1.Param)()),
|
|
94
|
+
__metadata("design:type", Function),
|
|
95
|
+
__metadata("design:paramtypes", [common_params_dto_1.CommonParamsDto]),
|
|
96
|
+
__metadata("design:returntype", Promise)
|
|
97
|
+
], AdminEmailTemplateController.prototype, "remove", null);
|
|
98
|
+
exports.AdminEmailTemplateController = AdminEmailTemplateController = __decorate([
|
|
99
|
+
(0, swagger_1.ApiTags)('Admin - Email Templates'),
|
|
100
|
+
(0, swagger_1.ApiBearerAuth)(),
|
|
101
|
+
(0, common_1.Controller)('api/admin/email-templates'),
|
|
102
|
+
__metadata("design:paramtypes", [admin_access_service_1.AdminAccessService,
|
|
103
|
+
template_service_1.TemplateService,
|
|
104
|
+
sql_service_1.SqlService])
|
|
105
|
+
], AdminEmailTemplateController);
|
|
106
|
+
//# sourceMappingURL=admin.email.template.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.email.template.controller.js","sourceRoot":"","sources":["../../../src/admin/controllers/admin.email.template.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SqlService } from '../../common/services/sql.service';
|
|
2
|
+
import { AdminAccessService } from '../services/admin.access.service';
|
|
3
|
+
import { TemplateService } from '../services/template.service';
|
|
4
|
+
import { CommonParamsDto } from '../../common/dtos/common.params.dto';
|
|
5
|
+
import { AddPdfTemplateDto } from '../dtos/add.pdf.template.dto';
|
|
6
|
+
import { PdfTemplateListDto } from '../dtos/pdf.template.list.dto';
|
|
7
|
+
import { PdfTemplateEntity } from '../../document/entities/pdf.template.entity';
|
|
8
|
+
export declare class AdminPdfTemplateController {
|
|
9
|
+
private readonly adminAccessService;
|
|
10
|
+
private readonly templateService;
|
|
11
|
+
private readonly sqlService;
|
|
12
|
+
constructor(adminAccessService: AdminAccessService, templateService: TemplateService, sqlService: SqlService);
|
|
13
|
+
save(dto: AddPdfTemplateDto): Promise<PdfTemplateEntity>;
|
|
14
|
+
list(dto: PdfTemplateListDto): Promise<{
|
|
15
|
+
records: import("../..").SqlRow[];
|
|
16
|
+
total: number;
|
|
17
|
+
page: number;
|
|
18
|
+
limit: number;
|
|
19
|
+
total_pages: number;
|
|
20
|
+
}>;
|
|
21
|
+
detail({ id }: CommonParamsDto): Promise<PdfTemplateEntity>;
|
|
22
|
+
remove({ id }: CommonParamsDto): Promise<import("../..").DeleteResult>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=admin.pdf.template.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.pdf.template.controller.d.ts","sourceRoot":"","sources":["../../../src/admin/controllers/admin.pdf.template.controller.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAGtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAQhF,qBAGa,0BAA0B;IAEnC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAFV,kBAAkB,EAAE,kBAAkB,EACtC,eAAe,EAAE,eAAe,EAChC,UAAU,EAAE,UAAU;IASnC,IAAI,CAAS,GAAG,EAAE,iBAAiB;IAUnC,IAAI,CAAS,GAAG,EAAE,kBAAkB;;;;;;;IAWpC,MAAM,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAgBpE,MAAM,CAAU,EAAE,EAAE,EAAE,EAAE,eAAe;CAI9C"}
|