@maravilla-labs/platform 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/src/index.ts ADDED
@@ -0,0 +1,170 @@
1
+ /**
2
+ * @fileoverview Maravilla Platform SDK
3
+ *
4
+ * This package provides the main interface for accessing Maravilla runtime services
5
+ * including Key-Value storage and Database operations. It automatically detects the
6
+ * runtime environment and provides the appropriate implementation.
7
+ *
8
+ * ## Environment Detection
9
+ *
10
+ * The SDK automatically detects and adapts to different environments:
11
+ * - **Production**: Uses native Maravilla runtime APIs
12
+ * - **Development**: Connects to development server via HTTP
13
+ * - **Testing**: Can be mocked or use development server
14
+ *
15
+ * ## Key Features
16
+ *
17
+ * - **KV Storage**: Cloudflare Workers KV-compatible API for key-value operations
18
+ * - **Database**: MongoDB-style document database operations
19
+ * - **Multi-tenancy**: Built-in tenant isolation and support
20
+ * - **TypeScript**: Fully typed APIs with comprehensive JSDoc comments
21
+ * - **Development-friendly**: Seamless development server integration
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { getPlatform } from '@maravilla/platform';
26
+ *
27
+ * const platform = getPlatform();
28
+ *
29
+ * // KV operations
30
+ * await platform.env.KV.cache.put('user:123', { name: 'John' });
31
+ * const user = await platform.env.KV.cache.get('user:123');
32
+ *
33
+ * // Database operations
34
+ * const userId = await platform.env.DB.insertOne('users', {
35
+ * name: 'John Doe',
36
+ * email: 'john@example.com'
37
+ * });
38
+ *
39
+ * const users = await platform.env.DB.find('users', { active: true });
40
+ * ```
41
+ *
42
+ * @author Maravilla Team
43
+ * @since 1.0.0
44
+ */
45
+
46
+ import type { Platform } from './types.js';
47
+ import { createRemoteClient } from './remote-client.js';
48
+
49
+ export * from './types.js';
50
+
51
+ /**
52
+ * Global platform instance injected by Maravilla runtime or development tools.
53
+ * This should not be accessed directly - use getPlatform() instead.
54
+ *
55
+ * @internal
56
+ */
57
+
58
+ declare global {
59
+ var __maravilla_platform: Platform | undefined;
60
+ var platform: Platform | undefined;
61
+ }
62
+
63
+ let cachedPlatform: Platform | null = null;
64
+
65
+ /**
66
+ * Get the platform instance. This will:
67
+ * 1. Check if running in Maravilla runtime (global.platform exists)
68
+ * 2. Check if a platform was injected via vite plugin or hooks
69
+ * 3. Fall back to remote client for development
70
+ *
71
+ * The platform provides access to KV storage and database operations,
72
+ * with automatic environment detection for seamless development and production.
73
+ *
74
+ * @param options - Optional configuration for development mode
75
+ * @param options.devServerUrl - URL of the development server (defaults to MARAVILLA_DEV_SERVER env var or http://localhost:3001)
76
+ * @param options.tenant - Tenant identifier for multi-tenancy (defaults to MARAVILLA_TENANT env var or 'dev-tenant')
77
+ * @returns Platform instance with access to KV and database services
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * import { getPlatform } from '@maravilla/platform';
82
+ *
83
+ * // Basic usage (auto-detects environment)
84
+ * const platform = getPlatform();
85
+ *
86
+ * // Development with custom server
87
+ * const platform = getPlatform({
88
+ * devServerUrl: 'http://localhost:3001',
89
+ * tenant: 'my-app'
90
+ * });
91
+ *
92
+ * // Use KV storage
93
+ * await platform.env.KV.cache.put('user:123', { name: 'John' });
94
+ * const user = await platform.env.KV.cache.get('user:123');
95
+ *
96
+ * // Use database
97
+ * const userId = await platform.env.DB.insertOne('users', {
98
+ * name: 'John Doe',
99
+ * email: 'john@example.com'
100
+ * });
101
+ * ```
102
+ */
103
+ export function getPlatform(options?: {
104
+ devServerUrl?: string;
105
+ tenant?: string;
106
+ }): Platform {
107
+ // Return cached if available
108
+ if (cachedPlatform) {
109
+ return cachedPlatform;
110
+ }
111
+
112
+ // 1. Check if we're in the real Maravilla runtime
113
+ if (typeof globalThis !== 'undefined') {
114
+ // Check for native platform (in production runtime)
115
+ if (globalThis.platform) {
116
+ console.log('[platform] Using native Maravilla platform');
117
+ cachedPlatform = globalThis.platform;
118
+ return cachedPlatform;
119
+ }
120
+
121
+ // Check for injected platform (from vite plugin or hooks)
122
+ if (globalThis.__maravilla_platform) {
123
+ console.log('[platform] Using injected platform');
124
+ cachedPlatform = globalThis.__maravilla_platform;
125
+ return cachedPlatform;
126
+ }
127
+ }
128
+
129
+ // 2. Fall back to remote client for development
130
+ const devServerUrl = options?.devServerUrl || process.env.MARAVILLA_DEV_SERVER || 'http://localhost:3001';
131
+ const tenant = options?.tenant || process.env.MARAVILLA_TENANT || 'dev-tenant';
132
+
133
+ console.log(`[platform] Creating remote client for ${devServerUrl}`);
134
+ cachedPlatform = createRemoteClient(devServerUrl, tenant);
135
+
136
+ // Cache it globally for other modules
137
+ if (typeof globalThis !== 'undefined') {
138
+ globalThis.__maravilla_platform = cachedPlatform;
139
+ }
140
+
141
+ return cachedPlatform;
142
+ }
143
+
144
+ /**
145
+ * Clear the cached platform instance (useful for testing).
146
+ *
147
+ * This function resets the internal platform cache and clears any globally
148
+ * injected platform instances. Subsequent calls to getPlatform() will
149
+ * re-initialize the platform based on the current environment.
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * import { clearPlatformCache, getPlatform } from '@maravilla/platform';
154
+ *
155
+ * // In tests, clear cache between test cases
156
+ * afterEach(() => {
157
+ * clearPlatformCache();
158
+ * });
159
+ *
160
+ * // Or when switching between different environments
161
+ * clearPlatformCache();
162
+ * const newPlatform = getPlatform({ devServerUrl: 'http://localhost:3002' });
163
+ * ```
164
+ */
165
+ export function clearPlatformCache(): void {
166
+ cachedPlatform = null;
167
+ if (typeof globalThis !== 'undefined') {
168
+ globalThis.__maravilla_platform = undefined;
169
+ }
170
+ }
@@ -0,0 +1,200 @@
1
+ import type { KvNamespace, KvListResult, Database, DbFindOptions } from './types.js';
2
+
3
+ /**
4
+ * Remote KV namespace implementation that communicates with a development server.
5
+ * This class provides the KV interface by making HTTP requests to the dev server.
6
+ *
7
+ * @internal
8
+ */
9
+ class RemoteKvNamespace implements KvNamespace {
10
+ constructor(
11
+ private baseUrl: string,
12
+ private namespace: string,
13
+ private headers: Record<string, string>
14
+ ) {}
15
+
16
+ /**
17
+ * Internal method for making HTTP requests to the dev server.
18
+ * Handles error responses and authentication headers.
19
+ *
20
+ * @internal
21
+ */
22
+ private async fetch(url: string, options: RequestInit = {}) {
23
+ const response = await fetch(url, {
24
+ ...options,
25
+ headers: { ...this.headers, ...options.headers },
26
+ });
27
+
28
+ if (!response.ok && response.status !== 404) {
29
+ const error = await response.text();
30
+ throw new Error(`Platform API error: ${response.status} - ${error}`);
31
+ }
32
+
33
+ return response;
34
+ }
35
+
36
+ async get(key: string): Promise<any> {
37
+ const response = await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`);
38
+ if (response.status === 404) return null;
39
+ return response.json();
40
+ }
41
+
42
+ async put(key: string, value: any, options?: { expirationTtl?: number }): Promise<void> {
43
+ const headers: Record<string, string> = {};
44
+ if (options?.expirationTtl) {
45
+ headers['X-TTL'] = options.expirationTtl.toString();
46
+ }
47
+
48
+ await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`, {
49
+ method: 'PUT',
50
+ headers,
51
+ body: JSON.stringify(value),
52
+ });
53
+ }
54
+
55
+ async delete(key: string): Promise<void> {
56
+ await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`, {
57
+ method: 'DELETE',
58
+ });
59
+ }
60
+
61
+ async list(options?: { prefix?: string; limit?: number; cursor?: string }): Promise<KvListResult> {
62
+ const response = await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}`, {
63
+ method: 'POST',
64
+ body: JSON.stringify(options || {}),
65
+ });
66
+ const data = await response.json() as any;
67
+ return {
68
+ keys: data.result || [],
69
+ list_complete: !data.result_info?.cursor,
70
+ cursor: data.result_info?.cursor,
71
+ };
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Remote Database implementation that communicates with a development server.
77
+ * This class provides the Database interface by making HTTP requests to the dev server.
78
+ *
79
+ * @internal
80
+ */
81
+ class RemoteDatabase implements Database {
82
+ constructor(
83
+ private baseUrl: string,
84
+ private headers: Record<string, string>
85
+ ) {}
86
+
87
+ /**
88
+ * Internal method for making HTTP requests to the dev server.
89
+ * Handles error responses and authentication headers.
90
+ *
91
+ * @internal
92
+ */
93
+ private async fetch(url: string, options: RequestInit = {}) {
94
+ const response = await fetch(url, {
95
+ ...options,
96
+ headers: { ...this.headers, ...options.headers },
97
+ });
98
+
99
+ if (!response.ok && response.status !== 404) {
100
+ const error = await response.text();
101
+ throw new Error(`Platform API error: ${response.status} - ${error}`);
102
+ }
103
+
104
+ return response;
105
+ }
106
+
107
+ async find(collection: string, filter: any = {}, options: DbFindOptions = {}): Promise<any[]> {
108
+ const response = await this.fetch(`${this.baseUrl}/api/db/${collection}`, {
109
+ method: 'POST',
110
+ body: JSON.stringify({ filter, options }),
111
+ });
112
+ return response.json() as Promise<any[]>;
113
+ }
114
+
115
+ async findOne(collection: string, filter: any): Promise<any | null> {
116
+ const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/findOne`, {
117
+ method: 'POST',
118
+ body: JSON.stringify(filter),
119
+ });
120
+ if (response.status === 404) return null;
121
+ return response.json();
122
+ }
123
+
124
+ async insertOne(collection: string, document: any): Promise<string> {
125
+ const response = await this.fetch(`${this.baseUrl}/api/db/${collection}`, {
126
+ method: 'PUT',
127
+ body: JSON.stringify(document),
128
+ });
129
+ const result = await response.json() as any;
130
+ return result.id;
131
+ }
132
+
133
+ async updateOne(collection: string, filter: any, update: any): Promise<{ modified: number }> {
134
+ const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/update`, {
135
+ method: 'POST',
136
+ body: JSON.stringify({ filter, update }),
137
+ });
138
+ return response.json() as Promise<{ modified: number }>;
139
+ }
140
+
141
+ async deleteOne(collection: string, filter: any): Promise<{ deleted: number }> {
142
+ const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/delete`, {
143
+ method: 'DELETE',
144
+ body: JSON.stringify(filter),
145
+ });
146
+ return response.json() as Promise<{ deleted: number }>;
147
+ }
148
+
149
+ async deleteMany(collection: string, filter: any): Promise<{ deleted: number }> {
150
+ // For now, deleteMany is the same as deleteOne in the remote client
151
+ // This would need to be implemented properly in the dev server
152
+ return this.deleteOne(collection, filter);
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Create a remote platform client for development environments.
158
+ *
159
+ * This function creates a platform instance that communicates with a development
160
+ * server over HTTP. It's used internally by getPlatform() when running in development
161
+ * mode and no native platform is available.
162
+ *
163
+ * @param baseUrl - The base URL of the development server
164
+ * @param tenant - The tenant identifier for multi-tenancy support
165
+ * @returns A platform instance that proxies requests to the development server
166
+ *
167
+ * @internal
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * // This is typically called internally by getPlatform()
172
+ * const platform = createRemoteClient('http://localhost:3001', 'dev-tenant');
173
+ *
174
+ * // The returned platform works the same as the native one
175
+ * await platform.env.KV.cache.put('key', 'value');
176
+ * await platform.env.DB.insertOne('users', { name: 'John' });
177
+ * ```
178
+ */
179
+ export function createRemoteClient(baseUrl: string, tenant: string) {
180
+ const headers = {
181
+ 'Content-Type': 'application/json',
182
+ 'X-Tenant-Id': tenant,
183
+ };
184
+
185
+ // Create KV namespaces proxy that dynamically creates namespace instances
186
+ const kvProxy = new Proxy({} as Record<string, KvNamespace>, {
187
+ get(_, namespace: string) {
188
+ return new RemoteKvNamespace(baseUrl, namespace, headers);
189
+ }
190
+ });
191
+
192
+ const db = new RemoteDatabase(baseUrl, headers);
193
+
194
+ return {
195
+ env: {
196
+ KV: kvProxy,
197
+ DB: db,
198
+ }
199
+ };
200
+ }
package/src/types.ts ADDED
@@ -0,0 +1,305 @@
1
+ /**
2
+ * Key-Value namespace interface for storing and retrieving data.
3
+ * Similar to Cloudflare Workers KV API for familiar developer experience.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const platform = getPlatform();
8
+ * const userKv = platform.env.KV.users;
9
+ *
10
+ * // Store user data
11
+ * await userKv.put('user:123', { name: 'John', email: 'john@example.com' });
12
+ *
13
+ * // Retrieve user data
14
+ * const user = await userKv.get('user:123');
15
+ *
16
+ * // List all user keys
17
+ * const result = await userKv.list({ prefix: 'user:' });
18
+ * ```
19
+ */
20
+ export interface KvNamespace {
21
+ /**
22
+ * Retrieve a value from the KV namespace.
23
+ *
24
+ * @param key - The key to retrieve
25
+ * @returns Promise that resolves to the stored value, or null if not found
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const user = await kv.get('user:123');
30
+ * if (user) {
31
+ * console.log(`Welcome back, ${user.name}!`);
32
+ * }
33
+ * ```
34
+ */
35
+ get(key: string): Promise<any>;
36
+
37
+ /**
38
+ * Store a value in the KV namespace.
39
+ *
40
+ * @param key - The key to store under
41
+ * @param value - The value to store (will be JSON serialized)
42
+ * @param options - Optional configuration
43
+ * @param options.expirationTtl - Time to live in seconds before the key expires
44
+ * @returns Promise that resolves when the operation completes
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * // Store permanent data
49
+ * await kv.put('config:theme', { dark: true });
50
+ *
51
+ * // Store temporary data (expires in 1 hour)
52
+ * await kv.put('session:abc123', sessionData, { expirationTtl: 3600 });
53
+ * ```
54
+ */
55
+ put(key: string, value: any, options?: { expirationTtl?: number }): Promise<void>;
56
+
57
+ /**
58
+ * Delete a key from the KV namespace.
59
+ *
60
+ * @param key - The key to delete
61
+ * @returns Promise that resolves when the operation completes
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * await kv.delete('user:123');
66
+ * ```
67
+ */
68
+ delete(key: string): Promise<void>;
69
+
70
+ /**
71
+ * List keys in the KV namespace with optional filtering.
72
+ *
73
+ * @param options - Optional filtering and pagination options
74
+ * @param options.prefix - Only return keys that start with this prefix
75
+ * @param options.limit - Maximum number of keys to return (default varies by implementation)
76
+ * @param options.cursor - Pagination cursor from previous list call
77
+ * @returns Promise that resolves to a list result with keys and pagination info
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * // List all keys
82
+ * const all = await kv.list();
83
+ *
84
+ * // List user keys only
85
+ * const users = await kv.list({ prefix: 'user:' });
86
+ *
87
+ * // Paginated listing
88
+ * const page1 = await kv.list({ limit: 10 });
89
+ * if (!page1.list_complete) {
90
+ * const page2 = await kv.list({ limit: 10, cursor: page1.cursor });
91
+ * }
92
+ * ```
93
+ */
94
+ list(options?: { prefix?: string; limit?: number; cursor?: string }): Promise<KvListResult>;
95
+ }
96
+
97
+ /**
98
+ * Result object returned by KV list operations.
99
+ * Contains the matching keys and pagination information.
100
+ */
101
+ export interface KvListResult {
102
+ /** Array of matching keys with their metadata */
103
+ keys: Array<{
104
+ /** The key name */
105
+ name: string;
106
+ /** Unix timestamp when the key expires (if set) */
107
+ expiration?: number;
108
+ /** Custom metadata associated with the key */
109
+ metadata?: any;
110
+ }>;
111
+ /** Whether this result contains all matching keys (true) or more results are available (false) */
112
+ list_complete: boolean;
113
+ /** Pagination cursor to use for the next list call, if list_complete is false */
114
+ cursor?: string;
115
+ }
116
+
117
+ /**
118
+ * Database interface for document-based operations.
119
+ * Provides MongoDB-like API for storing and querying structured data.
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const platform = getPlatform();
124
+ * const db = platform.env.DB;
125
+ *
126
+ * // Insert a new user
127
+ * const userId = await db.insertOne('users', {
128
+ * name: 'John Doe',
129
+ * email: 'john@example.com',
130
+ * createdAt: new Date()
131
+ * });
132
+ *
133
+ * // Find users by criteria
134
+ * const activeUsers = await db.find('users', { active: true });
135
+ *
136
+ * // Update a user
137
+ * await db.updateOne('users',
138
+ * { _id: userId },
139
+ * { $set: { lastLogin: new Date() } }
140
+ * );
141
+ * ```
142
+ */
143
+ export interface Database {
144
+ /**
145
+ * Find multiple documents in a collection.
146
+ *
147
+ * @param collection - The collection name
148
+ * @param filter - Query filter object (MongoDB-style)
149
+ * @param options - Optional query options for pagination and sorting
150
+ * @returns Promise that resolves to an array of matching documents
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * // Find all active users
155
+ * const users = await db.find('users', { active: true });
156
+ *
157
+ * // Find with pagination and sorting
158
+ * const recentPosts = await db.find('posts',
159
+ * { published: true },
160
+ * { limit: 10, sort: { createdAt: -1 } }
161
+ * );
162
+ * ```
163
+ */
164
+ find(collection: string, filter?: any, options?: DbFindOptions): Promise<any[]>;
165
+
166
+ /**
167
+ * Find a single document in a collection.
168
+ *
169
+ * @param collection - The collection name
170
+ * @param filter - Query filter object to match the document
171
+ * @returns Promise that resolves to the matching document, or null if not found
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const user = await db.findOne('users', { email: 'john@example.com' });
176
+ * if (user) {
177
+ * console.log(`Found user: ${user.name}`);
178
+ * }
179
+ * ```
180
+ */
181
+ findOne(collection: string, filter: any): Promise<any | null>;
182
+
183
+ /**
184
+ * Insert a single document into a collection.
185
+ *
186
+ * @param collection - The collection name
187
+ * @param document - The document to insert
188
+ * @returns Promise that resolves to the ID of the inserted document
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * const postId = await db.insertOne('posts', {
193
+ * title: 'Hello World',
194
+ * content: 'This is my first post',
195
+ * author: 'john@example.com',
196
+ * createdAt: new Date()
197
+ * });
198
+ * ```
199
+ */
200
+ insertOne(collection: string, document: any): Promise<string>;
201
+
202
+ /**
203
+ * Update a single document in a collection.
204
+ *
205
+ * @param collection - The collection name
206
+ * @param filter - Query filter to match the document to update
207
+ * @param update - Update operations (MongoDB-style with $set, $inc, etc.)
208
+ * @returns Promise that resolves to an object with the number of modified documents
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * const result = await db.updateOne('users',
213
+ * { email: 'john@example.com' },
214
+ * { $set: { lastLogin: new Date() }, $inc: { loginCount: 1 } }
215
+ * );
216
+ * console.log(`Modified ${result.modified} documents`);
217
+ * ```
218
+ */
219
+ updateOne(collection: string, filter: any, update: any): Promise<{ modified: number }>;
220
+
221
+ /**
222
+ * Delete a single document from a collection.
223
+ *
224
+ * @param collection - The collection name
225
+ * @param filter - Query filter to match the document to delete
226
+ * @returns Promise that resolves to an object with the number of deleted documents
227
+ *
228
+ * @example
229
+ * ```typescript
230
+ * const result = await db.deleteOne('posts', { _id: postId });
231
+ * console.log(`Deleted ${result.deleted} documents`);
232
+ * ```
233
+ */
234
+ deleteOne(collection: string, filter: any): Promise<{ deleted: number }>;
235
+
236
+ /**
237
+ * Delete multiple documents from a collection.
238
+ *
239
+ * @param collection - The collection name
240
+ * @param filter - Query filter to match documents to delete
241
+ * @returns Promise that resolves to an object with the number of deleted documents
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * // Delete all inactive users
246
+ * const result = await db.deleteMany('users', { active: false });
247
+ * console.log(`Deleted ${result.deleted} inactive users`);
248
+ * ```
249
+ */
250
+ deleteMany(collection: string, filter: any): Promise<{ deleted: number }>;
251
+ }
252
+
253
+ /**
254
+ * Options for database find operations.
255
+ * Provides MongoDB-style query options for pagination, sorting, and limiting results.
256
+ */
257
+ export interface DbFindOptions {
258
+ /** Maximum number of documents to return */
259
+ limit?: number;
260
+ /** Number of documents to skip (for pagination) */
261
+ skip?: number;
262
+ /** Sort order specification (MongoDB-style: { field: 1 } for ascending, { field: -1 } for descending) */
263
+ sort?: any;
264
+ }
265
+
266
+ /**
267
+ * Platform environment containing all available services.
268
+ * This is the main interface for accessing KV storage and database operations.
269
+ */
270
+ export interface PlatformEnv {
271
+ /**
272
+ * Key-Value storage namespaces. Access different KV namespaces by property name.
273
+ *
274
+ * @example
275
+ * ```typescript
276
+ * const userCache = platform.env.KV.users;
277
+ * const sessionStore = platform.env.KV.sessions;
278
+ * ```
279
+ */
280
+ KV: Record<string, KvNamespace>;
281
+ /** Database interface for document operations */
282
+ DB: Database;
283
+ }
284
+
285
+ /**
286
+ * Main platform interface providing access to all Maravilla runtime services.
287
+ * This is the primary interface developers will interact with.
288
+ *
289
+ * @example
290
+ * ```typescript
291
+ * import { getPlatform } from '@maravilla/platform';
292
+ *
293
+ * const platform = getPlatform();
294
+ *
295
+ * // Use KV storage
296
+ * await platform.env.KV.cache.put('key', 'value');
297
+ *
298
+ * // Use database
299
+ * await platform.env.DB.insertOne('users', { name: 'John' });
300
+ * ```
301
+ */
302
+ export interface Platform {
303
+ /** Environment containing all available platform services */
304
+ env: PlatformEnv;
305
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "lib": ["ES2022"],
6
+ "moduleResolution": "node",
7
+ "rootDir": "./src",
8
+ "outDir": "./dist",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "types": ["node"]
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm'],
6
+ dts: true,
7
+ splitting: false,
8
+ sourcemap: true,
9
+ clean: true,
10
+ target: 'es2022',
11
+ external: [],
12
+ });