kyro-connect 0.1.8 → 0.1.10

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 CHANGED
@@ -49,14 +49,25 @@ async function handleResponse(res) {
49
49
  } catch {
50
50
  throw new KyroConnectError(res.statusText, res.status);
51
51
  }
52
- throw new KyroConnectError(
53
- body2?.error?.message ?? res.statusText,
54
- res.status,
55
- body2
56
- );
52
+ const message = typeof body2?.error === "string" ? body2.error : res.statusText;
53
+ throw new KyroConnectError(message, res.status, body2);
57
54
  }
58
55
  const body = await res.json();
59
- return body?.result?.data ?? body;
56
+ if (body && typeof body === "object" && "result" in body) {
57
+ return body.result.data;
58
+ }
59
+ return body;
60
+ }
61
+ function buildSearchParams(params) {
62
+ if (!params) return "";
63
+ const sp = new URLSearchParams();
64
+ for (const [key, value] of Object.entries(params)) {
65
+ if (value !== void 0 && value !== null) {
66
+ sp.set(key, typeof value === "object" ? JSON.stringify(value) : String(value));
67
+ }
68
+ }
69
+ const qs = sp.toString();
70
+ return qs ? `?${qs}` : "";
60
71
  }
61
72
  function createClient(opts) {
62
73
  const baseUrl = opts.url.replace(/\/$/, "");
@@ -76,18 +87,19 @@ function createClient(opts) {
76
87
  method: "POST",
77
88
  headers: { "Content-Type": "application/json", ...headers() },
78
89
  body: JSON.stringify(input)
79
- }).then(handleResponse);
90
+ }).then((res) => handleResponse(res));
80
91
  }
81
92
  const qs = encodeURIComponent(JSON.stringify(input));
82
93
  return doFetch(`${baseUrl}/${pathStr}?input=${qs}`, {
83
94
  method: "GET",
84
95
  headers: headers()
85
- }).then(handleResponse);
96
+ }).then((res) => handleResponse(res));
86
97
  }
87
98
  function buildProxy(path) {
88
99
  return new Proxy(function() {
89
100
  }, {
90
- get(_, prop) {
101
+ get(target, prop) {
102
+ if (prop in target) return target[prop];
91
103
  return buildProxy([...path, prop]);
92
104
  },
93
105
  apply(_, __, args) {
@@ -95,7 +107,77 @@ function createClient(opts) {
95
107
  }
96
108
  });
97
109
  }
98
- return buildProxy([]);
110
+ const collection = (slug) => ({
111
+ async find(params) {
112
+ const res = await doFetch(`${baseUrl}/api/${slug}${buildSearchParams(params)}`, {
113
+ method: "GET",
114
+ headers: headers()
115
+ });
116
+ return handleResponse(res);
117
+ },
118
+ async findByID(id, params) {
119
+ const res = await doFetch(`${baseUrl}/api/${slug}/${id}${buildSearchParams(params)}`, {
120
+ method: "GET",
121
+ headers: headers()
122
+ });
123
+ const body = await handleResponse(res);
124
+ return body?.data ?? body;
125
+ },
126
+ async create(data, params) {
127
+ const res = await doFetch(`${baseUrl}/api/${slug}${buildSearchParams(params)}`, {
128
+ method: "POST",
129
+ headers: { "Content-Type": "application/json", ...headers() },
130
+ body: JSON.stringify(data)
131
+ });
132
+ const body = await handleResponse(res);
133
+ return body?.data ?? body;
134
+ },
135
+ async update(id, data, params) {
136
+ const res = await doFetch(`${baseUrl}/api/${slug}/${id}${buildSearchParams(params)}`, {
137
+ method: "PATCH",
138
+ headers: { "Content-Type": "application/json", ...headers() },
139
+ body: JSON.stringify(data)
140
+ });
141
+ const body = await handleResponse(res);
142
+ return body?.data ?? body;
143
+ },
144
+ async delete(id) {
145
+ const res = await doFetch(`${baseUrl}/api/${slug}/${id}`, {
146
+ method: "DELETE",
147
+ headers: headers()
148
+ });
149
+ return handleResponse(res);
150
+ }
151
+ });
152
+ const gql = async (query, variables) => {
153
+ const queryStr = typeof query === "string" ? query : query.toString();
154
+ const res = await doFetch(`${baseUrl}/api/graphql`, {
155
+ method: "POST",
156
+ headers: { "Content-Type": "application/json", ...headers() },
157
+ body: JSON.stringify({ query: queryStr, variables })
158
+ });
159
+ const body = await res.json();
160
+ if (body.errors) {
161
+ throw new KyroConnectError(body.errors[0]?.message || "GraphQL error", res.status, body);
162
+ }
163
+ return body.data;
164
+ };
165
+ const upload = async (url, file, filename) => {
166
+ const formData = new FormData();
167
+ formData.append("file", file, filename);
168
+ const res = await doFetch(`${baseUrl}${url}`, {
169
+ method: "POST",
170
+ headers: headers(),
171
+ body: formData
172
+ });
173
+ return handleResponse(res);
174
+ };
175
+ const proxy = buildProxy([]);
176
+ return Object.assign(proxy, {
177
+ collection,
178
+ gql,
179
+ upload
180
+ });
99
181
  }
100
182
  // Annotate the CommonJS export names for ESM import in node:
101
183
  0 && (module.exports = {
package/dist/index.d.cts CHANGED
@@ -12,9 +12,58 @@ type RouterClient<T> = {
12
12
  [K in keyof T]: T[K] extends {
13
13
  input: infer I;
14
14
  output: infer O;
15
- } ? ProcedureClient<I, O> : T[K] extends Record<string, any> ? RouterClient<T[K]> : T[K];
15
+ } ? ProcedureClient<I, O> : T[K] extends Record<string, unknown> ? RouterClient<T[K]> : T[K];
16
16
  };
17
- declare function createClient<TRouter extends Record<string, any> = any>(opts: ClientOptions): RouterClient<TRouter>;
17
+ interface CollectionFindResult<T> {
18
+ docs: T[];
19
+ totalDocs: number;
20
+ page: number;
21
+ totalPages: number;
22
+ hasNextPage?: boolean;
23
+ hasPrevPage?: boolean;
24
+ }
25
+ interface CollectionFindParams {
26
+ draft?: boolean;
27
+ depth?: number;
28
+ sort?: string;
29
+ page?: number;
30
+ limit?: number;
31
+ select?: string;
32
+ where?: Record<string, unknown>;
33
+ }
34
+ interface CollectionClient<T, F = CollectionFindParams> {
35
+ find(params?: F & CollectionFindParams): Promise<CollectionFindResult<T>>;
36
+ findByID(id: string, params?: {
37
+ draft?: boolean;
38
+ depth?: number;
39
+ select?: string;
40
+ }): Promise<T | null>;
41
+ create(data: Partial<T>, params?: {
42
+ draft?: boolean;
43
+ depth?: number;
44
+ }): Promise<T>;
45
+ update(id: string, data: Partial<T>, params?: {
46
+ draft?: boolean;
47
+ depth?: number;
48
+ }): Promise<T>;
49
+ delete(id: string): Promise<{
50
+ message: string;
51
+ }>;
52
+ }
53
+ interface GqlClient {
54
+ <TData = Record<string, unknown>, TVars extends Record<string, unknown> = Record<string, unknown>>(query: string | {
55
+ toString(): string;
56
+ }, variables?: TVars): Promise<TData>;
57
+ }
58
+ interface UploadClient {
59
+ <TResult = unknown>(url: string, file: File | Blob, filename?: string): Promise<TResult>;
60
+ }
61
+ type KyroClient<TRouter> = RouterClient<TRouter> & {
62
+ collection: <T, F = CollectionFindParams>(slug: string) => CollectionClient<T, F>;
63
+ gql: GqlClient;
64
+ upload: UploadClient;
65
+ };
66
+ declare function createClient<TRouter extends Record<string, unknown> = Record<string, unknown>>(opts: ClientOptions): KyroClient<TRouter>;
18
67
 
19
68
  declare class KyroConnectError extends Error {
20
69
  readonly status: number;
@@ -23,4 +72,4 @@ declare class KyroConnectError extends Error {
23
72
  constructor(message: string, status?: number, raw?: any);
24
73
  }
25
74
 
26
- export { type ClientOptions, KyroConnectError, type ProcedureClient, type RouterClient, createClient };
75
+ export { type ClientOptions, type CollectionClient, type CollectionFindParams, type CollectionFindResult, type GqlClient, type KyroClient, KyroConnectError, type ProcedureClient, type RouterClient, type UploadClient, createClient };
package/dist/index.d.ts CHANGED
@@ -12,9 +12,58 @@ type RouterClient<T> = {
12
12
  [K in keyof T]: T[K] extends {
13
13
  input: infer I;
14
14
  output: infer O;
15
- } ? ProcedureClient<I, O> : T[K] extends Record<string, any> ? RouterClient<T[K]> : T[K];
15
+ } ? ProcedureClient<I, O> : T[K] extends Record<string, unknown> ? RouterClient<T[K]> : T[K];
16
16
  };
17
- declare function createClient<TRouter extends Record<string, any> = any>(opts: ClientOptions): RouterClient<TRouter>;
17
+ interface CollectionFindResult<T> {
18
+ docs: T[];
19
+ totalDocs: number;
20
+ page: number;
21
+ totalPages: number;
22
+ hasNextPage?: boolean;
23
+ hasPrevPage?: boolean;
24
+ }
25
+ interface CollectionFindParams {
26
+ draft?: boolean;
27
+ depth?: number;
28
+ sort?: string;
29
+ page?: number;
30
+ limit?: number;
31
+ select?: string;
32
+ where?: Record<string, unknown>;
33
+ }
34
+ interface CollectionClient<T, F = CollectionFindParams> {
35
+ find(params?: F & CollectionFindParams): Promise<CollectionFindResult<T>>;
36
+ findByID(id: string, params?: {
37
+ draft?: boolean;
38
+ depth?: number;
39
+ select?: string;
40
+ }): Promise<T | null>;
41
+ create(data: Partial<T>, params?: {
42
+ draft?: boolean;
43
+ depth?: number;
44
+ }): Promise<T>;
45
+ update(id: string, data: Partial<T>, params?: {
46
+ draft?: boolean;
47
+ depth?: number;
48
+ }): Promise<T>;
49
+ delete(id: string): Promise<{
50
+ message: string;
51
+ }>;
52
+ }
53
+ interface GqlClient {
54
+ <TData = Record<string, unknown>, TVars extends Record<string, unknown> = Record<string, unknown>>(query: string | {
55
+ toString(): string;
56
+ }, variables?: TVars): Promise<TData>;
57
+ }
58
+ interface UploadClient {
59
+ <TResult = unknown>(url: string, file: File | Blob, filename?: string): Promise<TResult>;
60
+ }
61
+ type KyroClient<TRouter> = RouterClient<TRouter> & {
62
+ collection: <T, F = CollectionFindParams>(slug: string) => CollectionClient<T, F>;
63
+ gql: GqlClient;
64
+ upload: UploadClient;
65
+ };
66
+ declare function createClient<TRouter extends Record<string, unknown> = Record<string, unknown>>(opts: ClientOptions): KyroClient<TRouter>;
18
67
 
19
68
  declare class KyroConnectError extends Error {
20
69
  readonly status: number;
@@ -23,4 +72,4 @@ declare class KyroConnectError extends Error {
23
72
  constructor(message: string, status?: number, raw?: any);
24
73
  }
25
74
 
26
- export { type ClientOptions, KyroConnectError, type ProcedureClient, type RouterClient, createClient };
75
+ export { type ClientOptions, type CollectionClient, type CollectionFindParams, type CollectionFindResult, type GqlClient, type KyroClient, KyroConnectError, type ProcedureClient, type RouterClient, type UploadClient, createClient };
package/dist/index.js CHANGED
@@ -22,14 +22,25 @@ async function handleResponse(res) {
22
22
  } catch {
23
23
  throw new KyroConnectError(res.statusText, res.status);
24
24
  }
25
- throw new KyroConnectError(
26
- body2?.error?.message ?? res.statusText,
27
- res.status,
28
- body2
29
- );
25
+ const message = typeof body2?.error === "string" ? body2.error : res.statusText;
26
+ throw new KyroConnectError(message, res.status, body2);
30
27
  }
31
28
  const body = await res.json();
32
- return body?.result?.data ?? body;
29
+ if (body && typeof body === "object" && "result" in body) {
30
+ return body.result.data;
31
+ }
32
+ return body;
33
+ }
34
+ function buildSearchParams(params) {
35
+ if (!params) return "";
36
+ const sp = new URLSearchParams();
37
+ for (const [key, value] of Object.entries(params)) {
38
+ if (value !== void 0 && value !== null) {
39
+ sp.set(key, typeof value === "object" ? JSON.stringify(value) : String(value));
40
+ }
41
+ }
42
+ const qs = sp.toString();
43
+ return qs ? `?${qs}` : "";
33
44
  }
34
45
  function createClient(opts) {
35
46
  const baseUrl = opts.url.replace(/\/$/, "");
@@ -49,18 +60,19 @@ function createClient(opts) {
49
60
  method: "POST",
50
61
  headers: { "Content-Type": "application/json", ...headers() },
51
62
  body: JSON.stringify(input)
52
- }).then(handleResponse);
63
+ }).then((res) => handleResponse(res));
53
64
  }
54
65
  const qs = encodeURIComponent(JSON.stringify(input));
55
66
  return doFetch(`${baseUrl}/${pathStr}?input=${qs}`, {
56
67
  method: "GET",
57
68
  headers: headers()
58
- }).then(handleResponse);
69
+ }).then((res) => handleResponse(res));
59
70
  }
60
71
  function buildProxy(path) {
61
72
  return new Proxy(function() {
62
73
  }, {
63
- get(_, prop) {
74
+ get(target, prop) {
75
+ if (prop in target) return target[prop];
64
76
  return buildProxy([...path, prop]);
65
77
  },
66
78
  apply(_, __, args) {
@@ -68,7 +80,77 @@ function createClient(opts) {
68
80
  }
69
81
  });
70
82
  }
71
- return buildProxy([]);
83
+ const collection = (slug) => ({
84
+ async find(params) {
85
+ const res = await doFetch(`${baseUrl}/api/${slug}${buildSearchParams(params)}`, {
86
+ method: "GET",
87
+ headers: headers()
88
+ });
89
+ return handleResponse(res);
90
+ },
91
+ async findByID(id, params) {
92
+ const res = await doFetch(`${baseUrl}/api/${slug}/${id}${buildSearchParams(params)}`, {
93
+ method: "GET",
94
+ headers: headers()
95
+ });
96
+ const body = await handleResponse(res);
97
+ return body?.data ?? body;
98
+ },
99
+ async create(data, params) {
100
+ const res = await doFetch(`${baseUrl}/api/${slug}${buildSearchParams(params)}`, {
101
+ method: "POST",
102
+ headers: { "Content-Type": "application/json", ...headers() },
103
+ body: JSON.stringify(data)
104
+ });
105
+ const body = await handleResponse(res);
106
+ return body?.data ?? body;
107
+ },
108
+ async update(id, data, params) {
109
+ const res = await doFetch(`${baseUrl}/api/${slug}/${id}${buildSearchParams(params)}`, {
110
+ method: "PATCH",
111
+ headers: { "Content-Type": "application/json", ...headers() },
112
+ body: JSON.stringify(data)
113
+ });
114
+ const body = await handleResponse(res);
115
+ return body?.data ?? body;
116
+ },
117
+ async delete(id) {
118
+ const res = await doFetch(`${baseUrl}/api/${slug}/${id}`, {
119
+ method: "DELETE",
120
+ headers: headers()
121
+ });
122
+ return handleResponse(res);
123
+ }
124
+ });
125
+ const gql = async (query, variables) => {
126
+ const queryStr = typeof query === "string" ? query : query.toString();
127
+ const res = await doFetch(`${baseUrl}/api/graphql`, {
128
+ method: "POST",
129
+ headers: { "Content-Type": "application/json", ...headers() },
130
+ body: JSON.stringify({ query: queryStr, variables })
131
+ });
132
+ const body = await res.json();
133
+ if (body.errors) {
134
+ throw new KyroConnectError(body.errors[0]?.message || "GraphQL error", res.status, body);
135
+ }
136
+ return body.data;
137
+ };
138
+ const upload = async (url, file, filename) => {
139
+ const formData = new FormData();
140
+ formData.append("file", file, filename);
141
+ const res = await doFetch(`${baseUrl}${url}`, {
142
+ method: "POST",
143
+ headers: headers(),
144
+ body: formData
145
+ });
146
+ return handleResponse(res);
147
+ };
148
+ const proxy = buildProxy([]);
149
+ return Object.assign(proxy, {
150
+ collection,
151
+ gql,
152
+ upload
153
+ });
72
154
  }
73
155
  export {
74
156
  KyroConnectError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kyro-connect",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Universal SDK for Kyro CMS. Type-safe client + codegen for any platform.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",