@anchan828/nest-cloud-run-queue-worker 3.1.6 → 3.1.8

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 (41) hide show
  1. package/dist/{util.js → cjs/util.js} +1 -1
  2. package/dist/esm/constants.d.ts +6 -0
  3. package/dist/esm/constants.js +7 -0
  4. package/dist/esm/decorators.d.ts +22 -0
  5. package/dist/esm/decorators.js +27 -0
  6. package/dist/esm/explorer.service.d.ts +11 -0
  7. package/dist/esm/explorer.service.js +76 -0
  8. package/dist/esm/index.d.ts +6 -0
  9. package/dist/esm/index.js +5 -0
  10. package/dist/esm/interfaces.d.ts +153 -0
  11. package/dist/esm/interfaces.js +1 -0
  12. package/dist/esm/util.d.ts +33 -0
  13. package/dist/esm/util.js +136 -0
  14. package/dist/esm/worker.controller.d.ts +3 -0
  15. package/dist/esm/worker.controller.js +46 -0
  16. package/dist/esm/worker.d.ts +31 -0
  17. package/dist/esm/worker.js +80 -0
  18. package/dist/esm/worker.module.d.ts +6 -0
  19. package/dist/esm/worker.module.js +59 -0
  20. package/dist/esm/worker.service.d.ts +23 -0
  21. package/dist/esm/worker.service.js +79 -0
  22. package/package.json +21 -7
  23. /package/dist/{constants.d.ts → cjs/constants.d.ts} +0 -0
  24. /package/dist/{constants.js → cjs/constants.js} +0 -0
  25. /package/dist/{decorators.d.ts → cjs/decorators.d.ts} +0 -0
  26. /package/dist/{decorators.js → cjs/decorators.js} +0 -0
  27. /package/dist/{explorer.service.d.ts → cjs/explorer.service.d.ts} +0 -0
  28. /package/dist/{explorer.service.js → cjs/explorer.service.js} +0 -0
  29. /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
  30. /package/dist/{index.js → cjs/index.js} +0 -0
  31. /package/dist/{interfaces.d.ts → cjs/interfaces.d.ts} +0 -0
  32. /package/dist/{interfaces.js → cjs/interfaces.js} +0 -0
  33. /package/dist/{util.d.ts → cjs/util.d.ts} +0 -0
  34. /package/dist/{worker.controller.d.ts → cjs/worker.controller.d.ts} +0 -0
  35. /package/dist/{worker.controller.js → cjs/worker.controller.js} +0 -0
  36. /package/dist/{worker.d.ts → cjs/worker.d.ts} +0 -0
  37. /package/dist/{worker.js → cjs/worker.js} +0 -0
  38. /package/dist/{worker.module.d.ts → cjs/worker.module.d.ts} +0 -0
  39. /package/dist/{worker.module.js → cjs/worker.module.js} +0 -0
  40. /package/dist/{worker.service.d.ts → cjs/worker.service.d.ts} +0 -0
  41. /package/dist/{worker.service.js → cjs/worker.service.js} +0 -0
@@ -58,7 +58,7 @@ function isBase64(value) {
58
58
  if (len <= 4 && customBase64Strs.some((base64Str) => value.startsWith(base64Str))) {
59
59
  return true;
60
60
  }
61
- if ((len === 4 && ![2, 3].every((n) => value[n] === "=")) || !len || len % 4 !== 0 || /[^A-Z0-9+\/=]/i.test(value)) {
61
+ if ((len === 4 && ![2, 3].every((n) => value[n] === "=")) || !len || len % 4 !== 0 || /[^A-Z0-9+/=]/i.test(value)) {
62
62
  return false;
63
63
  }
64
64
  const firstPaddingChar = value.indexOf("=");
@@ -0,0 +1,6 @@
1
+ export declare const QUEUE_WORKER_MODULE_OPTIONS = "QUEUE_WORKER_MODULE_OPTIONS";
2
+ export declare const QUEUE_WORKER_DECORATOR = "QUEUE_WORKER_DECORATOR";
3
+ export declare const QUEUE_WORKER_PROCESS_DECORATOR = "QUEUE_WORKER_PROCESS_DECORATOR";
4
+ export declare const ERROR_INVALID_MESSAGE_FORMAT = "Invalid message format. The message must be an object that has a 'name' property.";
5
+ export declare const ERROR_QUEUE_WORKER_NAME_NOT_FOUND = "Worker name not found.";
6
+ export declare const ERROR_WORKER_NOT_FOUND: (name: string) => string;
@@ -0,0 +1,7 @@
1
+ export const QUEUE_WORKER_MODULE_OPTIONS = "QUEUE_WORKER_MODULE_OPTIONS";
2
+ export const QUEUE_WORKER_DECORATOR = "QUEUE_WORKER_DECORATOR";
3
+ export const QUEUE_WORKER_PROCESS_DECORATOR = "QUEUE_WORKER_PROCESS_DECORATOR";
4
+ // errors
5
+ export const ERROR_INVALID_MESSAGE_FORMAT = "Invalid message format. The message must be an object that has a 'name' property.";
6
+ export const ERROR_QUEUE_WORKER_NAME_NOT_FOUND = "Worker name not found.";
7
+ export const ERROR_WORKER_NOT_FOUND = (name) => `Worker '${name}' not found.`;
@@ -0,0 +1,22 @@
1
+ import { QueueWorkerName } from "@anchan828/nest-cloud-run-queue-common";
2
+ import { QueueWorkerOptions, QueueWorkerProcessOptions } from "./interfaces";
3
+ /**
4
+ * Define worker
5
+ *
6
+ * @export
7
+ * @param {QueueWorkerName} name
8
+ * @param {number} [priority=0] Highest priority is 0, and lower the larger integer you use.
9
+ * @returns {ClassDecorator}
10
+ */
11
+ export declare function QueueWorker(name: QueueWorkerName, priority?: number): ClassDecorator;
12
+ export declare function QueueWorker(names: QueueWorkerName[], priority?: number): ClassDecorator;
13
+ export declare function QueueWorker(options: QueueWorkerOptions): ClassDecorator;
14
+ /**
15
+ * Define worker processor
16
+ *
17
+ * @export
18
+ * @param {number} [priority=0] Highest priority is 0, and lower the larger integer you use.
19
+ * @returns {MethodDecorator}
20
+ */
21
+ export declare function QueueWorkerProcess(priority?: number): MethodDecorator;
22
+ export declare function QueueWorkerProcess(options?: QueueWorkerProcessOptions): MethodDecorator;
@@ -0,0 +1,27 @@
1
+ import { SetMetadata } from "@nestjs/common";
2
+ import { QUEUE_WORKER_DECORATOR, QUEUE_WORKER_PROCESS_DECORATOR } from "./constants";
3
+ export function QueueWorker(nameOrOptions, priority = 0) {
4
+ if (Array.isArray(nameOrOptions)) {
5
+ return SetMetadata(QUEUE_WORKER_DECORATOR, {
6
+ names: nameOrOptions,
7
+ priority,
8
+ });
9
+ }
10
+ if (typeof nameOrOptions === "string") {
11
+ return SetMetadata(QUEUE_WORKER_DECORATOR, {
12
+ names: [nameOrOptions],
13
+ priority,
14
+ });
15
+ }
16
+ return SetMetadata(QUEUE_WORKER_DECORATOR, {
17
+ enabled: nameOrOptions.enabled,
18
+ names: Array.isArray(nameOrOptions.name) ? nameOrOptions.name : [nameOrOptions.name],
19
+ priority: nameOrOptions.priority || 0,
20
+ });
21
+ }
22
+ export function QueueWorkerProcess(priorityOrOptions) {
23
+ const options = typeof priorityOrOptions === "number"
24
+ ? { priority: priorityOrOptions }
25
+ : Object.assign({ priority: 0 }, priorityOrOptions);
26
+ return SetMetadata(QUEUE_WORKER_PROCESS_DECORATOR, options);
27
+ }
@@ -0,0 +1,11 @@
1
+ import { DiscoveryService } from "@nestjs/core";
2
+ import { MetadataScanner } from "@nestjs/core/metadata-scanner";
3
+ import { QueueWorkerMetadata } from "./interfaces";
4
+ export declare class QueueWorkerExplorerService {
5
+ private readonly discoveryService;
6
+ private readonly metadataScanner;
7
+ constructor(discoveryService: DiscoveryService, metadataScanner: MetadataScanner);
8
+ explore(): QueueWorkerMetadata[];
9
+ private getWorkers;
10
+ private getQueueWorkerProcessors;
11
+ }
@@ -0,0 +1,76 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Injectable } from "@nestjs/common";
11
+ import { DiscoveryService } from "@nestjs/core";
12
+ import { MetadataScanner } from "@nestjs/core/metadata-scanner";
13
+ import { QUEUE_WORKER_DECORATOR, QUEUE_WORKER_PROCESS_DECORATOR } from "./constants";
14
+ import { sortByPriority } from "./util";
15
+ let QueueWorkerExplorerService = class QueueWorkerExplorerService {
16
+ constructor(discoveryService, metadataScanner) {
17
+ this.discoveryService = discoveryService;
18
+ this.metadataScanner = metadataScanner;
19
+ }
20
+ explore() {
21
+ const workers = this.getWorkers();
22
+ for (const worker of workers) {
23
+ worker.processors = sortByPriority(this.getQueueWorkerProcessors(worker));
24
+ }
25
+ return sortByPriority(workers);
26
+ }
27
+ getWorkers() {
28
+ const metadata = [];
29
+ for (const classInstanceWrapper of this.discoveryService
30
+ .getProviders()
31
+ .filter((instanceWrapper) => instanceWrapper.instance?.constructor)) {
32
+ const args = Reflect.getMetadata(QUEUE_WORKER_DECORATOR, classInstanceWrapper.instance.constructor);
33
+ if (args && Array.isArray(args.names)) {
34
+ if (args.enabled === false) {
35
+ continue;
36
+ }
37
+ for (const name of args.names) {
38
+ metadata.push({
39
+ className: classInstanceWrapper.metatype.name,
40
+ instance: classInstanceWrapper.instance,
41
+ name,
42
+ priority: args.priority || 0,
43
+ processors: [],
44
+ });
45
+ }
46
+ }
47
+ }
48
+ return metadata;
49
+ }
50
+ getQueueWorkerProcessors(worker) {
51
+ const metadata = [];
52
+ const instance = worker.instance;
53
+ const prototype = Object.getPrototypeOf(instance);
54
+ for (const methodName of this.metadataScanner.getAllMethodNames(prototype)) {
55
+ const args = Reflect.getMetadata(QUEUE_WORKER_PROCESS_DECORATOR, prototype[methodName]);
56
+ if (args) {
57
+ if (args.enabled === false) {
58
+ continue;
59
+ }
60
+ metadata.push({
61
+ priority: args.priority || 0,
62
+ processor: prototype[methodName].bind(instance),
63
+ processorName: `${worker.className}.${methodName}`,
64
+ workerName: worker.name,
65
+ });
66
+ }
67
+ }
68
+ return metadata;
69
+ }
70
+ };
71
+ QueueWorkerExplorerService = __decorate([
72
+ Injectable(),
73
+ __metadata("design:paramtypes", [DiscoveryService,
74
+ MetadataScanner])
75
+ ], QueueWorkerExplorerService);
76
+ export { QueueWorkerExplorerService };
@@ -0,0 +1,6 @@
1
+ export { QueueWorker, QueueWorkerProcess } from "./decorators";
2
+ export { QueueWorkerControllerInterface, QueueWorkerControllerMetadata, QueueWorkerDecodedMessage, QueueWorkerModuleAsyncOptions, QueueWorkerModuleOptions, QueueWorkerModuleOptionsFactory, QueueWorkerOptions, QueueWorkerProcessFailureResult, QueueWorkerProcessOptions, QueueWorkerProcessResult, QueueWorkerProcessSuccessResult, QueueWorkerProcessor, QueueWorkerRawMessage, QueueWorkerReceivedMessage, } from "./interfaces";
3
+ export { decodeMessage } from "./util";
4
+ export { Processor, Worker } from "./worker";
5
+ export { QueueWorkerModule } from "./worker.module";
6
+ export { QueueWorkerService } from "./worker.service";
@@ -0,0 +1,5 @@
1
+ export { QueueWorker, QueueWorkerProcess } from "./decorators";
2
+ export { decodeMessage } from "./util";
3
+ export { Processor, Worker } from "./worker";
4
+ export { QueueWorkerModule } from "./worker.module";
5
+ export { QueueWorkerService } from "./worker.service";
@@ -0,0 +1,153 @@
1
+ import { Message, ModuleAsyncOptions, ModuleOptions, ModuleOptionsFactory, QueueWorkerName } from "@anchan828/nest-cloud-run-queue-common";
2
+ import { RequestMappingMetadata } from "@nestjs/common";
3
+ import { Injectable } from "@nestjs/common/interfaces";
4
+ export interface QueueWorkerModuleOptions extends ModuleOptions {
5
+ /**
6
+ * Whether to return 4xx codes when throw error about nest-cloud-run-queue-pubsub module. Default is false.
7
+ * ex, Returns 204 instead of 400 when worker name not found. Returns 204 instead of 400 when message data is invalid.
8
+ * @type {boolean}
9
+ * @memberof QueueWorkerModuleOptions
10
+ */
11
+ throwModuleError?: boolean;
12
+ /**
13
+ * Max number of processor retry attempts. If an error occurs in a processor, it will try again.
14
+ *
15
+ * @type {number}
16
+ * @memberof QueueWorkerModuleOptions
17
+ */
18
+ maxRetryAttempts?: number;
19
+ /**
20
+ * extra config
21
+ *
22
+ * @type {QueueWorkerExtraConfig}
23
+ * @memberof QueueWorkerModuleOptions
24
+ */
25
+ extraConfig?: QueueWorkerExtraConfig;
26
+ /**
27
+ * Define a Route for the controller.
28
+ * Default: POST /
29
+ * If you provide your own Controller, set it to null.
30
+ * @type {(QueueWorkerControllerMetadata | null)}
31
+ * @memberof QueueWorkerModuleOptions
32
+ */
33
+ workerController?: QueueWorkerControllerMetadata | null;
34
+ }
35
+ export type QueueWorkerModuleAsyncOptions = ModuleAsyncOptions<Omit<QueueWorkerModuleOptions, "workerController">> & Pick<QueueWorkerModuleOptions, "workerController">;
36
+ export type QueueWorkerModuleOptionsFactory = ModuleOptionsFactory<Omit<QueueWorkerModuleOptions, "workerController">> & Pick<QueueWorkerModuleOptions, "workerController">;
37
+ export type QueueWorkerProcessor = <T>(message: T, raw: QueueWorkerRawMessage) => Promise<void> | void;
38
+ export interface QueueWorkerMetadata {
39
+ className: string;
40
+ instance: Injectable;
41
+ processors: QueueWorkerProcessorMetadata[];
42
+ name: QueueWorkerName;
43
+ priority: number;
44
+ }
45
+ export interface QueueWorkerProcessorMetadata extends QueueWorkerProcessDecoratorArgs {
46
+ workerName: QueueWorkerName;
47
+ processorName: string;
48
+ processor: QueueWorkerProcessor;
49
+ }
50
+ export type QueueWorkerExtraConfig = {
51
+ parseReviver?: (key: string, value: any) => any;
52
+ };
53
+ export interface QueueWorkerDecoratorArgs {
54
+ names: QueueWorkerName[];
55
+ /**
56
+ * Highest priority is 0, and lower the larger integer you use.
57
+ *
58
+ * @type {number}
59
+ * @memberof QueueWorkerDecoratorArgs
60
+ */
61
+ priority: number;
62
+ /**
63
+ * If you want to disable the worker, set it to false. Defaults to true.
64
+ */
65
+ enabled?: boolean;
66
+ }
67
+ export interface QueueWorkerProcessDecoratorArgs {
68
+ /**
69
+ * Highest priority is 0, and lower the larger integer you use.
70
+ *
71
+ * @type {number}
72
+ * @memberof QueueWorkerProcessDecoratorArgs
73
+ */
74
+ priority: number;
75
+ /**
76
+ * If you want to disable the process, set it to false. Defaults to true.
77
+ */
78
+ enabled?: boolean;
79
+ }
80
+ export type QueueWorkerRawMessage<T = any> = {
81
+ readonly data?: string | null | Message<T>;
82
+ readonly messageId?: string;
83
+ readonly headers?: Record<string, string>;
84
+ } & Record<string, any>;
85
+ export type QueueWorkerDecodedMessage<T = any> = {
86
+ /**
87
+ * The message ID is a unique identifier.
88
+ * If controller recieve from Pub/Sub, it will be body.message.messageId.
89
+ * If controller recieve from Cloud Tasks, it will be body.message.headers["X-CloudTasks-TaskName"].
90
+ * If nothing is obtained, it will be an empty string.
91
+ */
92
+ readonly id: string;
93
+ readonly data: Message<T>;
94
+ readonly headers?: Record<string, string>;
95
+ readonly raw: QueueWorkerRawMessage;
96
+ };
97
+ export type QueueWorkerReceivedMessage = {
98
+ readonly message: QueueWorkerRawMessage;
99
+ };
100
+ export interface QueueWorkerControllerMetadata extends RequestMappingMetadata {
101
+ /**
102
+ * Default: 200
103
+ *
104
+ * @type {number}
105
+ * @memberof QueueWorkerControllerMetadata
106
+ */
107
+ statusCode?: number;
108
+ /**
109
+ * Whether to throw the error as is when Processor throws an error. Default is true.
110
+ */
111
+ throwError?: boolean;
112
+ }
113
+ export interface QueueWorkerControllerInterface {
114
+ execute(body: QueueWorkerReceivedMessage, headers: Record<string, string>): Promise<void>;
115
+ }
116
+ export interface QueueWorkerOptions {
117
+ /**
118
+ * Worker name. If you want to define multiple names, use an array.
119
+ */
120
+ name: QueueWorkerName | QueueWorkerName[];
121
+ /**
122
+ * Highest priority is 0, and lower the larger integer you use.
123
+ */
124
+ priority?: number;
125
+ /**
126
+ * If you want to disable the worker, set it to false. Defaults to true.
127
+ */
128
+ enabled?: boolean;
129
+ }
130
+ export interface QueueWorkerProcessOptions {
131
+ /**
132
+ * Highest priority is 0, and lower the larger integer you use.
133
+ */
134
+ priority?: number;
135
+ /**
136
+ * If you want to disable the process, set it to false. Defaults to true.
137
+ */
138
+ enabled?: boolean;
139
+ }
140
+ export type QueueWorkerProcessResultBase<T = any> = {
141
+ workerName: QueueWorkerName;
142
+ processorName: string;
143
+ data?: T;
144
+ raw: QueueWorkerRawMessage<T>;
145
+ };
146
+ export type QueueWorkerProcessSuccessResult<T = any> = {
147
+ success: true;
148
+ } & QueueWorkerProcessResultBase<T>;
149
+ export type QueueWorkerProcessFailureResult<T = any> = {
150
+ success: false;
151
+ error: Error;
152
+ } & QueueWorkerProcessResultBase<T>;
153
+ export type QueueWorkerProcessResult<T = any> = QueueWorkerProcessSuccessResult<T> | QueueWorkerProcessFailureResult<T>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ import { Message } from "@anchan828/nest-cloud-run-queue-common";
2
+ import { QueueWorkerDecodedMessage, QueueWorkerRawMessage } from "./interfaces";
3
+ /**
4
+ * parse json string to javascript object.
5
+ * JSON.parse has receiver for Date.parse.
6
+ * @param json
7
+ */
8
+ export declare const parseJSON: <T>(json: string, reviver?: (key: string, value: any) => any) => T;
9
+ /**
10
+ * sort array by priority prop
11
+ *
12
+ * @export
13
+ * @template T
14
+ * @param {T[]} items
15
+ * @returns {T[]}
16
+ */
17
+ export declare function sortByPriority<T extends {
18
+ priority: number;
19
+ }>(items: T[]): T[];
20
+ /**
21
+ * Check if a string is base64 encoded.
22
+ *
23
+ * @export
24
+ * @param {string} value
25
+ * @return {*} {boolean}
26
+ */
27
+ export declare function isBase64<T = any>(value?: string | null | Message<T>): value is string;
28
+ export declare function decodeMessage<T = any>(message: QueueWorkerRawMessage<T> | Message, reviver?: (key: string, value: any) => any): QueueWorkerDecodedMessage<T>;
29
+ export declare function isDecodedMessage<T = any>(message: QueueWorkerRawMessage<T> | QueueWorkerDecodedMessage<T> | Message<T>): message is QueueWorkerDecodedMessage<T>;
30
+ export declare function isTaskMessage<T>(message?: QueueWorkerRawMessage<T> | Message<T> | null): message is Message<T> & {
31
+ headers?: Record<string, string>;
32
+ };
33
+ export declare function isMessage<T>(message?: QueueWorkerRawMessage<T> | Message<T> | null): message is Message<T>;
@@ -0,0 +1,136 @@
1
+ import { BadRequestException } from "@nestjs/common";
2
+ import { ERROR_INVALID_MESSAGE_FORMAT } from "./constants";
3
+ const dateRegExp = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
4
+ /**
5
+ * parse json string to javascript object.
6
+ * JSON.parse has receiver for Date.parse.
7
+ * @param json
8
+ */
9
+ export const parseJSON = (json, reviver) => {
10
+ return JSON.parse(json, (key, value) => reviver ? reviver(key, parseDate(key, value)) : parseDate(key, value));
11
+ };
12
+ function parseDate(key, value) {
13
+ if (typeof value === "string" && value.length === 24 && dateRegExp.test(value)) {
14
+ const date = new Date(value);
15
+ if (+date === +date) {
16
+ return date;
17
+ }
18
+ }
19
+ return value;
20
+ }
21
+ /**
22
+ * sort array by priority prop
23
+ *
24
+ * @export
25
+ * @template T
26
+ * @param {T[]} items
27
+ * @returns {T[]}
28
+ */
29
+ export function sortByPriority(items) {
30
+ return items.sort((x, y) => x.priority - y.priority);
31
+ }
32
+ const customBase64Strs = ["e30"];
33
+ /**
34
+ * Check if a string is base64 encoded.
35
+ *
36
+ * @export
37
+ * @param {string} value
38
+ * @return {*} {boolean}
39
+ */
40
+ export function isBase64(value) {
41
+ if (!value) {
42
+ return false;
43
+ }
44
+ if (typeof value !== "string") {
45
+ return false;
46
+ }
47
+ const len = value.length;
48
+ if (len <= 4 && customBase64Strs.some((base64Str) => value.startsWith(base64Str))) {
49
+ return true;
50
+ }
51
+ if ((len === 4 && ![2, 3].every((n) => value[n] === "=")) || !len || len % 4 !== 0 || /[^A-Z0-9+/=]/i.test(value)) {
52
+ return false;
53
+ }
54
+ const firstPaddingChar = value.indexOf("=");
55
+ return (firstPaddingChar === -1 || firstPaddingChar === len - 1 || (firstPaddingChar === len - 2 && value[len - 1] === "="));
56
+ }
57
+ export function decodeMessage(message, reviver) {
58
+ let data;
59
+ if (isBase64(message.data)) {
60
+ // pubsub
61
+ data = decodeData(message.data, reviver);
62
+ }
63
+ else if (isTaskMessage(message)) {
64
+ // tasks
65
+ data = { data: JSON.parse(JSON.stringify(message.data), reviver), name: message.name };
66
+ }
67
+ else {
68
+ // http / raw
69
+ const _message = isMessage(message) ? message : isMessage(message.data) ? message.data : undefined;
70
+ if (!_message) {
71
+ throw new BadRequestException(ERROR_INVALID_MESSAGE_FORMAT);
72
+ }
73
+ data = _message;
74
+ }
75
+ if (!data) {
76
+ throw new BadRequestException(ERROR_INVALID_MESSAGE_FORMAT);
77
+ }
78
+ return {
79
+ data,
80
+ headers: "headers" in message ? message.headers : undefined,
81
+ id: getMessageId(message),
82
+ raw: message,
83
+ };
84
+ }
85
+ export function isDecodedMessage(message) {
86
+ return "raw" in message;
87
+ }
88
+ export function isTaskMessage(message) {
89
+ if (!message) {
90
+ return false;
91
+ }
92
+ const keys = Object.keys(message);
93
+ return keys.length <= 3 && keys.includes("name") && keys.includes("headers");
94
+ }
95
+ export function isMessage(message) {
96
+ if (!message) {
97
+ return false;
98
+ }
99
+ const keys = Object.keys(message);
100
+ return keys.length <= 3 && keys.includes("name");
101
+ }
102
+ function getMessageId(raw) {
103
+ if (!raw) {
104
+ return "";
105
+ }
106
+ if ("messageId" in raw) {
107
+ return raw.messageId ?? "";
108
+ }
109
+ if ("headers" in raw && raw.headers?.["x-cloudtasks-taskname"]) {
110
+ return raw.headers["x-cloudtasks-taskname"];
111
+ }
112
+ return "";
113
+ }
114
+ function decodeData(data, reviver) {
115
+ if (!data) {
116
+ throw new BadRequestException(ERROR_INVALID_MESSAGE_FORMAT);
117
+ }
118
+ if (Buffer.isBuffer(data)) {
119
+ data = data.toString();
120
+ }
121
+ if (data instanceof Uint8Array) {
122
+ data = new TextDecoder("utf8").decode(data);
123
+ }
124
+ if (isBase64(data)) {
125
+ data = Buffer.from(data, "base64").toString();
126
+ }
127
+ try {
128
+ if (typeof data === "string") {
129
+ return parseJSON(data, reviver);
130
+ }
131
+ return data;
132
+ }
133
+ catch {
134
+ throw new BadRequestException(ERROR_INVALID_MESSAGE_FORMAT);
135
+ }
136
+ }
@@ -0,0 +1,3 @@
1
+ import { Type } from "@nestjs/common";
2
+ import { QueueWorkerControllerInterface, QueueWorkerControllerMetadata } from "./interfaces";
3
+ export declare function getWorkerController(metadata?: QueueWorkerControllerMetadata): Type<QueueWorkerControllerInterface>;
@@ -0,0 +1,46 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Body, Controller, Headers, HttpCode, RequestMapping, RequestMethod } from "@nestjs/common";
14
+ import { QueueWorkerService } from "./worker.service";
15
+ export function getWorkerController(metadata) {
16
+ const path = metadata?.path;
17
+ const method = metadata?.method || RequestMethod.POST;
18
+ const throwError = metadata?.throwError ?? true;
19
+ let WorkerController = class WorkerController {
20
+ constructor(service) {
21
+ this.service = service;
22
+ }
23
+ async execute(body, headers) {
24
+ const results = await this.service.execute({ ...body.message, headers });
25
+ for (const result of results) {
26
+ if (!result.success && throwError) {
27
+ throw result.error;
28
+ }
29
+ }
30
+ }
31
+ };
32
+ __decorate([
33
+ RequestMapping({ method, path }),
34
+ HttpCode(metadata?.statusCode || 200),
35
+ __param(0, Body()),
36
+ __param(1, Headers()),
37
+ __metadata("design:type", Function),
38
+ __metadata("design:paramtypes", [Object, Object]),
39
+ __metadata("design:returntype", Promise)
40
+ ], WorkerController.prototype, "execute", null);
41
+ WorkerController = __decorate([
42
+ Controller(),
43
+ __metadata("design:paramtypes", [QueueWorkerService])
44
+ ], WorkerController);
45
+ return WorkerController;
46
+ }
@@ -0,0 +1,31 @@
1
+ import { QueueWorkerDecodedMessage, QueueWorkerMetadata, QueueWorkerModuleOptions, QueueWorkerProcessorMetadata, QueueWorkerProcessResult } from "./interfaces";
2
+ export declare class Worker<T> {
3
+ private readonly message;
4
+ private readonly metadata;
5
+ private readonly options;
6
+ get name(): string;
7
+ get priority(): number;
8
+ get className(): string;
9
+ constructor(message: QueueWorkerDecodedMessage<T>, metadata: QueueWorkerMetadata, options: QueueWorkerModuleOptions);
10
+ /**
11
+ * Execute all processors in the worker. If you want to execute a each processor, use `getProcessors` method.
12
+ */
13
+ execute(): Promise<QueueWorkerProcessResult[]>;
14
+ /**
15
+ * Get all processors in the worker. Use this method to execute manually when you want to execute only on specific conditions using metadata such as class name or processor name.
16
+ */
17
+ getProcessors(): Processor<T>[];
18
+ }
19
+ export declare class Processor<T> {
20
+ private readonly message;
21
+ private readonly metadata;
22
+ private readonly options;
23
+ get name(): string;
24
+ get priority(): number;
25
+ get workerName(): string;
26
+ constructor(message: QueueWorkerDecodedMessage<T>, metadata: QueueWorkerProcessorMetadata, options: QueueWorkerModuleOptions);
27
+ /**
28
+ * Execute the processor.
29
+ */
30
+ execute(): Promise<QueueWorkerProcessResult<T>>;
31
+ }
@@ -0,0 +1,80 @@
1
+ export class Worker {
2
+ get name() {
3
+ return this.metadata.name;
4
+ }
5
+ get priority() {
6
+ return this.metadata.priority;
7
+ }
8
+ get className() {
9
+ return this.metadata.className;
10
+ }
11
+ constructor(message, metadata, options) {
12
+ this.message = message;
13
+ this.metadata = metadata;
14
+ this.options = options;
15
+ }
16
+ /**
17
+ * Execute all processors in the worker. If you want to execute a each processor, use `getProcessors` method.
18
+ */
19
+ async execute() {
20
+ const results = [];
21
+ const processors = this.getProcessors();
22
+ for (const processor of processors) {
23
+ results.push(await processor.execute());
24
+ }
25
+ return results;
26
+ }
27
+ /**
28
+ * Get all processors in the worker. Use this method to execute manually when you want to execute only on specific conditions using metadata such as class name or processor name.
29
+ */
30
+ getProcessors() {
31
+ return this.metadata.processors.map((processor) => new Processor(this.message, processor, this.options));
32
+ }
33
+ }
34
+ export class Processor {
35
+ get name() {
36
+ return this.metadata.processorName;
37
+ }
38
+ get priority() {
39
+ return this.metadata.priority;
40
+ }
41
+ get workerName() {
42
+ return this.metadata.workerName;
43
+ }
44
+ constructor(message, metadata, options) {
45
+ this.message = message;
46
+ this.metadata = metadata;
47
+ this.options = options;
48
+ }
49
+ /**
50
+ * Execute the processor.
51
+ */
52
+ async execute() {
53
+ const maxRetryAttempts = this.options.maxRetryAttempts ?? 1;
54
+ const resultBase = {
55
+ data: this.message.data.data,
56
+ processorName: this.metadata.processorName,
57
+ raw: this.message.raw,
58
+ workerName: this.metadata.workerName,
59
+ };
60
+ for (let i = 0; i < maxRetryAttempts; i++) {
61
+ try {
62
+ await this.metadata.processor(this.message.data.data, this.message.raw);
63
+ i = maxRetryAttempts;
64
+ }
65
+ catch (error) {
66
+ if (maxRetryAttempts === i + 1) {
67
+ return {
68
+ error,
69
+ success: false,
70
+ ...resultBase,
71
+ };
72
+ }
73
+ }
74
+ }
75
+ return {
76
+ success: true,
77
+ ...resultBase,
78
+ };
79
+ }
80
+ }
@@ -0,0 +1,6 @@
1
+ import { DynamicModule } from "@nestjs/common";
2
+ import { QueueWorkerModuleAsyncOptions, QueueWorkerModuleOptions } from "./interfaces";
3
+ export declare class QueueWorkerModule {
4
+ static register(options?: QueueWorkerModuleOptions): DynamicModule;
5
+ static registerAsync(options: QueueWorkerModuleAsyncOptions): DynamicModule;
6
+ }
@@ -0,0 +1,59 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var QueueWorkerModule_1;
8
+ import { createAsyncProviders, createOptionProvider } from "@anchan828/nest-cloud-run-queue-common";
9
+ import { Logger, Module } from "@nestjs/common";
10
+ import { DiscoveryModule } from "@nestjs/core";
11
+ import { MetadataScanner } from "@nestjs/core/metadata-scanner";
12
+ import { QUEUE_WORKER_MODULE_OPTIONS } from "./constants";
13
+ import { QueueWorkerExplorerService } from "./explorer.service";
14
+ import { getWorkerController } from "./worker.controller";
15
+ import { QueueWorkerService } from "./worker.service";
16
+ let QueueWorkerModule = QueueWorkerModule_1 = class QueueWorkerModule {
17
+ static register(options = {}) {
18
+ const controllers = [];
19
+ const providers = [createOptionProvider(QUEUE_WORKER_MODULE_OPTIONS, options)];
20
+ if (options.workerController !== null) {
21
+ const WorkerController = getWorkerController(options.workerController);
22
+ controllers.push(WorkerController);
23
+ }
24
+ return {
25
+ controllers,
26
+ global: true,
27
+ module: QueueWorkerModule_1,
28
+ providers,
29
+ };
30
+ }
31
+ static registerAsync(options) {
32
+ const controllers = [];
33
+ const providers = [...createAsyncProviders(QUEUE_WORKER_MODULE_OPTIONS, options)];
34
+ if (options.workerController !== null) {
35
+ const WorkerController = getWorkerController(options.workerController);
36
+ controllers.push(WorkerController);
37
+ }
38
+ return {
39
+ controllers,
40
+ global: true,
41
+ imports: [...(options.imports || [])],
42
+ module: QueueWorkerModule_1,
43
+ providers,
44
+ };
45
+ }
46
+ };
47
+ QueueWorkerModule = QueueWorkerModule_1 = __decorate([
48
+ Module({
49
+ exports: [QueueWorkerService],
50
+ imports: [DiscoveryModule],
51
+ providers: [
52
+ MetadataScanner,
53
+ QueueWorkerExplorerService,
54
+ QueueWorkerService,
55
+ { provide: Logger, useValue: new Logger("QueueWorkerModule") },
56
+ ],
57
+ })
58
+ ], QueueWorkerModule);
59
+ export { QueueWorkerModule };
@@ -0,0 +1,23 @@
1
+ import { Message } from "@anchan828/nest-cloud-run-queue-common";
2
+ import { QueueWorkerExplorerService } from "./explorer.service";
3
+ import { QueueWorkerDecodedMessage, QueueWorkerModuleOptions, QueueWorkerProcessResult, QueueWorkerRawMessage } from "./interfaces";
4
+ import { Worker } from "./worker";
5
+ export declare class QueueWorkerService {
6
+ #private;
7
+ private readonly options;
8
+ private readonly explorerService;
9
+ constructor(options: QueueWorkerModuleOptions, explorerService: QueueWorkerExplorerService);
10
+ /**
11
+ * Execute all workers that match the worker name. If you want to execute a each worker, use `getWorkers` method.
12
+ */
13
+ execute<T = any>(meessage: QueueWorkerRawMessage<T>): Promise<QueueWorkerProcessResult<T>[]>;
14
+ execute<T = any>(meessage: Message<T>): Promise<QueueWorkerProcessResult<T>[]>;
15
+ execute<T = any>(meessage: QueueWorkerDecodedMessage<T>): Promise<QueueWorkerProcessResult<T>[]>;
16
+ /**
17
+ * Get all workers that match the worker name. Use this method to execute manually when you want to execute only on specific conditions using metadata such as class name or processor name.
18
+ * If you want to execute all workers simply, use `execute` method.
19
+ */
20
+ getWorkers<T = any>(meessage: QueueWorkerRawMessage<T>): Worker<T>[];
21
+ getWorkers<T = any>(meessage: Message<T>): Worker<T>[];
22
+ getWorkers<T = any>(meessage: QueueWorkerDecodedMessage<T>): Worker<T>[];
23
+ }
@@ -0,0 +1,79 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
14
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
15
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
16
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
17
+ };
18
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
19
+ if (kind === "m") throw new TypeError("Private method is not writable");
20
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
21
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
22
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
23
+ };
24
+ var _QueueWorkerService_instances, _QueueWorkerService__allWorkers, _QueueWorkerService_allWorkers_get;
25
+ import { BadRequestException, Inject, Injectable } from "@nestjs/common";
26
+ import { ERROR_QUEUE_WORKER_NAME_NOT_FOUND, ERROR_WORKER_NOT_FOUND, QUEUE_WORKER_MODULE_OPTIONS } from "./constants";
27
+ import { QueueWorkerExplorerService } from "./explorer.service";
28
+ import { decodeMessage, isDecodedMessage } from "./util";
29
+ import { Worker } from "./worker";
30
+ let QueueWorkerService = class QueueWorkerService {
31
+ constructor(options, explorerService) {
32
+ _QueueWorkerService_instances.add(this);
33
+ this.options = options;
34
+ this.explorerService = explorerService;
35
+ _QueueWorkerService__allWorkers.set(this, void 0);
36
+ }
37
+ async execute(meessage) {
38
+ const decodedMessage = isDecodedMessage(meessage)
39
+ ? meessage
40
+ : decodeMessage(meessage, this.options.extraConfig?.parseReviver);
41
+ if (this.options.throwModuleError && !decodedMessage.data.name) {
42
+ throw new BadRequestException(ERROR_QUEUE_WORKER_NAME_NOT_FOUND);
43
+ }
44
+ const workers = await this.getWorkers(decodedMessage);
45
+ if (this.options.throwModuleError && workers.length === 0) {
46
+ throw new BadRequestException(ERROR_WORKER_NOT_FOUND(decodedMessage.data.name));
47
+ }
48
+ const results = [];
49
+ for (const worker of workers) {
50
+ results.push(...(await worker.execute()));
51
+ }
52
+ return results;
53
+ }
54
+ getWorkers(meessage) {
55
+ const decodedMessage = isDecodedMessage(meessage)
56
+ ? meessage
57
+ : decodeMessage(meessage, this.options.extraConfig?.parseReviver);
58
+ if (!decodedMessage.data.name) {
59
+ return [];
60
+ }
61
+ return __classPrivateFieldGet(this, _QueueWorkerService_instances, "a", _QueueWorkerService_allWorkers_get)
62
+ .filter((worker) => decodedMessage.data.name === worker.name)
63
+ .map((metadata) => new Worker(decodedMessage, metadata, this.options));
64
+ }
65
+ };
66
+ _QueueWorkerService__allWorkers = new WeakMap();
67
+ _QueueWorkerService_instances = new WeakSet();
68
+ _QueueWorkerService_allWorkers_get = function _QueueWorkerService_allWorkers_get() {
69
+ if (!__classPrivateFieldGet(this, _QueueWorkerService__allWorkers, "f")) {
70
+ __classPrivateFieldSet(this, _QueueWorkerService__allWorkers, this.explorerService.explore(), "f");
71
+ }
72
+ return __classPrivateFieldGet(this, _QueueWorkerService__allWorkers, "f");
73
+ };
74
+ QueueWorkerService = __decorate([
75
+ Injectable(),
76
+ __param(0, Inject(QUEUE_WORKER_MODULE_OPTIONS)),
77
+ __metadata("design:paramtypes", [Object, QueueWorkerExplorerService])
78
+ ], QueueWorkerService);
79
+ export { QueueWorkerService };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anchan828/nest-cloud-run-queue-worker",
3
- "version": "3.1.6",
3
+ "version": "3.1.8",
4
4
  "description": "> TODO: description",
5
5
  "homepage": "https://github.com/anchan828/nest-cloud-run-queue/tree/master/packages/worker#readme",
6
6
  "bugs": {
@@ -12,8 +12,8 @@
12
12
  },
13
13
  "license": "MIT",
14
14
  "author": "anchan828 <anchan828@gmail.com>",
15
- "main": "./dist/index.js",
16
- "types": "./dist/index.d.ts",
15
+ "main": "dist/cjs/index.js",
16
+ "types": "dist/cjs/index.d.ts",
17
17
  "directories": {
18
18
  "dist": "dist"
19
19
  },
@@ -21,10 +21,10 @@
21
21
  "dist"
22
22
  ],
23
23
  "scripts": {
24
- "build": "tsc -p tsconfig.build.json",
24
+ "build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",
25
25
  "build:watch": "tsc --watch",
26
26
  "copy:license": "cp ../../LICENSE ./",
27
- "lint": "TIMING=1 eslint --ignore-path ../../.eslintignore '**/*.ts'",
27
+ "lint": "TIMING=1 eslint '**/*.ts'",
28
28
  "lint:fix": "npm run lint -- --fix",
29
29
  "prepublishOnly": "rm -rf dist && npm run build && rm -f dist/*.tsbuildinfo && npm run copy:license",
30
30
  "test": "jest --coverage --logHeapUsage --runInBand",
@@ -33,7 +33,7 @@
33
33
  "watch": "tsc -w"
34
34
  },
35
35
  "dependencies": {
36
- "@anchan828/nest-cloud-run-queue-common": "^3.1.6"
36
+ "@anchan828/nest-cloud-run-queue-common": "^3.1.8"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@nestjs/common": "10.3.10",
@@ -46,5 +46,19 @@
46
46
  "access": "public"
47
47
  },
48
48
  "packageManager": "npm@10.8.2",
49
- "gitHead": "67c758aff5e7ea4fc721cbdfd908b95e08305810"
49
+ "exports": {
50
+ ".": {
51
+ "import": {
52
+ "types": "./dist/esm/index.d.ts",
53
+ "default": "./dist/esm/index.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/cjs/index.d.ts",
57
+ "default": "./dist/cjs/index.js"
58
+ },
59
+ "types": "./dist/cjs/index.d.ts",
60
+ "default": "./dist/cjs/index.js"
61
+ }
62
+ },
63
+ "gitHead": "c6565dcca7c5ed619b5929f3342f55804b05519c"
50
64
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes