@doany-ai/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +60 -0
  3. package/dist/client.d.ts +96 -0
  4. package/dist/client.js +395 -0
  5. package/dist/client.types.d.ts +149 -0
  6. package/dist/client.types.js +1 -0
  7. package/dist/index.d.ts +17 -0
  8. package/dist/index.js +5 -0
  9. package/dist/modules/agents.d.ts +2 -0
  10. package/dist/modules/agents.js +89 -0
  11. package/dist/modules/agents.types.d.ts +397 -0
  12. package/dist/modules/agents.types.js +1 -0
  13. package/dist/modules/ai-gateway.d.ts +2 -0
  14. package/dist/modules/ai-gateway.js +13 -0
  15. package/dist/modules/ai-gateway.types.d.ts +88 -0
  16. package/dist/modules/ai-gateway.types.js +1 -0
  17. package/dist/modules/analytics.d.ts +20 -0
  18. package/dist/modules/analytics.js +284 -0
  19. package/dist/modules/analytics.types.d.ts +122 -0
  20. package/dist/modules/analytics.types.js +1 -0
  21. package/dist/modules/app-logs.d.ts +11 -0
  22. package/dist/modules/app-logs.js +27 -0
  23. package/dist/modules/app-logs.types.d.ts +46 -0
  24. package/dist/modules/app-logs.types.js +1 -0
  25. package/dist/modules/app.types.d.ts +142 -0
  26. package/dist/modules/app.types.js +1 -0
  27. package/dist/modules/auth.d.ts +13 -0
  28. package/dist/modules/auth.js +240 -0
  29. package/dist/modules/auth.types.d.ts +517 -0
  30. package/dist/modules/auth.types.js +1 -0
  31. package/dist/modules/connectors.d.ts +20 -0
  32. package/dist/modules/connectors.js +98 -0
  33. package/dist/modules/connectors.types.d.ts +376 -0
  34. package/dist/modules/connectors.types.js +1 -0
  35. package/dist/modules/custom-integrations.d.ts +11 -0
  36. package/dist/modules/custom-integrations.js +32 -0
  37. package/dist/modules/custom-integrations.types.d.ts +89 -0
  38. package/dist/modules/custom-integrations.types.js +1 -0
  39. package/dist/modules/entities.d.ts +20 -0
  40. package/dist/modules/entities.js +163 -0
  41. package/dist/modules/entities.types.d.ts +702 -0
  42. package/dist/modules/entities.types.js +1 -0
  43. package/dist/modules/functions.d.ts +12 -0
  44. package/dist/modules/functions.js +79 -0
  45. package/dist/modules/functions.types.d.ts +150 -0
  46. package/dist/modules/functions.types.js +1 -0
  47. package/dist/modules/integrations.d.ts +11 -0
  48. package/dist/modules/integrations.js +77 -0
  49. package/dist/modules/integrations.types.d.ts +418 -0
  50. package/dist/modules/integrations.types.js +1 -0
  51. package/dist/modules/sso.d.ts +11 -0
  52. package/dist/modules/sso.js +22 -0
  53. package/dist/modules/sso.types.d.ts +68 -0
  54. package/dist/modules/sso.types.js +1 -0
  55. package/dist/modules/types.d.ts +5 -0
  56. package/dist/modules/types.js +5 -0
  57. package/dist/modules/users.d.ts +16 -0
  58. package/dist/modules/users.js +23 -0
  59. package/dist/types.d.ts +72 -0
  60. package/dist/types.js +1 -0
  61. package/dist/utils/auth-utils.d.ts +117 -0
  62. package/dist/utils/auth-utils.js +189 -0
  63. package/dist/utils/auth-utils.types.d.ts +146 -0
  64. package/dist/utils/auth-utils.types.js +1 -0
  65. package/dist/utils/axios-client.d.ts +100 -0
  66. package/dist/utils/axios-client.js +202 -0
  67. package/dist/utils/axios-client.types.d.ts +28 -0
  68. package/dist/utils/axios-client.types.js +1 -0
  69. package/dist/utils/common.d.ts +4 -0
  70. package/dist/utils/common.js +11 -0
  71. package/dist/utils/sharedInstance.d.ts +1 -0
  72. package/dist/utils/sharedInstance.js +15 -0
  73. package/dist/utils/socket-utils.d.ts +47 -0
  74. package/dist/utils/socket-utils.js +170 -0
  75. package/package.json +54 -0
@@ -0,0 +1,202 @@
1
+ import axios from "axios";
2
+ import { isInIFrame } from "./common.js";
3
+ import { v4 as uuidv4 } from "uuid";
4
+ import { getAnalyticsSessionId } from "../modules/analytics.js";
5
+ /**
6
+ * Custom error class for Base44 SDK errors.
7
+ *
8
+ * This error is thrown when API requests fail. It extends the standard `Error` class and includes additional information about the HTTP status, error code, and response data from the server.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * try {
13
+ * await client.entities.Todo.get('invalid-id');
14
+ * } catch (error) {
15
+ * if (error instanceof Base44Error) {
16
+ * console.error('Status:', error.status); // 404
17
+ * console.error('Message:', error.message); // "Not found"
18
+ * console.error('Code:', error.code); // "NOT_FOUND"
19
+ * console.error('Data:', error.data); // Full response data
20
+ * }
21
+ * }
22
+ * ```
23
+ *
24
+ */
25
+ export class Base44Error extends Error {
26
+ /**
27
+ * Creates a new Base44Error instance.
28
+ *
29
+ * @param message - Human-readable error message
30
+ * @param status - HTTP status code
31
+ * @param code - Error code from the API
32
+ * @param data - Full response data from the server
33
+ * @param originalError - Original axios error object
34
+ * @internal
35
+ */
36
+ constructor(message, status, code, data, originalError) {
37
+ super(message);
38
+ this.name = "Base44Error";
39
+ this.status = status;
40
+ this.code = code;
41
+ this.data = data;
42
+ this.originalError = originalError;
43
+ }
44
+ /**
45
+ * Serializes the error to a JSON-safe object.
46
+ *
47
+ * Useful for logging or sending error information to external services
48
+ * without circular reference issues.
49
+ *
50
+ * @returns JSON-safe representation of the error.
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * try {
55
+ * await client.entities.Todo.get('invalid-id');
56
+ * } catch (error) {
57
+ * if (error instanceof Base44Error) {
58
+ * const json = error.toJSON();
59
+ * console.log(json);
60
+ * // {
61
+ * // name: "Base44Error",
62
+ * // message: "Not found",
63
+ * // status: 404,
64
+ * // code: "NOT_FOUND",
65
+ * // data: { ... }
66
+ * // }
67
+ * }
68
+ * }
69
+ * ```
70
+ */
71
+ toJSON() {
72
+ return {
73
+ name: this.name,
74
+ message: this.message,
75
+ status: this.status,
76
+ code: this.code,
77
+ data: this.data,
78
+ };
79
+ }
80
+ }
81
+ /**
82
+ * Safely logs error information without circular references.
83
+ *
84
+ * @param prefix - Prefix for the log message
85
+ * @param error - The error to log
86
+ * @internal
87
+ */
88
+ function safeErrorLog(prefix, error) {
89
+ if (error instanceof Base44Error) {
90
+ console.error(`${prefix} ${error.status}: ${error.message}`);
91
+ if (error.data) {
92
+ try {
93
+ console.error("Error data:", JSON.stringify(error.data, null, 2));
94
+ }
95
+ catch (e) {
96
+ console.error("Error data: [Cannot stringify error data]");
97
+ }
98
+ }
99
+ }
100
+ else {
101
+ console.error(`${prefix} ${error instanceof Error ? error.message : String(error)}`);
102
+ }
103
+ }
104
+ /**
105
+ * Creates an axios client with default configuration and interceptors.
106
+ *
107
+ * Sets up an axios instance with:
108
+ * - Default headers
109
+ * - Authentication token injection
110
+ * - Response data unwrapping
111
+ * - Error transformation to Base44Error
112
+ * - iframe messaging support
113
+ *
114
+ * @param options - Client configuration options
115
+ * @returns Configured axios instance
116
+ * @internal
117
+ */
118
+ export function createAxiosClient({ baseURL, headers = {}, token, interceptResponses = true, onError, }) {
119
+ const client = axios.create({
120
+ baseURL,
121
+ headers: {
122
+ "Content-Type": "application/json",
123
+ Accept: "application/json",
124
+ ...headers,
125
+ },
126
+ });
127
+ // Add token to requests if available
128
+ if (token) {
129
+ client.defaults.headers.common["Authorization"] = `Bearer ${token}`;
130
+ }
131
+ // Add origin URL in browser environment
132
+ client.interceptors.request.use((config) => {
133
+ // `window.location` is absent on React Native (where `window` still exists),
134
+ // so guard on it before reading `.href`.
135
+ if (typeof window !== "undefined" && window.location) {
136
+ config.headers.set("X-Origin-URL", window.location.href);
137
+ // On unauthenticated requests, attach a stable anonymous visitor id so the
138
+ // backend can support anonymous agent access (conversation grouping + ownership).
139
+ // Authenticated requests are identified by their Authorization header instead.
140
+ if (!config.headers.get("Authorization")) {
141
+ config.headers.set("X-Base44-Anonymous-Id", getAnalyticsSessionId());
142
+ }
143
+ }
144
+ const requestId = uuidv4();
145
+ config.requestId = requestId;
146
+ if (isInIFrame) {
147
+ try {
148
+ window.parent.postMessage({
149
+ type: "api-request-start",
150
+ requestId,
151
+ data: {
152
+ url: baseURL + config.url,
153
+ method: config.method,
154
+ body: config.data instanceof FormData
155
+ ? "[FormData object]"
156
+ : config.data,
157
+ },
158
+ }, "*");
159
+ }
160
+ catch (_a) {
161
+ /* skip the logging */
162
+ }
163
+ }
164
+ return config;
165
+ });
166
+ // Handle responses
167
+ if (interceptResponses) {
168
+ client.interceptors.response.use((response) => {
169
+ var _a;
170
+ const requestId = (_a = response.config) === null || _a === void 0 ? void 0 : _a.requestId;
171
+ try {
172
+ if (isInIFrame && requestId) {
173
+ window.parent.postMessage({
174
+ type: "api-request-end",
175
+ requestId,
176
+ data: {
177
+ statusCode: response.status,
178
+ response: response.data,
179
+ },
180
+ }, "*");
181
+ }
182
+ }
183
+ catch (_b) {
184
+ /* do nothing */
185
+ }
186
+ return response.data;
187
+ }, (error) => {
188
+ var _a, _b, _c, _d, _e, _f, _g, _h;
189
+ const message = ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) ||
190
+ ((_d = (_c = error.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.detail) ||
191
+ error.message;
192
+ const base44Error = new Base44Error(message, (_e = error.response) === null || _e === void 0 ? void 0 : _e.status, (_g = (_f = error.response) === null || _f === void 0 ? void 0 : _f.data) === null || _g === void 0 ? void 0 : _g.code, (_h = error.response) === null || _h === void 0 ? void 0 : _h.data, error);
193
+ // Log errors in development
194
+ if (process.env.NODE_ENV !== "production") {
195
+ safeErrorLog("[Base44 SDK Error]", base44Error);
196
+ }
197
+ onError === null || onError === void 0 ? void 0 : onError(base44Error);
198
+ return Promise.reject(base44Error);
199
+ });
200
+ }
201
+ return client;
202
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * JSON representation of a Base44Error.
3
+ *
4
+ * This is the structure returned by {@linkcode Base44Error.toJSON | Base44Error.toJSON()}.
5
+ * Useful for logging or sending error information to external services.
6
+ */
7
+ export interface Base44ErrorJSON {
8
+ /**
9
+ * The error name, always "Base44Error".
10
+ */
11
+ name: string;
12
+ /**
13
+ * Human-readable error message.
14
+ */
15
+ message: string;
16
+ /**
17
+ * HTTP status code of the error.
18
+ */
19
+ status: number;
20
+ /**
21
+ * Error code from the API.
22
+ */
23
+ code: string;
24
+ /**
25
+ * Full response data from the server containing error details.
26
+ */
27
+ data: any;
28
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export declare const isNode: boolean;
2
+ export declare const isInIFrame: boolean;
3
+ export declare const isReactNative: boolean;
4
+ export declare const generateUuid: () => string;
@@ -0,0 +1,11 @@
1
+ export const isNode = typeof window === "undefined";
2
+ export const isInIFrame = !isNode && window.self !== window.top;
3
+ // React Native defines `window` (so `isNode` is false there) but not `document`.
4
+ // Browser-only code paths gated on `window`/`isNode` alone would run — and crash —
5
+ // on React Native. Node (no `window`) is already handled by those `window` guards;
6
+ // this flags the window-without-a-DOM case that isn't.
7
+ export const isReactNative = !isNode && typeof document === "undefined";
8
+ export const generateUuid = () => {
9
+ return (Math.random().toString(36).substring(2, 15) +
10
+ Math.random().toString(36).substring(2, 15));
11
+ };
@@ -0,0 +1 @@
1
+ export declare function getSharedInstance<T>(name: string, factory: () => T): T;
@@ -0,0 +1,15 @@
1
+ const windowObj = typeof window !== "undefined"
2
+ ? window
3
+ : { base44SharedInstances: {} };
4
+ // Singleton (shared between sdk instances)//
5
+ export function getSharedInstance(name, factory) {
6
+ if (!windowObj.base44SharedInstances) {
7
+ windowObj.base44SharedInstances = {};
8
+ }
9
+ if (!windowObj.base44SharedInstances[name]) {
10
+ windowObj.base44SharedInstances[name] = {
11
+ instance: factory(),
12
+ };
13
+ }
14
+ return windowObj.base44SharedInstances[name].instance;
15
+ }
@@ -0,0 +1,47 @@
1
+ import { Socket } from "socket.io-client";
2
+ export interface RoomsSocketConfig {
3
+ serverUrl: string;
4
+ mountPath: string;
5
+ transports: string[];
6
+ appId: string;
7
+ token?: string;
8
+ }
9
+ export type TSocketRoom = string;
10
+ export type TJsonStr = string;
11
+ type RoomsSocketEventsMap = {
12
+ listen: {
13
+ connect: () => Promise<void> | void;
14
+ update_model: (msg: {
15
+ room: string;
16
+ data: TJsonStr;
17
+ }) => Promise<void> | void;
18
+ error: (error: Error) => Promise<void> | void;
19
+ };
20
+ emit: {
21
+ join: (room: string) => void;
22
+ leave: (room: string) => void;
23
+ };
24
+ };
25
+ type TEvent = keyof RoomsSocketEventsMap["listen"];
26
+ type THandler<E extends TEvent> = RoomsSocketEventsMap["listen"][E];
27
+ export type RoomsSocket = ReturnType<typeof RoomsSocket>;
28
+ export declare function RoomsSocket({ config }: {
29
+ config: RoomsSocketConfig;
30
+ }): {
31
+ socket: Socket<{
32
+ connect: () => Promise<void> | void;
33
+ update_model: (msg: {
34
+ room: string;
35
+ data: TJsonStr;
36
+ }) => Promise<void> | void;
37
+ error: (error: Error) => Promise<void> | void;
38
+ }, {
39
+ join: (room: string) => void;
40
+ leave: (room: string) => void;
41
+ }>;
42
+ subscribeToRoom: (room: TSocketRoom, handlers: Partial<{ [k in TEvent]: THandler<k>; }>) => () => void;
43
+ updateConfig: (config: Partial<RoomsSocketConfig>) => void;
44
+ updateModel: (room: string, data: any) => Promise<void>;
45
+ disconnect: () => void;
46
+ };
47
+ export {};
@@ -0,0 +1,170 @@
1
+ import { io } from "socket.io-client";
2
+ import { getAccessToken } from "./auth-utils.js";
3
+ import { getAnalyticsSessionId } from "../modules/analytics.js";
4
+ const ROOM_LEAVE_GRACE_MS = 250;
5
+ function initializeSocket(config, handlers) {
6
+ var _a;
7
+ // On unauthenticated clients, send a stable anonymous visitor id on the
8
+ // handshake so the backend can verify room access for anonymous agent
9
+ // conversations (mirrors the X-Base44-Anonymous-Id HTTP header). Authenticated
10
+ // clients are identified by their token instead.
11
+ const resolvedToken = (_a = config.token) !== null && _a !== void 0 ? _a : getAccessToken();
12
+ const query = {
13
+ app_id: config.appId,
14
+ token: resolvedToken,
15
+ };
16
+ if (!resolvedToken) {
17
+ query.anonymous_id = getAnalyticsSessionId();
18
+ }
19
+ const socket = io(config.serverUrl, {
20
+ path: config.mountPath,
21
+ transports: config.transports,
22
+ query,
23
+ });
24
+ socket.on("connect", async () => {
25
+ var _a;
26
+ console.log("connect", socket.id);
27
+ return (_a = handlers.connect) === null || _a === void 0 ? void 0 : _a.call(handlers);
28
+ });
29
+ socket.on("update_model", async (msg) => {
30
+ var _a;
31
+ return (_a = handlers.update_model) === null || _a === void 0 ? void 0 : _a.call(handlers, msg);
32
+ });
33
+ socket.on("error", async (error) => {
34
+ var _a;
35
+ return (_a = handlers.error) === null || _a === void 0 ? void 0 : _a.call(handlers, error);
36
+ });
37
+ socket.on("connect_error", async (error) => {
38
+ var _a;
39
+ console.error("connect_error", error);
40
+ return (_a = handlers.error) === null || _a === void 0 ? void 0 : _a.call(handlers, error);
41
+ });
42
+ return socket;
43
+ }
44
+ export function RoomsSocket({ config }) {
45
+ let currentConfig = { ...config };
46
+ const roomsToListeners = {};
47
+ const pendingRoomLeaves = {};
48
+ const handlers = {
49
+ connect: async () => {
50
+ const promises = [];
51
+ Object.keys(roomsToListeners).forEach((room) => {
52
+ const listeners = getListeners(room);
53
+ if (listeners.length === 0) {
54
+ return;
55
+ }
56
+ joinRoom(room);
57
+ listeners.forEach(({ connect }) => {
58
+ const promise = async () => connect === null || connect === void 0 ? void 0 : connect();
59
+ promises.push(promise());
60
+ });
61
+ });
62
+ await Promise.all(promises);
63
+ },
64
+ update_model: async (msg) => {
65
+ const listeners = getListeners(msg.room);
66
+ const promises = listeners.map((listener) => { var _a; return (_a = listener.update_model) === null || _a === void 0 ? void 0 : _a.call(listener, msg); });
67
+ await Promise.all(promises);
68
+ },
69
+ error: async (error) => {
70
+ console.error("error", error);
71
+ const promises = Object.values(roomsToListeners)
72
+ .flat()
73
+ .map((listener) => { var _a; return (_a = listener.error) === null || _a === void 0 ? void 0 : _a.call(listener, error); });
74
+ await Promise.all(promises);
75
+ },
76
+ };
77
+ let socket = initializeSocket(config, handlers);
78
+ function cleanup() {
79
+ disconnect();
80
+ }
81
+ function disconnect() {
82
+ clearPendingRoomLeaves();
83
+ if (socket) {
84
+ socket.disconnect();
85
+ }
86
+ }
87
+ function updateConfig(config) {
88
+ cleanup();
89
+ currentConfig = {
90
+ ...currentConfig,
91
+ ...config,
92
+ };
93
+ socket = initializeSocket(currentConfig, handlers);
94
+ }
95
+ function joinRoom(room) {
96
+ socket.emit("join", room);
97
+ }
98
+ function leaveRoom(room) {
99
+ socket.emit("leave", room);
100
+ }
101
+ async function updateModel(room, data) {
102
+ var _a;
103
+ const dataStr = JSON.stringify(data);
104
+ return (_a = handlers.update_model) === null || _a === void 0 ? void 0 : _a.call(handlers, { room, data: dataStr });
105
+ }
106
+ function getListeners(room) {
107
+ var _a;
108
+ return (_a = roomsToListeners[room]) !== null && _a !== void 0 ? _a : [];
109
+ }
110
+ function cancelPendingRoomLeave(room) {
111
+ const pendingLeave = pendingRoomLeaves[room];
112
+ if (!pendingLeave) {
113
+ return;
114
+ }
115
+ clearTimeout(pendingLeave);
116
+ delete pendingRoomLeaves[room];
117
+ }
118
+ function clearPendingRoomLeaves() {
119
+ Object.keys(pendingRoomLeaves).forEach((room) => {
120
+ var _a, _b;
121
+ clearTimeout(pendingRoomLeaves[room]);
122
+ delete pendingRoomLeaves[room];
123
+ if (((_b = (_a = roomsToListeners[room]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) === 0) {
124
+ delete roomsToListeners[room];
125
+ }
126
+ });
127
+ }
128
+ function scheduleRoomLeave(room) {
129
+ cancelPendingRoomLeave(room);
130
+ pendingRoomLeaves[room] = setTimeout(() => {
131
+ var _a, _b;
132
+ delete pendingRoomLeaves[room];
133
+ if (((_b = (_a = roomsToListeners[room]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0) {
134
+ return;
135
+ }
136
+ leaveRoom(room);
137
+ delete roomsToListeners[room];
138
+ }, ROOM_LEAVE_GRACE_MS);
139
+ }
140
+ const subscribeToRoom = (room, handlers) => {
141
+ if (roomsToListeners[room]) {
142
+ cancelPendingRoomLeave(room);
143
+ }
144
+ else {
145
+ joinRoom(room);
146
+ roomsToListeners[room] = [];
147
+ }
148
+ roomsToListeners[room].push(handlers);
149
+ let unsubscribed = false;
150
+ return () => {
151
+ var _a, _b;
152
+ if (unsubscribed) {
153
+ return;
154
+ }
155
+ unsubscribed = true;
156
+ roomsToListeners[room] =
157
+ (_b = (_a = roomsToListeners[room]) === null || _a === void 0 ? void 0 : _a.filter((listener) => listener !== handlers)) !== null && _b !== void 0 ? _b : [];
158
+ if (roomsToListeners[room].length === 0) {
159
+ scheduleRoomLeave(room);
160
+ }
161
+ };
162
+ };
163
+ return {
164
+ socket,
165
+ subscribeToRoom,
166
+ updateConfig,
167
+ updateModel,
168
+ disconnect,
169
+ };
170
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@doany-ai/sdk",
3
+ "version": "0.1.0",
4
+ "description": "JavaScript SDK for the doany app platform (API-compatible fork of @base44/sdk)",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "lint": "eslint src",
14
+ "test": "npm run test:types && vitest run",
15
+ "test:types": "tsc --noEmit -p tsconfig.type-tests.json",
16
+ "test:unit": "vitest run tests/unit",
17
+ "test:e2e": "vitest run tests/e2e",
18
+ "test:watch": "vitest",
19
+ "test:coverage": "vitest run --coverage",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "dependencies": {
23
+ "axios": "^1.18.1",
24
+ "socket.io-client": "^4.8.3",
25
+ "uuid": "^13.0.2"
26
+ },
27
+ "devDependencies": {
28
+ "@types/hast": "^3.0.4",
29
+ "@types/node": "^25.0.1",
30
+ "@types/unist": "^3.0.3",
31
+ "@typescript-eslint/parser": "^8.51.0",
32
+ "@vitest/coverage-istanbul": "^4.1.9",
33
+ "@vitest/coverage-v8": "^4.1.9",
34
+ "@vitest/ui": "^4.1.9",
35
+ "dotenv": "^16.3.1",
36
+ "eslint": "^9.39.2",
37
+ "eslint-plugin-import": "^2.32.0",
38
+ "nock": "^13.4.0",
39
+ "typescript": "^5.3.2",
40
+ "typescript-eslint": "^8.51.0",
41
+ "vitest": "^4.1.9"
42
+ },
43
+ "keywords": [
44
+ "base44",
45
+ "api",
46
+ "sdk"
47
+ ],
48
+ "author": "doany",
49
+ "license": "MIT",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/InceptionsAI/doany-ai-app.git"
53
+ }
54
+ }