diff --git a/apps/e2e/demo-e2e-dts-consumer/e2e/dts-consumer.e2e.spec.ts b/apps/e2e/demo-e2e-dts-consumer/e2e/dts-consumer.e2e.spec.ts index 4506f6da4..8b27a2547 100644 --- a/apps/e2e/demo-e2e-dts-consumer/e2e/dts-consumer.e2e.spec.ts +++ b/apps/e2e/demo-e2e-dts-consumer/e2e/dts-consumer.e2e.spec.ts @@ -26,6 +26,7 @@ function toFixtureDiagnostic(diagnostic: ts.Diagnostic): FixtureDiagnostic { const fixtureFiles = [ 'provider-lifecycle-must-compile.ts', + 'sqlite-storage-must-compile.ts', 'tool-must-fail.ts', 'prompts-must-compile.ts', 'hooks-must-compile.ts', @@ -104,6 +105,10 @@ describe('@frontmcp/sdk declarations in a strict consumer project', () => { expect(describeEach(inFixtureFile('provider-lifecycle-must-compile.ts'))).toEqual([]); }); + it('types sqliteStorageProvider() and the storage SqliteStorageToken resolves to', () => { + expect(describeEach(inFixtureFile('sqlite-storage-must-compile.ts'))).toEqual([]); + }); + it('accepts the documented @Prompt forms', () => { expect(describeEach(inFixtureFile('prompts-must-compile.ts'))).toEqual([]); }); diff --git a/apps/e2e/demo-e2e-dts-consumer/fixture/sqlite-storage-must-compile.ts b/apps/e2e/demo-e2e-dts-consumer/fixture/sqlite-storage-must-compile.ts new file mode 100644 index 000000000..cf5996bb9 --- /dev/null +++ b/apps/e2e/demo-e2e-dts-consumer/fixture/sqlite-storage-must-compile.ts @@ -0,0 +1,43 @@ +import 'reflect-metadata'; + +import { + App, + createContainer, + FrontMcp, + sqliteStorageProvider, + SqliteStorageToken, + type SqliteStorageProviderOptions, +} from '@frontmcp/sdk'; + +const options: SqliteStorageProviderOptions = { + path: '/var/lib/counter/state.sqlite', + walMode: true, + busyTimeoutMs: 10_000, + prefix: 'counter:', +}; + +@App({ name: 'counter' }) +class CounterApp {} + +@FrontMcp({ + info: { name: 'sqlite-storage', version: '1.0.0' }, + apps: [CounterApp], + providers: [sqliteStorageProvider(options)], +}) +export class SqliteStorageServer {} + +// @ts-expect-error the database file's path is required +sqliteStorageProvider({ walMode: true }); + +// @ts-expect-error walMode is a boolean +sqliteStorageProvider({ path: '/var/lib/counter/state.sqlite', walMode: 'yes' }); + +export async function countVisit(): Promise { + const container = await createContainer({ providers: [sqliteStorageProvider(options)] }); + try { + const visits: number = await container.get(SqliteStorageToken).incr('visits'); + return visits; + } finally { + await container.dispose(); + } +} diff --git a/apps/e2e/demo-e2e-dts-consumer/fixture/tsconfig.json b/apps/e2e/demo-e2e-dts-consumer/fixture/tsconfig.json index 5333653fe..3947979dd 100644 --- a/apps/e2e/demo-e2e-dts-consumer/fixture/tsconfig.json +++ b/apps/e2e/demo-e2e-dts-consumer/fixture/tsconfig.json @@ -12,6 +12,7 @@ }, "files": [ "provider-lifecycle-must-compile.ts", + "sqlite-storage-must-compile.ts", "tool-must-fail.ts", "prompts-must-compile.ts", "hooks-must-compile.ts", diff --git a/apps/e2e/demo-e2e-local-runtime/e2e/helpers/workers.ts b/apps/e2e/demo-e2e-local-runtime/e2e/helpers/workers.ts new file mode 100644 index 000000000..bb97a0c69 --- /dev/null +++ b/apps/e2e/demo-e2e-local-runtime/e2e/helpers/workers.ts @@ -0,0 +1,80 @@ +/** Start fixture scripts that follow `fixture/worker-protocol.ts` and drive them line by line from a spec. */ +import { spawn, type ChildProcess } from 'node:child_process'; +import { join } from 'node:path'; + +const projectRoot = join(__dirname, '..', '..'); + +export interface Worker { + readonly child: ChildProcess; + /** Resolves when the worker prints `line`; rejects if it exits first. */ + waitFor(line: string): Promise; + send(line: string): void; + /** What the worker reported; rejects when it exits with a code other than 0. */ + readonly result: Promise; +} + +/** Run `fixture/