Skip to content

Commit

Permalink
Make build output esm (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
flakey5 authored Apr 26, 2024
1 parent bd4b5fa commit b7fb651
Show file tree
Hide file tree
Showing 29 changed files with 101 additions and 134 deletions.
54 changes: 14 additions & 40 deletions ai-providers/azure.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { ReadableStream, ReadableByteStreamController, UnderlyingByteSource } from 'stream/web'
import { AiProvider, NoContentError, StreamChunkCallback } from './provider'
import { AiStreamEvent, encodeEvent } from './event'
import { AiProvider, NoContentError, StreamChunkCallback } from './provider.js'
import { AiStreamEvent, encodeEvent } from './event.js'
import { AzureKeyCredential, ChatCompletions, EventStream, OpenAIClient } from '@azure/openai'

// @ts-expect-error
type AzureEventStream<T> = import('@azure/openai').EventStream<T>
// @ts-expect-error
type AzureChatCompletions = import('@azure/openai').ChatCompletions

type AzureStreamResponse = AzureEventStream<AzureChatCompletions>
type AzureStreamResponse = EventStream<ChatCompletions>

class AzureByteSource implements UnderlyingByteSource {
type: 'bytes' = 'bytes'
response: AzureStreamResponse
reader?: ReadableStreamDefaultReader<AzureChatCompletions>
reader?: ReadableStreamDefaultReader<ChatCompletions>
chunkCallback?: StreamChunkCallback

constructor (response: AzureStreamResponse, chunkCallback?: StreamChunkCallback) {
Expand Down Expand Up @@ -84,33 +80,22 @@ interface AzureProviderCtorOptions {
}

export class AzureProvider implements AiProvider {
endpoint: string
deploymentName: string
apiKey: string
// @ts-expect-error typescript doesn't like this type import even though
// it's fine in the Mistral client?
client?: import('@azure/openai').OpenAIClient = undefined
allowInsecureConnections: boolean
client: OpenAIClient

constructor ({ endpoint, apiKey, deploymentName, allowInsecureConnections }: AzureProviderCtorOptions) {
this.endpoint = endpoint
this.apiKey = apiKey
this.deploymentName = deploymentName
this.allowInsecureConnections = allowInsecureConnections ?? false

this.client = new OpenAIClient(
endpoint,
new AzureKeyCredential(apiKey),
{
allowInsecureConnection: allowInsecureConnections
}
)
}

async ask (prompt: string): Promise<string> {
if (this.client === undefined) {
const { OpenAIClient, AzureKeyCredential } = await import('@azure/openai')
this.client = new OpenAIClient(
this.endpoint,
new AzureKeyCredential(this.apiKey),
{
allowInsecureConnection: this.allowInsecureConnections
}
)
}

const { choices } = await this.client.getChatCompletions(this.deploymentName, [
{ role: 'user', content: prompt }
])
Expand All @@ -128,17 +113,6 @@ export class AzureProvider implements AiProvider {
}

async askStream (prompt: string, chunkCallback?: StreamChunkCallback | undefined): Promise<ReadableStream> {
if (this.client === undefined) {
const { OpenAIClient, AzureKeyCredential } = await import('@azure/openai')
this.client = new OpenAIClient(
this.endpoint,
new AzureKeyCredential(this.apiKey),
{
allowInsecureConnection: this.allowInsecureConnections
}
)
}

const response = await this.client.streamChatCompletions(this.deploymentName, [
{ role: 'user', content: prompt }
])
Expand Down
21 changes: 5 additions & 16 deletions ai-providers/mistral.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReadableStream, UnderlyingByteSource, ReadableByteStreamController } from 'node:stream/web'
import { ChatCompletionResponseChunk } from '@platformatic/mistral-client'
import { AiProvider, NoContentError, StreamChunkCallback } from './provider'
import { AiStreamEvent, encodeEvent } from './event'
import MistralClient, { ChatCompletionResponseChunk } from '@platformatic/mistral-client'
import { AiProvider, NoContentError, StreamChunkCallback } from './provider.js'
import { AiStreamEvent, encodeEvent } from './event.js'

type MistralStreamResponse = AsyncGenerator<ChatCompletionResponseChunk, void, unknown>

Expand Down Expand Up @@ -59,20 +59,14 @@ interface MistralProviderCtorOptions {

export class MistralProvider implements AiProvider {
model: string
apiKey: string
client?: import('@platformatic/mistral-client').default = undefined
client: MistralClient

constructor ({ model, apiKey }: MistralProviderCtorOptions) {
this.model = model
this.apiKey = apiKey
this.client = new MistralClient(apiKey)
}

async ask (prompt: string): Promise<string> {
if (this.client === undefined) {
const { default: MistralClient } = await import('@platformatic/mistral-client')
this.client = new MistralClient(this.apiKey)
}

const response = await this.client.chat({
model: this.model,
messages: [
Expand All @@ -88,11 +82,6 @@ export class MistralProvider implements AiProvider {
}

async askStream (prompt: string, chunkCallback?: StreamChunkCallback): Promise<ReadableStream> {
if (this.client === undefined) {
const { default: MistralClient } = await import('@platformatic/mistral-client')
this.client = new MistralClient(this.apiKey)
}

const response = this.client.chatStream({
model: this.model,
messages: [
Expand Down
4 changes: 2 additions & 2 deletions ai-providers/ollama.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReadableStream, UnderlyingByteSource, ReadableByteStreamController } from 'stream/web'
import { Ollama, ChatResponse } from 'ollama'
import { AiProvider, StreamChunkCallback } from './provider'
import { AiStreamEvent, encodeEvent } from './event'
import { AiProvider, StreamChunkCallback } from './provider.js'
import { AiStreamEvent, encodeEvent } from './event.js'

type OllamaStreamResponse = AsyncGenerator<ChatResponse>

Expand Down
8 changes: 4 additions & 4 deletions ai-providers/open-ai.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ReadableStream, UnderlyingByteSource, ReadableByteStreamController } from 'node:stream/web'
import OpenAI from 'openai'
import { AiProvider, NoContentError, StreamChunkCallback } from './provider'
import { AiProvider, NoContentError, StreamChunkCallback } from './provider.js'
import { ReadableStream as ReadableStreamPolyfill } from 'web-streams-polyfill'
import { fetch } from 'undici'
import { ChatCompletionChunk } from 'openai/resources/index.mjs'
import { AiStreamEvent, encodeEvent } from './event'
import { ChatCompletionChunk } from 'openai/resources/index'
import { AiStreamEvent, encodeEvent } from './event.js'
import createError from '@fastify/error'

const InvalidTypeError = createError<string>('DESERIALIZING_ERROR', 'Deserializing error: %s', 500)
Expand Down Expand Up @@ -125,6 +125,6 @@ export class OpenAiProvider implements AiProvider {
],
stream: true
})
return new ReadableStream(new OpenAiByteSource(response.toReadableStream(), chunkCallback))
return new ReadableStream(new OpenAiByteSource(response.toReadableStream() as ReadableStreamPolyfill, chunkCallback))
}
}
2 changes: 1 addition & 1 deletion cli/create.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import { join } from 'node:path'
import { parseArgs } from 'node:util'
import { Generator } from '../lib/generator'
import { Generator } from '../lib/generator.js'

async function execute (): Promise<void> {
const args = parseArgs({
Expand Down
2 changes: 1 addition & 1 deletion cli/start.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env node
import stackable from '../index'
import stackable from '../index.js'
import { start } from '@platformatic/service'
import { printAndExitLoadConfigError } from '@platformatic/config'

Expand Down
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReadableStream } from 'node:stream/web'
import { PlatformaticApp } from '@platformatic/service'
import { errorResponseBuilderContext } from '@fastify/rate-limit'
import { AiWarpConfig } from './config'
import { AiWarpConfig } from './config.js'

declare module 'fastify' {
interface FastifyInstance {
Expand Down
16 changes: 8 additions & 8 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { platformaticService, Stackable } from '@platformatic/service'
import fastifyUser from 'fastify-user'
import fastifyPlugin from 'fastify-plugin'
import { schema } from './lib/schema'
import { Generator } from './lib/generator'
import { AiWarpConfig } from './config'
import warpPlugin from './plugins/warp'
import authPlugin from './plugins/auth'
import apiPlugin from './plugins/api'
import rateLimitPlugin from './plugins/rate-limiting'
import { schema } from './lib/schema.js'
import { Generator } from './lib/generator.js'
import { AiWarpConfig } from './config.js'
import warpPlugin from './plugins/warp.js'
import authPlugin from './plugins/auth.js'
import apiPlugin from './plugins/api.js'
import rateLimitPlugin from './plugins/rate-limiting.js'

const stackable: Stackable<AiWarpConfig> = async function (fastify, opts) {
const { config } = fastify.platformatic
await fastify.register(fastifyUser, config.auth)
await fastify.register(fastifyUser as any, config.auth)
await fastify.register(authPlugin, opts)

await fastify.register(warpPlugin, opts) // needs to be registered here for fastify.ai to be decorated
Expand Down
13 changes: 8 additions & 5 deletions lib/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { join } from 'node:path'
import { readFile } from 'node:fs/promises'
import { Generator as ServiceGenerator } from '@platformatic/service'
import { BaseGenerator } from '@platformatic/generators'
import { schema } from './schema'
import { generateGlobalTypesFile } from './templates/types'
import { generatePluginWithTypesSupport } from '@platformatic/generators/lib/create-plugin'
import { schema } from './schema.js'
import { generateGlobalTypesFile } from './templates/types.js'
import { generatePlugins } from '@platformatic/generators/lib/create-plugin.js'

interface PackageJson {
name: string
Expand All @@ -22,7 +22,7 @@ class AiWarpGenerator extends ServiceGenerator {
// TODO: temporary fix, when running the typescript files directly
// (in tests) this goes a directory above the actual project. Exposing
// temporarily until I come up with something better
aiWarpPackageJsonPath: join(__dirname, '..', '..', 'package.json')
aiWarpPackageJsonPath: join(import.meta.dirname, '..', '..', 'package.json')
}
return Object.assign({}, defaultBaseConfig, defaultConfig)
}
Expand Down Expand Up @@ -147,7 +147,10 @@ class AiWarpGenerator extends ServiceGenerator {
})

if (this.config.plugin !== undefined && this.config.plugin) {
this.addFile(generatePluginWithTypesSupport(this.config.typescript ?? false))
const plugins = generatePlugins(this.config.typescript ?? false)
for (const plugin of plugins) {
this.addFile(plugin)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,6 @@ const aiWarpSchema = {

export { aiWarpSchema as schema }

if (require.main === module) {
if (process.argv.length > 2 && process.argv[2] === '--dump-schema') {
console.log(JSON.stringify(aiWarpSchema, null, 2))
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
"name": "@platformatic/ai-warp",
"version": "0.0.1",
"main": "dist/index.js",
"type": "module",
"bin": {
"create-ai-warp": "./dist/cli/create.js",
"start-ai-warp": "./dist/cli/start.js"
},
"scripts": {
"build": "tsc --build",
"build:config": "node ./dist/lib/schema.js | json2ts > config.d.ts",
"build:config": "node ./dist/lib/schema.js --dump-schema | json2ts > config.d.ts",
"clean": "rm -fr ./dist",
"lint": "ts-standard | snazzy",
"lint:fix": "ts-standard --fix | snazzy",
Expand Down
2 changes: 1 addition & 1 deletion plugins/rate-limiting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { FastifyInstance } from 'fastify'
import createError from '@fastify/error'
import fastifyPlugin from 'fastify-plugin'
import fastifyRateLimit from '@fastify/rate-limit'
import { AiWarpConfig } from '../config'
import { AiWarpConfig } from '../config.js'

interface RateLimitMax {
// One claim to many values & maxes
Expand Down
10 changes: 5 additions & 5 deletions plugins/warp.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// eslint-disable-next-line
/// <reference path="../index.d.ts" />
import fastifyPlugin from 'fastify-plugin'
import { OpenAiProvider } from '../ai-providers/open-ai'
import { OpenAiProvider } from '../ai-providers/open-ai.js'
import { MistralProvider } from '../ai-providers/mistral.js'
import { AiProvider, StreamChunkCallback } from '../ai-providers/provider'
import { AiWarpConfig } from '../config'
import { AiProvider, StreamChunkCallback } from '../ai-providers/provider.js'
import { AiWarpConfig } from '../config.js'
import createError from '@fastify/error'
import { OllamaProvider } from '../ai-providers/ollama'
import { AzureProvider } from '../ai-providers/azure'
import { OllamaProvider } from '../ai-providers/ollama.js'
import { AzureProvider } from '../ai-providers/azure.js'

const UnknownAiProviderError = createError('UNKNOWN_AI_PROVIDER', 'Unknown AI Provider')

Expand Down
10 changes: 5 additions & 5 deletions tests/e2e/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { before, after, describe, it } from 'node:test'
import assert from 'node:assert'
import { FastifyInstance } from 'fastify'
import fastifyPlugin from 'fastify-plugin'
import { AiWarpConfig } from '../../config'
import { buildAiWarpApp } from '../utils/stackable'
import { AZURE_DEPLOYMENT_NAME, AZURE_MOCK_HOST } from '../utils/mocks/azure'
import { MOCK_CONTENT_RESPONSE, buildExpectedStreamBodyString } from '../utils/mocks/base'
import { OLLAMA_MOCK_HOST } from '../utils/mocks/ollama'
import { AiWarpConfig } from '../../config.js'
import { buildAiWarpApp } from '../utils/stackable.js'
import { AZURE_DEPLOYMENT_NAME, AZURE_MOCK_HOST } from '../utils/mocks/azure.js'
import { MOCK_CONTENT_RESPONSE, buildExpectedStreamBodyString } from '../utils/mocks/base.js'
import { OLLAMA_MOCK_HOST } from '../utils/mocks/ollama.js'

const expectedStreamBody = buildExpectedStreamBodyString()

Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/auth.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
import { it } from 'node:test'
import assert from 'node:assert'
import { buildAiWarpApp } from '../utils/stackable'
import { AiWarpConfig } from '../../config'
import { authConfig, createToken } from '../utils/auth'
import { buildAiWarpApp } from '../utils/stackable.js'
import { AiWarpConfig } from '../../config.js'
import { authConfig, createToken } from '../utils/auth.js'

const aiProvider: AiWarpConfig['aiProvider'] = {
openai: {
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import './api.test'
import './rate-limiting.test'
import './auth.test'
import { mockAllProviders } from '../utils/mocks'
import { mockAllProviders } from '../utils/mocks/index.js'

mockAllProviders()
6 changes: 3 additions & 3 deletions tests/e2e/rate-limiting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { it } from 'node:test'
import assert from 'node:assert'
import fastifyPlugin from 'fastify-plugin'
import { AiWarpConfig } from '../../config'
import { buildAiWarpApp } from '../utils/stackable'
import { authConfig, createToken } from '../utils/auth'
import { AiWarpConfig } from '../../config.js'
import { buildAiWarpApp } from '../utils/stackable.js'
import { authConfig, createToken } from '../utils/auth.js'

const aiProvider: AiWarpConfig['aiProvider'] = {
openai: {
Expand Down
2 changes: 1 addition & 1 deletion tests/types/fastify.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ReadableStream } from 'node:stream/web'
import { FastifyInstance, FastifyRequest } from 'fastify'
import { errorResponseBuilderContext } from '@fastify/rate-limit'
import { expectAssignable } from 'tsd'
import '../../index.d'
import '../../index.js'

expectAssignable<FastifyInstance['ai']['warp']>(async (_: FastifyRequest, _2: string) => '')

Expand Down
2 changes: 1 addition & 1 deletion tests/types/schema.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expectAssignable } from 'tsd'
import { AiWarpConfig } from '../../config'
import { AiWarpConfig } from '../../config.js'

expectAssignable<AiWarpConfig['aiProvider']>({
openai: {
Expand Down
16 changes: 8 additions & 8 deletions tests/unit/ai-providers.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
import { describe, it } from 'node:test'
import assert from 'node:assert'
import { MistralProvider } from '../../ai-providers/mistral'
import { OpenAiProvider } from '../../ai-providers/open-ai'
import { AiProvider } from '../../ai-providers/provider'
import { OllamaProvider } from '../../ai-providers/ollama'
import { AzureProvider } from '../../ai-providers/azure'
import { MOCK_CONTENT_RESPONSE, buildExpectedStreamBodyString } from '../utils/mocks/base'
import { OLLAMA_MOCK_HOST } from '../utils/mocks/ollama'
import { AZURE_DEPLOYMENT_NAME, AZURE_MOCK_HOST } from '../utils/mocks/azure'
import { MistralProvider } from '../../ai-providers/mistral.js'
import { OpenAiProvider } from '../../ai-providers/open-ai.js'
import { AiProvider } from '../../ai-providers/provider.js'
import { OllamaProvider } from '../../ai-providers/ollama.js'
import { AzureProvider } from '../../ai-providers/azure.js'
import { MOCK_CONTENT_RESPONSE, buildExpectedStreamBodyString } from '../utils/mocks/base.js'
import { OLLAMA_MOCK_HOST } from '../utils/mocks/ollama.js'
import { AZURE_DEPLOYMENT_NAME, AZURE_MOCK_HOST } from '../utils/mocks/azure.js'

const expectedStreamBody = buildExpectedStreamBodyString()

Expand Down
Loading

0 comments on commit b7fb651

Please sign in to comment.