@tstdl/base 0.93.174 → 0.93.176

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.
Files changed (50) hide show
  1. package/api/server/middlewares/response-time.middleware.js +2 -5
  2. package/audit/auditor.js +1 -1
  3. package/authentication/client/authentication.service.js +13 -0
  4. package/authentication/server/authentication.service.d.ts +1 -1
  5. package/authentication/server/authentication.service.js +3 -3
  6. package/authentication/tests/authentication.client-service-refresh.test.js +19 -0
  7. package/authentication/tests/authentication.refresh-busy-loop.test.d.ts +1 -0
  8. package/authentication/tests/authentication.refresh-busy-loop.test.js +84 -0
  9. package/circuit-breaker/postgres/circuit-breaker.js +1 -1
  10. package/document-management/server/services/singleton.js +1 -1
  11. package/errors/format.d.ts +6 -1
  12. package/errors/format.js +1 -1
  13. package/http/index.d.ts +1 -0
  14. package/http/index.js +1 -0
  15. package/http/server/http-server-response.d.ts +2 -0
  16. package/http/server/http-server-response.js +2 -0
  17. package/http/server/node/node-http-server.js +3 -0
  18. package/http/server-timing.d.ts +31 -0
  19. package/http/server-timing.js +47 -0
  20. package/http/tests/server-timing.test.d.ts +1 -0
  21. package/http/tests/server-timing.test.js +42 -0
  22. package/key-value-store/postgres/key-value-store.service.js +1 -1
  23. package/lock/postgres/provider.js +1 -1
  24. package/mail/README.md +1 -1
  25. package/mail/drizzle/0001_married_tarantula.sql +10 -0
  26. package/mail/drizzle/meta/0001_snapshot.json +69 -0
  27. package/mail/drizzle/meta/_journal.json +7 -0
  28. package/mail/index.d.ts +1 -0
  29. package/mail/index.js +1 -0
  30. package/mail/mail.service.d.ts +21 -4
  31. package/mail/mail.service.js +44 -13
  32. package/mail/models/mail-log.model.d.ts +2 -1
  33. package/mail/models/mail-log.model.js +1 -1
  34. package/mail/task-definitions.d.ts +20 -0
  35. package/mail/task-definitions.js +1 -0
  36. package/package.json +3 -3
  37. package/rate-limit/postgres/postgres-rate-limiter.js +1 -1
  38. package/task-queue/postgres/drizzle/0001_rapid_infant_terrible.sql +16 -0
  39. package/task-queue/postgres/drizzle/meta/0001_snapshot.json +753 -0
  40. package/task-queue/postgres/drizzle/meta/_journal.json +7 -0
  41. package/task-queue/postgres/task-queue.js +13 -13
  42. package/task-queue/postgres/task.model.d.ts +2 -1
  43. package/task-queue/postgres/task.model.js +3 -3
  44. package/task-queue/task-queue.d.ts +4 -3
  45. package/task-queue/task-queue.js +12 -2
  46. package/task-queue/tests/coverage-branch.test.js +1 -1
  47. package/task-queue/tests/dependencies.test.js +2 -2
  48. package/task-queue/tests/queue.test.js +2 -2
  49. package/task-queue/tests/worker.test.js +39 -5
  50. package/tsconfig.json +0 -2
@@ -4,45 +4,62 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  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;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Singleton, inject, provide } from '../injector/index.js';
7
+ import { sql } from 'drizzle-orm';
8
+ import { serializeError } from '../errors/index.js';
9
+ import { Singleton, afterResolve, inject, provide } from '../injector/index.js';
8
10
  import { Logger } from '../logger/index.js';
11
+ import { buildJsonb } from '../orm/index.js';
9
12
  import { DatabaseConfig, injectRepository } from '../orm/server/index.js';
13
+ import { TaskProcessResult, TaskQueue } from '../task-queue/task-queue.js';
10
14
  import { TemplateService } from '../templates/template.service.js';
11
15
  import { currentTimestamp } from '../utils/date-time.js';
12
- import { formatError } from '../errors/index.js';
13
16
  import { assertDefined } from '../utils/type-guards.js';
14
17
  import { MailClient, MailClientConfig } from './mail.client.js';
15
18
  import { MailLog } from './models/index.js';
19
+ import { mailLog as mailLogTable } from './models/schemas.js';
16
20
  import { MailModuleConfig } from './module.js';
17
21
  import { MAIL_DEFAULT_DATA } from './tokens.js';
18
22
  let MailService = class MailService {
19
23
  #mailClient = inject(MailClient);
20
24
  #templateService = inject(TemplateService);
21
25
  #mailLogRepository = injectRepository(MailLog);
26
+ #taskQueue = inject((TaskQueue), 'mail');
22
27
  #defaultClientConfig = inject(MailClientConfig, undefined, { optional: true });
23
28
  #defaultData = inject(MAIL_DEFAULT_DATA, undefined, { optional: true });
24
29
  #logger = inject(Logger, 'MailService');
25
- async send(mailData, clientConfigOrTemplateName, templateNameOrNothing) {
26
- const clientConfig = (typeof clientConfigOrTemplateName == 'object') ? clientConfigOrTemplateName : this.#defaultClientConfig;
27
- const templateName = (typeof clientConfigOrTemplateName == 'object') ? templateNameOrNothing : clientConfigOrTemplateName;
28
- assertDefined(clientConfig, 'No mail client config provided.');
30
+ [afterResolve](_, { cancellationSignal }) {
31
+ this.#taskQueue.process({ cancellationSignal, types: ['send-email', 'send-template-email'] }, async (context) => {
32
+ if (context.type == 'send-email') {
33
+ await this.send(context.data);
34
+ }
35
+ else {
36
+ await this.sendTemplate(context.data.templateKey, context.data.mailData, context.data.templateContext);
37
+ }
38
+ return TaskProcessResult.Complete();
39
+ });
40
+ }
41
+ async send(mailData, options) {
42
+ const config = options?.clientConfig ?? this.#defaultClientConfig;
43
+ assertDefined(config, 'No mail client config provided.');
29
44
  const data = { ...this.#defaultData, ...mailData };
30
45
  let mailLog;
31
46
  mailLog = await this.#mailLogRepository.insert({
32
47
  timestamp: currentTimestamp(),
33
- template: templateName ?? null,
48
+ template: options?.templateName ?? null,
34
49
  data,
35
50
  sendResult: null,
36
- errors: null,
51
+ errors: [],
37
52
  });
38
53
  try {
39
- const result = await this.#mailClient.send(data, clientConfig);
54
+ const result = await this.#mailClient.send(data, config);
40
55
  await this.#mailLogRepository.update(mailLog.id, { sendResult: result });
41
56
  return result;
42
57
  }
43
58
  catch (error) {
44
59
  try {
45
- await this.#mailLogRepository.update(mailLog.id, { errors: [formatError(error)] });
60
+ await this.#mailLogRepository.update(mailLog.id, {
61
+ errors: sql `${mailLogTable.errors} || ${buildJsonb([serializeError(error)])}`,
62
+ });
46
63
  }
47
64
  catch (logError) {
48
65
  this.#logger.error(logError);
@@ -50,16 +67,30 @@ let MailService = class MailService {
50
67
  throw error;
51
68
  }
52
69
  }
53
- async sendTemplate(keyOrTemplate, mailData, templateContext, clientConfig) {
70
+ async sendTemplate(keyOrTemplate, mailData, templateContext, options) {
54
71
  const { name, fields: { subject, html, text } } = await this.#templateService.render(keyOrTemplate, templateContext);
55
72
  const fullMailData = { ...mailData, subject, content: { html, text } };
56
- return await this.send(fullMailData, clientConfig, name);
73
+ return await this.send(fullMailData, { ...options, templateName: name });
74
+ }
75
+ async enqueue(mailData, options) {
76
+ const data = { ...this.#defaultData, ...mailData };
77
+ await this.#taskQueue.enqueue('send-email', data, options);
78
+ }
79
+ async enqueueTemplate(keyOrTemplate, mailData, templateContext, options) {
80
+ if (typeof keyOrTemplate == 'string') {
81
+ await this.#taskQueue.enqueue('send-template-email', { templateKey: keyOrTemplate, mailData, templateContext }, options);
82
+ }
83
+ else {
84
+ const { fields: { subject, html, text } } = await this.#templateService.render(keyOrTemplate, templateContext);
85
+ const fullMailData = { ...mailData, subject, content: { html, text } };
86
+ await this.enqueue(fullMailData, options);
87
+ }
57
88
  }
58
89
  };
59
90
  MailService = __decorate([
60
91
  Singleton({
61
92
  providers: [
62
- provide(DatabaseConfig, { useFactory: (_, context) => context.resolve(MailModuleConfig).database ?? context.resolve(DatabaseConfig, undefined, { skipSelf: 2 }) }),
93
+ provide(DatabaseConfig, { useFactory: (_, context) => context.resolve(MailModuleConfig).database ?? context.resolve(DatabaseConfig, undefined, { skipSelf: true }) }),
63
94
  ],
64
95
  })
65
96
  ], MailService);
@@ -1,3 +1,4 @@
1
+ import type { SerializedError } from '../../errors/format.js';
1
2
  import { BaseEntity, type Json, type Timestamp } from '../../orm/index.js';
2
3
  import type { MailData } from './mail-data.model.js';
3
4
  import type { MailSendResult } from './mail-send-result.model.js';
@@ -6,5 +7,5 @@ export declare class MailLog extends BaseEntity {
6
7
  template: string | null;
7
8
  data: Json<MailData>;
8
9
  sendResult: Json<MailSendResult> | null;
9
- errors: string[] | null;
10
+ errors: Json<SerializedError[]>;
10
11
  }
@@ -33,7 +33,7 @@ __decorate([
33
33
  __metadata("design:type", Object)
34
34
  ], MailLog.prototype, "sendResult", void 0);
35
35
  __decorate([
36
- StringProperty({ array: true, nullable: true }),
36
+ JsonProperty(),
37
37
  __metadata("design:type", Object)
38
38
  ], MailLog.prototype, "errors", void 0);
39
39
  MailLog = __decorate([
@@ -0,0 +1,20 @@
1
+ import type { TaskDefinitionMap } from '../task-queue/types.js';
2
+ import type { Record, TypedOmit } from '../types/index.js';
3
+ import type { MailData } from './models/index.js';
4
+ export type MailTemplateTaskData = {
5
+ templateKey: string;
6
+ mailData: TypedOmit<MailData, 'content' | 'subject'>;
7
+ templateContext?: Record<string>;
8
+ };
9
+ export type MailTaskDefinitions = TaskDefinitionMap<{
10
+ 'send-email': {
11
+ data: MailData;
12
+ state: void;
13
+ result: void;
14
+ };
15
+ 'send-template-email': {
16
+ data: MailTemplateTaskData;
17
+ state: void;
18
+ result: void;
19
+ };
20
+ }>;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.174",
3
+ "version": "0.93.176",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -152,8 +152,8 @@
152
152
  "type-fest": "^5.5"
153
153
  },
154
154
  "peerDependencies": {
155
- "@aws-sdk/client-s3": "^3.1014",
156
- "@aws-sdk/s3-request-presigner": "^3.1014",
155
+ "@aws-sdk/client-s3": "^3.1015",
156
+ "@aws-sdk/s3-request-presigner": "^3.1015",
157
157
  "@genkit-ai/google-genai": "^1.30",
158
158
  "@google-cloud/storage": "^7.19",
159
159
  "@toon-format/toon": "^2.1.0",
@@ -56,7 +56,7 @@ PostgresRateLimiter = __decorate([
56
56
  Singleton({
57
57
  argumentIdentityProvider: JSON.stringify,
58
58
  providers: [
59
- provide(DatabaseConfig, { useFactory: (_, context) => context.resolve(PostgresRateLimiterModuleConfig).database ?? context.resolve(DatabaseConfig, undefined, { skipSelf: 2 }) }),
59
+ provide(DatabaseConfig, { useFactory: (_, context) => context.resolve(PostgresRateLimiterModuleConfig).database ?? context.resolve(DatabaseConfig, undefined, { skipSelf: true }) }),
60
60
  ],
61
61
  })
62
62
  ], PostgresRateLimiter);
@@ -0,0 +1,16 @@
1
+ ALTER TABLE "task_queue"."task" RENAME COLUMN "error" TO "errors";--> statement-breakpoint
2
+ ALTER TABLE "task_queue"."task" ALTER COLUMN "errors" SET DATA TYPE jsonb USING (
3
+ CASE
4
+ WHEN "errors" IS NULL THEN '[]'::jsonb
5
+ ELSE jsonb_build_array("errors")
6
+ END
7
+ );--> statement-breakpoint
8
+ ALTER TABLE "task_queue"."task" ALTER COLUMN "errors" SET NOT NULL;--> statement-breakpoint
9
+ ALTER TABLE "task_queue"."task_archive" RENAME COLUMN "error" TO "errors";--> statement-breakpoint
10
+ ALTER TABLE "task_queue"."task_archive" ALTER COLUMN "errors" SET DATA TYPE jsonb USING (
11
+ CASE
12
+ WHEN "errors" IS NULL THEN '[]'::jsonb
13
+ ELSE jsonb_build_array("errors")
14
+ END
15
+ );--> statement-breakpoint
16
+ ALTER TABLE "task_queue"."task_archive" ALTER COLUMN "errors" SET NOT NULL;