@sayrio/public 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.
- package/dist/index.cjs +154 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +152 -0
- package/dist/index.d.ts +152 -0
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.cjs +234 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +88 -0
- package/dist/react/index.d.ts +88 -0
- package/dist/react/index.js +203 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +41 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
default: () => index_default,
|
|
24
|
+
org: () => org,
|
|
25
|
+
ws: () => ws,
|
|
26
|
+
wsTypes: () => wsTypes
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/org.ts
|
|
31
|
+
var API = "https://sayr.io/api/public";
|
|
32
|
+
async function get(url) {
|
|
33
|
+
const res = await fetch(url);
|
|
34
|
+
const json = await res.json();
|
|
35
|
+
if (!json.success) throw json;
|
|
36
|
+
return json;
|
|
37
|
+
}
|
|
38
|
+
var org = {
|
|
39
|
+
async get(slug) {
|
|
40
|
+
const r = await get(
|
|
41
|
+
`${API}/organization/${slug}`
|
|
42
|
+
);
|
|
43
|
+
return r.data;
|
|
44
|
+
},
|
|
45
|
+
async labels(slug) {
|
|
46
|
+
const r = await get(
|
|
47
|
+
`${API}/organization/${slug}/labels`
|
|
48
|
+
);
|
|
49
|
+
return r.data;
|
|
50
|
+
},
|
|
51
|
+
async categories(slug, order = "desc") {
|
|
52
|
+
const r = await get(
|
|
53
|
+
`${API}/organization/${slug}/categories?order=${order}`
|
|
54
|
+
);
|
|
55
|
+
return r.data;
|
|
56
|
+
},
|
|
57
|
+
async tasks(slug, opts) {
|
|
58
|
+
const q = new URLSearchParams({
|
|
59
|
+
order: opts?.order ?? "desc",
|
|
60
|
+
limit: String(opts?.limit ?? 5),
|
|
61
|
+
page: String(opts?.page ?? 1)
|
|
62
|
+
});
|
|
63
|
+
const res = await fetch(
|
|
64
|
+
`${API}/organization/${slug}/tasks?${q}`
|
|
65
|
+
);
|
|
66
|
+
const json = await res.json();
|
|
67
|
+
if (!json.success) throw json;
|
|
68
|
+
return {
|
|
69
|
+
data: json.data,
|
|
70
|
+
pagination: json.pagination
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
async task(slug, shortId) {
|
|
74
|
+
const r = await get(
|
|
75
|
+
`${API}/organization/${slug}/tasks/${shortId}`
|
|
76
|
+
);
|
|
77
|
+
return r.data;
|
|
78
|
+
},
|
|
79
|
+
async comments(slug, shortId, opts) {
|
|
80
|
+
const q = new URLSearchParams({
|
|
81
|
+
order: opts?.order ?? "desc",
|
|
82
|
+
limit: String(opts?.limit ?? 5),
|
|
83
|
+
page: String(opts?.page ?? 1)
|
|
84
|
+
});
|
|
85
|
+
const res = await fetch(
|
|
86
|
+
`${API}/organization/${slug}/tasks/${shortId}/comments?${q}`
|
|
87
|
+
);
|
|
88
|
+
const json = await res.json();
|
|
89
|
+
if (!json.success) throw json;
|
|
90
|
+
return {
|
|
91
|
+
data: json.data,
|
|
92
|
+
pagination: json.pagination
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// src/ws.ts
|
|
98
|
+
var wsTypes = {
|
|
99
|
+
CONNECTION_STATUS: "CONNECTION_STATUS",
|
|
100
|
+
SUBSCRIBED: "SUBSCRIBED",
|
|
101
|
+
ERROR: "ERROR",
|
|
102
|
+
PING: "PING",
|
|
103
|
+
PONG: "PONG",
|
|
104
|
+
UPDATE_ORG: "UPDATE_ORG",
|
|
105
|
+
CREATE_TASK: "CREATE_TASK",
|
|
106
|
+
UPDATE_TASK: "UPDATE_TASK",
|
|
107
|
+
UPDATE_TASK_COMMENTS: "UPDATE_TASK_COMMENTS",
|
|
108
|
+
UPDATE_TASK_VOTE: "UPDATE_TASK_VOTE",
|
|
109
|
+
UPDATE_LABELS: "UPDATE_LABELS",
|
|
110
|
+
UPDATE_VIEWS: "UPDATE_VIEWS",
|
|
111
|
+
UPDATE_CATEGORIES: "UPDATE_CATEGORIES",
|
|
112
|
+
UPDATE_ISSUE_TEMPLATES: "UPDATE_ISSUE_TEMPLATES",
|
|
113
|
+
DISCONNECTED: "DISCONNECTED"
|
|
114
|
+
};
|
|
115
|
+
function ws(url, handlers = {}) {
|
|
116
|
+
let socket;
|
|
117
|
+
let retry = 0;
|
|
118
|
+
let closed = false;
|
|
119
|
+
function connect() {
|
|
120
|
+
if (closed) return;
|
|
121
|
+
socket = new WebSocket(url);
|
|
122
|
+
socket.onmessage = (e) => {
|
|
123
|
+
const msg = JSON.parse(e.data);
|
|
124
|
+
if (msg.type === wsTypes.PING) {
|
|
125
|
+
socket.send(JSON.stringify({ type: wsTypes.PONG }));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
handlers[msg.type]?.(msg.data, msg);
|
|
129
|
+
};
|
|
130
|
+
socket.onclose = () => {
|
|
131
|
+
if (closed) return;
|
|
132
|
+
setTimeout(connect, Math.min(1e3 * 2 ** retry++, 3e4));
|
|
133
|
+
};
|
|
134
|
+
socket.onerror = () => socket.close();
|
|
135
|
+
}
|
|
136
|
+
connect();
|
|
137
|
+
return {
|
|
138
|
+
close() {
|
|
139
|
+
closed = true;
|
|
140
|
+
socket?.close();
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/index.ts
|
|
146
|
+
var Sayr = { org, ws, wsTypes };
|
|
147
|
+
var index_default = Sayr;
|
|
148
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
149
|
+
0 && (module.exports = {
|
|
150
|
+
org,
|
|
151
|
+
ws,
|
|
152
|
+
wsTypes
|
|
153
|
+
});
|
|
154
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/org.ts","../src/ws.ts"],"sourcesContent":["import { org } from \"./org\";\r\nimport { ws, wsTypes } from \"./ws\";\r\n\r\nconst Sayr = { org, ws, wsTypes };\r\n\r\nexport default Sayr;\r\nexport { org, ws, wsTypes };\r\nexport * from \"./types\";","import {\r\n Organization,\r\n Label,\r\n Category,\r\n Task,\r\n Comment,\r\n Pagination,\r\n ApiSuccess\r\n} from \"./types\";\r\n\r\nconst API = \"https://sayr.io/api/public\";\r\n\r\nasync function get<T>(url: string): Promise<T> {\r\n const res = await fetch(url);\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n return json;\r\n}\r\n\r\nexport const org = {\r\n async get(slug: string): Promise<Organization> {\r\n const r = await get<ApiSuccess<Organization>>(\r\n `${API}/organization/${slug}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async labels(slug: string): Promise<Label[]> {\r\n const r = await get<ApiSuccess<Label[]>>(\r\n `${API}/organization/${slug}/labels`\r\n );\r\n return r.data;\r\n },\r\n\r\n async categories(\r\n slug: string,\r\n order: \"asc\" | \"desc\" = \"desc\"\r\n ): Promise<Category[]> {\r\n const r = await get<ApiSuccess<Category[]>>(\r\n `${API}/organization/${slug}/categories?order=${order}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async tasks(\r\n slug: string,\r\n opts?: { order?: \"asc\" | \"desc\"; limit?: number; page?: number }\r\n ): Promise<{ data: Task[]; pagination: Pagination }> {\r\n const q = new URLSearchParams({\r\n order: opts?.order ?? \"desc\",\r\n limit: String(opts?.limit ?? 5),\r\n page: String(opts?.page ?? 1)\r\n });\r\n\r\n const res = await fetch(\r\n `${API}/organization/${slug}/tasks?${q}`\r\n );\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n\r\n return {\r\n data: json.data,\r\n pagination: json.pagination\r\n };\r\n },\r\n\r\n async task(slug: string, shortId: number): Promise<Task> {\r\n const r = await get<ApiSuccess<Task>>(\r\n `${API}/organization/${slug}/tasks/${shortId}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async comments(\r\n slug: string,\r\n shortId: number,\r\n opts?: { order?: \"asc\" | \"desc\"; limit?: number; page?: number }\r\n ): Promise<{ data: Comment[]; pagination: Pagination }> {\r\n const q = new URLSearchParams({\r\n order: opts?.order ?? \"desc\",\r\n limit: String(opts?.limit ?? 5),\r\n page: String(opts?.page ?? 1)\r\n });\r\n\r\n const res = await fetch(\r\n `${API}/organization/${slug}/tasks/${shortId}/comments?${q}`\r\n );\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n\r\n return {\r\n data: json.data,\r\n pagination: json.pagination\r\n };\r\n }\r\n};","export type WSMessageType =\r\n | \"CONNECTION_STATUS\"\r\n | \"SUBSCRIBED\"\r\n | \"ERROR\"\r\n | \"PING\"\r\n | \"PONG\"\r\n | \"UPDATE_ORG\"\r\n | \"CREATE_TASK\"\r\n | \"UPDATE_TASK\"\r\n | \"UPDATE_TASK_COMMENTS\"\r\n | \"UPDATE_TASK_VOTE\"\r\n | \"UPDATE_LABELS\"\r\n | \"UPDATE_VIEWS\"\r\n | \"UPDATE_CATEGORIES\"\r\n | \"UPDATE_ISSUE_TEMPLATES\"\r\n | \"DISCONNECTED\";\r\n\r\nexport const wsTypes: Record<WSMessageType, WSMessageType> = {\r\n CONNECTION_STATUS: \"CONNECTION_STATUS\",\r\n SUBSCRIBED: \"SUBSCRIBED\",\r\n ERROR: \"ERROR\",\r\n PING: \"PING\",\r\n PONG: \"PONG\",\r\n UPDATE_ORG: \"UPDATE_ORG\",\r\n CREATE_TASK: \"CREATE_TASK\",\r\n UPDATE_TASK: \"UPDATE_TASK\",\r\n UPDATE_TASK_COMMENTS: \"UPDATE_TASK_COMMENTS\",\r\n UPDATE_TASK_VOTE: \"UPDATE_TASK_VOTE\",\r\n UPDATE_LABELS: \"UPDATE_LABELS\",\r\n UPDATE_VIEWS: \"UPDATE_VIEWS\",\r\n UPDATE_CATEGORIES: \"UPDATE_CATEGORIES\",\r\n UPDATE_ISSUE_TEMPLATES: \"UPDATE_ISSUE_TEMPLATES\",\r\n DISCONNECTED: \"DISCONNECTED\"\r\n};\r\n\r\nexport interface WSMessage<T = unknown> {\r\n type: WSMessageType;\r\n scope: \"PUBLIC\";\r\n data: T;\r\n meta?: { ts: number };\r\n}\r\n\r\ntype Handlers = Partial<\r\n Record<WSMessageType, (data: any, msg: WSMessage) => void>\r\n>;\r\n\r\nexport function ws(url: string, handlers: Handlers = {}) {\r\n let socket: WebSocket;\r\n let retry = 0;\r\n let closed = false;\r\n\r\n function connect() {\r\n if (closed) return;\r\n\r\n socket = new WebSocket(url);\r\n\r\n socket.onmessage = (e) => {\r\n const msg = JSON.parse(e.data) as WSMessage;\r\n\r\n if (msg.type === wsTypes.PING) {\r\n socket.send(JSON.stringify({ type: wsTypes.PONG }));\r\n return;\r\n }\r\n\r\n handlers[msg.type]?.(msg.data, msg);\r\n };\r\n\r\n socket.onclose = () => {\r\n if (closed) return;\r\n setTimeout(connect, Math.min(1000 * 2 ** retry++, 30000));\r\n };\r\n\r\n socket.onerror = () => socket.close();\r\n }\r\n\r\n connect();\r\n\r\n return {\r\n close() {\r\n closed = true;\r\n socket?.close();\r\n }\r\n };\r\n}"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
type WSMessageType = "CONNECTION_STATUS" | "SUBSCRIBED" | "ERROR" | "PING" | "PONG" | "UPDATE_ORG" | "CREATE_TASK" | "UPDATE_TASK" | "UPDATE_TASK_COMMENTS" | "UPDATE_TASK_VOTE" | "UPDATE_LABELS" | "UPDATE_VIEWS" | "UPDATE_CATEGORIES" | "UPDATE_ISSUE_TEMPLATES" | "DISCONNECTED";
|
|
2
|
+
declare const wsTypes: Record<WSMessageType, WSMessageType>;
|
|
3
|
+
interface WSMessage<T = unknown> {
|
|
4
|
+
type: WSMessageType;
|
|
5
|
+
scope: "PUBLIC";
|
|
6
|
+
data: T;
|
|
7
|
+
meta?: {
|
|
8
|
+
ts: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
type Handlers = Partial<Record<WSMessageType, (data: any, msg: WSMessage) => void>>;
|
|
12
|
+
declare function ws(url: string, handlers?: Handlers): {
|
|
13
|
+
close(): void;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
interface ApiSuccess<T> {
|
|
17
|
+
success: true;
|
|
18
|
+
data: T;
|
|
19
|
+
}
|
|
20
|
+
interface ApiError {
|
|
21
|
+
success: false;
|
|
22
|
+
error: string;
|
|
23
|
+
message?: string;
|
|
24
|
+
}
|
|
25
|
+
interface Pagination {
|
|
26
|
+
limit: number;
|
|
27
|
+
page: number;
|
|
28
|
+
totalPages: number;
|
|
29
|
+
totalItems: number;
|
|
30
|
+
hasMore: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface Organization {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
slug: string;
|
|
36
|
+
logo: string | null;
|
|
37
|
+
bannerImg: string | null;
|
|
38
|
+
description: string;
|
|
39
|
+
createdAt: string;
|
|
40
|
+
updatedAt: string;
|
|
41
|
+
wsUrl: string;
|
|
42
|
+
}
|
|
43
|
+
interface Label {
|
|
44
|
+
id: string;
|
|
45
|
+
organizationId: string;
|
|
46
|
+
name: string;
|
|
47
|
+
color: string | null;
|
|
48
|
+
createdAt: string;
|
|
49
|
+
}
|
|
50
|
+
interface Category {
|
|
51
|
+
id: string;
|
|
52
|
+
organizationId: string;
|
|
53
|
+
name: string;
|
|
54
|
+
color: string | null;
|
|
55
|
+
icon: string | null;
|
|
56
|
+
createdAt: string;
|
|
57
|
+
}
|
|
58
|
+
type TaskStatus = "backlog" | "todo" | "in-progress" | "done" | "canceled";
|
|
59
|
+
type TaskPriority = "none" | "low" | "medium" | "high" | "urgent";
|
|
60
|
+
interface Task {
|
|
61
|
+
id: string;
|
|
62
|
+
organizationId: string;
|
|
63
|
+
shortId: number | null;
|
|
64
|
+
visible: "public" | "private";
|
|
65
|
+
createdAt: string;
|
|
66
|
+
updatedAt: string;
|
|
67
|
+
title: string | null;
|
|
68
|
+
description: unknown | null;
|
|
69
|
+
status: TaskStatus;
|
|
70
|
+
priority: TaskPriority;
|
|
71
|
+
createdBy: string | null;
|
|
72
|
+
category: string | null;
|
|
73
|
+
voteCount: number;
|
|
74
|
+
descriptionHtml: string;
|
|
75
|
+
descriptionMarkdown: string;
|
|
76
|
+
}
|
|
77
|
+
interface CommentUser {
|
|
78
|
+
name: string | null;
|
|
79
|
+
image: string | null;
|
|
80
|
+
}
|
|
81
|
+
interface CommentReaction {
|
|
82
|
+
count: number;
|
|
83
|
+
users: string[];
|
|
84
|
+
}
|
|
85
|
+
interface Comment {
|
|
86
|
+
id: string;
|
|
87
|
+
organizationId: string;
|
|
88
|
+
taskId: string | null;
|
|
89
|
+
createdAt: string;
|
|
90
|
+
updatedAt: string;
|
|
91
|
+
content: unknown | null;
|
|
92
|
+
visibility: "public" | "internal";
|
|
93
|
+
contentHtml: string;
|
|
94
|
+
contentMarkdown: string;
|
|
95
|
+
createdBy: CommentUser | null;
|
|
96
|
+
reactions?: {
|
|
97
|
+
total: number;
|
|
98
|
+
reactions: Record<string, CommentReaction>;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
declare const org: {
|
|
103
|
+
get(slug: string): Promise<Organization>;
|
|
104
|
+
labels(slug: string): Promise<Label[]>;
|
|
105
|
+
categories(slug: string, order?: "asc" | "desc"): Promise<Category[]>;
|
|
106
|
+
tasks(slug: string, opts?: {
|
|
107
|
+
order?: "asc" | "desc";
|
|
108
|
+
limit?: number;
|
|
109
|
+
page?: number;
|
|
110
|
+
}): Promise<{
|
|
111
|
+
data: Task[];
|
|
112
|
+
pagination: Pagination;
|
|
113
|
+
}>;
|
|
114
|
+
task(slug: string, shortId: number): Promise<Task>;
|
|
115
|
+
comments(slug: string, shortId: number, opts?: {
|
|
116
|
+
order?: "asc" | "desc";
|
|
117
|
+
limit?: number;
|
|
118
|
+
page?: number;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
data: Comment[];
|
|
121
|
+
pagination: Pagination;
|
|
122
|
+
}>;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
declare const Sayr: {
|
|
126
|
+
org: {
|
|
127
|
+
get(slug: string): Promise<Organization>;
|
|
128
|
+
labels(slug: string): Promise<Label[]>;
|
|
129
|
+
categories(slug: string, order?: "asc" | "desc"): Promise<Category[]>;
|
|
130
|
+
tasks(slug: string, opts?: {
|
|
131
|
+
order?: "asc" | "desc";
|
|
132
|
+
limit?: number;
|
|
133
|
+
page?: number;
|
|
134
|
+
}): Promise<{
|
|
135
|
+
data: Task[];
|
|
136
|
+
pagination: Pagination;
|
|
137
|
+
}>;
|
|
138
|
+
task(slug: string, shortId: number): Promise<Task>;
|
|
139
|
+
comments(slug: string, shortId: number, opts?: {
|
|
140
|
+
order?: "asc" | "desc";
|
|
141
|
+
limit?: number;
|
|
142
|
+
page?: number;
|
|
143
|
+
}): Promise<{
|
|
144
|
+
data: Comment[];
|
|
145
|
+
pagination: Pagination;
|
|
146
|
+
}>;
|
|
147
|
+
};
|
|
148
|
+
ws: typeof ws;
|
|
149
|
+
wsTypes: Record<WSMessageType, WSMessageType>;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export { type ApiError, type ApiSuccess, type Category, type Comment, type CommentReaction, type CommentUser, type Label, type Organization, type Pagination, type Task, type TaskPriority, type TaskStatus, Sayr as default, org, ws, wsTypes };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
type WSMessageType = "CONNECTION_STATUS" | "SUBSCRIBED" | "ERROR" | "PING" | "PONG" | "UPDATE_ORG" | "CREATE_TASK" | "UPDATE_TASK" | "UPDATE_TASK_COMMENTS" | "UPDATE_TASK_VOTE" | "UPDATE_LABELS" | "UPDATE_VIEWS" | "UPDATE_CATEGORIES" | "UPDATE_ISSUE_TEMPLATES" | "DISCONNECTED";
|
|
2
|
+
declare const wsTypes: Record<WSMessageType, WSMessageType>;
|
|
3
|
+
interface WSMessage<T = unknown> {
|
|
4
|
+
type: WSMessageType;
|
|
5
|
+
scope: "PUBLIC";
|
|
6
|
+
data: T;
|
|
7
|
+
meta?: {
|
|
8
|
+
ts: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
type Handlers = Partial<Record<WSMessageType, (data: any, msg: WSMessage) => void>>;
|
|
12
|
+
declare function ws(url: string, handlers?: Handlers): {
|
|
13
|
+
close(): void;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
interface ApiSuccess<T> {
|
|
17
|
+
success: true;
|
|
18
|
+
data: T;
|
|
19
|
+
}
|
|
20
|
+
interface ApiError {
|
|
21
|
+
success: false;
|
|
22
|
+
error: string;
|
|
23
|
+
message?: string;
|
|
24
|
+
}
|
|
25
|
+
interface Pagination {
|
|
26
|
+
limit: number;
|
|
27
|
+
page: number;
|
|
28
|
+
totalPages: number;
|
|
29
|
+
totalItems: number;
|
|
30
|
+
hasMore: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface Organization {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
slug: string;
|
|
36
|
+
logo: string | null;
|
|
37
|
+
bannerImg: string | null;
|
|
38
|
+
description: string;
|
|
39
|
+
createdAt: string;
|
|
40
|
+
updatedAt: string;
|
|
41
|
+
wsUrl: string;
|
|
42
|
+
}
|
|
43
|
+
interface Label {
|
|
44
|
+
id: string;
|
|
45
|
+
organizationId: string;
|
|
46
|
+
name: string;
|
|
47
|
+
color: string | null;
|
|
48
|
+
createdAt: string;
|
|
49
|
+
}
|
|
50
|
+
interface Category {
|
|
51
|
+
id: string;
|
|
52
|
+
organizationId: string;
|
|
53
|
+
name: string;
|
|
54
|
+
color: string | null;
|
|
55
|
+
icon: string | null;
|
|
56
|
+
createdAt: string;
|
|
57
|
+
}
|
|
58
|
+
type TaskStatus = "backlog" | "todo" | "in-progress" | "done" | "canceled";
|
|
59
|
+
type TaskPriority = "none" | "low" | "medium" | "high" | "urgent";
|
|
60
|
+
interface Task {
|
|
61
|
+
id: string;
|
|
62
|
+
organizationId: string;
|
|
63
|
+
shortId: number | null;
|
|
64
|
+
visible: "public" | "private";
|
|
65
|
+
createdAt: string;
|
|
66
|
+
updatedAt: string;
|
|
67
|
+
title: string | null;
|
|
68
|
+
description: unknown | null;
|
|
69
|
+
status: TaskStatus;
|
|
70
|
+
priority: TaskPriority;
|
|
71
|
+
createdBy: string | null;
|
|
72
|
+
category: string | null;
|
|
73
|
+
voteCount: number;
|
|
74
|
+
descriptionHtml: string;
|
|
75
|
+
descriptionMarkdown: string;
|
|
76
|
+
}
|
|
77
|
+
interface CommentUser {
|
|
78
|
+
name: string | null;
|
|
79
|
+
image: string | null;
|
|
80
|
+
}
|
|
81
|
+
interface CommentReaction {
|
|
82
|
+
count: number;
|
|
83
|
+
users: string[];
|
|
84
|
+
}
|
|
85
|
+
interface Comment {
|
|
86
|
+
id: string;
|
|
87
|
+
organizationId: string;
|
|
88
|
+
taskId: string | null;
|
|
89
|
+
createdAt: string;
|
|
90
|
+
updatedAt: string;
|
|
91
|
+
content: unknown | null;
|
|
92
|
+
visibility: "public" | "internal";
|
|
93
|
+
contentHtml: string;
|
|
94
|
+
contentMarkdown: string;
|
|
95
|
+
createdBy: CommentUser | null;
|
|
96
|
+
reactions?: {
|
|
97
|
+
total: number;
|
|
98
|
+
reactions: Record<string, CommentReaction>;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
declare const org: {
|
|
103
|
+
get(slug: string): Promise<Organization>;
|
|
104
|
+
labels(slug: string): Promise<Label[]>;
|
|
105
|
+
categories(slug: string, order?: "asc" | "desc"): Promise<Category[]>;
|
|
106
|
+
tasks(slug: string, opts?: {
|
|
107
|
+
order?: "asc" | "desc";
|
|
108
|
+
limit?: number;
|
|
109
|
+
page?: number;
|
|
110
|
+
}): Promise<{
|
|
111
|
+
data: Task[];
|
|
112
|
+
pagination: Pagination;
|
|
113
|
+
}>;
|
|
114
|
+
task(slug: string, shortId: number): Promise<Task>;
|
|
115
|
+
comments(slug: string, shortId: number, opts?: {
|
|
116
|
+
order?: "asc" | "desc";
|
|
117
|
+
limit?: number;
|
|
118
|
+
page?: number;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
data: Comment[];
|
|
121
|
+
pagination: Pagination;
|
|
122
|
+
}>;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
declare const Sayr: {
|
|
126
|
+
org: {
|
|
127
|
+
get(slug: string): Promise<Organization>;
|
|
128
|
+
labels(slug: string): Promise<Label[]>;
|
|
129
|
+
categories(slug: string, order?: "asc" | "desc"): Promise<Category[]>;
|
|
130
|
+
tasks(slug: string, opts?: {
|
|
131
|
+
order?: "asc" | "desc";
|
|
132
|
+
limit?: number;
|
|
133
|
+
page?: number;
|
|
134
|
+
}): Promise<{
|
|
135
|
+
data: Task[];
|
|
136
|
+
pagination: Pagination;
|
|
137
|
+
}>;
|
|
138
|
+
task(slug: string, shortId: number): Promise<Task>;
|
|
139
|
+
comments(slug: string, shortId: number, opts?: {
|
|
140
|
+
order?: "asc" | "desc";
|
|
141
|
+
limit?: number;
|
|
142
|
+
page?: number;
|
|
143
|
+
}): Promise<{
|
|
144
|
+
data: Comment[];
|
|
145
|
+
pagination: Pagination;
|
|
146
|
+
}>;
|
|
147
|
+
};
|
|
148
|
+
ws: typeof ws;
|
|
149
|
+
wsTypes: Record<WSMessageType, WSMessageType>;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export { type ApiError, type ApiSuccess, type Category, type Comment, type CommentReaction, type CommentUser, type Label, type Organization, type Pagination, type Task, type TaskPriority, type TaskStatus, Sayr as default, org, ws, wsTypes };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// src/org.ts
|
|
2
|
+
var API = "https://sayr.io/api/public";
|
|
3
|
+
async function get(url) {
|
|
4
|
+
const res = await fetch(url);
|
|
5
|
+
const json = await res.json();
|
|
6
|
+
if (!json.success) throw json;
|
|
7
|
+
return json;
|
|
8
|
+
}
|
|
9
|
+
var org = {
|
|
10
|
+
async get(slug) {
|
|
11
|
+
const r = await get(
|
|
12
|
+
`${API}/organization/${slug}`
|
|
13
|
+
);
|
|
14
|
+
return r.data;
|
|
15
|
+
},
|
|
16
|
+
async labels(slug) {
|
|
17
|
+
const r = await get(
|
|
18
|
+
`${API}/organization/${slug}/labels`
|
|
19
|
+
);
|
|
20
|
+
return r.data;
|
|
21
|
+
},
|
|
22
|
+
async categories(slug, order = "desc") {
|
|
23
|
+
const r = await get(
|
|
24
|
+
`${API}/organization/${slug}/categories?order=${order}`
|
|
25
|
+
);
|
|
26
|
+
return r.data;
|
|
27
|
+
},
|
|
28
|
+
async tasks(slug, opts) {
|
|
29
|
+
const q = new URLSearchParams({
|
|
30
|
+
order: opts?.order ?? "desc",
|
|
31
|
+
limit: String(opts?.limit ?? 5),
|
|
32
|
+
page: String(opts?.page ?? 1)
|
|
33
|
+
});
|
|
34
|
+
const res = await fetch(
|
|
35
|
+
`${API}/organization/${slug}/tasks?${q}`
|
|
36
|
+
);
|
|
37
|
+
const json = await res.json();
|
|
38
|
+
if (!json.success) throw json;
|
|
39
|
+
return {
|
|
40
|
+
data: json.data,
|
|
41
|
+
pagination: json.pagination
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
async task(slug, shortId) {
|
|
45
|
+
const r = await get(
|
|
46
|
+
`${API}/organization/${slug}/tasks/${shortId}`
|
|
47
|
+
);
|
|
48
|
+
return r.data;
|
|
49
|
+
},
|
|
50
|
+
async comments(slug, shortId, opts) {
|
|
51
|
+
const q = new URLSearchParams({
|
|
52
|
+
order: opts?.order ?? "desc",
|
|
53
|
+
limit: String(opts?.limit ?? 5),
|
|
54
|
+
page: String(opts?.page ?? 1)
|
|
55
|
+
});
|
|
56
|
+
const res = await fetch(
|
|
57
|
+
`${API}/organization/${slug}/tasks/${shortId}/comments?${q}`
|
|
58
|
+
);
|
|
59
|
+
const json = await res.json();
|
|
60
|
+
if (!json.success) throw json;
|
|
61
|
+
return {
|
|
62
|
+
data: json.data,
|
|
63
|
+
pagination: json.pagination
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// src/ws.ts
|
|
69
|
+
var wsTypes = {
|
|
70
|
+
CONNECTION_STATUS: "CONNECTION_STATUS",
|
|
71
|
+
SUBSCRIBED: "SUBSCRIBED",
|
|
72
|
+
ERROR: "ERROR",
|
|
73
|
+
PING: "PING",
|
|
74
|
+
PONG: "PONG",
|
|
75
|
+
UPDATE_ORG: "UPDATE_ORG",
|
|
76
|
+
CREATE_TASK: "CREATE_TASK",
|
|
77
|
+
UPDATE_TASK: "UPDATE_TASK",
|
|
78
|
+
UPDATE_TASK_COMMENTS: "UPDATE_TASK_COMMENTS",
|
|
79
|
+
UPDATE_TASK_VOTE: "UPDATE_TASK_VOTE",
|
|
80
|
+
UPDATE_LABELS: "UPDATE_LABELS",
|
|
81
|
+
UPDATE_VIEWS: "UPDATE_VIEWS",
|
|
82
|
+
UPDATE_CATEGORIES: "UPDATE_CATEGORIES",
|
|
83
|
+
UPDATE_ISSUE_TEMPLATES: "UPDATE_ISSUE_TEMPLATES",
|
|
84
|
+
DISCONNECTED: "DISCONNECTED"
|
|
85
|
+
};
|
|
86
|
+
function ws(url, handlers = {}) {
|
|
87
|
+
let socket;
|
|
88
|
+
let retry = 0;
|
|
89
|
+
let closed = false;
|
|
90
|
+
function connect() {
|
|
91
|
+
if (closed) return;
|
|
92
|
+
socket = new WebSocket(url);
|
|
93
|
+
socket.onmessage = (e) => {
|
|
94
|
+
const msg = JSON.parse(e.data);
|
|
95
|
+
if (msg.type === wsTypes.PING) {
|
|
96
|
+
socket.send(JSON.stringify({ type: wsTypes.PONG }));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
handlers[msg.type]?.(msg.data, msg);
|
|
100
|
+
};
|
|
101
|
+
socket.onclose = () => {
|
|
102
|
+
if (closed) return;
|
|
103
|
+
setTimeout(connect, Math.min(1e3 * 2 ** retry++, 3e4));
|
|
104
|
+
};
|
|
105
|
+
socket.onerror = () => socket.close();
|
|
106
|
+
}
|
|
107
|
+
connect();
|
|
108
|
+
return {
|
|
109
|
+
close() {
|
|
110
|
+
closed = true;
|
|
111
|
+
socket?.close();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/index.ts
|
|
117
|
+
var Sayr = { org, ws, wsTypes };
|
|
118
|
+
var index_default = Sayr;
|
|
119
|
+
export {
|
|
120
|
+
index_default as default,
|
|
121
|
+
org,
|
|
122
|
+
ws,
|
|
123
|
+
wsTypes
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/org.ts","../src/ws.ts","../src/index.ts"],"sourcesContent":["import {\r\n Organization,\r\n Label,\r\n Category,\r\n Task,\r\n Comment,\r\n Pagination,\r\n ApiSuccess\r\n} from \"./types\";\r\n\r\nconst API = \"https://sayr.io/api/public\";\r\n\r\nasync function get<T>(url: string): Promise<T> {\r\n const res = await fetch(url);\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n return json;\r\n}\r\n\r\nexport const org = {\r\n async get(slug: string): Promise<Organization> {\r\n const r = await get<ApiSuccess<Organization>>(\r\n `${API}/organization/${slug}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async labels(slug: string): Promise<Label[]> {\r\n const r = await get<ApiSuccess<Label[]>>(\r\n `${API}/organization/${slug}/labels`\r\n );\r\n return r.data;\r\n },\r\n\r\n async categories(\r\n slug: string,\r\n order: \"asc\" | \"desc\" = \"desc\"\r\n ): Promise<Category[]> {\r\n const r = await get<ApiSuccess<Category[]>>(\r\n `${API}/organization/${slug}/categories?order=${order}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async tasks(\r\n slug: string,\r\n opts?: { order?: \"asc\" | \"desc\"; limit?: number; page?: number }\r\n ): Promise<{ data: Task[]; pagination: Pagination }> {\r\n const q = new URLSearchParams({\r\n order: opts?.order ?? \"desc\",\r\n limit: String(opts?.limit ?? 5),\r\n page: String(opts?.page ?? 1)\r\n });\r\n\r\n const res = await fetch(\r\n `${API}/organization/${slug}/tasks?${q}`\r\n );\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n\r\n return {\r\n data: json.data,\r\n pagination: json.pagination\r\n };\r\n },\r\n\r\n async task(slug: string, shortId: number): Promise<Task> {\r\n const r = await get<ApiSuccess<Task>>(\r\n `${API}/organization/${slug}/tasks/${shortId}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async comments(\r\n slug: string,\r\n shortId: number,\r\n opts?: { order?: \"asc\" | \"desc\"; limit?: number; page?: number }\r\n ): Promise<{ data: Comment[]; pagination: Pagination }> {\r\n const q = new URLSearchParams({\r\n order: opts?.order ?? \"desc\",\r\n limit: String(opts?.limit ?? 5),\r\n page: String(opts?.page ?? 1)\r\n });\r\n\r\n const res = await fetch(\r\n `${API}/organization/${slug}/tasks/${shortId}/comments?${q}`\r\n );\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n\r\n return {\r\n data: json.data,\r\n pagination: json.pagination\r\n };\r\n }\r\n};","export type WSMessageType =\r\n | \"CONNECTION_STATUS\"\r\n | \"SUBSCRIBED\"\r\n | \"ERROR\"\r\n | \"PING\"\r\n | \"PONG\"\r\n | \"UPDATE_ORG\"\r\n | \"CREATE_TASK\"\r\n | \"UPDATE_TASK\"\r\n | \"UPDATE_TASK_COMMENTS\"\r\n | \"UPDATE_TASK_VOTE\"\r\n | \"UPDATE_LABELS\"\r\n | \"UPDATE_VIEWS\"\r\n | \"UPDATE_CATEGORIES\"\r\n | \"UPDATE_ISSUE_TEMPLATES\"\r\n | \"DISCONNECTED\";\r\n\r\nexport const wsTypes: Record<WSMessageType, WSMessageType> = {\r\n CONNECTION_STATUS: \"CONNECTION_STATUS\",\r\n SUBSCRIBED: \"SUBSCRIBED\",\r\n ERROR: \"ERROR\",\r\n PING: \"PING\",\r\n PONG: \"PONG\",\r\n UPDATE_ORG: \"UPDATE_ORG\",\r\n CREATE_TASK: \"CREATE_TASK\",\r\n UPDATE_TASK: \"UPDATE_TASK\",\r\n UPDATE_TASK_COMMENTS: \"UPDATE_TASK_COMMENTS\",\r\n UPDATE_TASK_VOTE: \"UPDATE_TASK_VOTE\",\r\n UPDATE_LABELS: \"UPDATE_LABELS\",\r\n UPDATE_VIEWS: \"UPDATE_VIEWS\",\r\n UPDATE_CATEGORIES: \"UPDATE_CATEGORIES\",\r\n UPDATE_ISSUE_TEMPLATES: \"UPDATE_ISSUE_TEMPLATES\",\r\n DISCONNECTED: \"DISCONNECTED\"\r\n};\r\n\r\nexport interface WSMessage<T = unknown> {\r\n type: WSMessageType;\r\n scope: \"PUBLIC\";\r\n data: T;\r\n meta?: { ts: number };\r\n}\r\n\r\ntype Handlers = Partial<\r\n Record<WSMessageType, (data: any, msg: WSMessage) => void>\r\n>;\r\n\r\nexport function ws(url: string, handlers: Handlers = {}) {\r\n let socket: WebSocket;\r\n let retry = 0;\r\n let closed = false;\r\n\r\n function connect() {\r\n if (closed) return;\r\n\r\n socket = new WebSocket(url);\r\n\r\n socket.onmessage = (e) => {\r\n const msg = JSON.parse(e.data) as WSMessage;\r\n\r\n if (msg.type === wsTypes.PING) {\r\n socket.send(JSON.stringify({ type: wsTypes.PONG }));\r\n return;\r\n }\r\n\r\n handlers[msg.type]?.(msg.data, msg);\r\n };\r\n\r\n socket.onclose = () => {\r\n if (closed) return;\r\n setTimeout(connect, Math.min(1000 * 2 ** retry++, 30000));\r\n };\r\n\r\n socket.onerror = () => socket.close();\r\n }\r\n\r\n connect();\r\n\r\n return {\r\n close() {\r\n closed = true;\r\n socket?.close();\r\n }\r\n };\r\n}","import { org } from \"./org\";\r\nimport { ws, wsTypes } from \"./ws\";\r\n\r\nconst Sayr = { org, ws, wsTypes };\r\n\r\nexport default Sayr;\r\nexport { org, ws, wsTypes };\r\nexport * from \"./types\";"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/react/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
useComments: () => useComments,
|
|
24
|
+
useOrg: () => useOrg,
|
|
25
|
+
useSayrWS: () => useSayrWS,
|
|
26
|
+
useTask: () => useTask,
|
|
27
|
+
useTasks: () => useTasks
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/react/useOrg.ts
|
|
32
|
+
var import_react = require("react");
|
|
33
|
+
|
|
34
|
+
// src/org.ts
|
|
35
|
+
var API = "https://sayr.io/api/public";
|
|
36
|
+
async function get(url) {
|
|
37
|
+
const res = await fetch(url);
|
|
38
|
+
const json = await res.json();
|
|
39
|
+
if (!json.success) throw json;
|
|
40
|
+
return json;
|
|
41
|
+
}
|
|
42
|
+
var org = {
|
|
43
|
+
async get(slug) {
|
|
44
|
+
const r = await get(
|
|
45
|
+
`${API}/organization/${slug}`
|
|
46
|
+
);
|
|
47
|
+
return r.data;
|
|
48
|
+
},
|
|
49
|
+
async labels(slug) {
|
|
50
|
+
const r = await get(
|
|
51
|
+
`${API}/organization/${slug}/labels`
|
|
52
|
+
);
|
|
53
|
+
return r.data;
|
|
54
|
+
},
|
|
55
|
+
async categories(slug, order = "desc") {
|
|
56
|
+
const r = await get(
|
|
57
|
+
`${API}/organization/${slug}/categories?order=${order}`
|
|
58
|
+
);
|
|
59
|
+
return r.data;
|
|
60
|
+
},
|
|
61
|
+
async tasks(slug, opts) {
|
|
62
|
+
const q = new URLSearchParams({
|
|
63
|
+
order: opts?.order ?? "desc",
|
|
64
|
+
limit: String(opts?.limit ?? 5),
|
|
65
|
+
page: String(opts?.page ?? 1)
|
|
66
|
+
});
|
|
67
|
+
const res = await fetch(
|
|
68
|
+
`${API}/organization/${slug}/tasks?${q}`
|
|
69
|
+
);
|
|
70
|
+
const json = await res.json();
|
|
71
|
+
if (!json.success) throw json;
|
|
72
|
+
return {
|
|
73
|
+
data: json.data,
|
|
74
|
+
pagination: json.pagination
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
async task(slug, shortId) {
|
|
78
|
+
const r = await get(
|
|
79
|
+
`${API}/organization/${slug}/tasks/${shortId}`
|
|
80
|
+
);
|
|
81
|
+
return r.data;
|
|
82
|
+
},
|
|
83
|
+
async comments(slug, shortId, opts) {
|
|
84
|
+
const q = new URLSearchParams({
|
|
85
|
+
order: opts?.order ?? "desc",
|
|
86
|
+
limit: String(opts?.limit ?? 5),
|
|
87
|
+
page: String(opts?.page ?? 1)
|
|
88
|
+
});
|
|
89
|
+
const res = await fetch(
|
|
90
|
+
`${API}/organization/${slug}/tasks/${shortId}/comments?${q}`
|
|
91
|
+
);
|
|
92
|
+
const json = await res.json();
|
|
93
|
+
if (!json.success) throw json;
|
|
94
|
+
return {
|
|
95
|
+
data: json.data,
|
|
96
|
+
pagination: json.pagination
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// src/ws.ts
|
|
102
|
+
var wsTypes = {
|
|
103
|
+
CONNECTION_STATUS: "CONNECTION_STATUS",
|
|
104
|
+
SUBSCRIBED: "SUBSCRIBED",
|
|
105
|
+
ERROR: "ERROR",
|
|
106
|
+
PING: "PING",
|
|
107
|
+
PONG: "PONG",
|
|
108
|
+
UPDATE_ORG: "UPDATE_ORG",
|
|
109
|
+
CREATE_TASK: "CREATE_TASK",
|
|
110
|
+
UPDATE_TASK: "UPDATE_TASK",
|
|
111
|
+
UPDATE_TASK_COMMENTS: "UPDATE_TASK_COMMENTS",
|
|
112
|
+
UPDATE_TASK_VOTE: "UPDATE_TASK_VOTE",
|
|
113
|
+
UPDATE_LABELS: "UPDATE_LABELS",
|
|
114
|
+
UPDATE_VIEWS: "UPDATE_VIEWS",
|
|
115
|
+
UPDATE_CATEGORIES: "UPDATE_CATEGORIES",
|
|
116
|
+
UPDATE_ISSUE_TEMPLATES: "UPDATE_ISSUE_TEMPLATES",
|
|
117
|
+
DISCONNECTED: "DISCONNECTED"
|
|
118
|
+
};
|
|
119
|
+
function ws(url, handlers = {}) {
|
|
120
|
+
let socket;
|
|
121
|
+
let retry = 0;
|
|
122
|
+
let closed = false;
|
|
123
|
+
function connect() {
|
|
124
|
+
if (closed) return;
|
|
125
|
+
socket = new WebSocket(url);
|
|
126
|
+
socket.onmessage = (e) => {
|
|
127
|
+
const msg = JSON.parse(e.data);
|
|
128
|
+
if (msg.type === wsTypes.PING) {
|
|
129
|
+
socket.send(JSON.stringify({ type: wsTypes.PONG }));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
handlers[msg.type]?.(msg.data, msg);
|
|
133
|
+
};
|
|
134
|
+
socket.onclose = () => {
|
|
135
|
+
if (closed) return;
|
|
136
|
+
setTimeout(connect, Math.min(1e3 * 2 ** retry++, 3e4));
|
|
137
|
+
};
|
|
138
|
+
socket.onerror = () => socket.close();
|
|
139
|
+
}
|
|
140
|
+
connect();
|
|
141
|
+
return {
|
|
142
|
+
close() {
|
|
143
|
+
closed = true;
|
|
144
|
+
socket?.close();
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/react/useOrg.ts
|
|
150
|
+
function useOrg(slug) {
|
|
151
|
+
const [data, setData] = (0, import_react.useState)(null);
|
|
152
|
+
const [loading, setLoading] = (0, import_react.useState)(false);
|
|
153
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
154
|
+
(0, import_react.useEffect)(() => {
|
|
155
|
+
if (!slug) return;
|
|
156
|
+
setLoading(true);
|
|
157
|
+
org.get(slug).then(setData).catch(setError).finally(() => setLoading(false));
|
|
158
|
+
}, [slug]);
|
|
159
|
+
return { data, loading, error };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/react/useTasks.ts
|
|
163
|
+
var import_react3 = require("react");
|
|
164
|
+
|
|
165
|
+
// src/react/useSayrWS.ts
|
|
166
|
+
var import_react2 = require("react");
|
|
167
|
+
function useSayrWS(wsUrl, handlers) {
|
|
168
|
+
const connRef = (0, import_react2.useRef)(null);
|
|
169
|
+
(0, import_react2.useEffect)(() => {
|
|
170
|
+
if (!wsUrl) return;
|
|
171
|
+
connRef.current = ws(wsUrl, handlers);
|
|
172
|
+
return () => {
|
|
173
|
+
connRef.current?.close();
|
|
174
|
+
connRef.current = null;
|
|
175
|
+
};
|
|
176
|
+
}, [wsUrl]);
|
|
177
|
+
return connRef;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/react/useTasks.ts
|
|
181
|
+
function useTasks(slug, wsUrl) {
|
|
182
|
+
const [tasks, setTasks] = (0, import_react3.useState)([]);
|
|
183
|
+
const [loading, setLoading] = (0, import_react3.useState)(false);
|
|
184
|
+
function fetchTasks() {
|
|
185
|
+
if (!slug) return;
|
|
186
|
+
setLoading(true);
|
|
187
|
+
org.tasks(slug).then((r) => setTasks(r.data)).finally(() => setLoading(false));
|
|
188
|
+
}
|
|
189
|
+
(0, import_react3.useEffect)(fetchTasks, [slug]);
|
|
190
|
+
useSayrWS(wsUrl, {
|
|
191
|
+
[wsTypes.CREATE_TASK]: fetchTasks,
|
|
192
|
+
[wsTypes.UPDATE_TASK]: fetchTasks
|
|
193
|
+
});
|
|
194
|
+
return { tasks, loading, refetch: fetchTasks };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/react/useTask.ts
|
|
198
|
+
var import_react4 = require("react");
|
|
199
|
+
function useTask(slug, shortId) {
|
|
200
|
+
const [task, setTask] = (0, import_react4.useState)(null);
|
|
201
|
+
const [loading, setLoading] = (0, import_react4.useState)(false);
|
|
202
|
+
(0, import_react4.useEffect)(() => {
|
|
203
|
+
if (!slug || shortId == null) return;
|
|
204
|
+
setLoading(true);
|
|
205
|
+
org.task(slug, shortId).then(setTask).finally(() => setLoading(false));
|
|
206
|
+
}, [slug, shortId]);
|
|
207
|
+
return { task, loading };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/react/useComments.ts
|
|
211
|
+
var import_react5 = require("react");
|
|
212
|
+
function useComments(slug, shortId, wsUrl) {
|
|
213
|
+
const [comments, setComments] = (0, import_react5.useState)([]);
|
|
214
|
+
const [loading, setLoading] = (0, import_react5.useState)(false);
|
|
215
|
+
function fetchComments() {
|
|
216
|
+
if (!slug || shortId == null) return;
|
|
217
|
+
setLoading(true);
|
|
218
|
+
org.comments(slug, shortId).then((r) => setComments(r.data)).finally(() => setLoading(false));
|
|
219
|
+
}
|
|
220
|
+
(0, import_react5.useEffect)(fetchComments, [slug, shortId]);
|
|
221
|
+
useSayrWS(wsUrl, {
|
|
222
|
+
[wsTypes.UPDATE_TASK_COMMENTS]: fetchComments
|
|
223
|
+
});
|
|
224
|
+
return { comments, loading, refetch: fetchComments };
|
|
225
|
+
}
|
|
226
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
227
|
+
0 && (module.exports = {
|
|
228
|
+
useComments,
|
|
229
|
+
useOrg,
|
|
230
|
+
useSayrWS,
|
|
231
|
+
useTask,
|
|
232
|
+
useTasks
|
|
233
|
+
});
|
|
234
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/useOrg.ts","../../src/org.ts","../../src/ws.ts","../../src/react/useTasks.ts","../../src/react/useSayrWS.ts","../../src/react/useTask.ts","../../src/react/useComments.ts"],"sourcesContent":["export { useOrg } from \"./useOrg\";\r\nexport { useTasks } from \"./useTasks\";\r\nexport { useTask } from \"./useTask\";\r\nexport { useComments } from \"./useComments\";\r\nexport { useSayrWS } from \"./useSayrWS\";","import { useEffect, useState } from \"react\";\r\nimport { org, Organization } from \"../index\";\r\n\r\nexport function useOrg(slug?: string) {\r\n const [data, setData] = useState<Organization | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n const [error, setError] = useState<unknown>(null);\r\n\r\n useEffect(() => {\r\n if (!slug) return;\r\n\r\n setLoading(true);\r\n org\r\n .get(slug)\r\n .then(setData)\r\n .catch(setError)\r\n .finally(() => setLoading(false));\r\n }, [slug]);\r\n\r\n return { data, loading, error };\r\n}","import {\r\n Organization,\r\n Label,\r\n Category,\r\n Task,\r\n Comment,\r\n Pagination,\r\n ApiSuccess\r\n} from \"./types\";\r\n\r\nconst API = \"https://sayr.io/api/public\";\r\n\r\nasync function get<T>(url: string): Promise<T> {\r\n const res = await fetch(url);\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n return json;\r\n}\r\n\r\nexport const org = {\r\n async get(slug: string): Promise<Organization> {\r\n const r = await get<ApiSuccess<Organization>>(\r\n `${API}/organization/${slug}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async labels(slug: string): Promise<Label[]> {\r\n const r = await get<ApiSuccess<Label[]>>(\r\n `${API}/organization/${slug}/labels`\r\n );\r\n return r.data;\r\n },\r\n\r\n async categories(\r\n slug: string,\r\n order: \"asc\" | \"desc\" = \"desc\"\r\n ): Promise<Category[]> {\r\n const r = await get<ApiSuccess<Category[]>>(\r\n `${API}/organization/${slug}/categories?order=${order}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async tasks(\r\n slug: string,\r\n opts?: { order?: \"asc\" | \"desc\"; limit?: number; page?: number }\r\n ): Promise<{ data: Task[]; pagination: Pagination }> {\r\n const q = new URLSearchParams({\r\n order: opts?.order ?? \"desc\",\r\n limit: String(opts?.limit ?? 5),\r\n page: String(opts?.page ?? 1)\r\n });\r\n\r\n const res = await fetch(\r\n `${API}/organization/${slug}/tasks?${q}`\r\n );\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n\r\n return {\r\n data: json.data,\r\n pagination: json.pagination\r\n };\r\n },\r\n\r\n async task(slug: string, shortId: number): Promise<Task> {\r\n const r = await get<ApiSuccess<Task>>(\r\n `${API}/organization/${slug}/tasks/${shortId}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async comments(\r\n slug: string,\r\n shortId: number,\r\n opts?: { order?: \"asc\" | \"desc\"; limit?: number; page?: number }\r\n ): Promise<{ data: Comment[]; pagination: Pagination }> {\r\n const q = new URLSearchParams({\r\n order: opts?.order ?? \"desc\",\r\n limit: String(opts?.limit ?? 5),\r\n page: String(opts?.page ?? 1)\r\n });\r\n\r\n const res = await fetch(\r\n `${API}/organization/${slug}/tasks/${shortId}/comments?${q}`\r\n );\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n\r\n return {\r\n data: json.data,\r\n pagination: json.pagination\r\n };\r\n }\r\n};","export type WSMessageType =\r\n | \"CONNECTION_STATUS\"\r\n | \"SUBSCRIBED\"\r\n | \"ERROR\"\r\n | \"PING\"\r\n | \"PONG\"\r\n | \"UPDATE_ORG\"\r\n | \"CREATE_TASK\"\r\n | \"UPDATE_TASK\"\r\n | \"UPDATE_TASK_COMMENTS\"\r\n | \"UPDATE_TASK_VOTE\"\r\n | \"UPDATE_LABELS\"\r\n | \"UPDATE_VIEWS\"\r\n | \"UPDATE_CATEGORIES\"\r\n | \"UPDATE_ISSUE_TEMPLATES\"\r\n | \"DISCONNECTED\";\r\n\r\nexport const wsTypes: Record<WSMessageType, WSMessageType> = {\r\n CONNECTION_STATUS: \"CONNECTION_STATUS\",\r\n SUBSCRIBED: \"SUBSCRIBED\",\r\n ERROR: \"ERROR\",\r\n PING: \"PING\",\r\n PONG: \"PONG\",\r\n UPDATE_ORG: \"UPDATE_ORG\",\r\n CREATE_TASK: \"CREATE_TASK\",\r\n UPDATE_TASK: \"UPDATE_TASK\",\r\n UPDATE_TASK_COMMENTS: \"UPDATE_TASK_COMMENTS\",\r\n UPDATE_TASK_VOTE: \"UPDATE_TASK_VOTE\",\r\n UPDATE_LABELS: \"UPDATE_LABELS\",\r\n UPDATE_VIEWS: \"UPDATE_VIEWS\",\r\n UPDATE_CATEGORIES: \"UPDATE_CATEGORIES\",\r\n UPDATE_ISSUE_TEMPLATES: \"UPDATE_ISSUE_TEMPLATES\",\r\n DISCONNECTED: \"DISCONNECTED\"\r\n};\r\n\r\nexport interface WSMessage<T = unknown> {\r\n type: WSMessageType;\r\n scope: \"PUBLIC\";\r\n data: T;\r\n meta?: { ts: number };\r\n}\r\n\r\ntype Handlers = Partial<\r\n Record<WSMessageType, (data: any, msg: WSMessage) => void>\r\n>;\r\n\r\nexport function ws(url: string, handlers: Handlers = {}) {\r\n let socket: WebSocket;\r\n let retry = 0;\r\n let closed = false;\r\n\r\n function connect() {\r\n if (closed) return;\r\n\r\n socket = new WebSocket(url);\r\n\r\n socket.onmessage = (e) => {\r\n const msg = JSON.parse(e.data) as WSMessage;\r\n\r\n if (msg.type === wsTypes.PING) {\r\n socket.send(JSON.stringify({ type: wsTypes.PONG }));\r\n return;\r\n }\r\n\r\n handlers[msg.type]?.(msg.data, msg);\r\n };\r\n\r\n socket.onclose = () => {\r\n if (closed) return;\r\n setTimeout(connect, Math.min(1000 * 2 ** retry++, 30000));\r\n };\r\n\r\n socket.onerror = () => socket.close();\r\n }\r\n\r\n connect();\r\n\r\n return {\r\n close() {\r\n closed = true;\r\n socket?.close();\r\n }\r\n };\r\n}","import { useEffect, useState } from \"react\";\r\nimport { org, wsTypes } from \"..\";\r\nimport type { Task } from \"../types\";\r\nimport { useSayrWS } from \"./useSayrWS\";\r\nexport function useTasks(\r\n slug?: string,\r\n wsUrl?: string\r\n) {\r\n const [tasks, setTasks] = useState<Task[]>([]);\r\n const [loading, setLoading] = useState(false);\r\n\r\n function fetchTasks() {\r\n if (!slug) return;\r\n setLoading(true);\r\n org\r\n .tasks(slug)\r\n .then((r) => setTasks(r.data))\r\n .finally(() => setLoading(false));\r\n }\r\n\r\n useEffect(fetchTasks, [slug]);\r\n\r\n useSayrWS(wsUrl, {\r\n [wsTypes.CREATE_TASK]: fetchTasks,\r\n [wsTypes.UPDATE_TASK]: fetchTasks\r\n });\r\n\r\n return { tasks, loading, refetch: fetchTasks };\r\n}","import { useEffect, useRef } from \"react\";\r\nimport { ws } from \"..\";\r\nimport { WSMessageType } from \"../ws\";\r\n\r\ntype Handlers = Partial<\r\n Record<WSMessageType, (data: any, msg: any) => void>\r\n>;\r\n\r\nexport function useSayrWS(\r\n wsUrl?: string,\r\n handlers?: Handlers\r\n) {\r\n const connRef = useRef<ReturnType<typeof ws> | null>(null);\r\n\r\n useEffect(() => {\r\n if (!wsUrl) return;\r\n\r\n connRef.current = ws(wsUrl, handlers);\r\n\r\n return () => {\r\n connRef.current?.close();\r\n connRef.current = null;\r\n };\r\n }, [wsUrl]);\r\n\r\n return connRef;\r\n}","import { useEffect, useState } from \"react\";\r\nimport { org } from \"..\";\r\nimport type { Task } from \"../types\";\r\n\r\nexport function useTask(\r\n slug?: string,\r\n shortId?: number\r\n) {\r\n const [task, setTask] = useState<Task | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (!slug || shortId == null) return;\r\n\r\n setLoading(true);\r\n org\r\n .task(slug, shortId)\r\n .then(setTask)\r\n .finally(() => setLoading(false));\r\n }, [slug, shortId]);\r\n\r\n return { task, loading };\r\n}","import { useEffect, useState } from \"react\";\r\nimport { org, wsTypes } from \"..\";\r\nimport type { Comment } from \"../types\";\r\nimport { useSayrWS } from \"./useSayrWS\";\r\n\r\nexport function useComments(\r\n slug?: string,\r\n shortId?: number,\r\n wsUrl?: string\r\n) {\r\n const [comments, setComments] = useState<Comment[]>([]);\r\n const [loading, setLoading] = useState(false);\r\n\r\n function fetchComments() {\r\n if (!slug || shortId == null) return;\r\n\r\n setLoading(true);\r\n org\r\n .comments(slug, shortId)\r\n .then((r) => setComments(r.data))\r\n .finally(() => setLoading(false));\r\n }\r\n\r\n useEffect(fetchComments, [slug, shortId]);\r\n\r\n useSayrWS(wsUrl, {\r\n [wsTypes.UPDATE_TASK_COMMENTS]: fetchComments\r\n });\r\n\r\n return { comments, loading, refetch: fetchComments };\r\n}"],"mappings":"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","names":["import_react","import_react","import_react","import_react"]}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
type WSMessageType = "CONNECTION_STATUS" | "SUBSCRIBED" | "ERROR" | "PING" | "PONG" | "UPDATE_ORG" | "CREATE_TASK" | "UPDATE_TASK" | "UPDATE_TASK_COMMENTS" | "UPDATE_TASK_VOTE" | "UPDATE_LABELS" | "UPDATE_VIEWS" | "UPDATE_CATEGORIES" | "UPDATE_ISSUE_TEMPLATES" | "DISCONNECTED";
|
|
4
|
+
|
|
5
|
+
interface Organization {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
slug: string;
|
|
9
|
+
logo: string | null;
|
|
10
|
+
bannerImg: string | null;
|
|
11
|
+
description: string;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
wsUrl: string;
|
|
15
|
+
}
|
|
16
|
+
type TaskStatus = "backlog" | "todo" | "in-progress" | "done" | "canceled";
|
|
17
|
+
type TaskPriority = "none" | "low" | "medium" | "high" | "urgent";
|
|
18
|
+
interface Task {
|
|
19
|
+
id: string;
|
|
20
|
+
organizationId: string;
|
|
21
|
+
shortId: number | null;
|
|
22
|
+
visible: "public" | "private";
|
|
23
|
+
createdAt: string;
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
title: string | null;
|
|
26
|
+
description: unknown | null;
|
|
27
|
+
status: TaskStatus;
|
|
28
|
+
priority: TaskPriority;
|
|
29
|
+
createdBy: string | null;
|
|
30
|
+
category: string | null;
|
|
31
|
+
voteCount: number;
|
|
32
|
+
descriptionHtml: string;
|
|
33
|
+
descriptionMarkdown: string;
|
|
34
|
+
}
|
|
35
|
+
interface CommentUser {
|
|
36
|
+
name: string | null;
|
|
37
|
+
image: string | null;
|
|
38
|
+
}
|
|
39
|
+
interface CommentReaction {
|
|
40
|
+
count: number;
|
|
41
|
+
users: string[];
|
|
42
|
+
}
|
|
43
|
+
interface Comment {
|
|
44
|
+
id: string;
|
|
45
|
+
organizationId: string;
|
|
46
|
+
taskId: string | null;
|
|
47
|
+
createdAt: string;
|
|
48
|
+
updatedAt: string;
|
|
49
|
+
content: unknown | null;
|
|
50
|
+
visibility: "public" | "internal";
|
|
51
|
+
contentHtml: string;
|
|
52
|
+
contentMarkdown: string;
|
|
53
|
+
createdBy: CommentUser | null;
|
|
54
|
+
reactions?: {
|
|
55
|
+
total: number;
|
|
56
|
+
reactions: Record<string, CommentReaction>;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare function useOrg(slug?: string): {
|
|
61
|
+
data: Organization | null;
|
|
62
|
+
loading: boolean;
|
|
63
|
+
error: unknown;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
declare function useTasks(slug?: string, wsUrl?: string): {
|
|
67
|
+
tasks: Task[];
|
|
68
|
+
loading: boolean;
|
|
69
|
+
refetch: () => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
declare function useTask(slug?: string, shortId?: number): {
|
|
73
|
+
task: Task | null;
|
|
74
|
+
loading: boolean;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
declare function useComments(slug?: string, shortId?: number, wsUrl?: string): {
|
|
78
|
+
comments: Comment[];
|
|
79
|
+
loading: boolean;
|
|
80
|
+
refetch: () => void;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type Handlers = Partial<Record<WSMessageType, (data: any, msg: any) => void>>;
|
|
84
|
+
declare function useSayrWS(wsUrl?: string, handlers?: Handlers): react.RefObject<{
|
|
85
|
+
close(): void;
|
|
86
|
+
} | null>;
|
|
87
|
+
|
|
88
|
+
export { useComments, useOrg, useSayrWS, useTask, useTasks };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
type WSMessageType = "CONNECTION_STATUS" | "SUBSCRIBED" | "ERROR" | "PING" | "PONG" | "UPDATE_ORG" | "CREATE_TASK" | "UPDATE_TASK" | "UPDATE_TASK_COMMENTS" | "UPDATE_TASK_VOTE" | "UPDATE_LABELS" | "UPDATE_VIEWS" | "UPDATE_CATEGORIES" | "UPDATE_ISSUE_TEMPLATES" | "DISCONNECTED";
|
|
4
|
+
|
|
5
|
+
interface Organization {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
slug: string;
|
|
9
|
+
logo: string | null;
|
|
10
|
+
bannerImg: string | null;
|
|
11
|
+
description: string;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
wsUrl: string;
|
|
15
|
+
}
|
|
16
|
+
type TaskStatus = "backlog" | "todo" | "in-progress" | "done" | "canceled";
|
|
17
|
+
type TaskPriority = "none" | "low" | "medium" | "high" | "urgent";
|
|
18
|
+
interface Task {
|
|
19
|
+
id: string;
|
|
20
|
+
organizationId: string;
|
|
21
|
+
shortId: number | null;
|
|
22
|
+
visible: "public" | "private";
|
|
23
|
+
createdAt: string;
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
title: string | null;
|
|
26
|
+
description: unknown | null;
|
|
27
|
+
status: TaskStatus;
|
|
28
|
+
priority: TaskPriority;
|
|
29
|
+
createdBy: string | null;
|
|
30
|
+
category: string | null;
|
|
31
|
+
voteCount: number;
|
|
32
|
+
descriptionHtml: string;
|
|
33
|
+
descriptionMarkdown: string;
|
|
34
|
+
}
|
|
35
|
+
interface CommentUser {
|
|
36
|
+
name: string | null;
|
|
37
|
+
image: string | null;
|
|
38
|
+
}
|
|
39
|
+
interface CommentReaction {
|
|
40
|
+
count: number;
|
|
41
|
+
users: string[];
|
|
42
|
+
}
|
|
43
|
+
interface Comment {
|
|
44
|
+
id: string;
|
|
45
|
+
organizationId: string;
|
|
46
|
+
taskId: string | null;
|
|
47
|
+
createdAt: string;
|
|
48
|
+
updatedAt: string;
|
|
49
|
+
content: unknown | null;
|
|
50
|
+
visibility: "public" | "internal";
|
|
51
|
+
contentHtml: string;
|
|
52
|
+
contentMarkdown: string;
|
|
53
|
+
createdBy: CommentUser | null;
|
|
54
|
+
reactions?: {
|
|
55
|
+
total: number;
|
|
56
|
+
reactions: Record<string, CommentReaction>;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare function useOrg(slug?: string): {
|
|
61
|
+
data: Organization | null;
|
|
62
|
+
loading: boolean;
|
|
63
|
+
error: unknown;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
declare function useTasks(slug?: string, wsUrl?: string): {
|
|
67
|
+
tasks: Task[];
|
|
68
|
+
loading: boolean;
|
|
69
|
+
refetch: () => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
declare function useTask(slug?: string, shortId?: number): {
|
|
73
|
+
task: Task | null;
|
|
74
|
+
loading: boolean;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
declare function useComments(slug?: string, shortId?: number, wsUrl?: string): {
|
|
78
|
+
comments: Comment[];
|
|
79
|
+
loading: boolean;
|
|
80
|
+
refetch: () => void;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type Handlers = Partial<Record<WSMessageType, (data: any, msg: any) => void>>;
|
|
84
|
+
declare function useSayrWS(wsUrl?: string, handlers?: Handlers): react.RefObject<{
|
|
85
|
+
close(): void;
|
|
86
|
+
} | null>;
|
|
87
|
+
|
|
88
|
+
export { useComments, useOrg, useSayrWS, useTask, useTasks };
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// src/react/useOrg.ts
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
|
|
4
|
+
// src/org.ts
|
|
5
|
+
var API = "https://sayr.io/api/public";
|
|
6
|
+
async function get(url) {
|
|
7
|
+
const res = await fetch(url);
|
|
8
|
+
const json = await res.json();
|
|
9
|
+
if (!json.success) throw json;
|
|
10
|
+
return json;
|
|
11
|
+
}
|
|
12
|
+
var org = {
|
|
13
|
+
async get(slug) {
|
|
14
|
+
const r = await get(
|
|
15
|
+
`${API}/organization/${slug}`
|
|
16
|
+
);
|
|
17
|
+
return r.data;
|
|
18
|
+
},
|
|
19
|
+
async labels(slug) {
|
|
20
|
+
const r = await get(
|
|
21
|
+
`${API}/organization/${slug}/labels`
|
|
22
|
+
);
|
|
23
|
+
return r.data;
|
|
24
|
+
},
|
|
25
|
+
async categories(slug, order = "desc") {
|
|
26
|
+
const r = await get(
|
|
27
|
+
`${API}/organization/${slug}/categories?order=${order}`
|
|
28
|
+
);
|
|
29
|
+
return r.data;
|
|
30
|
+
},
|
|
31
|
+
async tasks(slug, opts) {
|
|
32
|
+
const q = new URLSearchParams({
|
|
33
|
+
order: opts?.order ?? "desc",
|
|
34
|
+
limit: String(opts?.limit ?? 5),
|
|
35
|
+
page: String(opts?.page ?? 1)
|
|
36
|
+
});
|
|
37
|
+
const res = await fetch(
|
|
38
|
+
`${API}/organization/${slug}/tasks?${q}`
|
|
39
|
+
);
|
|
40
|
+
const json = await res.json();
|
|
41
|
+
if (!json.success) throw json;
|
|
42
|
+
return {
|
|
43
|
+
data: json.data,
|
|
44
|
+
pagination: json.pagination
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
async task(slug, shortId) {
|
|
48
|
+
const r = await get(
|
|
49
|
+
`${API}/organization/${slug}/tasks/${shortId}`
|
|
50
|
+
);
|
|
51
|
+
return r.data;
|
|
52
|
+
},
|
|
53
|
+
async comments(slug, shortId, opts) {
|
|
54
|
+
const q = new URLSearchParams({
|
|
55
|
+
order: opts?.order ?? "desc",
|
|
56
|
+
limit: String(opts?.limit ?? 5),
|
|
57
|
+
page: String(opts?.page ?? 1)
|
|
58
|
+
});
|
|
59
|
+
const res = await fetch(
|
|
60
|
+
`${API}/organization/${slug}/tasks/${shortId}/comments?${q}`
|
|
61
|
+
);
|
|
62
|
+
const json = await res.json();
|
|
63
|
+
if (!json.success) throw json;
|
|
64
|
+
return {
|
|
65
|
+
data: json.data,
|
|
66
|
+
pagination: json.pagination
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/ws.ts
|
|
72
|
+
var wsTypes = {
|
|
73
|
+
CONNECTION_STATUS: "CONNECTION_STATUS",
|
|
74
|
+
SUBSCRIBED: "SUBSCRIBED",
|
|
75
|
+
ERROR: "ERROR",
|
|
76
|
+
PING: "PING",
|
|
77
|
+
PONG: "PONG",
|
|
78
|
+
UPDATE_ORG: "UPDATE_ORG",
|
|
79
|
+
CREATE_TASK: "CREATE_TASK",
|
|
80
|
+
UPDATE_TASK: "UPDATE_TASK",
|
|
81
|
+
UPDATE_TASK_COMMENTS: "UPDATE_TASK_COMMENTS",
|
|
82
|
+
UPDATE_TASK_VOTE: "UPDATE_TASK_VOTE",
|
|
83
|
+
UPDATE_LABELS: "UPDATE_LABELS",
|
|
84
|
+
UPDATE_VIEWS: "UPDATE_VIEWS",
|
|
85
|
+
UPDATE_CATEGORIES: "UPDATE_CATEGORIES",
|
|
86
|
+
UPDATE_ISSUE_TEMPLATES: "UPDATE_ISSUE_TEMPLATES",
|
|
87
|
+
DISCONNECTED: "DISCONNECTED"
|
|
88
|
+
};
|
|
89
|
+
function ws(url, handlers = {}) {
|
|
90
|
+
let socket;
|
|
91
|
+
let retry = 0;
|
|
92
|
+
let closed = false;
|
|
93
|
+
function connect() {
|
|
94
|
+
if (closed) return;
|
|
95
|
+
socket = new WebSocket(url);
|
|
96
|
+
socket.onmessage = (e) => {
|
|
97
|
+
const msg = JSON.parse(e.data);
|
|
98
|
+
if (msg.type === wsTypes.PING) {
|
|
99
|
+
socket.send(JSON.stringify({ type: wsTypes.PONG }));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
handlers[msg.type]?.(msg.data, msg);
|
|
103
|
+
};
|
|
104
|
+
socket.onclose = () => {
|
|
105
|
+
if (closed) return;
|
|
106
|
+
setTimeout(connect, Math.min(1e3 * 2 ** retry++, 3e4));
|
|
107
|
+
};
|
|
108
|
+
socket.onerror = () => socket.close();
|
|
109
|
+
}
|
|
110
|
+
connect();
|
|
111
|
+
return {
|
|
112
|
+
close() {
|
|
113
|
+
closed = true;
|
|
114
|
+
socket?.close();
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/react/useOrg.ts
|
|
120
|
+
function useOrg(slug) {
|
|
121
|
+
const [data, setData] = useState(null);
|
|
122
|
+
const [loading, setLoading] = useState(false);
|
|
123
|
+
const [error, setError] = useState(null);
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (!slug) return;
|
|
126
|
+
setLoading(true);
|
|
127
|
+
org.get(slug).then(setData).catch(setError).finally(() => setLoading(false));
|
|
128
|
+
}, [slug]);
|
|
129
|
+
return { data, loading, error };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/react/useTasks.ts
|
|
133
|
+
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
134
|
+
|
|
135
|
+
// src/react/useSayrWS.ts
|
|
136
|
+
import { useEffect as useEffect2, useRef } from "react";
|
|
137
|
+
function useSayrWS(wsUrl, handlers) {
|
|
138
|
+
const connRef = useRef(null);
|
|
139
|
+
useEffect2(() => {
|
|
140
|
+
if (!wsUrl) return;
|
|
141
|
+
connRef.current = ws(wsUrl, handlers);
|
|
142
|
+
return () => {
|
|
143
|
+
connRef.current?.close();
|
|
144
|
+
connRef.current = null;
|
|
145
|
+
};
|
|
146
|
+
}, [wsUrl]);
|
|
147
|
+
return connRef;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/react/useTasks.ts
|
|
151
|
+
function useTasks(slug, wsUrl) {
|
|
152
|
+
const [tasks, setTasks] = useState2([]);
|
|
153
|
+
const [loading, setLoading] = useState2(false);
|
|
154
|
+
function fetchTasks() {
|
|
155
|
+
if (!slug) return;
|
|
156
|
+
setLoading(true);
|
|
157
|
+
org.tasks(slug).then((r) => setTasks(r.data)).finally(() => setLoading(false));
|
|
158
|
+
}
|
|
159
|
+
useEffect3(fetchTasks, [slug]);
|
|
160
|
+
useSayrWS(wsUrl, {
|
|
161
|
+
[wsTypes.CREATE_TASK]: fetchTasks,
|
|
162
|
+
[wsTypes.UPDATE_TASK]: fetchTasks
|
|
163
|
+
});
|
|
164
|
+
return { tasks, loading, refetch: fetchTasks };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/react/useTask.ts
|
|
168
|
+
import { useEffect as useEffect4, useState as useState3 } from "react";
|
|
169
|
+
function useTask(slug, shortId) {
|
|
170
|
+
const [task, setTask] = useState3(null);
|
|
171
|
+
const [loading, setLoading] = useState3(false);
|
|
172
|
+
useEffect4(() => {
|
|
173
|
+
if (!slug || shortId == null) return;
|
|
174
|
+
setLoading(true);
|
|
175
|
+
org.task(slug, shortId).then(setTask).finally(() => setLoading(false));
|
|
176
|
+
}, [slug, shortId]);
|
|
177
|
+
return { task, loading };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/react/useComments.ts
|
|
181
|
+
import { useEffect as useEffect5, useState as useState4 } from "react";
|
|
182
|
+
function useComments(slug, shortId, wsUrl) {
|
|
183
|
+
const [comments, setComments] = useState4([]);
|
|
184
|
+
const [loading, setLoading] = useState4(false);
|
|
185
|
+
function fetchComments() {
|
|
186
|
+
if (!slug || shortId == null) return;
|
|
187
|
+
setLoading(true);
|
|
188
|
+
org.comments(slug, shortId).then((r) => setComments(r.data)).finally(() => setLoading(false));
|
|
189
|
+
}
|
|
190
|
+
useEffect5(fetchComments, [slug, shortId]);
|
|
191
|
+
useSayrWS(wsUrl, {
|
|
192
|
+
[wsTypes.UPDATE_TASK_COMMENTS]: fetchComments
|
|
193
|
+
});
|
|
194
|
+
return { comments, loading, refetch: fetchComments };
|
|
195
|
+
}
|
|
196
|
+
export {
|
|
197
|
+
useComments,
|
|
198
|
+
useOrg,
|
|
199
|
+
useSayrWS,
|
|
200
|
+
useTask,
|
|
201
|
+
useTasks
|
|
202
|
+
};
|
|
203
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/useOrg.ts","../../src/org.ts","../../src/ws.ts","../../src/react/useTasks.ts","../../src/react/useSayrWS.ts","../../src/react/useTask.ts","../../src/react/useComments.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\r\nimport { org, Organization } from \"../index\";\r\n\r\nexport function useOrg(slug?: string) {\r\n const [data, setData] = useState<Organization | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n const [error, setError] = useState<unknown>(null);\r\n\r\n useEffect(() => {\r\n if (!slug) return;\r\n\r\n setLoading(true);\r\n org\r\n .get(slug)\r\n .then(setData)\r\n .catch(setError)\r\n .finally(() => setLoading(false));\r\n }, [slug]);\r\n\r\n return { data, loading, error };\r\n}","import {\r\n Organization,\r\n Label,\r\n Category,\r\n Task,\r\n Comment,\r\n Pagination,\r\n ApiSuccess\r\n} from \"./types\";\r\n\r\nconst API = \"https://sayr.io/api/public\";\r\n\r\nasync function get<T>(url: string): Promise<T> {\r\n const res = await fetch(url);\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n return json;\r\n}\r\n\r\nexport const org = {\r\n async get(slug: string): Promise<Organization> {\r\n const r = await get<ApiSuccess<Organization>>(\r\n `${API}/organization/${slug}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async labels(slug: string): Promise<Label[]> {\r\n const r = await get<ApiSuccess<Label[]>>(\r\n `${API}/organization/${slug}/labels`\r\n );\r\n return r.data;\r\n },\r\n\r\n async categories(\r\n slug: string,\r\n order: \"asc\" | \"desc\" = \"desc\"\r\n ): Promise<Category[]> {\r\n const r = await get<ApiSuccess<Category[]>>(\r\n `${API}/organization/${slug}/categories?order=${order}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async tasks(\r\n slug: string,\r\n opts?: { order?: \"asc\" | \"desc\"; limit?: number; page?: number }\r\n ): Promise<{ data: Task[]; pagination: Pagination }> {\r\n const q = new URLSearchParams({\r\n order: opts?.order ?? \"desc\",\r\n limit: String(opts?.limit ?? 5),\r\n page: String(opts?.page ?? 1)\r\n });\r\n\r\n const res = await fetch(\r\n `${API}/organization/${slug}/tasks?${q}`\r\n );\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n\r\n return {\r\n data: json.data,\r\n pagination: json.pagination\r\n };\r\n },\r\n\r\n async task(slug: string, shortId: number): Promise<Task> {\r\n const r = await get<ApiSuccess<Task>>(\r\n `${API}/organization/${slug}/tasks/${shortId}`\r\n );\r\n return r.data;\r\n },\r\n\r\n async comments(\r\n slug: string,\r\n shortId: number,\r\n opts?: { order?: \"asc\" | \"desc\"; limit?: number; page?: number }\r\n ): Promise<{ data: Comment[]; pagination: Pagination }> {\r\n const q = new URLSearchParams({\r\n order: opts?.order ?? \"desc\",\r\n limit: String(opts?.limit ?? 5),\r\n page: String(opts?.page ?? 1)\r\n });\r\n\r\n const res = await fetch(\r\n `${API}/organization/${slug}/tasks/${shortId}/comments?${q}`\r\n );\r\n const json = await res.json();\r\n if (!json.success) throw json;\r\n\r\n return {\r\n data: json.data,\r\n pagination: json.pagination\r\n };\r\n }\r\n};","export type WSMessageType =\r\n | \"CONNECTION_STATUS\"\r\n | \"SUBSCRIBED\"\r\n | \"ERROR\"\r\n | \"PING\"\r\n | \"PONG\"\r\n | \"UPDATE_ORG\"\r\n | \"CREATE_TASK\"\r\n | \"UPDATE_TASK\"\r\n | \"UPDATE_TASK_COMMENTS\"\r\n | \"UPDATE_TASK_VOTE\"\r\n | \"UPDATE_LABELS\"\r\n | \"UPDATE_VIEWS\"\r\n | \"UPDATE_CATEGORIES\"\r\n | \"UPDATE_ISSUE_TEMPLATES\"\r\n | \"DISCONNECTED\";\r\n\r\nexport const wsTypes: Record<WSMessageType, WSMessageType> = {\r\n CONNECTION_STATUS: \"CONNECTION_STATUS\",\r\n SUBSCRIBED: \"SUBSCRIBED\",\r\n ERROR: \"ERROR\",\r\n PING: \"PING\",\r\n PONG: \"PONG\",\r\n UPDATE_ORG: \"UPDATE_ORG\",\r\n CREATE_TASK: \"CREATE_TASK\",\r\n UPDATE_TASK: \"UPDATE_TASK\",\r\n UPDATE_TASK_COMMENTS: \"UPDATE_TASK_COMMENTS\",\r\n UPDATE_TASK_VOTE: \"UPDATE_TASK_VOTE\",\r\n UPDATE_LABELS: \"UPDATE_LABELS\",\r\n UPDATE_VIEWS: \"UPDATE_VIEWS\",\r\n UPDATE_CATEGORIES: \"UPDATE_CATEGORIES\",\r\n UPDATE_ISSUE_TEMPLATES: \"UPDATE_ISSUE_TEMPLATES\",\r\n DISCONNECTED: \"DISCONNECTED\"\r\n};\r\n\r\nexport interface WSMessage<T = unknown> {\r\n type: WSMessageType;\r\n scope: \"PUBLIC\";\r\n data: T;\r\n meta?: { ts: number };\r\n}\r\n\r\ntype Handlers = Partial<\r\n Record<WSMessageType, (data: any, msg: WSMessage) => void>\r\n>;\r\n\r\nexport function ws(url: string, handlers: Handlers = {}) {\r\n let socket: WebSocket;\r\n let retry = 0;\r\n let closed = false;\r\n\r\n function connect() {\r\n if (closed) return;\r\n\r\n socket = new WebSocket(url);\r\n\r\n socket.onmessage = (e) => {\r\n const msg = JSON.parse(e.data) as WSMessage;\r\n\r\n if (msg.type === wsTypes.PING) {\r\n socket.send(JSON.stringify({ type: wsTypes.PONG }));\r\n return;\r\n }\r\n\r\n handlers[msg.type]?.(msg.data, msg);\r\n };\r\n\r\n socket.onclose = () => {\r\n if (closed) return;\r\n setTimeout(connect, Math.min(1000 * 2 ** retry++, 30000));\r\n };\r\n\r\n socket.onerror = () => socket.close();\r\n }\r\n\r\n connect();\r\n\r\n return {\r\n close() {\r\n closed = true;\r\n socket?.close();\r\n }\r\n };\r\n}","import { useEffect, useState } from \"react\";\r\nimport { org, wsTypes } from \"..\";\r\nimport type { Task } from \"../types\";\r\nimport { useSayrWS } from \"./useSayrWS\";\r\nexport function useTasks(\r\n slug?: string,\r\n wsUrl?: string\r\n) {\r\n const [tasks, setTasks] = useState<Task[]>([]);\r\n const [loading, setLoading] = useState(false);\r\n\r\n function fetchTasks() {\r\n if (!slug) return;\r\n setLoading(true);\r\n org\r\n .tasks(slug)\r\n .then((r) => setTasks(r.data))\r\n .finally(() => setLoading(false));\r\n }\r\n\r\n useEffect(fetchTasks, [slug]);\r\n\r\n useSayrWS(wsUrl, {\r\n [wsTypes.CREATE_TASK]: fetchTasks,\r\n [wsTypes.UPDATE_TASK]: fetchTasks\r\n });\r\n\r\n return { tasks, loading, refetch: fetchTasks };\r\n}","import { useEffect, useRef } from \"react\";\r\nimport { ws } from \"..\";\r\nimport { WSMessageType } from \"../ws\";\r\n\r\ntype Handlers = Partial<\r\n Record<WSMessageType, (data: any, msg: any) => void>\r\n>;\r\n\r\nexport function useSayrWS(\r\n wsUrl?: string,\r\n handlers?: Handlers\r\n) {\r\n const connRef = useRef<ReturnType<typeof ws> | null>(null);\r\n\r\n useEffect(() => {\r\n if (!wsUrl) return;\r\n\r\n connRef.current = ws(wsUrl, handlers);\r\n\r\n return () => {\r\n connRef.current?.close();\r\n connRef.current = null;\r\n };\r\n }, [wsUrl]);\r\n\r\n return connRef;\r\n}","import { useEffect, useState } from \"react\";\r\nimport { org } from \"..\";\r\nimport type { Task } from \"../types\";\r\n\r\nexport function useTask(\r\n slug?: string,\r\n shortId?: number\r\n) {\r\n const [task, setTask] = useState<Task | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (!slug || shortId == null) return;\r\n\r\n setLoading(true);\r\n org\r\n .task(slug, shortId)\r\n .then(setTask)\r\n .finally(() => setLoading(false));\r\n }, [slug, shortId]);\r\n\r\n return { task, loading };\r\n}","import { useEffect, useState } from \"react\";\r\nimport { org, wsTypes } from \"..\";\r\nimport type { Comment } from \"../types\";\r\nimport { useSayrWS } from \"./useSayrWS\";\r\n\r\nexport function useComments(\r\n slug?: string,\r\n shortId?: number,\r\n wsUrl?: string\r\n) {\r\n const [comments, setComments] = useState<Comment[]>([]);\r\n const [loading, setLoading] = useState(false);\r\n\r\n function fetchComments() {\r\n if (!slug || shortId == null) return;\r\n\r\n setLoading(true);\r\n org\r\n .comments(slug, shortId)\r\n .then((r) => setComments(r.data))\r\n .finally(() => setLoading(false));\r\n }\r\n\r\n useEffect(fetchComments, [slug, shortId]);\r\n\r\n useSayrWS(wsUrl, {\r\n [wsTypes.UPDATE_TASK_COMMENTS]: fetchComments\r\n });\r\n\r\n return { comments, loading, refetch: fetchComments };\r\n}"],"mappings":";AAAA,SAAS,WAAW,gBAAgB;;;ACUpC,IAAM,MAAM;AAEZ,eAAe,IAAO,KAAyB;AAC3C,QAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,CAAC,KAAK,QAAS,OAAM;AACzB,SAAO;AACX;AAEO,IAAM,MAAM;AAAA,EACf,MAAM,IAAI,MAAqC;AAC3C,UAAM,IAAI,MAAM;AAAA,MACZ,GAAG,GAAG,iBAAiB,IAAI;AAAA,IAC/B;AACA,WAAO,EAAE;AAAA,EACb;AAAA,EAEA,MAAM,OAAO,MAAgC;AACzC,UAAM,IAAI,MAAM;AAAA,MACZ,GAAG,GAAG,iBAAiB,IAAI;AAAA,IAC/B;AACA,WAAO,EAAE;AAAA,EACb;AAAA,EAEA,MAAM,WACF,MACA,QAAwB,QACL;AACnB,UAAM,IAAI,MAAM;AAAA,MACZ,GAAG,GAAG,iBAAiB,IAAI,qBAAqB,KAAK;AAAA,IACzD;AACA,WAAO,EAAE;AAAA,EACb;AAAA,EAEA,MAAM,MACF,MACA,MACiD;AACjD,UAAM,IAAI,IAAI,gBAAgB;AAAA,MAC1B,OAAO,MAAM,SAAS;AAAA,MACtB,OAAO,OAAO,MAAM,SAAS,CAAC;AAAA,MAC9B,MAAM,OAAO,MAAM,QAAQ,CAAC;AAAA,IAChC,CAAC;AAED,UAAM,MAAM,MAAM;AAAA,MACd,GAAG,GAAG,iBAAiB,IAAI,UAAU,CAAC;AAAA,IAC1C;AACA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,KAAK,QAAS,OAAM;AAEzB,WAAO;AAAA,MACH,MAAM,KAAK;AAAA,MACX,YAAY,KAAK;AAAA,IACrB;AAAA,EACJ;AAAA,EAEA,MAAM,KAAK,MAAc,SAAgC;AACrD,UAAM,IAAI,MAAM;AAAA,MACZ,GAAG,GAAG,iBAAiB,IAAI,UAAU,OAAO;AAAA,IAChD;AACA,WAAO,EAAE;AAAA,EACb;AAAA,EAEA,MAAM,SACF,MACA,SACA,MACoD;AACpD,UAAM,IAAI,IAAI,gBAAgB;AAAA,MAC1B,OAAO,MAAM,SAAS;AAAA,MACtB,OAAO,OAAO,MAAM,SAAS,CAAC;AAAA,MAC9B,MAAM,OAAO,MAAM,QAAQ,CAAC;AAAA,IAChC,CAAC;AAED,UAAM,MAAM,MAAM;AAAA,MACd,GAAG,GAAG,iBAAiB,IAAI,UAAU,OAAO,aAAa,CAAC;AAAA,IAC9D;AACA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,KAAK,QAAS,OAAM;AAEzB,WAAO;AAAA,MACH,MAAM,KAAK;AAAA,MACX,YAAY,KAAK;AAAA,IACrB;AAAA,EACJ;AACJ;;;AC9EO,IAAM,UAAgD;AAAA,EACzD,mBAAmB;AAAA,EACnB,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,cAAc;AAClB;AAaO,SAAS,GAAG,KAAa,WAAqB,CAAC,GAAG;AACrD,MAAI;AACJ,MAAI,QAAQ;AACZ,MAAI,SAAS;AAEb,WAAS,UAAU;AACf,QAAI,OAAQ;AAEZ,aAAS,IAAI,UAAU,GAAG;AAE1B,WAAO,YAAY,CAAC,MAAM;AACtB,YAAM,MAAM,KAAK,MAAM,EAAE,IAAI;AAE7B,UAAI,IAAI,SAAS,QAAQ,MAAM;AAC3B,eAAO,KAAK,KAAK,UAAU,EAAE,MAAM,QAAQ,KAAK,CAAC,CAAC;AAClD;AAAA,MACJ;AAEA,eAAS,IAAI,IAAI,IAAI,IAAI,MAAM,GAAG;AAAA,IACtC;AAEA,WAAO,UAAU,MAAM;AACnB,UAAI,OAAQ;AACZ,iBAAW,SAAS,KAAK,IAAI,MAAO,KAAK,SAAS,GAAK,CAAC;AAAA,IAC5D;AAEA,WAAO,UAAU,MAAM,OAAO,MAAM;AAAA,EACxC;AAEA,UAAQ;AAER,SAAO;AAAA,IACH,QAAQ;AACJ,eAAS;AACT,cAAQ,MAAM;AAAA,IAClB;AAAA,EACJ;AACJ;;;AFhFO,SAAS,OAAO,MAAe;AAClC,QAAM,CAAC,MAAM,OAAO,IAAI,SAA8B,IAAI;AAC1D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAkB,IAAI;AAEhD,YAAU,MAAM;AACZ,QAAI,CAAC,KAAM;AAEX,eAAW,IAAI;AACf,QACK,IAAI,IAAI,EACR,KAAK,OAAO,EACZ,MAAM,QAAQ,EACd,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,EACxC,GAAG,CAAC,IAAI,CAAC;AAET,SAAO,EAAE,MAAM,SAAS,MAAM;AAClC;;;AGpBA,SAAS,aAAAA,YAAW,YAAAC,iBAAgB;;;ACApC,SAAS,aAAAC,YAAW,cAAc;AAQ3B,SAAS,UACZ,OACA,UACF;AACE,QAAM,UAAU,OAAqC,IAAI;AAEzD,EAAAC,WAAU,MAAM;AACZ,QAAI,CAAC,MAAO;AAEZ,YAAQ,UAAU,GAAG,OAAO,QAAQ;AAEpC,WAAO,MAAM;AACT,cAAQ,SAAS,MAAM;AACvB,cAAQ,UAAU;AAAA,IACtB;AAAA,EACJ,GAAG,CAAC,KAAK,CAAC;AAEV,SAAO;AACX;;;ADtBO,SAAS,SACZ,MACA,OACF;AACE,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAiB,CAAC,CAAC;AAC7C,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAE5C,WAAS,aAAa;AAClB,QAAI,CAAC,KAAM;AACX,eAAW,IAAI;AACf,QACK,MAAM,IAAI,EACV,KAAK,CAAC,MAAM,SAAS,EAAE,IAAI,CAAC,EAC5B,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,EACxC;AAEA,EAAAC,WAAU,YAAY,CAAC,IAAI,CAAC;AAE5B,YAAU,OAAO;AAAA,IACb,CAAC,QAAQ,WAAW,GAAG;AAAA,IACvB,CAAC,QAAQ,WAAW,GAAG;AAAA,EAC3B,CAAC;AAED,SAAO,EAAE,OAAO,SAAS,SAAS,WAAW;AACjD;;;AE5BA,SAAS,aAAAC,YAAW,YAAAC,iBAAgB;AAI7B,SAAS,QACZ,MACA,SACF;AACE,QAAM,CAAC,MAAM,OAAO,IAAIC,UAAsB,IAAI;AAClD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAE5C,EAAAC,WAAU,MAAM;AACZ,QAAI,CAAC,QAAQ,WAAW,KAAM;AAE9B,eAAW,IAAI;AACf,QACK,KAAK,MAAM,OAAO,EAClB,KAAK,OAAO,EACZ,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,EACxC,GAAG,CAAC,MAAM,OAAO,CAAC;AAElB,SAAO,EAAE,MAAM,QAAQ;AAC3B;;;ACtBA,SAAS,aAAAC,YAAW,YAAAC,iBAAgB;AAK7B,SAAS,YACZ,MACA,SACA,OACF;AACE,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAoB,CAAC,CAAC;AACtD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAE5C,WAAS,gBAAgB;AACrB,QAAI,CAAC,QAAQ,WAAW,KAAM;AAE9B,eAAW,IAAI;AACf,QACK,SAAS,MAAM,OAAO,EACtB,KAAK,CAAC,MAAM,YAAY,EAAE,IAAI,CAAC,EAC/B,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,EACxC;AAEA,EAAAC,WAAU,eAAe,CAAC,MAAM,OAAO,CAAC;AAExC,YAAU,OAAO;AAAA,IACb,CAAC,QAAQ,oBAAoB,GAAG;AAAA,EACpC,CAAC;AAED,SAAO,EAAE,UAAU,SAAS,SAAS,cAAc;AACvD;","names":["useEffect","useState","useEffect","useEffect","useState","useEffect","useEffect","useState","useState","useEffect","useEffect","useState","useState","useEffect"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sayrio/public",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Sayr.io public REST + WebSocket SDK",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.cjs",
|
|
8
|
+
"module": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./react": {
|
|
17
|
+
"import": "./dist/react/index.js",
|
|
18
|
+
"require": "./dist/react/index.cjs",
|
|
19
|
+
"types": "./dist/react/index.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"react": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/react": "^19.2.8",
|
|
34
|
+
"tsup": "^8.0.0",
|
|
35
|
+
"typescript": "^5.3.3"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"dev": "tsup --watch"
|
|
40
|
+
}
|
|
41
|
+
}
|