@gasboost/client 0.1.0

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 (63) hide show
  1. package/dist/AppsScriptClient.d.ts +30 -0
  2. package/dist/AppsScriptClient.js +43 -0
  3. package/dist/AppsScriptJob.d.ts +28 -0
  4. package/dist/AppsScriptJob.js +84 -0
  5. package/dist/AppsScriptJobQueue.d.ts +14 -0
  6. package/dist/AppsScriptJobQueue.js +40 -0
  7. package/dist/AppsScriptJobRunner.d.ts +20 -0
  8. package/dist/AppsScriptJobRunner.js +93 -0
  9. package/dist/AppsScriptJobStore.d.ts +7 -0
  10. package/dist/AppsScriptJobStore.js +9 -0
  11. package/dist/google.d.ts +36 -0
  12. package/dist/google.js +8 -0
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.js +7 -0
  15. package/dist/job/AppsScriptJob.d.ts +28 -0
  16. package/dist/job/AppsScriptJob.js +84 -0
  17. package/dist/job/AppsScriptJobQueue.d.ts +14 -0
  18. package/dist/job/AppsScriptJobQueue.js +40 -0
  19. package/dist/job/AppsScriptJobRunner.d.ts +20 -0
  20. package/dist/job/AppsScriptJobRunner.js +93 -0
  21. package/dist/job/AppsScriptJobStore.d.ts +7 -0
  22. package/dist/job/AppsScriptJobStore.js +9 -0
  23. package/dist/navigation/AppsScriptContainer.d.ts +9 -0
  24. package/dist/navigation/AppsScriptContainer.js +38 -0
  25. package/dist/navigation/AppsScriptHistoryPipeline.d.ts +9 -0
  26. package/dist/navigation/AppsScriptHistoryPipeline.js +28 -0
  27. package/dist/navigation/AppsScriptIframe.d.ts +9 -0
  28. package/dist/navigation/AppsScriptIframe.js +45 -0
  29. package/dist/navigation/HashProperty.d.ts +7 -0
  30. package/dist/navigation/HashProperty.js +27 -0
  31. package/dist/navigation/NavigationEntry.d.ts +9 -0
  32. package/dist/navigation/NavigationEntry.js +54 -0
  33. package/dist/navigation/NavigationLocation.d.ts +8 -0
  34. package/dist/navigation/NavigationLocation.js +43 -0
  35. package/package.json +20 -0
  36. package/src/AppsScriptClient.ts +81 -0
  37. package/src/google.ts +55 -0
  38. package/src/index.ts +4 -0
  39. package/src/job/AppsScriptJob.ts +85 -0
  40. package/src/job/AppsScriptJobQueue.ts +48 -0
  41. package/src/job/AppsScriptJobRunner.ts +107 -0
  42. package/src/job/AppsScriptJobStore.ts +16 -0
  43. package/src/navigation/AppsScriptContainer.ts +47 -0
  44. package/src/navigation/AppsScriptHistoryPipeline.ts +29 -0
  45. package/src/navigation/AppsScriptIframe.ts +63 -0
  46. package/src/navigation/HashProperty.ts +20 -0
  47. package/src/navigation/NavigationEntry.ts +82 -0
  48. package/src/navigation/NavigationLocation.ts +54 -0
  49. package/tests/AppsScriptClient.spec.ts +322 -0
  50. package/tests/AppsScriptClient.type.spec.ts +52 -0
  51. package/tests/AppsScriptContainer.spec.ts +502 -0
  52. package/tests/AppsScriptHistoryPipeline.spec.ts +303 -0
  53. package/tests/AppsScriptIframe.spec.ts +452 -0
  54. package/tests/AppsScriptJob.spec.ts +83 -0
  55. package/tests/AppsScriptJobQueue.spec.ts +125 -0
  56. package/tests/AppsScriptJobRunner.spec.ts +361 -0
  57. package/tests/HashProperty.spec.ts +29 -0
  58. package/tests/NavigationEntry.spec.ts +507 -0
  59. package/tests/NavigationLocation.spec.ts +189 -0
  60. package/tests/setup.ts +15 -0
  61. package/tsconfig.build.json +14 -0
  62. package/tsconfig.json +6 -0
  63. package/vitest.config.mts +8 -0
@@ -0,0 +1,30 @@
1
+ import { AppsScriptJob } from "./job/AppsScriptJob";
2
+ type RpcResponse = {
3
+ contents: string;
4
+ };
5
+ type RpcDefinition = {
6
+ args: unknown[];
7
+ result: unknown;
8
+ };
9
+ type RpcApp = Record<string, RpcDefinition>;
10
+ type AppsScriptClient<TApp extends RpcApp> = {
11
+ [K in keyof TApp]: TApp[K] extends {
12
+ args: infer TArgs extends unknown[];
13
+ result: infer TResult;
14
+ } ? (...args: TArgs) => Promise<TResult> : never;
15
+ };
16
+ export declare const appsScriptTransport: {
17
+ call(name: string, args: unknown[]): Promise<RpcResponse>;
18
+ };
19
+ interface AppsScriptJobs {
20
+ start: <T>(label: string, execute: () => Promise<T>) => Promise<T>;
21
+ cancel: (jobId: string) => void;
22
+ retry: (jobId: string) => void;
23
+ subscribe: (listener: () => void) => () => void;
24
+ getSnapshot: () => AppsScriptJob<any>[];
25
+ }
26
+ export declare function appsScriptClient<TApp extends RpcApp>(): {
27
+ client: AppsScriptClient<TApp>;
28
+ jobs: AppsScriptJobs;
29
+ };
30
+ export {};
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.appsScriptTransport = void 0;
4
+ exports.appsScriptClient = appsScriptClient;
5
+ const google_1 = require("./google");
6
+ const AppsScriptJobQueue_1 = require("./job/AppsScriptJobQueue");
7
+ const AppsScriptJobRunner_1 = require("./job/AppsScriptJobRunner");
8
+ const AppsScriptJobStore_1 = require("./job/AppsScriptJobStore");
9
+ exports.appsScriptTransport = {
10
+ call(name, args) {
11
+ return new Promise((resolve, reject) => {
12
+ google_1.google.script.run
13
+ .withSuccessHandler(resolve)
14
+ .withFailureHandler(reject)[name](...args);
15
+ });
16
+ },
17
+ };
18
+ function appsScriptClient() {
19
+ const jobQueue = new AppsScriptJobQueue_1.AppsScriptJobQueue();
20
+ const jobRunner = new AppsScriptJobRunner_1.AppsScriptJobRunner(jobQueue);
21
+ const jobStore = (0, AppsScriptJobStore_1.appsScriptJobStore)(jobRunner);
22
+ const client = new Proxy({}, {
23
+ get(_target, property) {
24
+ if (typeof property !== "string") {
25
+ return undefined;
26
+ }
27
+ return (...args) => {
28
+ return jobQueue.enqueue(property, async () => {
29
+ const res = await exports.appsScriptTransport.call(property, args);
30
+ return JSON.parse(res.contents);
31
+ });
32
+ };
33
+ },
34
+ });
35
+ const jobs = {
36
+ start: jobQueue.enqueue.bind(jobQueue),
37
+ cancel: jobRunner.cancel.bind(jobRunner),
38
+ retry: jobRunner.retry.bind(jobRunner),
39
+ subscribe: jobStore.subscribe.bind(jobStore),
40
+ getSnapshot: jobStore.getSnapshot.bind(jobStore),
41
+ };
42
+ return { client, jobs };
43
+ }
@@ -0,0 +1,28 @@
1
+ export declare class AppsScriptJob<T> {
2
+ readonly label: string;
3
+ readonly execute: () => Promise<T>;
4
+ private resolve;
5
+ private reject;
6
+ readonly id: string;
7
+ readonly createdAt: Date;
8
+ private _startedAt;
9
+ private _endedAt;
10
+ private _result;
11
+ private _error;
12
+ constructor(label: string, execute: () => Promise<T>, resolve: (value: T) => void, reject: (reason?: any) => void, id?: string, createdAt?: Date);
13
+ start(): void;
14
+ success(result: T): void;
15
+ fail(error: unknown): void;
16
+ get endedAt(): Date | null;
17
+ get result(): T | null;
18
+ get error(): unknown;
19
+ isPending(): boolean;
20
+ isRunning(): boolean;
21
+ isSuccess(): boolean;
22
+ isFailed(): boolean;
23
+ get status(): "failed" | "pending" | "running" | "success" | "unknown";
24
+ cancel(): boolean;
25
+ }
26
+ export declare class AppsScriptJobCancelledError extends Error {
27
+ constructor();
28
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppsScriptJobCancelledError = exports.AppsScriptJob = void 0;
4
+ class AppsScriptJob {
5
+ label;
6
+ execute;
7
+ resolve;
8
+ reject;
9
+ id;
10
+ createdAt;
11
+ _startedAt = null;
12
+ _endedAt = null;
13
+ _result = null;
14
+ _error = null;
15
+ constructor(label, execute, resolve, reject, id = crypto.randomUUID(), createdAt = new Date()) {
16
+ this.label = label;
17
+ this.execute = execute;
18
+ this.resolve = resolve;
19
+ this.reject = reject;
20
+ this.id = id;
21
+ this.createdAt = createdAt;
22
+ }
23
+ start() {
24
+ this._startedAt = new Date();
25
+ }
26
+ success(result) {
27
+ this._endedAt = new Date();
28
+ this._result = result;
29
+ this.resolve(result);
30
+ }
31
+ fail(error) {
32
+ this._endedAt = new Date();
33
+ this._error = error;
34
+ this.reject(error);
35
+ }
36
+ get endedAt() {
37
+ return this._endedAt;
38
+ }
39
+ get result() {
40
+ return this._result;
41
+ }
42
+ get error() {
43
+ return this._error;
44
+ }
45
+ isPending() {
46
+ return this._startedAt === null;
47
+ }
48
+ isRunning() {
49
+ return this._startedAt !== null && this._endedAt === null;
50
+ }
51
+ isSuccess() {
52
+ return this._endedAt !== null && this._error === null;
53
+ }
54
+ isFailed() {
55
+ return this._endedAt !== null && this._error !== null;
56
+ }
57
+ get status() {
58
+ if (this.isPending())
59
+ return "pending";
60
+ if (this.isRunning())
61
+ return "running";
62
+ if (this.isSuccess())
63
+ return "success";
64
+ if (this.isFailed())
65
+ return "failed";
66
+ return "unknown";
67
+ }
68
+ cancel() {
69
+ if (!this.isPending()) {
70
+ return false;
71
+ }
72
+ const error = new AppsScriptJobCancelledError();
73
+ this.fail(error);
74
+ return true;
75
+ }
76
+ }
77
+ exports.AppsScriptJob = AppsScriptJob;
78
+ class AppsScriptJobCancelledError extends Error {
79
+ constructor() {
80
+ super("Job cancelled");
81
+ this.name = "AppsScriptJobCancelledError";
82
+ }
83
+ }
84
+ exports.AppsScriptJobCancelledError = AppsScriptJobCancelledError;
@@ -0,0 +1,14 @@
1
+ import { AppsScriptJob } from "./AppsScriptJob";
2
+ export interface RunnableJob {
3
+ run(): Promise<void>;
4
+ addJob<T>(job: AppsScriptJob<T>): void;
5
+ }
6
+ export declare class AppsScriptJobQueue {
7
+ private jobs;
8
+ private listeners;
9
+ enqueue<T>(label: string, execute: () => Promise<T>): Promise<T>;
10
+ dequeue(): AppsScriptJob<any> | undefined;
11
+ private notify;
12
+ subscribe(listener: RunnableJob): () => boolean;
13
+ remove(jobId: string): void;
14
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppsScriptJobQueue = void 0;
4
+ const AppsScriptJob_1 = require("./AppsScriptJob");
5
+ class AppsScriptJobQueue {
6
+ jobs = [];
7
+ listeners = new Set();
8
+ enqueue(label, execute) {
9
+ const promise = new Promise((resolve, reject) => {
10
+ // キューにジョブを追加
11
+ const job = new AppsScriptJob_1.AppsScriptJob(label, execute, resolve, reject);
12
+ this.jobs.push(job);
13
+ this.notify(job);
14
+ });
15
+ return promise;
16
+ }
17
+ dequeue() {
18
+ const job = this.jobs.shift();
19
+ if (!job)
20
+ return undefined;
21
+ return job;
22
+ }
23
+ notify(job) {
24
+ this.listeners.forEach((listener) => {
25
+ listener.addJob(job);
26
+ listener.run();
27
+ });
28
+ }
29
+ subscribe(listener) {
30
+ this.listeners.add(listener);
31
+ return () => this.listeners.delete(listener);
32
+ }
33
+ remove(jobId) {
34
+ const index = this.jobs.findIndex((job) => job.id === jobId);
35
+ if (index !== -1) {
36
+ this.jobs.splice(index, 1);
37
+ }
38
+ }
39
+ }
40
+ exports.AppsScriptJobQueue = AppsScriptJobQueue;
@@ -0,0 +1,20 @@
1
+ import { AppsScriptJob } from "./AppsScriptJob";
2
+ import { AppsScriptJobQueue, RunnableJob } from "./AppsScriptJobQueue";
3
+ export declare class AppsScriptJobRunner implements RunnableJob {
4
+ readonly queue: AppsScriptJobQueue;
5
+ private jobs;
6
+ private listeners;
7
+ private MAX_CONCURRENT;
8
+ private running;
9
+ private snapshot;
10
+ private dirty;
11
+ constructor(queue: AppsScriptJobQueue);
12
+ addJob<T>(job: AppsScriptJob<T>): void;
13
+ getJobs(): AppsScriptJob<any>[];
14
+ run(): Promise<void>;
15
+ remove(jobId: string): void;
16
+ cancel(jobId: string): void;
17
+ retry(jobId: AppsScriptJob<any>["id"]): void;
18
+ subscribe(listener: () => void): () => boolean;
19
+ private notify;
20
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppsScriptJobRunner = void 0;
4
+ class AppsScriptJobRunner {
5
+ queue;
6
+ jobs = [];
7
+ listeners = new Set();
8
+ MAX_CONCURRENT = 30;
9
+ running = false;
10
+ snapshot = null;
11
+ dirty = true;
12
+ constructor(queue) {
13
+ this.queue = queue;
14
+ this.queue.subscribe(this);
15
+ }
16
+ addJob(job) {
17
+ this.jobs.push(job);
18
+ this.notify();
19
+ }
20
+ getJobs() {
21
+ if (this.dirty || !this.snapshot) {
22
+ this.snapshot = [...this.jobs];
23
+ this.dirty = false;
24
+ }
25
+ return this.snapshot;
26
+ }
27
+ async run() {
28
+ if (this.running)
29
+ return;
30
+ this.running = true;
31
+ while (true) {
32
+ const runningCount = this.jobs.filter((j) => j.isRunning()).length;
33
+ if (runningCount >= this.MAX_CONCURRENT)
34
+ break;
35
+ const job = this.queue.dequeue();
36
+ if (!job)
37
+ break;
38
+ job.start();
39
+ this.notify();
40
+ job
41
+ .execute()
42
+ .then((result) => {
43
+ job.success(result);
44
+ const index = this.jobs.indexOf(job);
45
+ if (index !== -1) {
46
+ this.jobs.splice(index, 1);
47
+ }
48
+ })
49
+ .catch((error) => {
50
+ job.fail(error);
51
+ })
52
+ .finally(() => {
53
+ this.notify();
54
+ this.running = false;
55
+ this.run();
56
+ });
57
+ }
58
+ this.running = false;
59
+ }
60
+ remove(jobId) {
61
+ const index = this.jobs.findIndex((job) => job.id === jobId);
62
+ if (index === -1) {
63
+ return;
64
+ }
65
+ this.jobs.splice(index, 1);
66
+ this.notify();
67
+ }
68
+ cancel(jobId) {
69
+ const job = this.jobs.find((job) => job.id === jobId);
70
+ if (!job || !job.cancel()) {
71
+ return;
72
+ }
73
+ this.queue.remove(jobId);
74
+ this.jobs.splice(this.jobs.indexOf(job), 1);
75
+ this.notify();
76
+ }
77
+ retry(jobId) {
78
+ const job = this.jobs.find((j) => j.id === jobId);
79
+ if (job) {
80
+ this.remove(job.id);
81
+ this.queue.enqueue(job.label, job.execute);
82
+ }
83
+ }
84
+ subscribe(listener) {
85
+ this.listeners.add(listener);
86
+ return () => this.listeners.delete(listener);
87
+ }
88
+ notify() {
89
+ this.dirty = true;
90
+ this.listeners.forEach((listener) => listener());
91
+ }
92
+ }
93
+ exports.AppsScriptJobRunner = AppsScriptJobRunner;
@@ -0,0 +1,7 @@
1
+ import { AppsScriptJob } from "./AppsScriptJob";
2
+ import { AppsScriptJobRunner } from "./AppsScriptJobRunner";
3
+ export interface AppsScriptJobStore {
4
+ subscribe: (listener: () => void) => () => void;
5
+ getSnapshot: () => AppsScriptJob<any>[];
6
+ }
7
+ export declare function appsScriptJobStore(runner: AppsScriptJobRunner): AppsScriptJobStore;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.appsScriptJobStore = appsScriptJobStore;
4
+ function appsScriptJobStore(runner) {
5
+ return {
6
+ subscribe: runner.subscribe.bind(runner),
7
+ getSnapshot: runner.getJobs.bind(runner),
8
+ };
9
+ }
@@ -0,0 +1,36 @@
1
+ export type GoogleScriptRun = {
2
+ withSuccessHandler<T = unknown>(callback: (result: T) => void): GoogleScriptRun;
3
+ withFailureHandler(callback: (error: Error) => void): GoogleScriptRun;
4
+ [serverFunctionName: string]: any;
5
+ };
6
+ export type GoogleScriptHistoryEvent = {
7
+ state: Record<string, unknown>;
8
+ location: {
9
+ hash: string;
10
+ parameter: Record<string, string>;
11
+ parameters: Record<string, string[]>;
12
+ };
13
+ };
14
+ export type GoogleScriptUrlLocation = {
15
+ hash: string;
16
+ parameter: Record<string, string>;
17
+ parameters: Record<string, string[]>;
18
+ };
19
+ export type GoogleApi = {
20
+ script: {
21
+ run: GoogleScriptRun;
22
+ history: {
23
+ push: (stateObject: Record<string, unknown>, params: Record<string, unknown>, hash: string) => void;
24
+ replace: (stateObject: Record<string, unknown>, params: Record<string, unknown>, hash: string) => void;
25
+ setChangeHandler: (callback: (event: GoogleScriptHistoryEvent) => void) => void;
26
+ };
27
+ url: {
28
+ getLocation: (callback: (location: GoogleScriptUrlLocation) => void) => void;
29
+ };
30
+ };
31
+ };
32
+ /**
33
+ * google.script.* は Apps Script のランタイムが注入するグローバル。
34
+ * ここでは「型付きで参照」だけ提供する。
35
+ */
36
+ export declare const google: GoogleApi;
package/dist/google.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.google = void 0;
4
+ /**
5
+ * google.script.* は Apps Script のランタイムが注入するグローバル。
6
+ * ここでは「型付きで参照」だけ提供する。
7
+ */
8
+ exports.google = globalThis.google;
@@ -0,0 +1,4 @@
1
+ export { appsScriptClient } from "./AppsScriptClient";
2
+ export type { AppsScriptJob } from "./job/AppsScriptJob";
3
+ export { AppsScriptJobStore } from "./job/AppsScriptJobStore";
4
+ export { AppsScriptHistoryPipeline } from "./navigation/AppsScriptHistoryPipeline";
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppsScriptHistoryPipeline = exports.appsScriptClient = void 0;
4
+ var AppsScriptClient_1 = require("./AppsScriptClient");
5
+ Object.defineProperty(exports, "appsScriptClient", { enumerable: true, get: function () { return AppsScriptClient_1.appsScriptClient; } });
6
+ var AppsScriptHistoryPipeline_1 = require("./navigation/AppsScriptHistoryPipeline");
7
+ Object.defineProperty(exports, "AppsScriptHistoryPipeline", { enumerable: true, get: function () { return AppsScriptHistoryPipeline_1.AppsScriptHistoryPipeline; } });
@@ -0,0 +1,28 @@
1
+ export declare class AppsScriptJob<T> {
2
+ readonly label: string;
3
+ readonly execute: () => Promise<T>;
4
+ private resolve;
5
+ private reject;
6
+ readonly id: string;
7
+ readonly createdAt: Date;
8
+ private _startedAt;
9
+ private _endedAt;
10
+ private _result;
11
+ private _error;
12
+ constructor(label: string, execute: () => Promise<T>, resolve: (value: T) => void, reject: (reason?: any) => void, id?: string, createdAt?: Date);
13
+ start(): void;
14
+ success(result: T): void;
15
+ fail(error: unknown): void;
16
+ get endedAt(): Date | null;
17
+ get result(): T | null;
18
+ get error(): unknown;
19
+ isPending(): boolean;
20
+ isRunning(): boolean;
21
+ isSuccess(): boolean;
22
+ isFailed(): boolean;
23
+ get status(): "failed" | "pending" | "running" | "success" | "unknown";
24
+ cancel(): boolean;
25
+ }
26
+ export declare class AppsScriptJobCancelledError extends Error {
27
+ constructor();
28
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppsScriptJobCancelledError = exports.AppsScriptJob = void 0;
4
+ class AppsScriptJob {
5
+ label;
6
+ execute;
7
+ resolve;
8
+ reject;
9
+ id;
10
+ createdAt;
11
+ _startedAt = null;
12
+ _endedAt = null;
13
+ _result = null;
14
+ _error = null;
15
+ constructor(label, execute, resolve, reject, id = crypto.randomUUID(), createdAt = new Date()) {
16
+ this.label = label;
17
+ this.execute = execute;
18
+ this.resolve = resolve;
19
+ this.reject = reject;
20
+ this.id = id;
21
+ this.createdAt = createdAt;
22
+ }
23
+ start() {
24
+ this._startedAt = new Date();
25
+ }
26
+ success(result) {
27
+ this._endedAt = new Date();
28
+ this._result = result;
29
+ this.resolve(result);
30
+ }
31
+ fail(error) {
32
+ this._endedAt = new Date();
33
+ this._error = error;
34
+ this.reject(error);
35
+ }
36
+ get endedAt() {
37
+ return this._endedAt;
38
+ }
39
+ get result() {
40
+ return this._result;
41
+ }
42
+ get error() {
43
+ return this._error;
44
+ }
45
+ isPending() {
46
+ return this._startedAt === null;
47
+ }
48
+ isRunning() {
49
+ return this._startedAt !== null && this._endedAt === null;
50
+ }
51
+ isSuccess() {
52
+ return this._endedAt !== null && this._error === null;
53
+ }
54
+ isFailed() {
55
+ return this._endedAt !== null && this._error !== null;
56
+ }
57
+ get status() {
58
+ if (this.isPending())
59
+ return "pending";
60
+ if (this.isRunning())
61
+ return "running";
62
+ if (this.isSuccess())
63
+ return "success";
64
+ if (this.isFailed())
65
+ return "failed";
66
+ return "unknown";
67
+ }
68
+ cancel() {
69
+ if (!this.isPending()) {
70
+ return false;
71
+ }
72
+ const error = new AppsScriptJobCancelledError();
73
+ this.fail(error);
74
+ return true;
75
+ }
76
+ }
77
+ exports.AppsScriptJob = AppsScriptJob;
78
+ class AppsScriptJobCancelledError extends Error {
79
+ constructor() {
80
+ super("Job cancelled");
81
+ this.name = "AppsScriptJobCancelledError";
82
+ }
83
+ }
84
+ exports.AppsScriptJobCancelledError = AppsScriptJobCancelledError;
@@ -0,0 +1,14 @@
1
+ import { AppsScriptJob } from "./AppsScriptJob";
2
+ export interface RunnableJob {
3
+ run(): Promise<void>;
4
+ addJob<T>(job: AppsScriptJob<T>): void;
5
+ }
6
+ export declare class AppsScriptJobQueue {
7
+ private jobs;
8
+ private listeners;
9
+ enqueue<T>(label: string, execute: () => Promise<T>): Promise<T>;
10
+ dequeue(): AppsScriptJob<any> | undefined;
11
+ private notify;
12
+ subscribe(listener: RunnableJob): () => boolean;
13
+ remove(jobId: string): void;
14
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppsScriptJobQueue = void 0;
4
+ const AppsScriptJob_1 = require("./AppsScriptJob");
5
+ class AppsScriptJobQueue {
6
+ jobs = [];
7
+ listeners = new Set();
8
+ enqueue(label, execute) {
9
+ const promise = new Promise((resolve, reject) => {
10
+ // キューにジョブを追加
11
+ const job = new AppsScriptJob_1.AppsScriptJob(label, execute, resolve, reject);
12
+ this.jobs.push(job);
13
+ this.notify(job);
14
+ });
15
+ return promise;
16
+ }
17
+ dequeue() {
18
+ const job = this.jobs.shift();
19
+ if (!job)
20
+ return undefined;
21
+ return job;
22
+ }
23
+ notify(job) {
24
+ this.listeners.forEach((listener) => {
25
+ listener.addJob(job);
26
+ listener.run();
27
+ });
28
+ }
29
+ subscribe(listener) {
30
+ this.listeners.add(listener);
31
+ return () => this.listeners.delete(listener);
32
+ }
33
+ remove(jobId) {
34
+ const index = this.jobs.findIndex((job) => job.id === jobId);
35
+ if (index !== -1) {
36
+ this.jobs.splice(index, 1);
37
+ }
38
+ }
39
+ }
40
+ exports.AppsScriptJobQueue = AppsScriptJobQueue;
@@ -0,0 +1,20 @@
1
+ import { AppsScriptJob } from "./AppsScriptJob";
2
+ import { AppsScriptJobQueue, RunnableJob } from "./AppsScriptJobQueue";
3
+ export declare class AppsScriptJobRunner implements RunnableJob {
4
+ readonly queue: AppsScriptJobQueue;
5
+ private jobs;
6
+ private listeners;
7
+ private MAX_CONCURRENT;
8
+ private running;
9
+ private snapshot;
10
+ private dirty;
11
+ constructor(queue: AppsScriptJobQueue);
12
+ addJob<T>(job: AppsScriptJob<T>): void;
13
+ getJobs(): AppsScriptJob<any>[];
14
+ run(): Promise<void>;
15
+ remove(jobId: string): void;
16
+ cancel(jobId: string): void;
17
+ retry(jobId: AppsScriptJob<any>["id"]): void;
18
+ subscribe(listener: () => void): () => boolean;
19
+ private notify;
20
+ }