kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: tiny kitty feet stomping around
rodzic
c7064c6f47
commit
817e726044
|
@ -1,4 +1,5 @@
|
||||||
import { assert, parseZodSchema, pick, sha256 } from '@agentic/platform-core'
|
import { assert, parseZodSchema, pick, sha256 } from '@agentic/platform-core'
|
||||||
|
import { validateOriginAdapter } from '@agentic/platform-schemas'
|
||||||
import { validators } from '@agentic/platform-validators'
|
import { validators } from '@agentic/platform-validators'
|
||||||
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
||||||
|
|
||||||
|
@ -7,7 +8,6 @@ import { db, eq, schema } from '@/db'
|
||||||
import { acl } from '@/lib/acl'
|
import { acl } from '@/lib/acl'
|
||||||
import { normalizeDeploymentVersion } from '@/lib/deployments/normalize-deployment-version'
|
import { normalizeDeploymentVersion } from '@/lib/deployments/normalize-deployment-version'
|
||||||
import { publishDeployment } from '@/lib/deployments/publish-deployment'
|
import { publishDeployment } from '@/lib/deployments/publish-deployment'
|
||||||
import { validateDeploymentOriginAdapter } from '@/lib/deployments/validate-deployment-origin-adapter'
|
|
||||||
import { ensureAuthUser } from '@/lib/ensure-auth-user'
|
import { ensureAuthUser } from '@/lib/ensure-auth-user'
|
||||||
import {
|
import {
|
||||||
openapiAuthenticatedSecuritySchemas,
|
openapiAuthenticatedSecuritySchemas,
|
||||||
|
@ -99,10 +99,10 @@ export function registerV1DeploymentsCreateDeployment(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate OpenAPI originUrl and originAdapter
|
// Validate origin config, including any OpenAPI or MCP specs
|
||||||
await validateDeploymentOriginAdapter({
|
await validateOriginAdapter({
|
||||||
...pick(body, 'originUrl', 'originAdapter'),
|
...pick(body, 'originUrl', 'originAdapter'),
|
||||||
deploymentIdentifier,
|
label: `deployment "${deploymentIdentifier}"`,
|
||||||
logger
|
logger
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -137,8 +137,7 @@ export async function upsertStripePricing({
|
||||||
|
|
||||||
// Upsert the Stripe Price
|
// Upsert the Stripe Price
|
||||||
if (!project._stripePriceIdMap[pricingPlanLineItemHashForStripePrice]) {
|
if (!project._stripePriceIdMap[pricingPlanLineItemHashForStripePrice]) {
|
||||||
const interval =
|
const interval = pricingPlan.interval ?? project.defaultPricingInterval
|
||||||
pricingPlanLineItem.interval ?? project.defaultPricingInterval
|
|
||||||
|
|
||||||
const nickname = [
|
const nickname = [
|
||||||
'price',
|
'price',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { assert } from '@agentic/platform-core'
|
import { assert, type Logger } from '@agentic/platform-core'
|
||||||
import * as Sentry from '@sentry/node'
|
import * as Sentry from '@sentry/node'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
|
@ -7,14 +7,6 @@ import { env } from '@/lib/env'
|
||||||
|
|
||||||
import { getTraceId } from './utils'
|
import { getTraceId } from './utils'
|
||||||
|
|
||||||
export interface Logger {
|
|
||||||
trace(message?: any, ...detail: any[]): void
|
|
||||||
debug(message?: any, ...detail: any[]): void
|
|
||||||
info(message?: any, ...detail: any[]): void
|
|
||||||
warn(message?: any, ...detail: any[]): void
|
|
||||||
error(message?: any, ...detail: any[]): void
|
|
||||||
}
|
|
||||||
|
|
||||||
const rawLogLevels = ['trace', 'debug', 'info', 'warn', 'error'] as const
|
const rawLogLevels = ['trace', 'debug', 'info', 'warn', 'error'] as const
|
||||||
export const logLevelsSchema = z.enum(rawLogLevels)
|
export const logLevelsSchema = z.enum(rawLogLevels)
|
||||||
export type LogLevel = z.infer<typeof logLevelsSchema>
|
export type LogLevel = z.infer<typeof logLevelsSchema>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
import type { Logger } from '@agentic/platform-core'
|
||||||
import { vi } from 'vitest'
|
import { vi } from 'vitest'
|
||||||
|
|
||||||
import type { Logger } from '@/lib/logger'
|
|
||||||
|
|
||||||
export function setupMockLogger() {
|
export function setupMockLogger() {
|
||||||
return {
|
return {
|
||||||
trace: vi.fn(),
|
trace: vi.fn(),
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
import type { Logger } from '@agentic/platform-core'
|
||||||
import type { Context } from 'hono'
|
import type { Context } from 'hono'
|
||||||
|
|
||||||
import type { RawTeamMember, RawUser } from '@/db'
|
import type { RawTeamMember, RawUser } from '@/db'
|
||||||
|
|
||||||
import type { Env } from './env'
|
import type { Env } from './env'
|
||||||
import type { Logger } from './logger'
|
|
||||||
|
|
||||||
export type Environment = Env['NODE_ENV']
|
export type Environment = Env['NODE_ENV']
|
||||||
export type Service = 'api'
|
export type Service = 'api'
|
||||||
|
|
|
@ -54,15 +54,15 @@ exports[`loadAgenticConfig > basic-raw-free-ts 1`] = `
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`loadAgenticConfig > invalid: invalid-name-0 1`] = `[ZodValidationError: Validation error: Invalid project name "Test Invalid Name 0". Must be lower kebab-case with no spaces between 2 and 64 characters. at "name"]`;
|
exports[`loadAgenticConfig > invalid: invalid-name-0 1`] = `[Error: Invalid project name "Test Invalid Name 0". Must be lower kebab-case with no spaces between 2 and 64 characters. Example: "my-project" or "linkedin-resolver-23"]`;
|
||||||
|
|
||||||
exports[`loadAgenticConfig > invalid: invalid-name-1 1`] = `[ZodValidationError: Validation error: Invalid project name "Test-Invalid-Name-1". Must be lower kebab-case with no spaces between 2 and 64 characters. at "name"]`;
|
exports[`loadAgenticConfig > invalid: invalid-name-1 1`] = `[Error: Invalid project name "Test-Invalid-Name-1". Must be lower kebab-case with no spaces between 2 and 64 characters. Example: "my-project" or "linkedin-resolver-23"]`;
|
||||||
|
|
||||||
exports[`loadAgenticConfig > invalid: invalid-name-2 1`] = `[ZodValidationError: Validation error: Invalid project name "test_invalid_name_2". Must be lower kebab-case with no spaces between 2 and 64 characters. at "name"]`;
|
exports[`loadAgenticConfig > invalid: invalid-name-2 1`] = `[Error: Invalid project name "test_invalid_name_2". Must be lower kebab-case with no spaces between 2 and 64 characters. Example: "my-project" or "linkedin-resolver-23"]`;
|
||||||
|
|
||||||
exports[`loadAgenticConfig > invalid: invalid-name-3 1`] = `[ZodValidationError: Validation error: Required at "name"]`;
|
exports[`loadAgenticConfig > invalid: invalid-name-3 1`] = `[ZodValidationError: Validation error: Required at "name"]`;
|
||||||
|
|
||||||
exports[`loadAgenticConfig > invalid: invalid-name-4 1`] = `[ZodValidationError: Validation error: Invalid project name "@foo/bar". Must be lower kebab-case with no spaces between 2 and 64 characters. at "name"]`;
|
exports[`loadAgenticConfig > invalid: invalid-name-4 1`] = `[Error: Invalid project name "@foo/bar". Must be lower kebab-case with no spaces between 2 and 64 characters. Example: "my-project" or "linkedin-resolver-23"]`;
|
||||||
|
|
||||||
exports[`loadAgenticConfig > invalid: invalid-origin-url-0 1`] = `[Error: Invalid originUrl: must be a valid https URL]`;
|
exports[`loadAgenticConfig > invalid: invalid-origin-url-0 1`] = `[Error: Invalid originUrl: must be a valid https URL]`;
|
||||||
|
|
||||||
|
@ -124,7 +124,6 @@ exports[`loadAgenticConfig > pricing-3-plans 1`] = `
|
||||||
"lineItems": [
|
"lineItems": [
|
||||||
{
|
{
|
||||||
"amount": 999,
|
"amount": 999,
|
||||||
"interval": "month",
|
|
||||||
"slug": "base",
|
"slug": "base",
|
||||||
"usageType": "licensed",
|
"usageType": "licensed",
|
||||||
},
|
},
|
||||||
|
@ -142,7 +141,6 @@ exports[`loadAgenticConfig > pricing-3-plans 1`] = `
|
||||||
"lineItems": [
|
"lineItems": [
|
||||||
{
|
{
|
||||||
"amount": 2999,
|
"amount": 2999,
|
||||||
"interval": "month",
|
|
||||||
"slug": "base",
|
"slug": "base",
|
||||||
"usageType": "licensed",
|
"usageType": "licensed",
|
||||||
},
|
},
|
||||||
|
@ -183,13 +181,11 @@ exports[`loadAgenticConfig > pricing-custom-0 1`] = `
|
||||||
"lineItems": [
|
"lineItems": [
|
||||||
{
|
{
|
||||||
"amount": 500,
|
"amount": 500,
|
||||||
"interval": "month",
|
|
||||||
"slug": "base",
|
"slug": "base",
|
||||||
"usageType": "licensed",
|
"usageType": "licensed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"billingScheme": "per_unit",
|
"billingScheme": "per_unit",
|
||||||
"interval": "month",
|
|
||||||
"rateLimit": {
|
"rateLimit": {
|
||||||
"interval": 2592000,
|
"interval": 2592000,
|
||||||
"maxPerInterval": 1000,
|
"maxPerInterval": 1000,
|
||||||
|
@ -207,13 +203,11 @@ exports[`loadAgenticConfig > pricing-custom-0 1`] = `
|
||||||
"lineItems": [
|
"lineItems": [
|
||||||
{
|
{
|
||||||
"amount": 4800,
|
"amount": 4800,
|
||||||
"interval": "year",
|
|
||||||
"slug": "base",
|
"slug": "base",
|
||||||
"usageType": "licensed",
|
"usageType": "licensed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"billingScheme": "per_unit",
|
"billingScheme": "per_unit",
|
||||||
"interval": "year",
|
|
||||||
"rateLimit": {
|
"rateLimit": {
|
||||||
"interval": 2592000,
|
"interval": 2592000,
|
||||||
"maxPerInterval": 1500,
|
"maxPerInterval": 1500,
|
||||||
|
@ -258,7 +252,6 @@ exports[`loadAgenticConfig > pricing-freemium 1`] = `
|
||||||
"lineItems": [
|
"lineItems": [
|
||||||
{
|
{
|
||||||
"amount": 499,
|
"amount": 499,
|
||||||
"interval": "month",
|
|
||||||
"slug": "base",
|
"slug": "base",
|
||||||
"usageType": "licensed",
|
"usageType": "licensed",
|
||||||
},
|
},
|
||||||
|
@ -300,7 +293,6 @@ exports[`loadAgenticConfig > pricing-monthly-annual 1`] = `
|
||||||
"lineItems": [
|
"lineItems": [
|
||||||
{
|
{
|
||||||
"amount": 100,
|
"amount": 100,
|
||||||
"interval": "month",
|
|
||||||
"slug": "custom",
|
"slug": "custom",
|
||||||
"usageType": "licensed",
|
"usageType": "licensed",
|
||||||
},
|
},
|
||||||
|
@ -313,7 +305,6 @@ exports[`loadAgenticConfig > pricing-monthly-annual 1`] = `
|
||||||
"lineItems": [
|
"lineItems": [
|
||||||
{
|
{
|
||||||
"amount": 70,
|
"amount": 70,
|
||||||
"interval": "year",
|
|
||||||
"slug": "custom",
|
"slug": "custom",
|
||||||
"usageType": "licensed",
|
"usageType": "licensed",
|
||||||
},
|
},
|
||||||
|
@ -363,7 +354,6 @@ exports[`loadAgenticConfig > pricing-pay-as-you-go 1`] = `
|
||||||
"lineItems": [
|
"lineItems": [
|
||||||
{
|
{
|
||||||
"billingScheme": "tiered",
|
"billingScheme": "tiered",
|
||||||
"interval": "month",
|
|
||||||
"slug": "requests",
|
"slug": "requests",
|
||||||
"tiers": [
|
"tiers": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import type { AgenticProjectConfigOutput } from '@agentic/platform-schemas'
|
import {
|
||||||
|
type AgenticProjectConfig,
|
||||||
|
validateAgenticProjectConfig
|
||||||
|
} from '@agentic/platform-schemas'
|
||||||
import { loadConfig } from 'unconfig'
|
import { loadConfig } from 'unconfig'
|
||||||
|
|
||||||
import { validateAgenticConfig } from './validate-agentic-config'
|
|
||||||
|
|
||||||
export async function loadAgenticConfig({
|
export async function loadAgenticConfig({
|
||||||
cwd
|
cwd
|
||||||
}: {
|
}: {
|
||||||
cwd?: string
|
cwd?: string
|
||||||
}): Promise<AgenticProjectConfigOutput> {
|
}): Promise<AgenticProjectConfig> {
|
||||||
const { config } = await loadConfig({
|
const { config } = await loadConfig({
|
||||||
cwd,
|
cwd,
|
||||||
sources: [
|
sources: [
|
||||||
|
@ -18,5 +19,5 @@ export async function loadAgenticConfig({
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
return validateAgenticConfig(config)
|
return validateAgenticProjectConfig(config)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export * from './errors'
|
export * from './errors'
|
||||||
|
export type * from './types'
|
||||||
export * from './utils'
|
export * from './utils'
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { expectTypeOf, test } from 'vitest'
|
||||||
|
|
||||||
|
import type { Logger } from './types'
|
||||||
|
|
||||||
|
test('Logger type is compatible with Console', () => {
|
||||||
|
expectTypeOf<Console>().toExtend<Logger>()
|
||||||
|
})
|
|
@ -0,0 +1,7 @@
|
||||||
|
export interface Logger {
|
||||||
|
trace(message?: any, ...detail: any[]): void
|
||||||
|
debug(message?: any, ...detail: any[]): void
|
||||||
|
info(message?: any, ...detail: any[]): void
|
||||||
|
warn(message?: any, ...detail: any[]): void
|
||||||
|
error(message?: any, ...detail: any[]): void
|
||||||
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
export type Logger = Pick<Console, 'debug' | 'info' | 'warn' | 'error'>
|
|
||||||
|
|
||||||
// These loose OpenAPI types are taken from https://github.com/openapi-ts/openapi-typescript/blob/main/packages/openapi-typescript/src/types.ts
|
// These loose OpenAPI types are taken from https://github.com/openapi-ts/openapi-typescript/blob/main/packages/openapi-typescript/src/types.ts
|
||||||
|
|
||||||
// Note: these OpenAPI types are meant only for internal use, not external
|
// Note: these OpenAPI types are meant only for internal use, not external
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
import { assert, parseJson } from '@agentic/platform-core'
|
import { assert, type Logger, parseJson } from '@agentic/platform-core'
|
||||||
import {
|
import {
|
||||||
BaseResolver,
|
BaseResolver,
|
||||||
bundle,
|
bundle,
|
||||||
|
@ -12,7 +12,7 @@ import {
|
||||||
Source
|
Source
|
||||||
} from '@redocly/openapi-core'
|
} from '@redocly/openapi-core'
|
||||||
|
|
||||||
import type { Logger, LooseOpenAPI3Spec } from './types'
|
import type { LooseOpenAPI3Spec } from './types'
|
||||||
import { getDefaultRedoclyConfig } from './redocly-config'
|
import { getDefaultRedoclyConfig } from './redocly-config'
|
||||||
|
|
||||||
interface ParseSchemaOptions {
|
interface ParseSchemaOptions {
|
||||||
|
|
|
@ -23,11 +23,14 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@agentic/platform-core": "workspace:*",
|
"@agentic/platform-core": "workspace:*",
|
||||||
|
"@agentic/platform-openapi": "workspace:*",
|
||||||
"@agentic/platform-validators": "workspace:*",
|
"@agentic/platform-validators": "workspace:*",
|
||||||
"@hono/zod-openapi": "^0.19.6",
|
"@hono/zod-openapi": "^0.19.6",
|
||||||
|
"ms": "^2.1.3",
|
||||||
"zod": "catalog:"
|
"zod": "catalog:"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/ms": "^2.1.0",
|
||||||
"restore-cursor": "catalog:",
|
"restore-cursor": "catalog:",
|
||||||
"zod-to-json-schema": "^3.24.5"
|
"zod-to-json-schema": "^3.24.5"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,280 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft-07/schema",
|
|
||||||
"title": "Agentic Project Config Schema",
|
|
||||||
"description": "JSON Schema used by `agentic.config.{ts,js,json}` files to configure Agentic projects.",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the project."
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A one-sentence description of the project."
|
|
||||||
},
|
|
||||||
"readme": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A readme documenting the project (supports GitHub-flavored markdown)."
|
|
||||||
},
|
|
||||||
"sourceUrl": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri",
|
|
||||||
"description": "Optional URL to the source code for the project."
|
|
||||||
},
|
|
||||||
"iconUrl": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri",
|
|
||||||
"description": "Optional logo image URL to use for the project. Logos should have a square aspect ratio."
|
|
||||||
},
|
|
||||||
"originUrl": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri",
|
|
||||||
"description": "Required base URL of the externally hosted origin API server. Must be a valid `https` URL.\n\nNOTE: Agentic currently only supports `external` API servers. If you'd like to host your API or MCP server on Agentic's infrastructure, please reach out to support@agentic.so."
|
|
||||||
},
|
|
||||||
"originAdapter": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "openapi"
|
|
||||||
},
|
|
||||||
"spec": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "JSON stringified OpenAPI spec describing the origin API server."
|
|
||||||
},
|
|
||||||
"location": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "external"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["type", "spec", "location"],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "raw"
|
|
||||||
},
|
|
||||||
"location": {
|
|
||||||
"$ref": "#/properties/originAdapter/anyOf/0/properties/location"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["type", "location"],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Deployment origin API adapter is used to configure the origin API server downstream from Agentic's API gateway. It specifies whether the origin API server denoted by `originUrl` is hosted externally or deployed internally to Agentic's infrastructure. It also specifies the format for how origin tools / services are defined: either as an OpenAPI spec, an MCP server, or as a raw HTTP REST API.\n\nNOTE: Agentic currently only supports `external` API servers. If you'd like to host your API or MCP server on Agentic's infrastructure, please reach out to support@agentic.so.",
|
|
||||||
"default": {
|
|
||||||
"location": "external",
|
|
||||||
"type": "raw"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pricingPlans": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1
|
|
||||||
},
|
|
||||||
"slug": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "PricingPlan slug (\"free\", \"starter-monthly\", \"pro-annual\", etc)"
|
|
||||||
},
|
|
||||||
"interval": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["day", "week", "month", "year"],
|
|
||||||
"description": "The frequency at which a subscription is billed."
|
|
||||||
},
|
|
||||||
"desc": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"features": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"trialPeriodDays": {
|
|
||||||
"type": "number",
|
|
||||||
"minimum": 0
|
|
||||||
},
|
|
||||||
"lineItems": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"slug": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"const": "base"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"const": "requests"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"interval": {
|
|
||||||
"$ref": "#/properties/pricingPlans/items/properties/interval",
|
|
||||||
"description": "The frequency at which a subscription is billed."
|
|
||||||
},
|
|
||||||
"label": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"usageType": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "licensed"
|
|
||||||
},
|
|
||||||
"amount": {
|
|
||||||
"type": "number",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["slug", "usageType", "amount"],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"slug": {
|
|
||||||
"$ref": "#/properties/pricingPlans/items/properties/lineItems/items/anyOf/0/properties/slug"
|
|
||||||
},
|
|
||||||
"interval": {
|
|
||||||
"$ref": "#/properties/pricingPlans/items/properties/lineItems/items/anyOf/0/properties/interval"
|
|
||||||
},
|
|
||||||
"label": {
|
|
||||||
"$ref": "#/properties/pricingPlans/items/properties/lineItems/items/anyOf/0/properties/label"
|
|
||||||
},
|
|
||||||
"usageType": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "metered"
|
|
||||||
},
|
|
||||||
"unitLabel": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"rateLimit": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"interval": {
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"maxPerInterval": {
|
|
||||||
"type": "number"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["interval", "maxPerInterval"],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"billingScheme": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["per_unit", "tiered"]
|
|
||||||
},
|
|
||||||
"unitAmount": {
|
|
||||||
"type": "number",
|
|
||||||
"minimum": 0
|
|
||||||
},
|
|
||||||
"tiersMode": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["graduated", "volume"]
|
|
||||||
},
|
|
||||||
"tiers": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"unitAmount": {
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"flatAmount": {
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
"upTo": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "number"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"const": "inf"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["upTo"],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultAggregation": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"formula": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["sum", "count", "last"],
|
|
||||||
"default": "sum"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"transformQuantity": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"divideBy": {
|
|
||||||
"type": "number",
|
|
||||||
"exclusiveMinimum": 0
|
|
||||||
},
|
|
||||||
"round": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["down", "up"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["divideBy", "round"],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["slug", "usageType", "billingScheme"],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PricingPlanLineItems represent a single line-item in a Stripe Subscription. They map to a Stripe billing `Price` and possibly a corresponding Stripe `Meter` for metered usage."
|
|
||||||
},
|
|
||||||
"minItems": 1,
|
|
||||||
"maxItems": 20
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["name", "slug", "lineItems"],
|
|
||||||
"additionalProperties": false,
|
|
||||||
"description": "Represents the config for a Stripe subscription with one or more PricingPlanLineItems."
|
|
||||||
},
|
|
||||||
"minItems": 1,
|
|
||||||
"description": "List of PricingPlans to enable subscriptions for the project. Defaults to a single free tier.",
|
|
||||||
"default": [
|
|
||||||
{
|
|
||||||
"name": "Free",
|
|
||||||
"slug": "free",
|
|
||||||
"lineItems": [
|
|
||||||
{
|
|
||||||
"slug": "base",
|
|
||||||
"usageType": "licensed",
|
|
||||||
"amount": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["name", "originUrl"]
|
|
||||||
}
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { validators } from '@agentic/platform-validators'
|
|
||||||
import { z } from '@hono/zod-openapi'
|
import { z } from '@hono/zod-openapi'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -39,15 +38,7 @@ export const agenticProjectConfigSchema = z.object({
|
||||||
* @example "my-project"
|
* @example "my-project"
|
||||||
* @example "linkedin-resolver-23"
|
* @example "linkedin-resolver-23"
|
||||||
*/
|
*/
|
||||||
name: z
|
name: z.string().nonempty().describe('Name of the project.'),
|
||||||
.string()
|
|
||||||
.describe('Name of the project.')
|
|
||||||
.refine(
|
|
||||||
(name) => validators.projectName(name),
|
|
||||||
(name) => ({
|
|
||||||
message: `Invalid project name "${name}". Must be lower kebab-case with no spaces between 2 and 64 characters.`
|
|
||||||
})
|
|
||||||
),
|
|
||||||
|
|
||||||
/** Optional short description of the project. */
|
/** Optional short description of the project. */
|
||||||
description: z
|
description: z
|
||||||
|
@ -111,9 +102,9 @@ NOTE: Agentic currently only supports \`external\` API servers. If you'd like to
|
||||||
* Note that for every pricing interval, you must define a corresponding set
|
* Note that for every pricing interval, you must define a corresponding set
|
||||||
* of PricingPlans in the `pricingPlans` array. If you only have one pricing
|
* of PricingPlans in the `pricingPlans` array. If you only have one pricing
|
||||||
* interval (like the default `month` interval), `pricingPlans` don't need to
|
* interval (like the default `month` interval), `pricingPlans` don't need to
|
||||||
* specify their `interval` property. Otherwise, all PricingPlans and
|
* specify their `interval` property. Otherwise, all PricingPlans must
|
||||||
* LineItems must specify their `interval` property to differentiate between
|
* specify their `interval` property to differentiate between different
|
||||||
* different pricing intervals.
|
* pricing intervals.
|
||||||
*/
|
*/
|
||||||
pricingIntervals: z
|
pricingIntervals: z
|
||||||
.array(pricingIntervalSchema)
|
.array(pricingIntervalSchema)
|
||||||
|
@ -127,6 +118,4 @@ NOTE: Agentic currently only supports \`external\` API servers. If you'd like to
|
||||||
export type AgenticProjectConfigInput = z.input<
|
export type AgenticProjectConfigInput = z.input<
|
||||||
typeof agenticProjectConfigSchema
|
typeof agenticProjectConfigSchema
|
||||||
>
|
>
|
||||||
export type AgenticProjectConfigOutput = z.output<
|
export type AgenticProjectConfig = z.output<typeof agenticProjectConfigSchema>
|
||||||
typeof agenticProjectConfigSchema
|
|
||||||
>
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { parseZodSchema } from '@agentic/platform-core'
|
import { parseZodSchema } from '@agentic/platform-core'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
type AgenticProjectConfig,
|
||||||
type AgenticProjectConfigInput,
|
type AgenticProjectConfigInput,
|
||||||
type AgenticProjectConfigOutput,
|
|
||||||
agenticProjectConfigSchema
|
agenticProjectConfigSchema
|
||||||
} from './agentic-project-config-schema'
|
} from './agentic-project-config-schema'
|
||||||
|
|
||||||
export function defineConfig(
|
export function defineConfig(
|
||||||
config: AgenticProjectConfigInput
|
config: AgenticProjectConfigInput
|
||||||
): AgenticProjectConfigOutput {
|
): AgenticProjectConfig {
|
||||||
return parseZodSchema(agenticProjectConfigSchema, config)
|
return parseZodSchema(agenticProjectConfigSchema, config)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
export * from './agentic-project-config-schema'
|
export * from './agentic-project-config-schema'
|
||||||
export * from './define-config'
|
export * from './define-config'
|
||||||
export * from './schemas'
|
export * from './schemas'
|
||||||
|
export * from './validate-agentic-project-config'
|
||||||
|
export * from './validate-origin-adapter'
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { z } from '@hono/zod-openapi'
|
import { z } from '@hono/zod-openapi'
|
||||||
|
import parseIntervalAsMs from 'ms'
|
||||||
|
|
||||||
export const webhookSchema = z
|
export const webhookSchema = z
|
||||||
.object({
|
.object({
|
||||||
|
@ -13,10 +14,55 @@ export type Webhook = z.infer<typeof webhookSchema>
|
||||||
*/
|
*/
|
||||||
export const rateLimitSchema = z
|
export const rateLimitSchema = z
|
||||||
.object({
|
.object({
|
||||||
interval: z.number(), // seconds
|
/**
|
||||||
maxPerInterval: z.number() // unitless
|
* The interval at which the rate limit is applied.
|
||||||
|
*
|
||||||
|
* Either a number in seconds or a valid [ms](https://github.com/vercel/ms)
|
||||||
|
* string (eg, `10s`, `1m`, `1h`, `1d`, `1w`, `1y`, etc).
|
||||||
|
*/
|
||||||
|
interval: z.union([
|
||||||
|
z.number().nonnegative(), // seconds
|
||||||
|
z
|
||||||
|
.string()
|
||||||
|
.nonempty()
|
||||||
|
.transform((value, ctx) => {
|
||||||
|
try {
|
||||||
|
// TODO: `ms` module has broken types
|
||||||
|
const ms = parseIntervalAsMs(value as any) as unknown as number
|
||||||
|
|
||||||
|
if (typeof ms !== 'number' || ms < 0) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
message: `Invalid interval "${value}"`,
|
||||||
|
path: ctx.path
|
||||||
|
})
|
||||||
|
|
||||||
|
return z.NEVER
|
||||||
|
}
|
||||||
|
|
||||||
|
const seconds = Math.floor(ms / 1000)
|
||||||
|
return seconds
|
||||||
|
} catch {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
message: `Invalid interval "${value}"`,
|
||||||
|
path: ctx.path
|
||||||
|
})
|
||||||
|
|
||||||
|
return z.NEVER
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of operations per interval (unitless).
|
||||||
|
*/
|
||||||
|
maxPerInterval: z
|
||||||
|
.number()
|
||||||
|
.describe('Maximum number of operations per interval (unitless).')
|
||||||
})
|
})
|
||||||
.openapi('RateLimit')
|
.openapi('RateLimit')
|
||||||
|
export type RateLimitInput = z.input<typeof rateLimitSchema>
|
||||||
export type RateLimit = z.infer<typeof rateLimitSchema>
|
export type RateLimit = z.infer<typeof rateLimitSchema>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,21 +155,13 @@ const commonPricingPlanLineItemSchema = z.object({
|
||||||
*
|
*
|
||||||
* The `base` slug is reserved for a plan's default `licensed` line-item.
|
* The `base` slug is reserved for a plan's default `licensed` line-item.
|
||||||
*
|
*
|
||||||
* The `requests` slug is reserved for charging using `metered billing based
|
* The `requests` slug is reserved for charging using `metered` billing based
|
||||||
* on the number of request made during a given billing interval.
|
* on the number of request made during a given billing interval.
|
||||||
*
|
*
|
||||||
* All other PricingPlanLineItem `slugs` are considered custom LineItems.
|
* All other PricingPlanLineItem `slugs` are considered custom LineItems.
|
||||||
*/
|
*/
|
||||||
slug: z.union([z.string(), z.literal('base'), z.literal('requests')]),
|
slug: z.union([z.string(), z.literal('base'), z.literal('requests')]),
|
||||||
|
|
||||||
/**
|
|
||||||
* The frequency at which a subscription is billed.
|
|
||||||
*
|
|
||||||
* Only optional on free plans (when `PricingPlan.slug` is `free`), since
|
|
||||||
* free plans don't depend on a billing interval.
|
|
||||||
*/
|
|
||||||
interval: pricingIntervalSchema.optional(),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional label for the line-item which will be displayed on customer bills.
|
* Optional label for the line-item which will be displayed on customer bills.
|
||||||
*
|
*
|
||||||
|
@ -317,7 +355,7 @@ export const pricingPlanSchema = z
|
||||||
.openapi('slug', { example: 'starter-monthly' }),
|
.openapi('slug', { example: 'starter-monthly' }),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The frequency at which a subscription is billed.
|
* The frequency at which this subscription is billed.
|
||||||
*/
|
*/
|
||||||
interval: pricingIntervalSchema.optional(),
|
interval: pricingIntervalSchema.optional(),
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { z } from '@hono/zod-openapi'
|
||||||
|
|
||||||
export const authProviderTypeSchema = z
|
export const authProviderTypeSchema = z
|
||||||
.union([
|
.union([
|
||||||
z.literal('github'),
|
z.literal('github'),
|
||||||
|
|
|
@ -1,22 +1,30 @@
|
||||||
import type { ZodTypeDef } from 'zod'
|
import type { ZodTypeDef } from 'zod'
|
||||||
import { assert, parseZodSchema } from '@agentic/platform-core'
|
import { assert, type Logger, parseZodSchema } from '@agentic/platform-core'
|
||||||
import {
|
import { validators } from '@agentic/platform-validators'
|
||||||
type AgenticProjectConfigInput,
|
|
||||||
type AgenticProjectConfigOutput,
|
|
||||||
agenticProjectConfigSchema,
|
|
||||||
type PricingPlanLineItem
|
|
||||||
} from '@agentic/platform-schemas'
|
|
||||||
|
|
||||||
export async function validateAgenticConfig(
|
import type { PricingPlanLineItem } from './schemas'
|
||||||
inputConfig: unknown
|
import {
|
||||||
): Promise<AgenticProjectConfigOutput> {
|
type AgenticProjectConfig,
|
||||||
|
type AgenticProjectConfigInput,
|
||||||
|
agenticProjectConfigSchema
|
||||||
|
} from './agentic-project-config-schema'
|
||||||
|
import { validateOriginAdapter } from './validate-origin-adapter'
|
||||||
|
|
||||||
|
export async function validateAgenticProjectConfig(
|
||||||
|
inputConfig: unknown,
|
||||||
|
opts: { logger?: Logger; cwd?: URL } = {}
|
||||||
|
): Promise<AgenticProjectConfig> {
|
||||||
const config = parseZodSchema<
|
const config = parseZodSchema<
|
||||||
AgenticProjectConfigOutput,
|
AgenticProjectConfig,
|
||||||
ZodTypeDef,
|
ZodTypeDef,
|
||||||
AgenticProjectConfigInput
|
AgenticProjectConfigInput
|
||||||
>(agenticProjectConfigSchema, inputConfig)
|
>(agenticProjectConfigSchema, inputConfig)
|
||||||
|
|
||||||
const { pricingIntervals, pricingPlans, originUrl } = config
|
const { name, pricingIntervals, pricingPlans, originUrl } = config
|
||||||
|
assert(
|
||||||
|
validators.projectName(name),
|
||||||
|
`Invalid project name "${name}". Must be lower kebab-case with no spaces between 2 and 64 characters. Example: "my-project" or "linkedin-resolver-23"`
|
||||||
|
)
|
||||||
assert(
|
assert(
|
||||||
pricingPlans?.length,
|
pricingPlans?.length,
|
||||||
'Invalid pricingPlans: must be a non-empty array'
|
'Invalid pricingPlans: must be a non-empty array'
|
||||||
|
@ -67,20 +75,6 @@ export async function validateAgenticConfig(
|
||||||
pricingPlan.interval !== undefined,
|
pricingPlan.interval !== undefined,
|
||||||
`Invalid pricingPlan "${pricingPlan.slug}": non-free PricingPlan "${pricingPlan.slug}" must specify an "interval" because the project supports multiple pricing intervals.`
|
`Invalid pricingPlan "${pricingPlan.slug}": non-free PricingPlan "${pricingPlan.slug}" must specify an "interval" because the project supports multiple pricing intervals.`
|
||||||
)
|
)
|
||||||
|
|
||||||
for (const lineItem of pricingPlan.lineItems) {
|
|
||||||
lineItem.interval ??= pricingPlan.interval
|
|
||||||
|
|
||||||
assert(
|
|
||||||
lineItem.interval === pricingPlan.interval,
|
|
||||||
`Invalid pricingPlan "${pricingPlan.slug}": non-free PricingPlan "${pricingPlan.slug}" LineItem "${lineItem.slug}" "interval" must match the PricingPlan interval "${pricingPlan.interval}" because the project supports multiple pricing intervals.`
|
|
||||||
)
|
|
||||||
|
|
||||||
assert(
|
|
||||||
pricingIntervalsSet.has(lineItem.interval),
|
|
||||||
`Invalid pricingPlan "${pricingPlan.slug}": PricingPlan "${pricingPlan.slug}" LineItem "${lineItem.slug}" has invalid interval "${pricingPlan.interval}" which is not included in the "pricingIntervals" array.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Only a single pricing interval is supported, so default all pricing
|
// Only a single pricing interval is supported, so default all pricing
|
||||||
|
@ -102,15 +96,6 @@ export async function validateAgenticConfig(
|
||||||
if (pricingPlan.slug === 'free') continue
|
if (pricingPlan.slug === 'free') continue
|
||||||
|
|
||||||
pricingPlan.interval ??= defaultPricingInterval
|
pricingPlan.interval ??= defaultPricingInterval
|
||||||
|
|
||||||
for (const lineItem of pricingPlan.lineItems) {
|
|
||||||
lineItem.interval ??= defaultPricingInterval
|
|
||||||
|
|
||||||
assert(
|
|
||||||
pricingIntervalsSet.has(lineItem.interval),
|
|
||||||
`Invalid pricingPlan "${pricingPlan.slug}": PricingPlan "${pricingPlan.slug}" LineItem "${lineItem.slug}" has invalid interval "${pricingPlan.interval}" which is not included in the "pricingIntervals" array.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,5 +199,12 @@ export async function validateAgenticConfig(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await validateOriginAdapter({
|
||||||
|
...opts,
|
||||||
|
label: `project "${name}"`,
|
||||||
|
originUrl,
|
||||||
|
originAdapter: config.originAdapter
|
||||||
|
})
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
|
@ -1,40 +1,37 @@
|
||||||
import type { DeploymentOriginAdapter } from '@agentic/platform-schemas'
|
import type { DeploymentOriginAdapter } from '@agentic/platform-schemas'
|
||||||
import { assert } from '@agentic/platform-core'
|
import { assert, type Logger } from '@agentic/platform-core'
|
||||||
import { validateOpenAPISpec } from '@agentic/platform-openapi'
|
import { validateOpenAPISpec } from '@agentic/platform-openapi'
|
||||||
|
|
||||||
import type { Logger } from '@/lib/logger'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates and normalizes the origin adapter config for a deployment.
|
* Validates and normalizes the origin adapter config for a project.
|
||||||
*
|
*
|
||||||
* NOTE: This method may mutate `originAdapter.spec`.
|
* NOTE: This method may mutate `originAdapter.spec`.
|
||||||
*/
|
*/
|
||||||
export async function validateDeploymentOriginAdapter({
|
export async function validateOriginAdapter({
|
||||||
deploymentIdentifier,
|
|
||||||
originUrl,
|
originUrl,
|
||||||
originAdapter,
|
originAdapter,
|
||||||
|
label,
|
||||||
|
cwd,
|
||||||
logger
|
logger
|
||||||
}: {
|
}: {
|
||||||
deploymentIdentifier: string
|
|
||||||
originUrl: string
|
originUrl: string
|
||||||
originAdapter: DeploymentOriginAdapter
|
originAdapter: DeploymentOriginAdapter
|
||||||
logger: Logger
|
label: string
|
||||||
|
cwd?: URL
|
||||||
|
logger?: Logger
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
assert(
|
assert(originUrl, 400, `Origin URL is required for ${label}`)
|
||||||
originUrl,
|
|
||||||
400,
|
|
||||||
`Origin URL is required for deployment "${deploymentIdentifier}"`
|
|
||||||
)
|
|
||||||
|
|
||||||
if (originAdapter.type === 'openapi') {
|
if (originAdapter.type === 'openapi') {
|
||||||
assert(
|
assert(
|
||||||
originAdapter.spec,
|
originAdapter.spec,
|
||||||
400,
|
400,
|
||||||
`OpenAPI spec is required for deployment "${deploymentIdentifier}" with origin adapter type set to "openapi"`
|
`OpenAPI spec is required for ${label} with origin adapter type set to "openapi"`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Validate and normalize the OpenAPI spec
|
// Validate and normalize the OpenAPI spec
|
||||||
const openapiSpec = await validateOpenAPISpec(originAdapter.spec, {
|
const openapiSpec = await validateOpenAPISpec(originAdapter.spec, {
|
||||||
|
cwd,
|
||||||
logger
|
logger
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -54,7 +51,7 @@ export async function validateDeploymentOriginAdapter({
|
||||||
assert(
|
assert(
|
||||||
originAdapter.type === 'raw',
|
originAdapter.type === 'raw',
|
||||||
400,
|
400,
|
||||||
`Invalid origin adapter type "${originAdapter.type}" for deployment "${deploymentIdentifier}"`
|
`Invalid origin adapter type "${originAdapter.type}" for ${label}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -325,16 +325,25 @@ importers:
|
||||||
'@agentic/platform-core':
|
'@agentic/platform-core':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../core
|
version: link:../core
|
||||||
|
'@agentic/platform-openapi':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../openapi
|
||||||
'@agentic/platform-validators':
|
'@agentic/platform-validators':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../validators
|
version: link:../validators
|
||||||
'@hono/zod-openapi':
|
'@hono/zod-openapi':
|
||||||
specifier: ^0.19.6
|
specifier: ^0.19.6
|
||||||
version: 0.19.6(hono@4.7.9)(zod@3.24.4)
|
version: 0.19.6(hono@4.7.9)(zod@3.24.4)
|
||||||
|
ms:
|
||||||
|
specifier: ^2.1.3
|
||||||
|
version: 2.1.3
|
||||||
zod:
|
zod:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 3.24.4
|
version: 3.24.4
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@types/ms':
|
||||||
|
specifier: ^2.1.0
|
||||||
|
version: 2.1.0
|
||||||
restore-cursor:
|
restore-cursor:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 5.1.0
|
version: 5.1.0
|
||||||
|
@ -1415,6 +1424,9 @@ packages:
|
||||||
'@types/json5@0.0.29':
|
'@types/json5@0.0.29':
|
||||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||||
|
|
||||||
|
'@types/ms@2.1.0':
|
||||||
|
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||||
|
|
||||||
'@types/mysql@2.15.26':
|
'@types/mysql@2.15.26':
|
||||||
resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==}
|
resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==}
|
||||||
|
|
||||||
|
@ -5080,6 +5092,8 @@ snapshots:
|
||||||
|
|
||||||
'@types/json5@0.0.29': {}
|
'@types/json5@0.0.29': {}
|
||||||
|
|
||||||
|
'@types/ms@2.1.0': {}
|
||||||
|
|
||||||
'@types/mysql@2.15.26':
|
'@types/mysql@2.15.26':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.15.18
|
'@types/node': 22.15.18
|
||||||
|
|
Ładowanie…
Reference in New Issue