# @lumi.new/sdk The official JavaScript/TypeScript SDK for Lumi.new. It offers a simple interface for handling user authentication and managing your project's data entities. ## Installation ```bash # pnpm pnpm add @lumi.new/sdk # npm npm install @lumi.new/sdk # yarn yarn add @lumi.new/sdk ``` ## Getting Started First, initialize the Lumi client. You can get your `projectId` from your Lumi project settings. ```typescript import { createClient } from '@lumi.new/sdk' export const lumi = createClient({ projectId: 'YOUR_PROJECT_ID', apiBaseUrl: 'YOUR_API_BASE_URL', authOrigin: 'YOUR_AUTH_ORIGIN', }) ``` ## Authentication The Lumi SDK provides methods to handle user authentication. ### Sign In To sign in a user, call the `signIn` method. This will open a popup window for the user to authenticate. Upon successful authentication, the access token and user information will be automatically stored. ```typescript import { LumiClient } from '@lumi.new/sdk' async function handleSignIn(lumi: LumiClient) { try { const { user, accessToken } = await lumi.auth.signIn() console.log('Signed in as:', user) console.log('Access Token:', accessToken) } catch (error) { console.error('Authentication failed:', error) } } ``` ### Sign Out To sign out a user, simply call the `signOut` method. This will clear the stored access token and user information. ```typescript function handleSignOut(lumi: LumiClient) { lumi.auth.signOut() console.log('User signed out.') } ``` ### Refresh User Profile Fetch the latest profile of the currently authenticated user and update the local cache. This method requires a valid access token. ```typescript async function fetchUser(lumi: LumiClient) { if (lumi.auth.isAuthenticated) { try { const user = await lumi.auth.refreshUser() console.log('Current user:', user) } catch (error) { console.error('Failed to fetch user:', error) } } else { console.log('User is not authenticated.') } } ``` ### Manage Access Token You can directly access the access token. ```typescript // Get the access token const token = lumi.auth.accessToken // Check if the user is authenticated const isAuthenticated = lumi.auth.isAuthenticated ``` ### Access User Information You can directly access the cached user data. This data is available after a successful sign-in or a call to `refreshUser`. ```typescript // Get the user object from the cache const user = lumi.auth.user if (user) { console.log('Current user from cache:', user.userName) } ``` ### Listen for Auth Changes You can listen for changes in the authentication state. This is useful for reacting to sign-ins, sign-outs, or any direct modifications to the access token or user information, whether they happen in the current tab or another one. ```typescript function listenForAuthChanges(lumi: LumiClient) { const unsubscribe = lumi.auth.onAuthChange(({ isAuthenticated, user }) => { console.log(`User is now ${isAuthenticated ? 'signed in' : 'signed out'}.`) if (isAuthenticated) { console.log('User details:', user) } // You can update your UI based on the authentication state }) // To stop listening, call the unsubscribe function // unsubscribe() } ``` ## Entities The `entities` client allows you to interact with your project's data collections. You can access a specific entity by its name. ```typescript const posts = lumi.entities.Posts ``` ### List Records Retrieve a list of records from an entity. This method returns an object containing the list of records and the total count. You can use `filter`, `sort`, `limit`, and `skip` to control the query. ```typescript async function getPosts() { const { list, total } = await lumi.entities.Posts.list({ filter: { published: true }, sort: { createdAt: -1 }, // Sort by creation date in descending order limit: 10, skip: 0, }) console.log('Posts:', list) console.log('Total records:', total) } // Example Request: getPosts(); // Example Response: // Posts: [ // { id: 'post-id-1', title: 'First Post', content: '...', published: true, createdAt: '...' }, // { id: 'post-id-2', title: 'Second Post', content: '...', published: true, createdAt: '...' } // ] // Total records: 2 ``` ### Get a Single Record Retrieve a single record by its ID. ```typescript async function getPost(id: string) { const post = await lumi.entities.Posts.get(id) console.log('Post:', post) } // Example Request: getPost('your-post-id'); // Example Response: // Post: { id: 'post-id-1', title: 'My Post', content: '...', published: true, createdAt: '...' } ``` ### Create a Record Create a new record in an entity. ```typescript async function createPost(title: string, content: string) { const newPost = await lumi.entities.Posts.create({ title, content, published: false, }) console.log('Created post:', newPost) } // Example Request: createPost('My Awesome Post', 'This is the content of my new post.'); // Example Response: // Created post: { id: 'new-post-id', title: 'My Awesome Post', content: 'This is the content of my new post.', published: false, creator: 'user-id-123', createdAt: '2024-01-16T10:30:00Z', updatedAt: '2024-01-16T10:30:00Z' } ``` ### Create Multiple Records Create multiple records in a single request. ```typescript async function createMultiplePosts(newPostsData: any[]) { const newPosts = await lumi.entities.Posts.createMany(newPostsData) console.log('Created posts:', newPosts) } // Example Request: const postsToCreate = [ { title: 'First Awesome Post', content: 'Content for the first post.' }, { title: 'Second Awesome Post', content: 'Content for the second post.' } ]; createMultiplePosts(postsToCreate); // Example Response: // Created posts: [ // { id: 'post-1', title: 'Post 1', content: '...', published: false, creator: 'user-id-123', createdAt: '...', updatedAt: '...' }, // { id: 'post-2', title: 'Post 2', content: '...', published: false, creator: 'user-id-123', createdAt: '...', updatedAt: '...' } // ] ``` ### Update a Record Update an existing record by its ID. ```typescript async function updatePost(id: string, updates: Record) { const updatedPost = await lumi.entities.Posts.update(id, updates) console.log('Updated post:', updatedPost) } // Example Request: updatePost('your-post-id', { published: true, title: 'My Updated Post' }); // Example Response: // Updated post: { id: 'post-id-1', title: 'My Updated Post', content: '...', published: true, creator: 'user-id-123', createdAt: '...', updatedAt: '...' } ``` ### Delete a Record Delete a record by its ID. ```typescript async function deletePost(id: string) { await lumi.entities.Posts.delete(id) console.log('Post deleted.') } // Example Request: deletePost('your-post-id'); ``` ### Delete Multiple Records Delete multiple records by their IDs in a single request. ```typescript async function deleteMultiplePosts(ids: string[]) { await lumi.entities.Posts.deleteMany(ids) console.log('Posts deleted.') } // Example Request: deleteMultiplePosts(['post-id-1', 'post-id-2']); ``` ## Tools The `tools` client provides access to various utilities, such as sending emails. ### Send an Email You can send an email using the `email.send` method. ```typescript async function sendWelcomeEmail(email: string) { try { await lumi.tools.email.send({ to: email, subject: 'Welcome to Our Service!', fromName: 'The Team', html: '

Welcome!

We are glad to have you with us.

', }); console.log('Email sent successfully.'); } catch (error) { console.error('Failed to send email:', error); } } // Example Request: sendWelcomeEmail('test@example.com'); ``` ### Upload Files Upload multiple files in a single request. This method returns an array of objects, each representing the result of one file upload. ```typescript async function uploadFiles(files: File[]) { const results = await lumi.tools.file.upload(files) console.log('Upload results:', results) } // Example Request (in a browser environment): // const fileInput = document.querySelector('input[type="file"]'); // if (fileInput.files) { // uploadFiles(Array.from(fileInput.files)); // } // Example Response: // Upload results: [ // { fileName: 'image.png', fileUrl: 'https://your-storage.com/image.png' }, // { fileName: 'application.exe', uploadError: 'Invalid file type' } // ] ``` ### Delete Files Delete multiple files by their URLs in a single request. ```typescript async function deleteFiles(urls:string[]) { await lumi.tools.file.delete(urls); console.log('Files deleted.'); } // Example Request: const filesToDelete = [ 'https://your-storage.com/image.png', 'https://your-storage.com/document.pdf' ]; deleteFiles(filesToDelete); ``` --- ## API Reference ### `createClient(config)` Initializes the Lumi client. **Parameters:** - `config` (`object`): The configuration object for the client. - `projectId` (`string`): Your Lumi project ID. - `apiBaseUrl` (`string`): The base URL of the Lumi API. - `authOrigin` (`string`): The origin URL for the authentication popup. **Returns:** - `LumiClient`: An instance of the Lumi client. ### Authentication (`lumi.auth`) Provides methods for user authentication. #### `signIn()` Initiates the sign-in process by opening a popup window. **Returns:** - `Promise`: A promise that resolves with an object containing: - `projectId` (`string`): The project ID associated with the authenticated session. - `user` (`object`): The authenticated user's information. - `userId` (`string`): The user's unique identifier. - `email` (`string`): The user's email address. - `userName` (`string`): The user's name. - `createdTime` (`string`): The timestamp of when the user was created. - `accessToken` (`string`): The access token for the session. #### `signOut()` Signs out the current user by clearing the stored access token and user data. #### `refreshUser()` Fetches the latest profile of the currently authenticated user and updates the local cache. Requires a valid access token. **Returns:** - `Promise`: A promise that resolves with the user's profile information. - `userId` (`string`): The user's unique identifier. - `email` (`string`): The user's email address. - `userName` (`string`): The user's name. - `createdTime` (`string`): The timestamp of when the user was created. #### `accessToken` A getter/setter for the access token. - **Get**: `lumi.auth.accessToken` (`string | null`): Returns the currently stored access token, or `null` if not authenticated. - **Set**: `lumi.auth.accessToken = 'YOUR_TOKEN'`: Sets the access token in local storage. Note: This will trigger the `onAuthChange` event. #### `user` A getter/setter for the cached user object. The user object is automatically set on sign-in and after calling `refreshUser`. - **Get**: `lumi.auth.user` (`User | null`): Returns the currently cached user object, or `null` if it's not available. - **Set**: `lumi.auth.user = userObject`: Sets the user object in local storage. Note: This will trigger the `onAuthChange` event. #### `isAuthenticated` A getter that checks if a user is currently authenticated. - **Get**: `lumi.auth.isAuthenticated` (`boolean`): Returns `true` if an access token exists, otherwise `false`. #### `onAuthChange(callback)` Listens for changes in the authentication state. It triggers when `signIn()` or `signOut()` is called, or when `accessToken` or `user` are modified directly. This works across different browser tabs and within the same page. **Parameters:** - `callback` (`({ isAuthenticated: boolean, user: User | null }) => void`): A function that is called whenever the authentication state changes. It receives an object containing the `isAuthenticated` flag and the `user` object from local storage. **Returns:** - `() => void`: A function that, when called, unsubscribes the listener. **Example:** ```typescript const unsubscribe = lumi.auth.onAuthChange(({ isAuthenticated, user }) => { console.log('Authentication state changed:', isAuthenticated) if (isAuthenticated) { // Typically you would update your UI here console.log('User is now signed in:', user) } else { // And here as well console.log('User is now signed out.') } }) // When the component unmounts or you no longer need to listen for changes: // unsubscribe(); ``` ### Entities (`lumi.entities.YourEntity`) Provides methods for interacting with your project's data entities. #### `list(options)` Retrieves a list of records from an entity. **Parameters:** - `options` (`object`, optional): Query options. - `filter` (`object`, optional): An object specifying query conditions. - `sort` (`object`, optional): An object specifying the sort order. Use `1` for ascending and `-1` for descending. Example: `{ createdAt: -1 }`. - `limit` (`number`, optional): The maximum number of records to return. - `skip` (`number`, optional): The number of records to skip from the beginning. **Returns:** - `Promise`: A promise that resolves with an object containing: - `list` (`Array`): An array of the retrieved records. - `total` (`number`): The total number of records matching the query. #### `get(id)` Retrieves a single record by its ID. **Parameters:** - `id` (`string`): The unique identifier of the record to retrieve. **Returns:** - `Promise`: A promise that resolves with the record object, or `null` if not found. #### `create(data)` Creates a new record. **Parameters:** - `data` (`object`): The data for the new record. **Returns:** - `Promise`: A promise that resolves with the newly created record object. #### `createMany(data)` Creates multiple records in a single request. **Parameters:** - `data` (`Array`): An array of data objects for the new records. **Returns:** - `Promise>`: A promise that resolves with an array of the newly created record objects. #### `update(id, data)` Updates an existing record by its ID. **Parameters:** - `id` (`string`): The unique identifier of the record to update. - `data` (`object`): An object containing the fields to update. **Returns:** - `Promise`: A promise that resolves with the updated record object. #### `delete(id)` Deletes a record by its ID. **Parameters:** - `id` (`string`): The unique identifier of the record to delete. **Returns:** - `Promise`: A promise that resolves when the operation is complete. #### `deleteMany(ids)` Deletes multiple records by their IDs. **Parameters:** - `ids` (`Array`): An array of unique identifiers of the records to delete. **Returns:** - `Promise`: A promise that resolves when the operation is complete. ### Tools (`lumi.tools`) Provides access to various tools and utilities. #### `email.send(options)` Sends an email. **Parameters:** - `options` (`object`): Email options. - `to` (`string | string[]`): The recipient's email address or addresses. - `subject` (`string`): The subject of the email. - `fromName` (`string`, optional): The sender's name. - `html` (`string`, optional): The HTML body of the email. At least one of `html` or `text` must be provided. - `text` (`string`, optional): The plain text body of the email. At least one of `html` or `text` must be provided. - `replyTo` (`string | string[]`, optional): Email address or addresses to reply to. - `scheduledAt` (`string`, optional): An ISO 8601 formatted date string to schedule the email for later sending. **Returns:** - `Promise`: A promise that resolves when the email sending request is accepted. #### `file.upload(files)` Uploads one or more files. **Parameters:** - `files` (`File[]`): An array of `File` objects to upload. **Returns:** - `Promise>`: A promise that resolves with an array of objects, where each object represents the result of a single file upload. - `fileName` (`string`): The original name of the file. - `fileUrl` (`string`, optional): The URL of the uploaded file. Present only on successful upload. - `uploadError` (`string`, optional): An error message if the upload for this specific file failed. #### `file.delete(fileUrls)` Deletes one or more files based on their URLs. **Parameters:** - `fileUrls` (`string[]`): An array of file URLs to be deleted. **Returns:** - `Promise`: A promise that resolves when the delete operation is complete.