use generated contract

This commit is contained in:
Stephen Zhou 2026-04-30 15:32:19 +08:00
parent eb60ddc35f
commit e62e7951cd
No known key found for this signature in database
33 changed files with 8629 additions and 682 deletions

View File

@ -15,6 +15,7 @@ export default antfu(
'!package.json',
'!pnpm-workspace.yaml',
'!vite.config.ts',
'web/contract/generated/**',
...original,
],
typescript: {

174
pnpm-lock.yaml generated
View File

@ -48,6 +48,9 @@ catalogs:
'@heroicons/react':
specifier: 2.2.0
version: 2.2.0
'@hey-api/openapi-ts':
specifier: 0.97.0
version: 0.97.0
'@hono/node-server':
specifier: 2.0.0
version: 2.0.0
@ -1125,6 +1128,9 @@ importers:
'@eslint-react/eslint-plugin':
specifier: 'catalog:'
version: 3.0.0(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)
'@hey-api/openapi-ts':
specifier: 'catalog:'
version: 0.97.0(magicast@0.5.2)(typescript@6.0.3)
'@hono/node-server':
specifier: 'catalog:'
version: 2.0.0(hono@4.12.15)
@ -2072,6 +2078,31 @@ packages:
peerDependencies:
react: '>= 16 || ^19.0.0-rc'
'@hey-api/codegen-core@0.8.1':
resolution: {integrity: sha512-Iciv2vUCJTW9lWM/ROvyZLblmcbYJHPuXfzb1SzeDVVn4xEXu2ilLU1pq3fn+09FZ/Y0P7VyvRE47UDU6om8xA==}
engines: {node: '>=22.13.0'}
'@hey-api/json-schema-ref-parser@1.4.1':
resolution: {integrity: sha512-DoPJGxVApDlktP1yYLjmOrF0YBEqb32ieCbx1S1i09n8TyCgdoh4yQaQ3kp0sMTauH+bwNKPsFh7S8qiWCoKZA==}
engines: {node: '>=22.13.0'}
'@hey-api/openapi-ts@0.97.0':
resolution: {integrity: sha512-WZkKgrDlZpxKlDv2HkBCzaAYeuM+EtZKFmKGBv9/JblAKpX3JQTROi7PzlCZE3eisetRPSakbcRgn+LGyB7EiQ==}
engines: {node: '>=22.13.0'}
hasBin: true
peerDependencies:
typescript: '>=5.5.3 || >=6.0.0 || 6.0.1-rc'
'@hey-api/shared@0.4.2':
resolution: {integrity: sha512-4fconS10E0Xr4/acV8G+BkApxaIStxrT0GhB9BDTQWvrFTy5/nV933SyFk8qImcbpKvgv9hpn3N+7bV8oFrbjA==}
engines: {node: '>=22.13.0'}
'@hey-api/spec-types@0.2.0':
resolution: {integrity: sha512-ibQ8Is7evMavzr8GNyJCcTg975d8DpaMUyLmOrQ85UBdy1l6t1KuRAwgChAbesJsIlNV6gjmlXruWyegDX18Fg==}
'@hey-api/types@0.1.4':
resolution: {integrity: sha512-thWfawrDIP7wSI9ioT13I5soaaqB5vAPIiZmgD8PbeEVKNrkonc0N/Sjj97ezl7oQgusZmaNphGdMKipPO6IBg==}
'@hono/node-server@2.0.0':
resolution: {integrity: sha512-n3GfHwwCvHCkGmOwKfxUPOlbfzuO64Sbc5XC4NGPIXxkuOnJrdgExdRKmHfF924r914WRJPT397GdqLvdYTeyQ==}
engines: {node: '>=20'}
@ -2294,6 +2325,9 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
'@jsdevtools/ono@7.1.3':
resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==}
'@lexical/clipboard@0.44.0':
resolution: {integrity: sha512-nfmNIs7uENqlDI7cm2E4I1Yp8mDJGMhEQIrIV2rNWnL1oeHVXQ7yuYdyoPdcY1zuj/9nvkYBQYUEh0QiGwpETA==}
@ -2369,6 +2403,10 @@ packages:
peerDependencies:
yjs: '>=13.5.22'
'@lukeed/ms@2.0.2':
resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==}
engines: {node: '>=8'}
'@mdx-js/loader@3.1.1':
resolution: {integrity: sha512-0TTacJyZ9mDmY+VefuthVshaNIyCGZHJG2fMnGaDttCt8HmjUF7SizlHJpaCDoGnN635nK1wpzfpx/Xx5S4WnQ==}
peerDependencies:
@ -4653,6 +4691,10 @@ packages:
ajv@6.14.0:
resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==}
ansi-colors@4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'}
ansi-regex@4.1.1:
resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==}
engines: {node: '>=6'}
@ -4792,6 +4834,14 @@ packages:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'}
c12@3.3.4:
resolution: {integrity: sha512-cM0ApFQSBXuourJejzwv/AuPRvAxordTyParRVcHjjtXirtkzM0uK2L9TTn9s0cXZbG7E55jCivRQzoxYmRAlA==}
peerDependencies:
magicast: '*'
peerDependenciesMeta:
magicast:
optional: true
cac@7.0.0:
resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==}
engines: {node: '>=20.19.0'}
@ -4858,6 +4908,10 @@ packages:
chevrotain@11.1.2:
resolution: {integrity: sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==}
chokidar@5.0.0:
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
engines: {node: '>= 20.19.0'}
chownr@1.1.4:
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
@ -4931,6 +4985,10 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
color-support@1.1.3:
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
hasBin: true
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
@ -5250,6 +5308,9 @@ packages:
resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
engines: {node: '>=12'}
defu@6.1.7:
resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
delaunator@5.1.0:
resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==}
@ -5257,6 +5318,9 @@ packages:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
destr@2.0.5:
resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@ -5309,6 +5373,10 @@ packages:
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
engines: {node: '>=12'}
dotenv@17.4.2:
resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==}
engines: {node: '>=12'}
echarts-for-react@3.0.6:
resolution: {integrity: sha512-4zqLgTGWS3JvkQDXjzkR1k1CHRdpd6by0988TWMJgnvDytegWLbeP/VNZmMa+0VJx2eD7Y632bi2JquXDgiGJg==}
peerDependencies:
@ -5893,6 +5961,10 @@ packages:
get-tsconfig@4.14.0:
resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==}
giget@3.2.0:
resolution: {integrity: sha512-GvHTWcykIR/fP8cj8dMpuMMkvaeJfPvYnhq0oW+chSeIr+ldX21ifU2Ms6KBoyKZQZmVaUAAhQ2EZ68KJF8a7A==}
hasBin: true
github-from-package@0.0.0:
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
@ -7137,6 +7209,9 @@ packages:
resolution: {integrity: sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA==}
engines: {node: '>=14.18.0'}
rc9@3.0.1:
resolution: {integrity: sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ==}
rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
@ -7310,6 +7385,10 @@ packages:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
readdirp@5.0.0:
resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
engines: {node: '>= 20.19.0'}
recast@0.23.11:
resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==}
engines: {node: '>= 4'}
@ -9332,6 +9411,56 @@ snapshots:
dependencies:
react: 19.2.5
'@hey-api/codegen-core@0.8.1(magicast@0.5.2)':
dependencies:
'@hey-api/types': 0.1.4
ansi-colors: 4.1.3
c12: 3.3.4(magicast@0.5.2)
color-support: 1.1.3
transitivePeerDependencies:
- magicast
'@hey-api/json-schema-ref-parser@1.4.1':
dependencies:
'@jsdevtools/ono': 7.1.3
'@types/json-schema': 7.0.15
yaml: 2.8.3
'@hey-api/openapi-ts@0.97.0(magicast@0.5.2)(typescript@6.0.3)':
dependencies:
'@hey-api/codegen-core': 0.8.1(magicast@0.5.2)
'@hey-api/json-schema-ref-parser': 1.4.1
'@hey-api/shared': 0.4.2(magicast@0.5.2)
'@hey-api/spec-types': 0.2.0
'@hey-api/types': 0.1.4
'@lukeed/ms': 2.0.2
ansi-colors: 4.1.3
color-support: 1.1.3
commander: 14.0.3
get-tsconfig: 4.14.0
typescript: 6.0.3
transitivePeerDependencies:
- magicast
'@hey-api/shared@0.4.2(magicast@0.5.2)':
dependencies:
'@hey-api/codegen-core': 0.8.1(magicast@0.5.2)
'@hey-api/json-schema-ref-parser': 1.4.1
'@hey-api/spec-types': 0.2.0
'@hey-api/types': 0.1.4
ansi-colors: 4.1.3
cross-spawn: 7.0.6
open: 11.0.0
semver: 7.7.4
transitivePeerDependencies:
- magicast
'@hey-api/spec-types@0.2.0':
dependencies:
'@hey-api/types': 0.1.4
'@hey-api/types@0.1.4': {}
'@hono/node-server@2.0.0(hono@4.12.15)':
dependencies:
hono: 4.12.15
@ -9517,6 +9646,8 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@jsdevtools/ono@7.1.3': {}
'@lexical/clipboard@0.44.0':
dependencies:
'@lexical/extension': 0.44.0
@ -9669,6 +9800,8 @@ snapshots:
'@lexical/selection': 0.44.0
lexical: 0.44.0
'@lukeed/ms@2.0.2': {}
'@mdx-js/loader@3.1.1':
dependencies:
'@mdx-js/mdx': 3.1.1
@ -11863,6 +11996,8 @@ snapshots:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
ansi-colors@4.1.3: {}
ansi-regex@4.1.1: {}
ansi-regex@5.0.1: {}
@ -11977,6 +12112,23 @@ snapshots:
bytes@3.1.2: {}
c12@3.3.4(magicast@0.5.2):
dependencies:
chokidar: 5.0.0
confbox: 0.2.4
defu: 6.1.7
dotenv: 17.4.2
exsolve: 1.0.8
giget: 3.2.0
jiti: 2.6.1
ohash: 2.0.11
pathe: 2.0.3
perfect-debounce: 2.1.0
pkg-types: 2.3.0
rc9: 3.0.1
optionalDependencies:
magicast: 0.5.2
cac@7.0.0: {}
camelize@1.0.1: {}
@ -12064,6 +12216,10 @@ snapshots:
'@chevrotain/utils': 11.1.2
lodash-es: 4.18.0
chokidar@5.0.0:
dependencies:
readdirp: 5.0.0
chownr@1.1.4:
optional: true
@ -12135,6 +12291,8 @@ snapshots:
color-name@1.1.4: {}
color-support@1.1.3: {}
comma-separated-tokens@2.0.3: {}
commander@14.0.0: {}
@ -12457,12 +12615,16 @@ snapshots:
define-lazy-prop@3.0.0: {}
defu@6.1.7: {}
delaunator@5.1.0:
dependencies:
robust-predicates: 3.0.3
dequal@2.0.3: {}
destr@2.0.5: {}
detect-libc@2.1.2: {}
detect-node-es@1.1.0: {}
@ -12511,6 +12673,8 @@ snapshots:
dotenv@16.6.1: {}
dotenv@17.4.2: {}
echarts-for-react@3.0.6(echarts@6.0.0)(react@19.2.5):
dependencies:
echarts: 6.0.0
@ -13274,6 +13438,8 @@ snapshots:
dependencies:
resolve-pkg-maps: 1.0.0
giget@3.2.0: {}
github-from-package@0.0.0:
optional: true
@ -14928,6 +15094,11 @@ snapshots:
radash@12.1.1: {}
rc9@3.0.1:
dependencies:
defu: 6.1.7
destr: 2.0.5
rc@1.2.8:
dependencies:
deep-extend: 0.6.0
@ -15126,6 +15297,8 @@ snapshots:
util-deprecate: 1.0.2
optional: true
readdirp@5.0.0: {}
recast@0.23.11:
dependencies:
ast-types: 0.16.1
@ -16330,6 +16503,7 @@ snapshots:
time:
'@amplitude/analytics-browser@2.42.0': '2026-04-28T17:01:08.442Z'
'@amplitude/plugin-session-replay-browser@1.28.1': '2026-04-28T17:01:37.145Z'
'@hey-api/openapi-ts@0.97.0': '2026-04-28T03:33:22.380Z'
'@hono/node-server@2.0.0': '2026-04-21T00:25:40.852Z'
'@lexical/link@0.44.0': '2026-04-27T14:47:45.477Z'
'@lexical/list@0.44.0': '2026-04-27T14:47:48.463Z'

View File

@ -68,6 +68,7 @@ catalog:
'@formatjs/intl-localematcher': 0.8.4
'@headlessui/react': 2.2.10
'@heroicons/react': 2.2.0
'@hey-api/openapi-ts': 0.97.0
'@hono/node-server': 2.0.0
'@iconify-json/heroicons': 1.2.3
'@iconify-json/ri': 1.2.10

View File

@ -1,604 +0,0 @@
import { type } from '@orpc/contract'
import { base } from '../base'
type Timestamp = string
export type ConsoleAppSummary = {
id?: string
name?: string
description?: string
icon?: string
mode?: string
status?: string
createdAt?: Timestamp
}
export type ConsoleEnvironmentSummary = {
id?: string
name?: string
description?: string
runtime?: string
backend?: string
type?: string
status?: string
tags?: string[]
}
export type ConsoleReleaseSummary = {
id?: string
name?: string
shortCommitId?: string
createdAt?: Timestamp
displayId?: string
commitId?: string
description?: string
status?: string
}
export type ConsoleUser = {
id?: string
name?: string
displayName?: string
}
export type DeploymentStatusCount = {
status?: string
count?: number
}
export type AppDeploymentSummary = {
id?: string
name?: string
icon?: string
mode?: string
sourceAppName?: string
statuses?: DeploymentStatusCount[]
lastDeployedAt?: Timestamp | null
}
export type Pagination = {
total?: number
page?: number
limit?: number
totalCount?: number
perPage?: number
currentPage?: number
totalPages?: number
}
export type ListAppDeploymentsReply = {
data?: AppDeploymentSummary[]
pagination?: Pagination
}
export type AppInstanceOverview = {
id?: string
name?: string
description?: string
sourceAppId?: string
sourceAppName?: string
mode?: string
createdAt?: Timestamp
}
export type DeploymentSummaryRow = {
environment?: ConsoleEnvironmentSummary
release?: ConsoleReleaseSummary
status?: string
}
export type AccessSummary = {
accessChannelsEnabled?: boolean
webappUrl?: string
cliUrl?: string
developerApiEnabled?: boolean
apiKeyCount?: number
}
export type GetDeploymentOverviewReply = {
instance?: AppInstanceOverview
deployments?: DeploymentSummaryRow[]
access?: AccessSummary
}
export type RuntimeBindingDisplay = {
kind?: string
label?: string
displayValue?: string
valueType?: string
slot?: string
displayName?: string
maskedValue?: string
}
export type RuntimeEndpoints = {
run?: string
health?: string
}
export type RuntimeInstanceDetail = {
deploymentName?: string
replicas?: number
runtimeMode?: string
runtimeNote?: string
endpoints?: RuntimeEndpoints
bindings?: RuntimeBindingDisplay[]
}
export type EnvironmentDeploymentRow = {
id?: string
environment?: ConsoleEnvironmentSummary
status?: string
currentRelease?: ConsoleReleaseSummary
detail?: RuntimeInstanceDetail
}
export type ListEnvironmentDeploymentsReply = {
data?: EnvironmentDeploymentRow[]
}
export type DeploymentEnvironmentOption = ConsoleEnvironmentSummary & {
managedBy?: string
deployable?: boolean
disabledReason?: string
}
export type ListDeploymentEnvironmentOptionsReply = {
environments?: DeploymentEnvironmentOption[]
}
export type EnvironmentOption = DeploymentEnvironmentOption & {
disabled?: boolean
}
export type ReleaseRuntimePreviewReply = {
release?: ConsoleReleaseSummary
bindings?: RuntimeBindingDisplay[]
}
export type CreateReleaseReply = {
release?: ConsoleReleaseSummary
}
export type DeployedToSummary = {
environmentId?: string
environmentName?: string
instanceStatus?: string
}
export type ReleaseHistoryRow = ConsoleReleaseSummary & {
createdBy?: ConsoleUser
deployedTo?: DeployedToSummary[]
release?: ConsoleReleaseSummary
}
export type ListReleaseHistoryReply = {
data?: ReleaseHistoryRow[]
pagination?: Pagination
}
export type AccessPermission = {
environment?: ConsoleEnvironmentSummary
currentRelease?: ConsoleReleaseSummary
accessMode?: string
accessModeLabel?: string
hint?: string
}
export type WebAppAccessRow = {
environment?: ConsoleEnvironmentSummary
url?: string
}
export type AccessChannelsSummary = {
enabled?: boolean
webappRows?: WebAppAccessRow[]
cli?: {
url?: string
}
}
export type DeveloperAPIKeySummary = {
id?: string
name?: string
environment?: ConsoleEnvironmentSummary
environmentId?: string
environmentName?: string
maskedKey?: string
maskedPrefix?: string
token?: string
createdAt?: Timestamp
}
export type DeveloperAPISummary = {
enabled?: boolean
apiKeys?: DeveloperAPIKeySummary[]
}
export type GetAccessConfigReply = {
permissions?: AccessPermission[]
accessChannels?: AccessChannelsSummary
developerApi?: DeveloperAPISummary
}
export type AccessSubjectDisplay = {
id?: string
subjectId?: string
subjectType?: string
name?: string
avatarUrl?: string
memberCount?: number
}
export type AccessPolicyOption = {
mode?: string
label?: string
selected?: boolean
disabled?: boolean
groups?: AccessSubjectDisplay[]
members?: AccessSubjectDisplay[]
}
export type AccessPolicyDetail = {
id?: string
enabled?: boolean
accessMode?: string
version?: number
options?: AccessPolicyOption[]
subjects?: AccessSubjectDisplay[]
}
export type GetEnvironmentAccessPolicyReply = {
policy?: AccessPolicyDetail
}
export type AccessSubject = {
subjectId?: string
subjectType?: string
}
export type AccessPolicy = {
id?: string
appInstanceId?: string
environmentId?: string
accessMode?: string
subjects?: AccessSubject[]
}
export type UpdateEnvironmentAccessPolicyReply = {
policy?: AccessPolicy
}
export type SearchAccessSubjectsReply = {
data?: AccessSubjectDisplay[]
}
export type PatchAccessChannelReply = {
enabled?: boolean
}
export type PatchDeveloperAPIReply = {
enabled?: boolean
}
export type CreateDeploymentReply = {
runtimeInstanceId?: string
deploymentId?: string
status?: string
}
export type CancelDeploymentReply = {
status?: string
}
export type UndeployEnvironmentReply = {
deploymentId?: string
status?: string
}
export type APIToken = DeveloperAPIKeySummary
export type CreateEnvironmentAPITokenReply = {
apiToken?: APIToken
}
export type DeleteEnvironmentAPITokenReply = Record<string, never>
export type CreateAppInstanceReply = {
appInstanceId?: string
initialRelease?: ConsoleReleaseSummary
}
export type GetAppInstanceSettingsReply = {
name?: string
description?: string
deleteGuard?: {
canDelete?: boolean
disabledReason?: string
}
}
export type UpdateAppInstanceReply = GetAppInstanceSettingsReply
export type DeleteAppInstanceReply = Record<string, never>
export type ListAppDeploymentsQuery = {
environmentId?: string
notDeployed?: boolean
query?: string
pageNumber?: number
resultsPerPage?: number
}
export const listAppDeploymentsContract = base
.route({
path: '/enterprise/app-instances',
method: 'GET',
})
.input(type<{
query?: ListAppDeploymentsQuery
}>())
.output(type<ListAppDeploymentsReply>())
export const createAppInstanceContract = base
.route({
path: '/enterprise/app-instances',
method: 'POST',
})
.input(type<{
body: {
sourceAppId: string
name: string
description?: string
}
}>())
.output(type<CreateAppInstanceReply>())
export const deploymentOverviewContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/overview',
method: 'GET',
})
.input(type<{ params: { appInstanceId: string } }>())
.output(type<GetDeploymentOverviewReply>())
export const runtimeInstancesContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/runtime-instances',
method: 'GET',
})
.input(type<{
params: { appInstanceId: string }
}>())
.output(type<ListEnvironmentDeploymentsReply>())
export const deploymentEnvironmentOptionsContract = base
.route({
path: '/enterprise/deployment-environment-options',
method: 'GET',
})
.output(type<ListDeploymentEnvironmentOptionsReply>())
export const previewReleaseContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/releases:preview',
method: 'POST',
})
.input(type<{
params: { appInstanceId: string }
body: {
releaseId?: string
}
}>())
.output(type<ReleaseRuntimePreviewReply>())
export const createReleaseContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/releases',
method: 'POST',
})
.input(type<{
params: { appInstanceId: string }
body: {
description?: string
name: string
}
}>())
.output(type<CreateReleaseReply>())
export const releaseHistoryContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/releases',
method: 'GET',
})
.input(type<{
params: { appInstanceId: string }
query?: {
pageNumber?: number
resultsPerPage?: number
}
}>())
.output(type<ListReleaseHistoryReply>())
export const createDeploymentContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/deployments',
method: 'POST',
})
.input(type<{
params: {
appInstanceId: string
}
body: {
environmentId: string
releaseId: string
}
}>())
.output(type<CreateDeploymentReply>())
export const cancelDeploymentContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/runtime-instances/{runtimeInstanceId}/deployment:cancel',
method: 'POST',
})
.input(type<{
params: {
appInstanceId: string
runtimeInstanceId: string
}
}>())
.output(type<CancelDeploymentReply>())
export const undeployEnvironmentContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/runtime-instances/{runtimeInstanceId}:undeploy',
method: 'POST',
})
.input(type<{
params: {
appInstanceId: string
runtimeInstanceId: string
}
}>())
.output(type<UndeployEnvironmentReply>())
export const accessConfigContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/access',
method: 'GET',
})
.input(type<{ params: { appInstanceId: string } }>())
.output(type<GetAccessConfigReply>())
export const environmentAccessPolicyContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/environments/{environmentId}/access-policy',
method: 'GET',
})
.input(type<{
params: {
appInstanceId: string
environmentId: string
}
}>())
.output(type<GetEnvironmentAccessPolicyReply>())
export const updateEnvironmentAccessPolicyContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/environments/{environmentId}/access-policy',
method: 'PUT',
})
.input(type<{
params: {
appInstanceId: string
environmentId: string
}
body: {
accessMode: string
subjects: AccessSubject[]
}
}>())
.output(type<UpdateEnvironmentAccessPolicyReply>())
export const searchAccessSubjectsContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/access-subjects:search',
method: 'GET',
})
.input(type<{
params: { appInstanceId: string }
query?: {
keyword?: string
subjectTypes?: string[]
}
}>())
.output(type<SearchAccessSubjectsReply>())
export const patchAccessChannelContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/access-channels',
method: 'PATCH',
})
.input(type<{
params: {
appInstanceId: string
}
body: {
enabled: boolean
}
}>())
.output(type<PatchAccessChannelReply>())
export const patchDeveloperAPIContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/developer-api',
method: 'PATCH',
})
.input(type<{
params: {
appInstanceId: string
}
body: {
enabled: boolean
}
}>())
.output(type<PatchDeveloperAPIReply>())
export const createEnvironmentAPITokenContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/api-keys',
method: 'POST',
})
.input(type<{
params: {
appInstanceId: string
}
body: {
environmentId: string
name: string
}
}>())
.output(type<CreateEnvironmentAPITokenReply>())
export const deleteEnvironmentAPITokenContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/api-keys/{apiKeyId}',
method: 'DELETE',
})
.input(type<{
params: {
appInstanceId: string
apiKeyId: string
}
}>())
.output(type<DeleteEnvironmentAPITokenReply>())
export const appInstanceSettingsContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}/settings',
method: 'GET',
})
.input(type<{ params: { appInstanceId: string } }>())
.output(type<GetAppInstanceSettingsReply>())
export const updateAppInstanceContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}',
method: 'PATCH',
})
.input(type<{
params: { appInstanceId: string }
body: {
name: string
description?: string
}
}>())
.output(type<UpdateAppInstanceReply>())
export const deleteAppInstanceContract = base
.route({
path: '/enterprise/app-instances/{appInstanceId}',
method: 'DELETE',
})
.input(type<{ params: { appInstanceId: string } }>())
.output(type<DeleteAppInstanceReply>())

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,30 +2,6 @@ import type { InferContractRouterInputs } from '@orpc/contract'
import { accountAvatarContract } from './console/account'
import { appDeleteContract, workflowOnlineUsersContract } from './console/apps'
import { bindPartnerStackContract, invoicesContract } from './console/billing'
import {
accessConfigContract,
appInstanceSettingsContract,
cancelDeploymentContract,
createAppInstanceContract,
createDeploymentContract,
createEnvironmentAPITokenContract,
createReleaseContract,
deleteAppInstanceContract,
deleteEnvironmentAPITokenContract,
deploymentEnvironmentOptionsContract,
deploymentOverviewContract,
environmentAccessPolicyContract,
listAppDeploymentsContract,
patchAccessChannelContract,
patchDeveloperAPIContract,
previewReleaseContract,
releaseHistoryContract,
runtimeInstancesContract,
searchAccessSubjectsContract,
undeployEnvironmentContract,
updateAppInstanceContract,
updateEnvironmentAccessPolicyContract,
} from './console/deployments'
import {
exploreAppDetailContract,
exploreAppsContract,
@ -66,6 +42,30 @@ import {
workflowDraftUpdateFeaturesContract,
} from './console/workflow'
import { workflowCommentContracts } from './console/workflow-comment'
import {
enterpriseAppDeployConsoleCancelRuntimeDeployment,
enterpriseAppDeployConsoleCreateAppInstance,
enterpriseAppDeployConsoleCreateDeployment,
enterpriseAppDeployConsoleCreateDeveloperApiKey,
enterpriseAppDeployConsoleCreateRelease,
enterpriseAppDeployConsoleDeleteAppInstance,
enterpriseAppDeployConsoleDeleteDeveloperApiKey,
enterpriseAppDeployConsoleGetAppInstanceAccess,
enterpriseAppDeployConsoleGetAppInstanceOverview,
enterpriseAppDeployConsoleGetAppInstanceSettings,
enterpriseAppDeployConsoleGetEnvironmentAccessPolicy,
enterpriseAppDeployConsoleListAppInstances,
enterpriseAppDeployConsoleListDeploymentEnvironmentOptions,
enterpriseAppDeployConsoleListReleases,
enterpriseAppDeployConsoleListRuntimeInstances,
enterpriseAppDeployConsolePreviewRelease,
enterpriseAppDeployConsoleSearchAccessSubjects,
enterpriseAppDeployConsoleUndeployRuntimeInstance,
enterpriseAppDeployConsoleUpdateAccessChannels,
enterpriseAppDeployConsoleUpdateAppInstance,
enterpriseAppDeployConsoleUpdateDeveloperApi,
enterpriseAppDeployConsoleUpdateEnvironmentAccessPolicy,
} from './generated/enterprise/orpc.gen'
import { collectionPluginsContract, collectionsContract, searchAdvancedContract, templateDetailContract } from './marketplace'
export const marketplaceRouterContract = {
@ -116,28 +116,28 @@ export const consoleRouterContract = {
bindPartnerStack: bindPartnerStackContract,
},
deployments: {
list: listAppDeploymentsContract,
createInstance: createAppInstanceContract,
overview: deploymentOverviewContract,
environmentDeployments: runtimeInstancesContract,
deploymentEnvironmentOptions: deploymentEnvironmentOptionsContract,
previewRelease: previewReleaseContract,
releaseHistory: releaseHistoryContract,
accessConfig: accessConfigContract,
environmentAccessPolicy: environmentAccessPolicyContract,
updateEnvironmentAccessPolicy: updateEnvironmentAccessPolicyContract,
searchAccessSubjects: searchAccessSubjectsContract,
patchAccessChannel: patchAccessChannelContract,
patchDeveloperAPI: patchDeveloperAPIContract,
createRelease: createReleaseContract,
createDeployment: createDeploymentContract,
cancelDeployment: cancelDeploymentContract,
undeployEnvironment: undeployEnvironmentContract,
createEnvironmentAPIToken: createEnvironmentAPITokenContract,
deleteEnvironmentAPIToken: deleteEnvironmentAPITokenContract,
settings: appInstanceSettingsContract,
updateInstance: updateAppInstanceContract,
deleteInstance: deleteAppInstanceContract,
list: enterpriseAppDeployConsoleListAppInstances,
createInstance: enterpriseAppDeployConsoleCreateAppInstance,
overview: enterpriseAppDeployConsoleGetAppInstanceOverview,
environmentDeployments: enterpriseAppDeployConsoleListRuntimeInstances,
deploymentEnvironmentOptions: enterpriseAppDeployConsoleListDeploymentEnvironmentOptions,
previewRelease: enterpriseAppDeployConsolePreviewRelease,
releaseHistory: enterpriseAppDeployConsoleListReleases,
accessConfig: enterpriseAppDeployConsoleGetAppInstanceAccess,
environmentAccessPolicy: enterpriseAppDeployConsoleGetEnvironmentAccessPolicy,
updateEnvironmentAccessPolicy: enterpriseAppDeployConsoleUpdateEnvironmentAccessPolicy,
searchAccessSubjects: enterpriseAppDeployConsoleSearchAccessSubjects,
patchAccessChannel: enterpriseAppDeployConsoleUpdateAccessChannels,
patchDeveloperAPI: enterpriseAppDeployConsoleUpdateDeveloperApi,
createRelease: enterpriseAppDeployConsoleCreateRelease,
createDeployment: enterpriseAppDeployConsoleCreateDeployment,
cancelDeployment: enterpriseAppDeployConsoleCancelRuntimeDeployment,
undeployEnvironment: enterpriseAppDeployConsoleUndeployRuntimeInstance,
createEnvironmentAPIToken: enterpriseAppDeployConsoleCreateDeveloperApiKey,
deleteEnvironmentAPIToken: enterpriseAppDeployConsoleDeleteDeveloperApiKey,
settings: enterpriseAppDeployConsoleGetAppInstanceSettings,
updateInstance: enterpriseAppDeployConsoleUpdateAppInstance,
deleteInstance: enterpriseAppDeployConsoleDeleteAppInstance,
},
workflowDraft: {
environmentVariables: workflowDraftEnvironmentVariablesContract,

View File

@ -27,7 +27,7 @@ export default antfu(
'react/no-unnecessary-use-prefix': 'error',
},
},
ignores: ['public', 'types/doc-paths.ts', 'eslint-suppressions.json'],
ignores: ['public', 'types/doc-paths.ts', 'eslint-suppressions.json', 'contract/generated/**'],
typescript: {
overrides: {
'ts/consistent-type-definitions': ['error', 'type'],

View File

@ -33,7 +33,7 @@ const DeployDrawer: FC = () => {
[environmentOptionsReply],
)
const environments = environmentOptions
const releases = releaseHistory?.data?.map(row => row.release ?? row).filter(release => release.id) ?? []
const releases = releaseHistory?.data?.filter(release => release.id) ?? []
const defaultReleaseId = releases[0]?.id
const formKey = `${drawer.appInstanceId ?? 'none'}-${drawer.environmentId ?? 'any'}-${drawer.releaseId ?? 'new'}-${open ? '1' : '0'}`

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { ConsoleReleaseSummary, EnvironmentOption, RuntimeBindingDisplay } from '@/contract/console/deployments'
import type { ConsoleReleaseSummary, EnvironmentOption, RuntimeBindingDisplay } from '@/features/deployments/types'
import { Button } from '@langgenius/dify-ui/button'
import { DialogDescription, DialogTitle } from '@langgenius/dify-ui/dialog'
import { skipToken, useQuery } from '@tanstack/react-query'

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { EnvironmentOption } from '@/contract/console/deployments'
import type { EnvironmentOption } from '@/features/deployments/types'
import { cn } from '@langgenius/dify-ui/cn'
import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectItemText, SelectTrigger } from '@langgenius/dify-ui/select'
import { useTranslation } from 'react-i18next'

View File

@ -69,8 +69,8 @@ const RollbackModal: FC = () => {
const currentRow = deployedRows(environmentDeployments?.data)
.find(row => environmentId(row.environment) === modal.environmentId)
const targetRelease = [
...(releaseHistory?.data?.map(row => row.release ?? row).filter(release => !!release?.id) ?? []),
].find(release => release?.id === modal.targetReleaseId)
...(releaseHistory?.data?.filter(release => !!release.id) ?? []),
].find(release => release.id === modal.targetReleaseId)
const currentRelease = activeRelease(currentRow)
const environment = currentRow?.environment
?? environmentOptions.find(env => env.id === modal.environmentId)

View File

@ -5,7 +5,7 @@ import type {
AccessPermission,
AccessSubject,
ConsoleEnvironmentSummary,
} from '@/contract/console/deployments'
} from '@/features/deployments/types'
import { useQuery } from '@tanstack/react-query'
import { useMemo, useState } from 'react'
import { consoleQuery } from '@/service/client'
@ -72,7 +72,7 @@ const AccessTab: FC<AccessTabProps> = ({ instanceId: appId }) => {
const apiKeys = accessConfig?.developerApi?.apiKeys ?? []
const createApiKeyLabel = (environmentId: string) => {
const existingCount = apiKeys.filter(key =>
(key.environmentId ?? key.environment?.id) === environmentId,
key.environment?.id === environmentId,
).length
const name = deployedEnvs.find(env => env.id === environmentId)?.name ?? 'env'
@ -91,8 +91,8 @@ const AccessTab: FC<AccessTabProps> = ({ instanceId: appId }) => {
},
{
onSuccess: (response) => {
if (response.apiToken?.token)
setCreatedApiToken({ appId, token: response.apiToken.token })
if (response.token)
setCreatedApiToken({ appId, token: response.token })
},
},
)

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { ConsoleEnvironmentSummary, DeveloperAPIKeySummary } from '@/contract/console/deployments'
import type { ConsoleEnvironmentSummary, DeveloperAPIKeySummary } from '@/features/deployments/types'
import { cn } from '@langgenius/dify-ui/cn'
import {
DropdownMenu,

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { WebAppAccessRow } from '@/contract/console/deployments'
import type { WebAppAccessRow } from '@/features/deployments/types'
import { Switch } from '@langgenius/dify-ui/switch'
import { useTranslation } from 'react-i18next'
import { environmentName, webappUrl } from '../../utils'

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { ConsoleEnvironmentSummary, DeveloperAPIKeySummary } from '@/contract/console/deployments'
import type { ConsoleEnvironmentSummary, DeveloperAPIKeySummary } from '@/features/deployments/types'
import { Switch } from '@langgenius/dify-ui/switch'
import { useTranslation } from 'react-i18next'
import { ApiKeyGenerateMenu, ApiKeyRow } from './api-keys'

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { AccessPermission, AccessSubject, ConsoleEnvironmentSummary } from '@/contract/console/deployments'
import type { AccessPermission, AccessSubject, ConsoleEnvironmentSummary } from '@/features/deployments/types'
import { useTranslation } from 'react-i18next'
import { Section } from './common'
import { EnvironmentPermissionRow } from './permissions'

View File

@ -8,7 +8,7 @@ import type {
AccessSubject,
AccessSubjectDisplay,
ConsoleEnvironmentSummary,
} from '@/contract/console/deployments'
} from '@/features/deployments/types'
import { cn } from '@langgenius/dify-ui/cn'
import {
DropdownMenu,
@ -328,10 +328,12 @@ export const EnvironmentPermissionRow: FC<EnvironmentPermissionRowProps> = ({
}))
const detailPolicy = policyQuery.data?.policy
const policyKind = accessModeToPermissionKey(detailPolicy?.accessMode ?? summaryPolicy?.accessMode)
const policySubjectFingerprint = detailPolicy?.subjects
?.map(subject => `${subject.subjectType ?? ''}:${subject.id ?? ''}`)
.join(',')
const policyFingerprint = [
detailPolicy?.id ?? 'new',
detailPolicy?.version ?? 0,
detailPolicy?.accessMode ?? summaryPolicy?.accessMode ?? '',
policySubjectFingerprint ?? '',
].join(':')
const policySelectedSubjects = useMemo(
() => policyKind === 'specific' ? selectedSubjectsFromPolicy(detailPolicy) : [],

View File

@ -1,7 +1,7 @@
'use client'
import type { FC, ReactNode } from 'react'
import type { EnvironmentDeploymentRow } from '@/contract/console/deployments'
import type { EnvironmentDeploymentRow } from '@/features/deployments/types'
import { cn } from '@langgenius/dify-ui/cn'
import { useTranslation } from 'react-i18next'
import {

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { EnvironmentDeploymentRow } from '@/contract/console/deployments'
import type { EnvironmentDeploymentRow } from '@/features/deployments/types'
import { useTranslation } from 'react-i18next'
import {
activeRelease,

View File

@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { AppInfo } from '../types'
import type { GetAppInstanceSettingsReply } from '@/contract/console/deployments'
import type { GetAppInstanceSettingsReply } from '@/features/deployments/types'
import {
AlertDialog,
AlertDialogActions,

View File

@ -30,7 +30,7 @@ const VersionsTab: FC<VersionsTabProps> = ({ instanceId: appId }) => {
const { data: releaseHistory } = useQuery(deploymentReleaseHistoryQueryOptions(appId))
const { data: environmentDeployments } = useQuery(deploymentEnvironmentDeploymentsQueryOptions(appId))
const releaseRows = useMemo(
() => releaseHistory?.data?.filter(row => (row.release ?? row).id) ?? [],
() => releaseHistory?.data?.filter(row => row.id) ?? [],
[releaseHistory?.data],
)
const deploymentRows = useMemo(
@ -73,7 +73,7 @@ const VersionsTab: FC<VersionsTabProps> = ({ instanceId: appId }) => {
</div>
{releaseRows.map((row) => {
const release = row.release ?? row
const release = row
const releaseDeployments = getReleaseDeployments(row, deploymentRows)
return (
<div key={release.id} className="border-b border-divider-subtle last:border-b-0">
@ -95,7 +95,7 @@ const VersionsTab: FC<VersionsTabProps> = ({ instanceId: appId }) => {
<div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 system-xs-regular text-text-secondary">
<span>{formatDate(release.createdAt)}</span>
<span aria-hidden>·</span>
<span>{row.createdBy?.displayName ?? row.createdBy?.name ?? '—'}</span>
<span>{row.createdBy?.name ?? '—'}</span>
</div>
</div>
<div className="flex shrink-0 justify-end gap-1">
@ -138,7 +138,7 @@ const VersionsTab: FC<VersionsTabProps> = ({ instanceId: appId }) => {
</Tooltip>
</div>
<div className="system-sm-regular text-text-secondary">{formatDate(release.createdAt)}</div>
<div className="system-sm-regular text-text-secondary">{row.createdBy?.displayName ?? row.createdBy?.name ?? '—'}</div>
<div className="system-sm-regular text-text-secondary">{row.createdBy?.name ?? '—'}</div>
<div className="flex flex-wrap gap-1">
{releaseDeployments.length === 0
? <span className="system-sm-regular text-text-quaternary"></span>

View File

@ -1,4 +1,4 @@
import type { EnvironmentDeploymentRow, ReleaseHistoryRow } from '@/contract/console/deployments'
import type { EnvironmentDeploymentRow, ReleaseHistoryRow } from '@/features/deployments/types'
import { describe, expect, it } from 'vitest'
import { getReleaseDeployments } from '../release-deployments'

View File

@ -1,4 +1,4 @@
import type { DeployedToSummary, EnvironmentDeploymentRow, ReleaseHistoryRow } from '@/contract/console/deployments'
import type { DeployedToSummary, EnvironmentDeploymentRow, ReleaseHistoryRow } from '@/features/deployments/types'
import {
activeRelease,
deploymentStatus,

View File

@ -1,7 +1,7 @@
'use client'
import type { QueryClient, QueryKey } from '@tanstack/react-query'
import type { ConsoleReleaseSummary } from '@/contract/console/deployments'
import type { ConsoleReleaseSummary } from '@/features/deployments/types'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { consoleClient, consoleQuery } from '@/service/client'
import {
@ -224,6 +224,10 @@ export const useUndeployDeployment = () => {
appInstanceId,
runtimeInstanceId,
},
body: {
appInstanceId,
runtimeInstanceId,
},
})
}
return consoleClient.deployments.undeployEnvironment({
@ -231,6 +235,10 @@ export const useUndeployDeployment = () => {
appInstanceId,
runtimeInstanceId,
},
body: {
appInstanceId,
runtimeInstanceId,
},
})
},
onSuccess: (_data, variables) => {

View File

@ -2,7 +2,7 @@
import type { FC, MouseEvent } from 'react'
import type { AppInfo } from '../types'
import type { AppDeploymentSummary } from '@/contract/console/deployments'
import type { AppDeploymentSummary } from '@/features/deployments/types'
import type { AppModeEnum } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
import {
@ -50,7 +50,7 @@ export const InstanceCard: FC<InstanceCardProps> = ({ app, summary }) => {
const envCount = failedCount + deployingCount + readyCount
const lastDeployedAt = summary?.lastDeployedAt
? new Date(summary.lastDeployedAt).getTime()
? Date.parse(summary.lastDeployedAt)
: null
const primaryStatus: 'none' | 'failed' | 'deploying' | 'ready' = envCount === 0

View File

@ -1,4 +1,4 @@
import type { ListAppDeploymentsQuery } from '@/contract/console/deployments'
import type { ListAppDeploymentsQuery } from '@/features/deployments/types'
import { skipToken } from '@tanstack/react-query'
import { consoleQuery } from '@/service/client'
import { DEPLOYMENT_PAGE_SIZE, SOURCE_APPS_PAGE_SIZE } from './data'

View File

@ -1,5 +1,57 @@
import type {
DifyEnterpriseApiEnterpriseAccessChannels,
DifyEnterpriseApiEnterpriseAccessModeOption,
DifyEnterpriseApiEnterpriseAccessPolicyDetail,
DifyEnterpriseApiEnterpriseAccessStatus,
DifyEnterpriseApiEnterpriseAccessSubject,
DifyEnterpriseApiEnterpriseAccessSubjectDisplay,
DifyEnterpriseApiEnterpriseAppInstanceBasicInfo,
DifyEnterpriseApiEnterpriseAppInstanceCard,
DifyEnterpriseApiEnterpriseCancelRuntimeDeploymentReply,
DifyEnterpriseApiEnterpriseConsoleEnvironment,
DifyEnterpriseApiEnterpriseConsoleRelease,
DifyEnterpriseApiEnterpriseConsoleUser,
DifyEnterpriseApiEnterpriseCreateAppInstanceReply,
DifyEnterpriseApiEnterpriseCreateDeploymentReply,
DifyEnterpriseApiEnterpriseCreateDeveloperApiKeyReply,
DifyEnterpriseApiEnterpriseCreateReleaseReply,
DifyEnterpriseApiEnterpriseDeleteAppInstanceReply,
DifyEnterpriseApiEnterpriseDeleteDeveloperApiKeyReply,
DifyEnterpriseApiEnterpriseDeployedEnvironment,
DifyEnterpriseApiEnterpriseDeploymentEnvironmentOption,
DifyEnterpriseApiEnterpriseDeploymentStatusRow,
DifyEnterpriseApiEnterpriseDeveloperApiAccess,
DifyEnterpriseApiEnterpriseDeveloperApiKeyRow,
DifyEnterpriseApiEnterpriseEnvironmentAccessRow,
DifyEnterpriseApiEnterpriseGetAppInstanceAccessReply,
DifyEnterpriseApiEnterpriseGetAppInstanceOverviewReply,
DifyEnterpriseApiEnterpriseGetAppInstanceSettingsReply,
DifyEnterpriseApiEnterpriseGetEnvironmentAccessPolicyReply,
DifyEnterpriseApiEnterpriseListAppInstancesReply,
DifyEnterpriseApiEnterpriseListDeploymentEnvironmentOptionsReply,
DifyEnterpriseApiEnterpriseListReleasesReply,
DifyEnterpriseApiEnterpriseListRuntimeInstancesReply,
DifyEnterpriseApiEnterprisePreviewReleaseReply,
DifyEnterpriseApiEnterpriseReleaseRow,
DifyEnterpriseApiEnterpriseReleaseRuntimeBinding,
DifyEnterpriseApiEnterpriseRuntimeEndpoints,
DifyEnterpriseApiEnterpriseRuntimeInstanceDetail,
DifyEnterpriseApiEnterpriseRuntimeInstanceRow,
DifyEnterpriseApiEnterpriseSearchAccessSubjectsReply,
DifyEnterpriseApiEnterpriseStatusCount,
DifyEnterpriseApiEnterpriseUndeployRuntimeInstanceReply,
DifyEnterpriseApiEnterpriseUpdateAccessChannelsReply,
DifyEnterpriseApiEnterpriseUpdateAppInstanceReply,
DifyEnterpriseApiEnterpriseUpdateDeveloperApiReply,
DifyEnterpriseApiEnterpriseUpdateEnvironmentAccessPolicyReply,
DifyEnterpriseApiEnterpriseWebAppAccessRow,
EnterpriseAppDeployConsoleListAppInstancesData,
PaginationPagination,
} from '@/contract/generated/enterprise/types.gen'
import type { AppIconType } from '@/types/app'
type Timestamp = string
export type EnvironmentMode = 'shared' | 'isolated'
export type EnvironmentHealth = 'ready' | 'degraded'
@ -21,3 +73,220 @@ export type AppInfo = {
sourceAppId?: string
sourceAppName?: string
}
export type ConsoleAppSummary = {
id?: string
name?: string
description?: string
icon?: string
mode?: string
status?: string
createdAt?: Timestamp
}
export type ConsoleEnvironmentSummary = DifyEnterpriseApiEnterpriseConsoleEnvironment & {
backend?: string
description?: string
tags?: string[]
}
export type ConsoleReleaseSummary = DifyEnterpriseApiEnterpriseConsoleRelease & {
commitId?: string
description?: string
displayId?: string
status?: string
}
export type ConsoleUser = DifyEnterpriseApiEnterpriseConsoleUser & {
displayName?: string
}
export type DeploymentStatusCount = DifyEnterpriseApiEnterpriseStatusCount
export type AppDeploymentSummary = DifyEnterpriseApiEnterpriseAppInstanceCard & {
createdAt?: Timestamp
description?: string
status?: string
}
export type Pagination = PaginationPagination
export type ListAppDeploymentsReply = Omit<DifyEnterpriseApiEnterpriseListAppInstancesReply, 'data'> & {
data?: AppDeploymentSummary[]
}
export type AppInstanceOverview = DifyEnterpriseApiEnterpriseAppInstanceBasicInfo
export type DeploymentSummaryRow = Omit<DifyEnterpriseApiEnterpriseDeploymentStatusRow, 'environment' | 'release'> & {
environment?: ConsoleEnvironmentSummary
release?: ConsoleReleaseSummary
}
export type AccessSummary = DifyEnterpriseApiEnterpriseAccessStatus
export type GetDeploymentOverviewReply = Omit<DifyEnterpriseApiEnterpriseGetAppInstanceOverviewReply, 'deployments' | 'instance'> & {
deployments?: DeploymentSummaryRow[]
instance?: AppInstanceOverview
}
export type RuntimeBindingDisplay = DifyEnterpriseApiEnterpriseReleaseRuntimeBinding & {
displayName?: string
maskedValue?: string
slot?: string
}
export type RuntimeEndpoints = DifyEnterpriseApiEnterpriseRuntimeEndpoints
export type RuntimeInstanceDetail = Omit<DifyEnterpriseApiEnterpriseRuntimeInstanceDetail, 'bindings'> & {
bindings?: RuntimeBindingDisplay[]
}
export type EnvironmentDeploymentRow = Omit<DifyEnterpriseApiEnterpriseRuntimeInstanceRow, 'currentRelease' | 'detail' | 'environment'> & {
currentRelease?: ConsoleReleaseSummary
detail?: RuntimeInstanceDetail
environment?: ConsoleEnvironmentSummary
}
export type ListEnvironmentDeploymentsReply = Omit<DifyEnterpriseApiEnterpriseListRuntimeInstancesReply, 'data'> & {
data?: EnvironmentDeploymentRow[]
}
export type DeploymentEnvironmentOption = DifyEnterpriseApiEnterpriseDeploymentEnvironmentOption & {
description?: string
runtime?: string
tags?: string[]
}
export type ListDeploymentEnvironmentOptionsReply = Omit<DifyEnterpriseApiEnterpriseListDeploymentEnvironmentOptionsReply, 'environments'> & {
environments?: DeploymentEnvironmentOption[]
}
export type EnvironmentOption = DeploymentEnvironmentOption & {
disabled?: boolean
}
export type ReleaseRuntimePreviewReply = Omit<DifyEnterpriseApiEnterprisePreviewReleaseReply, 'bindings' | 'release'> & {
bindings?: RuntimeBindingDisplay[]
release?: ConsoleReleaseSummary
}
export type CreateReleaseReply = Omit<DifyEnterpriseApiEnterpriseCreateReleaseReply, 'release'> & {
release?: ConsoleReleaseSummary
}
export type DeployedToSummary = DifyEnterpriseApiEnterpriseDeployedEnvironment & {
instanceStatus?: string
}
export type ReleaseHistoryRow = Omit<DifyEnterpriseApiEnterpriseReleaseRow, 'createdBy' | 'deployedTo'> & {
commitId?: string
createdBy?: ConsoleUser
deployedTo?: DeployedToSummary[]
description?: string
displayId?: string
release?: ConsoleReleaseSummary
shortCommitId?: string
status?: string
}
export type ListReleaseHistoryReply = Omit<DifyEnterpriseApiEnterpriseListReleasesReply, 'data'> & {
data?: ReleaseHistoryRow[]
}
export type AccessPermission = Omit<DifyEnterpriseApiEnterpriseEnvironmentAccessRow, 'currentRelease' | 'environment'> & {
currentRelease?: ConsoleReleaseSummary
environment?: ConsoleEnvironmentSummary
}
export type WebAppAccessRow = Omit<DifyEnterpriseApiEnterpriseWebAppAccessRow, 'environment'> & {
environment?: ConsoleEnvironmentSummary
}
export type AccessChannelsSummary = Omit<DifyEnterpriseApiEnterpriseAccessChannels, 'webappRows'> & {
webappRows?: WebAppAccessRow[]
}
export type DeveloperAPIKeySummary = Omit<DifyEnterpriseApiEnterpriseDeveloperApiKeyRow, 'environment'> & {
createdAt?: Timestamp
environment?: ConsoleEnvironmentSummary
environmentId?: string
environmentName?: string
maskedPrefix?: string
token?: string
}
export type DeveloperAPISummary = Omit<DifyEnterpriseApiEnterpriseDeveloperApiAccess, 'apiKeys'> & {
apiKeys?: DeveloperAPIKeySummary[]
}
export type GetAccessConfigReply = Omit<DifyEnterpriseApiEnterpriseGetAppInstanceAccessReply, 'accessChannels' | 'developerApi' | 'permissions'> & {
accessChannels?: AccessChannelsSummary
developerApi?: DeveloperAPISummary
permissions?: AccessPermission[]
}
export type AccessSubjectDisplay = Omit<DifyEnterpriseApiEnterpriseAccessSubjectDisplay, 'memberCount'> & {
memberCount?: number | string
subjectId?: string
}
export type AccessPolicyOption = DifyEnterpriseApiEnterpriseAccessModeOption & {
groups?: AccessSubjectDisplay[]
members?: AccessSubjectDisplay[]
}
export type AccessPolicyDetail = Omit<DifyEnterpriseApiEnterpriseAccessPolicyDetail, 'options' | 'subjects'> & {
enabled?: boolean
id?: string
options?: AccessPolicyOption[]
subjects?: AccessSubjectDisplay[]
version?: number
}
export type GetEnvironmentAccessPolicyReply = Omit<DifyEnterpriseApiEnterpriseGetEnvironmentAccessPolicyReply, 'policy'> & {
policy?: AccessPolicyDetail
}
export type AccessSubject = DifyEnterpriseApiEnterpriseAccessSubject
export type AccessPolicy = {
accessMode?: string
appInstanceId?: string
environmentId?: string
id?: string
subjects?: AccessSubject[]
}
export type UpdateEnvironmentAccessPolicyReply = DifyEnterpriseApiEnterpriseUpdateEnvironmentAccessPolicyReply
export type SearchAccessSubjectsReply = Omit<DifyEnterpriseApiEnterpriseSearchAccessSubjectsReply, 'data'> & {
data?: AccessSubjectDisplay[]
}
export type PatchAccessChannelReply = DifyEnterpriseApiEnterpriseUpdateAccessChannelsReply
export type PatchDeveloperAPIReply = DifyEnterpriseApiEnterpriseUpdateDeveloperApiReply
export type CreateDeploymentReply = DifyEnterpriseApiEnterpriseCreateDeploymentReply
export type CancelDeploymentReply = DifyEnterpriseApiEnterpriseCancelRuntimeDeploymentReply
export type UndeployEnvironmentReply = DifyEnterpriseApiEnterpriseUndeployRuntimeInstanceReply
export type APIToken = DeveloperAPIKeySummary
export type CreateEnvironmentAPITokenReply = DifyEnterpriseApiEnterpriseCreateDeveloperApiKeyReply
export type DeleteEnvironmentAPITokenReply = DifyEnterpriseApiEnterpriseDeleteDeveloperApiKeyReply
export type CreateAppInstanceReply = Omit<DifyEnterpriseApiEnterpriseCreateAppInstanceReply, 'initialRelease'> & {
initialRelease?: ConsoleReleaseSummary
}
export type GetAppInstanceSettingsReply = DifyEnterpriseApiEnterpriseGetAppInstanceSettingsReply
export type UpdateAppInstanceReply = DifyEnterpriseApiEnterpriseUpdateAppInstanceReply
export type DeleteAppInstanceReply = DifyEnterpriseApiEnterpriseDeleteAppInstanceReply
export type ListAppDeploymentsQuery = NonNullable<EnterpriseAppDeployConsoleListAppInstancesData['query']>

View File

@ -1,7 +1,9 @@
import type { AccessPermissionKind, AppInfo, AppMode } from './types'
import type {
AccessPermissionKind,
AppDeploymentSummary,
AppInfo,
AppInstanceOverview,
AppMode,
ConsoleEnvironmentSummary,
ConsoleReleaseSummary,
EnvironmentDeploymentRow,
@ -9,7 +11,7 @@ import type {
ListAppDeploymentsReply,
ListDeploymentEnvironmentOptionsReply,
RuntimeBindingDisplay,
} from '@/contract/console/deployments'
} from './types'
import { PUBLIC_API_PREFIX } from '@/config'
export type DeploymentUiStatus = 'ready' | 'deploying' | 'deploy_failed'

View File

@ -0,0 +1,65 @@
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { defineConfig } from '@hey-api/openapi-ts'
import yaml from 'js-yaml'
type JsonObject = Record<string, unknown>
type OpenApiDocument = JsonObject & {
paths?: Record<string, unknown>
}
const currentDir = path.dirname(fileURLToPath(import.meta.url))
const enterpriseServerDir = process.env.DIFY_ENTERPRISE_SERVER
? path.resolve(process.env.DIFY_ENTERPRISE_SERVER)
: path.resolve(currentDir, '../../dify-enterprise/server')
const enterpriseOpenApiPath = path.join(enterpriseServerDir, 'pkg/apis/enterprise/openapi.yaml')
const stripConsoleApiPrefix = (routePath: string) => {
if (routePath.startsWith('/console/api/'))
return routePath.replace('/console/api', '')
return routePath
}
const normalizeEnterpriseOpenApi = () => {
const openApi = yaml.load(fs.readFileSync(enterpriseOpenApiPath, 'utf8'))
if (!openApi || typeof openApi !== 'object' || Array.isArray(openApi))
throw new Error(`Invalid enterprise OpenAPI document: ${enterpriseOpenApiPath}`)
const document = openApi as OpenApiDocument
const paths = document.paths ?? {}
document.paths = Object.fromEntries(
Object.entries(paths).map(([routePath, pathItem]) => [stripConsoleApiPrefix(routePath), pathItem]),
)
return document
}
export default defineConfig({
input: normalizeEnterpriseOpenApi(),
output: {
path: 'contract/generated/enterprise',
fileName: {
suffix: '.gen',
},
header: ctx => [
'/* eslint-disable */',
...ctx.defaultValue,
],
},
plugins: [
{
name: '@hey-api/typescript',
comments: false,
},
'zod',
{
name: 'orpc',
validator: 'zod',
},
],
})

View File

@ -31,6 +31,7 @@
"dev:proxy": "tsx ./scripts/dev-hono-proxy.ts",
"dev:vinext": "vinext dev",
"gen-doc-paths": "tsx ./scripts/gen-doc-paths.ts",
"gen-enterprise-contract": "openapi-ts -f openapi-ts.enterprise.config.ts",
"gen-icons": "pnpm --filter @dify/iconify-collections generate && node ./scripts/gen-icons.mjs && eslint --fix app/components/base/icons/src/",
"i18n:check": "tsx ./scripts/check-i18n.js",
"knip": "knip",
@ -158,6 +159,7 @@
"@dify/tsconfig": "workspace:*",
"@egoist/tailwindcss-icons": "catalog:",
"@eslint-react/eslint-plugin": "catalog:",
"@hey-api/openapi-ts": "catalog:",
"@hono/node-server": "catalog:",
"@iconify-json/heroicons": "catalog:",
"@iconify-json/ri": "catalog:",