target-supabase-sdk 0.1.7 → 0.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 (76) hide show
  1. package/dist/auth/auth.api.js +6 -6
  2. package/dist/auth/auth.api.js.map +1 -1
  3. package/dist/core.api.d.ts +46 -6
  4. package/dist/core.api.d.ts.map +1 -1
  5. package/dist/core.api.js +105 -97
  6. package/dist/core.api.js.map +1 -1
  7. package/dist/core.interface.d.ts +2 -1
  8. package/dist/core.interface.d.ts.map +1 -1
  9. package/dist/core.interface.js +1 -1
  10. package/dist/core.interface.js.map +1 -1
  11. package/dist/core.utils.d.ts +0 -2
  12. package/dist/core.utils.d.ts.map +1 -1
  13. package/dist/core.utils.js +0 -5
  14. package/dist/core.utils.js.map +1 -1
  15. package/dist/file-list/file-list.api.js +1 -1
  16. package/dist/file-list/file-list.api.js.map +1 -1
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/list/list.interface.d.ts +2 -2
  22. package/dist/list/list.interface.d.ts.map +1 -1
  23. package/dist/node/node.api.d.ts +32 -0
  24. package/dist/node/node.api.d.ts.map +1 -0
  25. package/dist/node/node.api.js +137 -0
  26. package/dist/node/node.api.js.map +1 -0
  27. package/dist/node/node.interface.d.ts +28 -0
  28. package/dist/node/node.interface.d.ts.map +1 -0
  29. package/dist/node/node.interface.js +17 -0
  30. package/dist/node/node.interface.js.map +1 -0
  31. package/dist/question-list/question-list.api.js +1 -1
  32. package/dist/question-list/question-list.api.js.map +1 -1
  33. package/dist/repo/repo.interface.d.ts +20 -0
  34. package/dist/repo/repo.interface.d.ts.map +1 -0
  35. package/dist/repo/repo.interface.js +8 -0
  36. package/dist/repo/repo.interface.js.map +1 -0
  37. package/dist/review/review.api.js +5 -5
  38. package/dist/review/review.api.js.map +1 -1
  39. package/dist/task/task-node-manager.d.ts +1 -0
  40. package/dist/task/task-node-manager.d.ts.map +1 -0
  41. package/dist/task/task-node-manager.js +2 -0
  42. package/dist/task/task-node-manager.js.map +1 -0
  43. package/dist/task/task.api.d.ts +1 -0
  44. package/dist/task/task.api.d.ts.map +1 -0
  45. package/dist/task/task.api.js +2 -0
  46. package/dist/task/task.api.js.map +1 -0
  47. package/dist/task/task.interface.d.ts +49 -0
  48. package/dist/task/task.interface.d.ts.map +1 -0
  49. package/dist/task/task.interface.js +26 -0
  50. package/dist/task/task.interface.js.map +1 -0
  51. package/dist/task/task.utils.d.ts +1 -0
  52. package/dist/task/task.utils.d.ts.map +1 -0
  53. package/dist/task/task.utils.js +2 -0
  54. package/dist/task/task.utils.js.map +1 -0
  55. package/dist/word/word.api.d.ts +5 -5
  56. package/dist/word/word.api.d.ts.map +1 -1
  57. package/dist/word/word.api.js +1 -1
  58. package/dist/word/word.api.js.map +1 -1
  59. package/package.json +1 -1
  60. package/src/auth/auth.api.ts +6 -6
  61. package/src/core.api.ts +194 -117
  62. package/src/core.interface.ts +3 -1
  63. package/src/core.utils.ts +0 -6
  64. package/src/file-list/file-list.api.ts +1 -1
  65. package/src/index.ts +6 -0
  66. package/src/list/list.interface.ts +2 -2
  67. package/src/node/node.api.ts +161 -0
  68. package/src/node/node.interface.ts +32 -0
  69. package/src/question-list/question-list.api.ts +1 -1
  70. package/src/repo/repo.interface.ts +23 -0
  71. package/src/review/review.api.ts +5 -5
  72. package/src/task/task-node-manager.ts +0 -0
  73. package/src/task/task.api.ts +0 -0
  74. package/src/task/task.interface.ts +60 -0
  75. package/src/task/task.utils.ts +0 -0
  76. package/src/word/word.api.ts +6 -6
@@ -0,0 +1,161 @@
1
+ import { CategoryTask, Task, TaskDetails, TaskStatus } from "../task/task.interface";
2
+ import { createTarget, getPossibleTarget, updateTargetDetails } from "../core.api";
3
+ import { generateResponse } from "../core.interface";
4
+ import { BaseValidator } from "../core.utils";
5
+ import { CategoryNode, Node, NodeDetails, NodeStatus } from "./node.interface";
6
+
7
+ export interface PostRegisterNodePayload {
8
+ }
9
+
10
+ export class PostListValidator extends BaseValidator<PostRegisterNodePayload> {
11
+ protected requiredFields: (keyof PostRegisterNodePayload)[] = [];
12
+ protected optionalFields: (keyof PostRegisterNodePayload)[] = [];
13
+
14
+ constructor() {
15
+ super();
16
+ // Add custom
17
+ this.addCustomValidator((val) => {
18
+ return true;
19
+ });
20
+ }
21
+ }
22
+
23
+
24
+
25
+ export const postRegisterNode = async (payload: PostRegisterNodePayload) => {
26
+ return createTarget<Node, PostRegisterNodePayload>({
27
+ payload: payload,
28
+ validator: PostListValidator,
29
+ createFn: (validPayload) => {
30
+ const details: NodeDetails = {
31
+ manifestVersion: 0,
32
+ status: NodeStatus.READY,
33
+ lastHeartBeat: Date.now(),
34
+ };
35
+ return {
36
+ name: '',
37
+ category: CategoryNode.NODE,
38
+ value: '',
39
+ tagList: [],
40
+ details,
41
+ };
42
+ },
43
+ });
44
+ };
45
+
46
+ export const patchNodeHeartBeat = async ({ nodeId }: { nodeId: string }) => {
47
+ const lastHeartBeat = Date.now();
48
+ await updateTargetDetails<Node, NodeDetails>({
49
+ id: nodeId,
50
+ updateFn: (details) => {
51
+ return {
52
+ ...details,
53
+ lastHeartBeat,
54
+ };
55
+ },
56
+ });
57
+ return generateResponse.success(lastHeartBeat);
58
+ };
59
+
60
+ export const patchStopNode = async ({ nodeId }: { nodeId: string }) => {
61
+ const lastHeartBeat = Date.now();
62
+ // TODO 等待任務全部完成才下綫 應該先使用NodeStatus.DRAINING
63
+ await updateTargetDetails<Node, NodeDetails>({
64
+ id: nodeId,
65
+ updateFn: (details) => {
66
+ return {
67
+ ...details,
68
+ lastHeartBeat,
69
+ status: NodeStatus.LOST,
70
+ };
71
+ },
72
+ });
73
+ return generateResponse.success(lastHeartBeat);
74
+ };
75
+
76
+ export interface PatchClaimTaskPayload {
77
+ nodeId: string;
78
+ availableTaskList: string[];
79
+ }
80
+
81
+ /**
82
+ * Atomically claim one TODO task for this node.
83
+ *
84
+ * Flow: find a candidate (TODO + value in availableTaskList) → UPDATE with optimistic lock
85
+ * (status must still be TODO) → return the updated Task row for the executor to run.
86
+ *
87
+ * Returns `data: null` when no TODO task matches. On optimistic lock conflict,
88
+ * `updateTargetDetails` throws — callers may catch `isOptimisticLockError` to retry.
89
+ */
90
+ export const patchClaimTask = async ({
91
+ nodeId,
92
+ availableTaskList,
93
+ }: PatchClaimTaskPayload) => {
94
+ if (availableTaskList.length === 0) {
95
+ console.log("[patchClaimTask] skipped: availableTaskList is empty", { nodeId });
96
+ return generateResponse.success(null);
97
+ }
98
+
99
+ // Step 1: Pick one matching TODO task (not locked; another node may claim the same row next).
100
+ const { data: possibleTask } = await getPossibleTarget({
101
+ filterList: [
102
+ {
103
+ field: "category",
104
+ operator: "eq",
105
+ value: CategoryTask.TASK,
106
+ },
107
+ {
108
+ field: "details->>status",
109
+ operator: "eq",
110
+ value: TaskStatus.TODO,
111
+ },
112
+ {
113
+ field: "value",
114
+ operator: "in",
115
+ value: availableTaskList,
116
+ },
117
+ ],
118
+ });
119
+
120
+ if (possibleTask == null) {
121
+ console.log("[patchClaimTask] no TODO task for node capabilities", {
122
+ nodeId,
123
+ availableTaskList,
124
+ });
125
+ return generateResponse.success(null);
126
+ }
127
+
128
+ const todoTask = possibleTask as Task;
129
+ console.log("[patchClaimTask] attempting claim", {
130
+ nodeId,
131
+ taskId: todoTask.id,
132
+ taskValue: todoTask.value,
133
+ });
134
+
135
+ // Step 2: Claim with DB optimistic lock — UPDATE only if status is still TODO.
136
+ const data = await updateTargetDetails<Task, TaskDetails>({
137
+ id: todoTask.id,
138
+ optimisticLockFilterList: [
139
+ {
140
+ field: "details->>status",
141
+ operator: "eq",
142
+ value: TaskStatus.TODO,
143
+ },
144
+ ],
145
+ updateFn: (details) => ({
146
+ ...details,
147
+ status: TaskStatus.DOING,
148
+ nodeId,
149
+ }),
150
+ });
151
+
152
+ console.log("[patchClaimTask] claim succeeded", {
153
+ nodeId,
154
+ taskId: data.id,
155
+ taskValue: data.value,
156
+ status: (data as Task).details.status,
157
+ });
158
+
159
+ // Return full updated row so executor can read repo/params without another fetch.
160
+ return generateResponse.success(data);
161
+ };
@@ -0,0 +1,32 @@
1
+ import { Target } from "../core.interface";
2
+
3
+ export enum NodeStatus {
4
+ READY = "READY",
5
+ BUSY = "BUSY",
6
+ /** Heartbeat lost or voluntarily offline; considered unavailable by the scheduler. */
7
+ LOST = "LOST",
8
+ /** TODO Gracefully draining: not accepting new tasks, waiting for in-flight tasks to complete. */
9
+ DRAINING = "DRAINING",
10
+ /** TODO Disabled by an administrator; excluded from scheduling. */
11
+ DISABLED = "DISABLED",
12
+ }
13
+
14
+ export enum CategoryNode {
15
+ NODE = "node",
16
+ }
17
+
18
+ export interface Node extends Target {
19
+ /** Empty */
20
+ name: string;
21
+ /** Empty */
22
+ value: string;
23
+ details: NodeDetails;
24
+ category: CategoryNode;
25
+ }
26
+
27
+ export interface NodeDetails {
28
+ manifestVersion: number;
29
+ status: NodeStatus;
30
+ lastHeartBeat: number;
31
+ };
32
+
@@ -9,7 +9,7 @@ export class PostCreateQuestionListValidator extends BaseValidator<PostCreateQue
9
9
  constructor() {
10
10
  super();
11
11
  // Add custom
12
- this.addValidator((val) => {
12
+ this.addCustomValidator((val) => {
13
13
  return true;
14
14
  });
15
15
  }
@@ -0,0 +1,23 @@
1
+ import { Target } from "../core.interface";
2
+
3
+ export enum CategoryRepo {
4
+ /** Project */
5
+ REPO = "repo",
6
+ SCRIPT = "script",
7
+ }
8
+
9
+ export interface Repo extends Target {
10
+ /** Key */
11
+ name: string;
12
+ /** Url */
13
+ value: string;
14
+ details: RepoDetails;
15
+ category: CategoryRepo;
16
+ }
17
+
18
+ export interface RepoDetails {
19
+ manifestVersion: number;
20
+ context?: unknown;
21
+ hash: string;
22
+ };
23
+
@@ -1,6 +1,6 @@
1
1
  import { cloneDeep } from "lodash-es";
2
2
  import { createTarget, getPossibleTarget, updateTargetDetails } from "../core.api";
3
- import { createResponse } from "../core.interface";
3
+ import { generateResponse } from "../core.interface";
4
4
  import { BaseValidator } from "../core.utils";
5
5
  import { CategoryReview, Review, ReviewDetails } from "./review.interface";
6
6
 
@@ -12,7 +12,7 @@ class PatchUpsertReviewValidator extends BaseValidator<ReviewDetails> {
12
12
  constructor() {
13
13
  super();
14
14
  // Add custom
15
- this.addValidator((val) => {
15
+ this.addCustomValidator((val) => {
16
16
  if (val.reviewResult == null || Object.values(val.reviewResult).some((v) => typeof v !== "number")) {
17
17
  return "[Check reviewResult] reviewResult invalid";
18
18
  }
@@ -69,7 +69,7 @@ export const patchUpsertReview = async (payload: ReviewDetails) => {
69
69
  return details;
70
70
  },
71
71
  });
72
- return createResponse.success<Review>(data);
72
+ return generateResponse.success<Review>(data);
73
73
  }
74
74
  // Create
75
75
  const { data: newReview } = await postReview({
@@ -81,7 +81,7 @@ export const patchUpsertReview = async (payload: ReviewDetails) => {
81
81
  console.error(msg);
82
82
  throw new Error(msg);
83
83
  }
84
- return createResponse.success<Review>(newReview);
84
+ return generateResponse.success<Review>(newReview);
85
85
  };
86
86
 
87
87
  export interface PostReviewPayload {
@@ -96,7 +96,7 @@ export class PostReviewValidator extends BaseValidator<PostReviewPayload> {
96
96
  constructor() {
97
97
  super();
98
98
  // Add custom
99
- this.addValidator((val) => {
99
+ this.addCustomValidator((val) => {
100
100
  return true;
101
101
  });
102
102
  }
File without changes
File without changes
@@ -0,0 +1,60 @@
1
+ import { Target } from "../core.interface";
2
+ import { Repo } from "../repo/repo.interface";
3
+
4
+ export enum CategoryTask {
5
+ TASK = "task",
6
+ }
7
+
8
+ export enum TaskStatus {
9
+ OPEN = "OPEN",
10
+ TODO = "TODO",
11
+ DOING = "DOING",
12
+ DONE = "DONE",
13
+ CLOSED = "CLOSED",
14
+ }
15
+
16
+ export enum ResultCode {
17
+ SUCCESS = 1000,
18
+
19
+ /** 3xxx 依赖 / 外部 */
20
+ PARAMS_NOT_VALID = 3001,
21
+ REPO_NOT_VALID = 3002,
22
+
23
+ /** 4xxx — 运行环境 */
24
+ TIMEOUT = 4001,
25
+ CANCELLED = 4002,
26
+ NODE_UNAVAILABLE = 4003,
27
+
28
+ UNKNOWN_ERROR = 9999,
29
+ }
30
+
31
+ export interface Task extends Target {
32
+ /** Readable */
33
+ name: string;
34
+ /** Unique key, as TaskType */
35
+ value: string;
36
+ details: TaskDetails;
37
+ category: CategoryTask;
38
+ }
39
+
40
+ export interface TaskDetails {
41
+ manifestVersion: number;
42
+ status: TaskStatus;
43
+ repo: Repo;
44
+ params: unknown;
45
+ /** [0,100] */
46
+ progress: number;
47
+ nodeId: null | string;
48
+ result?: {
49
+ cost: number;
50
+ code: ResultCode;
51
+ errorMessage?: string;
52
+ data?: unknown;
53
+ }
54
+ };
55
+
56
+ // TODO loop condition combination
57
+ export interface TaskFlow extends Target {
58
+
59
+ }
60
+
File without changes
@@ -2,16 +2,16 @@ import { createTarget } from "../core.api";
2
2
  import { BaseValidator } from "../core.utils";
3
3
  import { Word, WordDetails } from "./word.interface";
4
4
 
5
- export interface PostWordCreatePayload {
5
+ export interface PostWordPayload {
6
6
  name: Word["name"];
7
7
  value: Word["value"];
8
8
  category: Word["category"];
9
9
  details: WordDetails;
10
10
  }
11
11
 
12
- export class PostWordValidator extends BaseValidator<PostWordCreatePayload> {
13
- protected requiredFields: (keyof PostWordCreatePayload)[] = ["name", "value", "category", "details"];
14
- protected optionalFields: (keyof PostWordCreatePayload)[] = [];
12
+ export class PostWordValidator extends BaseValidator<PostWordPayload> {
13
+ protected requiredFields: (keyof PostWordPayload)[] = ["name", "value", "category", "details"];
14
+ protected optionalFields: (keyof PostWordPayload)[] = [];
15
15
 
16
16
  constructor() {
17
17
  super();
@@ -24,8 +24,8 @@ export class PostWordValidator extends BaseValidator<PostWordCreatePayload> {
24
24
 
25
25
 
26
26
 
27
- export const postWordCreate = async (payload: PostWordCreatePayload) => {
28
- return createTarget<Word, PostWordCreatePayload>({
27
+ export const postWord = async (payload: PostWordPayload) => {
28
+ return createTarget<Word, PostWordPayload>({
29
29
  payload: payload,
30
30
  validator: PostWordValidator,
31
31
  createFn: (validPayload) => {