diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44ce0cd..f6bb78c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,10 @@ on: - 'integrated/**' - 'stl-preview-head/**' - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' jobs: lint: diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b287fa5..1ebbce7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.0.0-alpha.18" + ".": "3.0.0-alpha.19" } diff --git a/.stats.yml b/.stats.yml index d8ed8fd..62d8721 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/supermemory--inc%2Fsupermemory-new-c56ce3c876eec0737db8394bd6235bff8dc42314b6460f3365c06945749d8714.yml -openapi_spec_hash: 9e633a8fe5c71fa8bd5cbc34073b7c52 -config_hash: 9126c561d449a28cea7267ac5773a0ed +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/supermemory--inc%2Fsupermemory-new-4c45e387cbdc7c80d75cdb8eb924cf92a3a48a0c10060fda917b83a7e454aef5.yml +openapi_spec_hash: c859ac2e3429ad3663337b99c722f317 +config_hash: 3b2810c1e7a7de95e23e3d2121374740 diff --git a/CHANGELOG.md b/CHANGELOG.md index c89fc26..917c369 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## 3.0.0-alpha.19 (2025-06-24) + +Full Changelog: [v3.0.0-alpha.18...v3.0.0-alpha.19](https://github.com/supermemoryai/sdk-ts/compare/v3.0.0-alpha.18...v3.0.0-alpha.19) + +### Features + +* **api:** api update ([7f31200](https://github.com/supermemoryai/sdk-ts/commit/7f312003f01cc5e7820d9d7169822b655366ebda)) +* **api:** api update ([fd23b75](https://github.com/supermemoryai/sdk-ts/commit/fd23b7509fc43f59b55ca98401b8293b940f748a)) +* **api:** api update ([ca755ef](https://github.com/supermemoryai/sdk-ts/commit/ca755efd0450f19b6780b11c5461bba7bac8b72f)) +* **client:** add support for endpoint-specific base URLs ([950b6e6](https://github.com/supermemoryai/sdk-ts/commit/950b6e66eb30a3908621bb64250d495b8187eab0)) + + +### Bug Fixes + +* **client:** explicitly copy fetch in withOptions ([ea7d42b](https://github.com/supermemoryai/sdk-ts/commit/ea7d42bf3e1cda451d587285a668b163674a34ef)) + + +### Chores + +* **ci:** enable for pull requests ([b9d3281](https://github.com/supermemoryai/sdk-ts/commit/b9d32816e77fe57348a5c07fd1b93ab387717753)) +* **client:** refactor imports ([ae245a4](https://github.com/supermemoryai/sdk-ts/commit/ae245a4cc035602bc89c5d8d0c1a94827d93ad72)) +* **readme:** update badges ([74cd982](https://github.com/supermemoryai/sdk-ts/commit/74cd982784564d11817fb8aaff756128a64e964c)) +* **readme:** use better example snippet for undocumented params ([76142a1](https://github.com/supermemoryai/sdk-ts/commit/76142a1abf13c4460d8716060200dc53d5c1b9be)) + + +### Refactors + +* **types:** replace Record with mapped types ([687fd59](https://github.com/supermemoryai/sdk-ts/commit/687fd59d82a8ab6b0b287e5c86fb69518008e96a)) + ## 3.0.0-alpha.18 (2025-06-14) Full Changelog: [v3.0.0-alpha.17...v3.0.0-alpha.18](https://github.com/supermemoryai/sdk-ts/compare/v3.0.0-alpha.17...v3.0.0-alpha.18) diff --git a/README.md b/README.md index bcb776c..b591495 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Supermemory TypeScript API Library -[![NPM version](https://img.shields.io/npm/v/supermemory.svg)](https://npmjs.org/package/supermemory) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/supermemory) +[![NPM version]()](https://npmjs.org/package/supermemory) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/supermemory) This library provides convenient access to the Supermemory REST API from server-side TypeScript or JavaScript. @@ -231,9 +231,8 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.foo.create({ - foo: 'my_param', - bar: 12, +client.search.execute({ + // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', }); diff --git a/package.json b/package.json index 0dc527a..08c4152 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "supermemory", - "version": "3.0.0-alpha.18", + "version": "3.0.0-alpha.19", "description": "The official TypeScript library for the Supermemory API", "author": "Supermemory ", "types": "dist/index.d.ts", @@ -42,7 +42,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "typescript": "5.8.3" }, diff --git a/src/client.ts b/src/client.ts index b857dbf..d1df32c 100644 --- a/src/client.ts +++ b/src/client.ts @@ -5,7 +5,6 @@ import type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestIni import { uuid4 } from './internal/utils/uuid'; import { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values'; import { sleep } from './internal/utils/sleep'; -import { type Logger, type LogLevel, parseLogLevel } from './internal/utils/log'; export type { Logger, LogLevel } from './internal/utils/log'; import { castToError, isAbortError } from './internal/errors'; import type { APIResponseProps } from './internal/parse'; @@ -17,9 +16,6 @@ import * as Errors from './core/error'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; -import { type Fetch } from './internal/builtin-types'; -import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; -import { FinalRequestOptions, RequestOptions } from './internal/request-options'; import { ConnectionCreateParams, ConnectionCreateResponse, @@ -52,8 +48,17 @@ import { SettingUpdateResponse, Settings, } from './resources/settings'; +import { type Fetch } from './internal/builtin-types'; +import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; +import { FinalRequestOptions, RequestOptions } from './internal/request-options'; import { readEnv } from './internal/utils/env'; -import { formatRequestDetails, loggerFor } from './internal/utils/log'; +import { + type LogLevel, + type Logger, + formatRequestDetails, + loggerFor, + parseLogLevel, +} from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; export interface ClientOptions { @@ -207,12 +212,20 @@ export class Supermemory { timeout: this.timeout, logger: this.logger, logLevel: this.logLevel, + fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, ...options, }); } + /** + * Check whether the base URL is set to its default. + */ + #baseURLOverridden(): boolean { + return this.baseURL !== 'https://api.supermemory.ai'; + } + protected defaultQuery(): Record | undefined { return this._options.defaultQuery; } @@ -262,11 +275,16 @@ export class Supermemory { return Errors.APIError.generate(status, error, message, headers); } - buildURL(path: string, query: Record | null | undefined): string { + buildURL( + path: string, + query: Record | null | undefined, + defaultBaseURL?: string | undefined, + ): string { + const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL; const url = isAbsoluteURL(path) ? new URL(path) - : new URL(this.baseURL + (this.baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); const defaultQuery = this.defaultQuery(); if (!isEmptyObj(defaultQuery)) { @@ -607,9 +625,9 @@ export class Supermemory { { retryCount = 0 }: { retryCount?: number } = {}, ): { req: FinalizedRequestInit; url: string; timeout: number } { const options = { ...inputOptions }; - const { method, path, query } = options; + const { method, path, query, defaultBaseURL } = options; - const url = this.buildURL(path!, query as Record); + const url = this.buildURL(path!, query as Record, defaultBaseURL); if ('timeout' in options) validatePositiveInteger('timeout', options.timeout); options.timeout = options.timeout ?? this.timeout; const { bodyHeaders, body } = this.buildBody({ options }); diff --git a/src/internal/request-options.ts b/src/internal/request-options.ts index d2ade9e..7de032f 100644 --- a/src/internal/request-options.ts +++ b/src/internal/request-options.ts @@ -20,6 +20,7 @@ export type RequestOptions = { fetchOptions?: MergedRequestInit; signal?: AbortSignal | undefined | null; idempotencyKey?: string; + defaultBaseURL?: string | undefined; __binaryResponse?: boolean | undefined; }; diff --git a/src/resources/connections.ts b/src/resources/connections.ts index 52a2be6..79ac86d 100644 --- a/src/resources/connections.ts +++ b/src/resources/connections.ts @@ -47,12 +47,13 @@ export class Connections extends APIResource { * ```ts * const response = await client.connections.deleteByProvider( * 'notion', + * { containerTags: ['user_123', 'project_123'] }, * ); * ``` */ deleteByProvider( provider: 'notion' | 'google-drive' | 'onedrive', - body: ConnectionDeleteByProviderParams | null | undefined = {}, + body: ConnectionDeleteByProviderParams, options?: RequestOptions, ): APIPromise { return this._client.delete(path`/v3/connections/${provider}`, { body, ...options }); @@ -156,24 +157,14 @@ export namespace ConnectionListResponse { expiresAt?: number; - metadata?: Record; + metadata?: { [key: string]: unknown }; } } export interface ConnectionDeleteByProviderResponse { - deletedConnections: Array; - - deletedCount: number; - - success: boolean; -} - -export namespace ConnectionDeleteByProviderResponse { - export interface DeletedConnection { - id: string; + id: string; - provider: string; - } + provider: string; } export interface ConnectionGetByIDResponse { @@ -189,7 +180,7 @@ export interface ConnectionGetByIDResponse { expiresAt?: number; - metadata?: Record; + metadata?: { [key: string]: unknown }; } export interface ConnectionGetByTagsResponse { @@ -205,7 +196,7 @@ export interface ConnectionGetByTagsResponse { expiresAt?: number; - metadata?: Record; + metadata?: { [key: string]: unknown }; } export type ConnectionListDocumentsResponse = @@ -234,7 +225,7 @@ export interface ConnectionCreateParams { documentLimit?: number; - metadata?: Record | null; + metadata?: { [key: string]: string | number | boolean } | null; redirectUrl?: string; } @@ -250,7 +241,7 @@ export interface ConnectionDeleteByProviderParams { /** * Optional comma-separated list of container tags to filter connections by */ - containerTags?: Array; + containerTags: Array; } export interface ConnectionGetByTagsParams { diff --git a/src/resources/memories.ts b/src/resources/memories.ts index aadfa85..00483f0 100644 --- a/src/resources/memories.ts +++ b/src/resources/memories.ts @@ -132,7 +132,7 @@ export namespace MemoryListResponse { * case sensitive. Values can be strings, numbers, or booleans. You cannot nest * objects. */ - metadata: string | number | boolean | Record | Array | null; + metadata: string | number | boolean | { [key: string]: unknown } | Array | null; /** * Status of the memory @@ -162,7 +162,8 @@ export namespace MemoryListResponse { | 'image' | 'video' | 'notion_doc' - | 'webpage'; + | 'webpage' + | 'onedrive'; /** * Last update timestamp @@ -241,7 +242,7 @@ export interface MemoryGetResponse { * case sensitive. Values can be strings, numbers, or booleans. You cannot nest * objects. */ - metadata: string | number | boolean | Record | Array | null; + metadata: string | number | boolean | { [key: string]: unknown } | Array | null; ogImage: string | null; @@ -278,7 +279,8 @@ export interface MemoryGetResponse { | 'image' | 'video' | 'notion_doc' - | 'webpage'; + | 'webpage' + | 'onedrive'; /** * Last update timestamp @@ -334,7 +336,7 @@ export interface MemoryUpdateParams { * case sensitive. Values can be strings, numbers, or booleans. You cannot nest * objects. */ - metadata?: Record; + metadata?: { [key: string]: string | number | boolean }; } export interface MemoryListParams { @@ -402,7 +404,7 @@ export interface MemoryAddParams { * case sensitive. Values can be strings, numbers, or booleans. You cannot nest * objects. */ - metadata?: Record; + metadata?: { [key: string]: string | number | boolean }; } export declare namespace Memories { diff --git a/src/resources/search.ts b/src/resources/search.ts index ecd2476..b79ee23 100644 --- a/src/resources/search.ts +++ b/src/resources/search.ts @@ -48,7 +48,7 @@ export namespace SearchExecuteResponse { /** * Document metadata */ - metadata: Record | null; + metadata: { [key: string]: unknown } | null; /** * Relevance score of the match @@ -134,7 +134,7 @@ export interface SearchExecuteParams { /** * Optional filters to apply to the search */ - filters?: SearchExecuteParams.UnionMember0 | Record; + filters?: SearchExecuteParams.UnionMember0 | { [key: string]: unknown }; /** * If true, include full document in the response. This is helpful if you want a diff --git a/src/resources/settings.ts b/src/resources/settings.ts index ca7ab5b..12ed781 100644 --- a/src/resources/settings.ts +++ b/src/resources/settings.ts @@ -33,40 +33,94 @@ export interface SettingUpdateResponse { export namespace SettingUpdateResponse { export interface Updated { - excludeItems?: Array; + excludeItems?: string | number | boolean | { [key: string]: unknown } | Array | null; - filterPrompt?: string; + filterPrompt?: string | null; - filterTags?: Record>; + filterTags?: string | number | boolean | { [key: string]: unknown } | Array | null; - includeItems?: Array; + googleDriveClientId?: string | null; - shouldLLMFilter?: boolean; + googleDriveClientSecret?: string | null; + + googleDriveCustomKeyEnabled?: boolean | null; + + includeItems?: string | number | boolean | { [key: string]: unknown } | Array | null; + + notionClientId?: string | null; + + notionClientSecret?: string | null; + + notionCustomKeyEnabled?: boolean | null; + + onedriveClientId?: string | null; + + onedriveClientSecret?: string | null; + + onedriveCustomKeyEnabled?: boolean | null; + + shouldLLMFilter?: boolean | null; } } export interface SettingGetResponse { - excludeItems?: Array; + excludeItems?: string | number | boolean | { [key: string]: unknown } | Array | null; + + filterPrompt?: string | null; + + filterTags?: string | number | boolean | { [key: string]: unknown } | Array | null; + + googleDriveClientId?: string | null; + + googleDriveClientSecret?: string | null; + + googleDriveCustomKeyEnabled?: boolean | null; - filterPrompt?: string; + includeItems?: string | number | boolean | { [key: string]: unknown } | Array | null; - filterTags?: Record>; + notionClientId?: string | null; - includeItems?: Array; + notionClientSecret?: string | null; - shouldLLMFilter?: boolean; + notionCustomKeyEnabled?: boolean | null; + + onedriveClientId?: string | null; + + onedriveClientSecret?: string | null; + + onedriveCustomKeyEnabled?: boolean | null; + + shouldLLMFilter?: boolean | null; } export interface SettingUpdateParams { - excludeItems?: Array; + excludeItems?: string | number | boolean | { [key: string]: unknown } | Array | null; + + filterPrompt?: string | null; + + filterTags?: string | number | boolean | { [key: string]: unknown } | Array | null; + + googleDriveClientId?: string | null; + + googleDriveClientSecret?: string | null; + + googleDriveCustomKeyEnabled?: boolean | null; + + includeItems?: string | number | boolean | { [key: string]: unknown } | Array | null; + + notionClientId?: string | null; + + notionClientSecret?: string | null; + + notionCustomKeyEnabled?: boolean | null; - filterPrompt?: string; + onedriveClientId?: string | null; - filterTags?: Record>; + onedriveClientSecret?: string | null; - includeItems?: Array; + onedriveCustomKeyEnabled?: boolean | null; - shouldLLMFilter?: boolean; + shouldLLMFilter?: boolean | null; } export declare namespace Settings { diff --git a/src/version.ts b/src/version.ts index fc25925..c49ee06 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '3.0.0-alpha.18'; // x-release-please-version +export const VERSION = '3.0.0-alpha.19'; // x-release-please-version diff --git a/tests/api-resources/connections.test.ts b/tests/api-resources/connections.test.ts index a328534..7e44e17 100644 --- a/tests/api-resources/connections.test.ts +++ b/tests/api-resources/connections.test.ts @@ -61,8 +61,10 @@ describe('resource connections', () => { }); // skipped: tests are disabled for the time being - test.skip('deleteByProvider', async () => { - const responsePromise = client.connections.deleteByProvider('notion'); + test.skip('deleteByProvider: only required params', async () => { + const responsePromise = client.connections.deleteByProvider('notion', { + containerTags: ['user_123', 'project_123'], + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -73,15 +75,10 @@ describe('resource connections', () => { }); // skipped: tests are disabled for the time being - test.skip('deleteByProvider: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.connections.deleteByProvider( - 'notion', - { containerTags: ['user_123', 'project_123'] }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Supermemory.NotFoundError); + test.skip('deleteByProvider: required and optional params', async () => { + const response = await client.connections.deleteByProvider('notion', { + containerTags: ['user_123', 'project_123'], + }); }); // skipped: tests are disabled for the time being diff --git a/tests/api-resources/settings.test.ts b/tests/api-resources/settings.test.ts index c984b99..3b258cc 100644 --- a/tests/api-resources/settings.test.ts +++ b/tests/api-resources/settings.test.ts @@ -26,10 +26,19 @@ describe('resource settings', () => { await expect( client.settings.update( { - excludeItems: ['x'], - filterPrompt: 'x', - filterTags: { foo: ['string'] }, - includeItems: ['x'], + excludeItems: 'string', + filterPrompt: 'filterPrompt', + filterTags: 'string', + googleDriveClientId: 'googleDriveClientId', + googleDriveClientSecret: 'googleDriveClientSecret', + googleDriveCustomKeyEnabled: true, + includeItems: 'string', + notionClientId: 'notionClientId', + notionClientSecret: 'notionClientSecret', + notionCustomKeyEnabled: true, + onedriveClientId: 'onedriveClientId', + onedriveClientSecret: 'onedriveClientSecret', + onedriveCustomKeyEnabled: true, shouldLLMFilter: true, }, { path: '/_stainless_unknown_path' }, diff --git a/tests/index.test.ts b/tests/index.test.ts index b626a0d..21b43d2 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -314,6 +314,28 @@ describe('instantiate client', () => { const client = new Supermemory({ apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://api.supermemory.ai'); }); + + test('in request options', () => { + const client = new Supermemory({ apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/option/foo', + ); + }); + + test('in request options overridden by client options', () => { + const client = new Supermemory({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/client/foo', + ); + }); + + test('in request options overridden by env variable', () => { + process.env['SUPERMEMORY_BASE_URL'] = 'http://localhost:5000/env'; + const client = new Supermemory({ apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/env/foo', + ); + }); }); test('maxRetries option is correctly set', () => { diff --git a/yarn.lock b/yarn.lock index c611c53..58c08d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3283,9 +3283,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz": - version "1.1.7" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.7/tsc-multi.tgz#52f40adf8b808bd0b633346d11cc4a8aeea465cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz": + version "1.1.8" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04" dependencies: debug "^4.3.7" fast-glob "^3.3.2"