diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cdaeb19cc..1b5f4714f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -162,6 +162,16 @@ jobs: strategy: all tag: ${{ env.TAG }} + - name: Publish SDK Portal package + uses: JS-DevTools/npm-publish@v3 + with: + token: ${{ secrets.NPM_TOKEN }} + package: ./packages/portal/package.json + access: public + provenance: false + strategy: all + tag: ${{ env.TAG }} + - name: Publish SDK The Graph package uses: JS-DevTools/npm-publish@v3 with: @@ -193,6 +203,7 @@ jobs: | ------- | -------------------- | | SDK Cli | `@settlemint/sdk-cli@${{ env.VERSION }}` | | SDK The Graph | `@settlemint/sdk-thegraph@${{ env.VERSION }}` | + | SDK Portal | `@settlemint/sdk-portal@${{ env.VERSION }}` | | SDK Hasura | `@settlemint/sdk-hasura@${{ env.VERSION }}` | | SDK JS | `@settlemint/sdk-js@${{ env.VERSION }}` | | SDK Utils | `@settlemint/sdk-utils@${{ env.VERSION }}` | diff --git a/packages/hasura/src/hasura.ts b/packages/hasura/src/hasura.ts index bfc16328c..0adeea32f 100644 --- a/packages/hasura/src/hasura.ts +++ b/packages/hasura/src/hasura.ts @@ -2,7 +2,12 @@ import { ensureServer } from "@settlemint/sdk-utils/runtime"; import { validate } from "@settlemint/sdk-utils/validation"; import { type AbstractSetupSchema, initGraphQLTada } from "gql.tada"; import { GraphQLClient } from "graphql-request"; -import { type ClientOptions, ClientOptionsSchema, ServerClientOptionsSchema } from "./helpers/client-options.schema.js"; +import { + type ClientOptions, + ClientOptionsSchema, + type ServerClientOptions, + ServerClientOptionsSchema, +} from "./helpers/client-options.schema.js"; export type RequestConfig = ConstructorParameters[1]; @@ -63,7 +68,7 @@ export function createHasuraClient( * }); */ export function createServerHasuraClient( - options: ClientOptions, + options: ServerClientOptions, requestConfig?: RequestConfig, ) { ensureServer(); @@ -72,7 +77,7 @@ export function createServerHasuraClient(); return { - client: new GraphQLClient(`${validatedOptions.instance}/v1/graphql`, { + client: new GraphQLClient(validatedOptions.instance, { ...requestConfig, headers: { ...requestConfig?.headers, diff --git a/packages/portal/.gitignore b/packages/portal/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/packages/portal/LICENSE b/packages/portal/LICENSE new file mode 100644 index 000000000..d74c76357 --- /dev/null +++ b/packages/portal/LICENSE @@ -0,0 +1,110 @@ +# Functional Source License, Version 1.1, MIT Future License + +## Abbreviation + +FSL-1.1-MIT + +## Notice + +Copyright 2024 SettleMint + +## Terms and Conditions + +### Licensor ("We") + +The party offering the Software under these Terms and Conditions. + +### The Software + +The "Software" is each version of the software that we make available under +these Terms and Conditions, as indicated by our inclusion of these Terms and +Conditions with the Software. + +### License Grant + +Subject to your compliance with this License Grant and the Patents, +Redistribution and Trademark clauses below, we hereby grant you the right to +use, copy, modify, create derivative works, publicly perform, publicly display +and redistribute the Software for any Permitted Purpose identified below. + +### Permitted Purpose + +A Permitted Purpose is any purpose other than a Competing Use. A Competing Use +means making the Software available to others in a commercial product or +service that: + +1. substitutes for the Software; + +2. substitutes for any other product or service we offer using the Software + that exists as of the date we make the Software available; or + +3. offers the same or substantially similar functionality as the Software. + +Permitted Purposes specifically include using the Software: + +1. for your internal use and access; + +2. for non-commercial education; + +3. for non-commercial research; and + +4. in connection with professional services that you provide to a licensee + using the Software in accordance with these Terms and Conditions. + +### Patents + +To the extent your use for a Permitted Purpose would necessarily infringe our +patents, the license grant above includes a license under our patents. If you +make a claim against any party that the Software infringes or contributes to +the infringement of any patent, then your patent license to the Software ends +immediately. + +### Redistribution + +The Terms and Conditions apply to all copies, modifications and derivatives of +the Software. + +If you redistribute any copies, modifications or derivatives of the Software, +you must include a copy of or a link to these Terms and Conditions and not +remove any copyright notices provided in or with the Software. + +### Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR +PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT. + +IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE +SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, +EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE. + +### Trademarks + +Except for displaying the License Details and identifying us as the origin of +the Software, you have no right under these Terms and Conditions to use our +trademarks, trade names, service marks or product names. + +## Grant of Future License + +We hereby irrevocably grant you an additional license to use the Software under +the MIT license that is effective on the second anniversary of the date we make +the Software available. On or after that date, you may use the Software under +the MIT license, in which case the following will apply: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/portal/README.md b/packages/portal/README.md new file mode 100644 index 000000000..77fc25444 --- /dev/null +++ b/packages/portal/README.md @@ -0,0 +1,172 @@ +

+ SettleMint logo +

SettleMint SDK

+

+ ✨ https://settlemint.com ✨ +
+ Integrate SettleMint into your application with ease. +

+

+ +

+CI status +License +npm +stars +

+ +
+ Documentation +   •   + Discord +   •   + NPM +   •   + Issues +
+
+ +## Table of Contents + +- [Installation](#installation) +- [Usage](#usage) +- [API Reference](#api-reference) +- [Examples](#examples) +- [Contributing](#contributing) +- [License](#license) + +## Installation + +To install the SettleMint SDK, you can use one of the following package managers: + +```bash +# Using npm +npm install @settlemint/sdk + +# Using yarn +yarn add @settlemint/sdk + +# Using pnpm +pnpm add @settlemint/sdk + +# Using Bun +bun add @settlemint/sdk +``` + +We recommend using Bun for faster installation and better performance. + +## Usage + +To use the SettleMint SDK in your Node.js application, follow these steps: + +1. Import the SDK: + +```javascript +import { createSettleMintClient } from '@settlemint/sdk'; +``` + +2. Create a client instance: + +```javascript +const client = createSettleMintClient({ + accessToken: 'your_access_token', + instance: 'https://console.settlemint.com' +}); +``` + +3. Use the client to interact with SettleMint resources: + +```javascript +// Example: List workspaces +const workspaces = await client.workspace.list(); +console.log(workspaces); +``` + +## API Reference + +The SettleMint SDK provides access to various resources. Here's an overview of the available methods: + +### Workspace + +- `workspace.list()`: List all workspaces and their applications +- `workspace.read(workspaceId)`: Read a specific workspace and its applications + +### Blockchain Network + +- `blockchainNetwork.list(applicationId)`: List blockchain networks for a given application +- `blockchainNetwork.read(blockchainNetworkId)`: Read a specific blockchain network + +### Blockchain Node + +- `blockchainNode.list(applicationId)`: List blockchain nodes for a given application +- `blockchainNode.read(blockchainNodeId)`: Read a specific blockchain node + +### Middleware + +- `middleware.list(applicationId)`: List middlewares for a given application +- `middleware.read(middlewareId)`: Read a specific middleware + +### Integration Tool + +- `integrationTool.list(applicationId)`: List integration tools for a given application +- `integrationTool.read(integrationId)`: Read a specific integration tool + +### Storage + +- `storage.list(applicationId)`: List storage items for a given application +- `storage.read(storageId)`: Read a specific storage item + +### Private Key + +- `privateKey.list(applicationId)`: List private keys for a given application +- `privateKey.read(privateKeyId)`: Read a specific private key + +### Insights + +- `insights.list(applicationId)`: List insights for a given application +- `insights.read(insightsId)`: Read a specific insight + +## Examples + +Here are some examples of how to use the SettleMint SDK: + +### List Workspaces + +```javascript +const client = createSettleMintClient({ + accessToken: 'your_access_token', + instance: 'https://console.settlemint.com' +}); + +const workspaces = await client.workspace.list(); +console.log(workspaces); +``` + +### Read a Specific Blockchain Network + +```javascript +const client = createSettleMintClient({ + accessToken: 'your_access_token', + instance: 'https://console.settlemint.com' +}); + +const networkId = 'your_network_id'; +const network = await client.blockchainNetwork.read(networkId); +console.log(network); +``` + +## Contributing + +We welcome contributions to the SettleMint SDK! If you'd like to contribute, please follow these steps: + +1. Fork the repository +2. Create a new branch for your feature or bug fix +3. Make your changes and commit them with a clear commit message +4. Push your changes to your fork +5. Create a pull request to the main repository + +Please ensure that your code follows the existing style and includes appropriate tests and documentation. + +## License + +The SettleMint SDK is released under the [FSL Software License](https://fsl.software). See the [LICENSE](LICENSE) file for more details. \ No newline at end of file diff --git a/packages/portal/knip.json b/packages/portal/knip.json new file mode 100644 index 000000000..dc6220535 --- /dev/null +++ b/packages/portal/knip.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://unpkg.com/knip@5/schema.json", + "ignoreDependencies": [], + "ignore": ["dist/**"], + "entry": ["src/settlemint.ts"] +} diff --git a/packages/portal/package.json b/packages/portal/package.json new file mode 100644 index 000000000..8f985381f --- /dev/null +++ b/packages/portal/package.json @@ -0,0 +1,59 @@ +{ + "name": "@settlemint/sdk-portal", + "description": "SettleMint SDK, integrate SettleMint into your application with ease.", + "version": "0.0.1", + "type": "module", + "private": false, + "license": "FSL-1.1-MIT", + "author": { + "name": "SettleMint", + "email": "support@settlemint.com", + "url": "https://settlemint.com" + }, + "homepage": "https://github.com/settlemint/sdk/blob/main/packages/js/README.md", + "repository": { + "type": "git", + "url": "git+https://github.com/settlemint/sdk.git", + "directory": "packages/portal" + }, + "bugs": { + "url": "https://github.com/settlemint/sdk/issues", + "email": "support@settlemint.com" + }, + "files": ["dist"], + "main": "./dist/portal.cjs", + "module": "./dist/portal.mjs", + "types": "./dist/portal.d.ts", + "exports": { + "./package.json": "./package.json", + ".": { + "import": { + "types": "./dist/portal.d.ts", + "default": "./dist/portal.mjs" + }, + "require": { + "types": "./dist/portal.d.cts", + "default": "./dist/portal.cjs" + } + } + }, + "scripts": { + "build": "tsup-node", + "dev": "tsup-node --watch", + "publint": "publint run --strict", + "attw": "attw --pack .", + "test": "bun test", + "test:coverage": "bun test --coverage", + "typecheck": "tsc --noEmit" + }, + "devDependencies": {}, + "dependencies": { + "@settlemint/sdk-utils": "workspace:*", + "graphql-request": "^7", + "zod": "^3" + }, + "peerDependencies": {}, + "engines": { + "node": ">=20" + } +} diff --git a/packages/portal/src/helpers/client-options.schema.ts b/packages/portal/src/helpers/client-options.schema.ts new file mode 100644 index 000000000..32b6161a7 --- /dev/null +++ b/packages/portal/src/helpers/client-options.schema.ts @@ -0,0 +1,27 @@ +import { AccessTokenSchema, UrlSchema } from "@settlemint/sdk-utils/validation"; +import { z } from "zod"; + +/** + * Schema for validating client options for the Portal client. + */ +export const ClientOptionsSchema = z.object({ + instance: UrlSchema, +}); + +/** + * Type definition for client options derived from the ClientOptionsSchema. + */ +export type ClientOptions = z.infer; + +/** + * Schema for validating server client options for the Portal client. + * Extends the ClientOptionsSchema with additional server-specific fields. + */ +export const ServerClientOptionsSchema = ClientOptionsSchema.extend({ + accessToken: AccessTokenSchema, +}); + +/** + * Type definition for server client options derived from the ServerClientOptionsSchema. + */ +export type ServerClientOptions = z.infer; diff --git a/packages/portal/src/portal.ts b/packages/portal/src/portal.ts new file mode 100644 index 000000000..20e8a0a21 --- /dev/null +++ b/packages/portal/src/portal.ts @@ -0,0 +1,92 @@ +import { ensureServer } from "@settlemint/sdk-utils/runtime"; +import { validate } from "@settlemint/sdk-utils/validation"; +import { type AbstractSetupSchema, initGraphQLTada } from "gql.tada"; +import { GraphQLClient } from "graphql-request"; +import { + type ClientOptions, + ClientOptionsSchema, + type ServerClientOptions, + ServerClientOptionsSchema, +} from "./helpers/client-options.schema.js"; + +export type RequestConfig = ConstructorParameters[1]; + +/** + * Creates a Portal client for client-side use. + * + * @param options - The client options for configuring the Portal client. + * @param requestConfig - Optional configuration for GraphQL requests. + * @returns An object containing the GraphQL client and the initialized graphql function. + * @throws Will throw an error if the options fail validation. + * + * @example + * const { client, graphql } = createPortalClient<{ + * introspection: introspection; + * disableMasking: true; + * scalars: { + * DateTime: Date; + * JSON: Record; + * }; + * }>({ + * instance: 'https://your-portal-instance.com', + * }); + */ +export function createPortalClient( + options: ClientOptions, + requestConfig?: RequestConfig, +) { + const validatedOptions = validate(ClientOptionsSchema, options); + + const graphql = initGraphQLTada(); + + return { + client: new GraphQLClient(validatedOptions.instance, requestConfig), + graphql, + }; +} + +/** + * Creates a Portal client for server-side use with additional authentication. + * + * @param options - The server client options for configuring the Portal client. + * @param requestConfig - Optional configuration for GraphQL requests. + * @returns An object containing the GraphQL client and the initialized graphql function. + * @throws Will throw an error if not called on the server or if the options fail validation. + * + * @example + * const { client, graphql } = createServerPortalClient<{ + * introspection: introspection; + * disableMasking: true; + * scalars: { + * DateTime: Date; + * JSON: Record; + * }; + * }>({ + * instance: 'https://your-portal-instance.com', + * accessToken: 'your-access-token', + * adminSecret: 'your-admin-secret', + * }); + */ +export function createServerPortalClient( + options: ServerClientOptions, + requestConfig?: RequestConfig, +) { + ensureServer(); + const validatedOptions = validate(ServerClientOptionsSchema, options); + + const graphql = initGraphQLTada(); + + return { + client: new GraphQLClient(validatedOptions.instance, { + ...requestConfig, + headers: { + ...requestConfig?.headers, + "x-auth-token": validatedOptions.accessToken, + }, + }), + graphql, + }; +} + +export { readFragment } from "gql.tada"; +export type { FragmentOf, ResultOf, VariablesOf } from "gql.tada"; diff --git a/packages/portal/tsconfig.json b/packages/portal/tsconfig.json new file mode 100644 index 000000000..136719a44 --- /dev/null +++ b/packages/portal/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "declaration": true, + "esModuleInterop": true, + "isolatedModules": true, + "lib": ["es2022", "DOM", "DOM.Iterable"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "noUncheckedIndexedAccess": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ES2022", + "outDir": "dist", + "jsx": "react-jsx", + "noEmit": true, + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/portal/tsup.config.ts b/packages/portal/tsup.config.ts new file mode 100644 index 000000000..56b08af15 --- /dev/null +++ b/packages/portal/tsup.config.ts @@ -0,0 +1,21 @@ +import { type Options, defineConfig } from "tsup"; + +const sharedConfig: Options = { + sourcemap: true, + dts: true, + splitting: false, + treeshake: false, + format: ["cjs", "esm"], + outExtension: ({ format }) => ({ + js: format === "esm" ? ".mjs" : ".cjs", + }), +}; + +export default defineConfig(({ watch }) => { + return [ + { + entry: ["src/portal.ts"], + ...sharedConfig, + }, + ]; +}); diff --git a/packages/thegraph/src/helpers/client-options.schema.ts b/packages/thegraph/src/helpers/client-options.schema.ts index edfa38c03..a56104fc8 100644 --- a/packages/thegraph/src/helpers/client-options.schema.ts +++ b/packages/thegraph/src/helpers/client-options.schema.ts @@ -2,11 +2,10 @@ import { AccessTokenSchema, UrlSchema } from "@settlemint/sdk-utils/validation"; import { z } from "zod"; /** - * Schema for validating client options for the Hasura client. + * Schema for validating client options for the The Graph client. */ export const ClientOptionsSchema = z.object({ instance: UrlSchema, - subgraph: z.string(), }); /** @@ -15,7 +14,7 @@ export const ClientOptionsSchema = z.object({ export type ClientOptions = z.infer; /** - * Schema for validating server client options for the Hasura client. + * Schema for validating server client options for the The Graph client. * Extends the ClientOptionsSchema with additional server-specific fields. */ export const ServerClientOptionsSchema = ClientOptionsSchema.extend({ diff --git a/packages/thegraph/src/thegraph.ts b/packages/thegraph/src/thegraph.ts index 7da13a239..a2c6125cb 100644 --- a/packages/thegraph/src/thegraph.ts +++ b/packages/thegraph/src/thegraph.ts @@ -2,7 +2,12 @@ import { ensureServer } from "@settlemint/sdk-utils/runtime"; import { validate } from "@settlemint/sdk-utils/validation"; import { type AbstractSetupSchema, initGraphQLTada } from "gql.tada"; import { GraphQLClient } from "graphql-request"; -import { type ClientOptions, ClientOptionsSchema, ServerClientOptionsSchema } from "./helpers/client-options.schema.js"; +import { + type ClientOptions, + ClientOptionsSchema, + type ServerClientOptions, + ServerClientOptionsSchema, +} from "./helpers/client-options.schema.js"; export type RequestConfig = ConstructorParameters[1]; @@ -35,10 +40,7 @@ export function createTheGraphClient( const graphql = initGraphQLTada(); return { - client: new GraphQLClient( - `${validatedOptions.instance}/subgraphs/name/${validatedOptions.subgraph}`, - requestConfig, - ), + client: new GraphQLClient(validatedOptions.instance, requestConfig), graphql, }; } @@ -65,7 +67,7 @@ export function createTheGraphClient( * }); */ export function createServerTheGraphClient( - options: ClientOptions, + options: ServerClientOptions, requestConfig?: RequestConfig, ) { ensureServer(); @@ -74,7 +76,7 @@ export function createServerTheGraphClient(); return { - client: new GraphQLClient(`${validatedOptions.instance}/subgraphs/name/${validatedOptions.subgraph}`, { + client: new GraphQLClient(validatedOptions.instance, { ...requestConfig, headers: { ...requestConfig?.headers,