@devoplus/one-sdk 0.0.0-stage → 0.2.0-next.112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/CHANGELOG.md +268 -0
  2. package/README.md +894 -2
  3. package/bin/accessRequest.d.mts +96 -0
  4. package/bin/accessRequest.mjs +340 -0
  5. package/bin/appOps.d.mts +97 -0
  6. package/bin/appOps.mjs +336 -0
  7. package/bin/dataCommand.mjs +131 -0
  8. package/bin/devConfig.mjs +132 -0
  9. package/bin/one.mjs +341 -0
  10. package/bin/session.mjs +239 -0
  11. package/dist/agentInput.d.ts +9 -0
  12. package/dist/agentInput.d.ts.map +1 -0
  13. package/dist/agentInput.js +102 -0
  14. package/dist/agentInput.js.map +1 -0
  15. package/dist/agentTools.d.ts +83 -0
  16. package/dist/agentTools.d.ts.map +1 -0
  17. package/dist/agentTools.js +164 -0
  18. package/dist/agentTools.js.map +1 -0
  19. package/dist/ai.d.ts +67 -0
  20. package/dist/ai.d.ts.map +1 -0
  21. package/dist/ai.js +129 -0
  22. package/dist/ai.js.map +1 -0
  23. package/dist/audit.d.ts +21 -0
  24. package/dist/audit.d.ts.map +1 -0
  25. package/dist/audit.js +58 -0
  26. package/dist/audit.js.map +1 -0
  27. package/dist/backend.d.ts +27 -0
  28. package/dist/backend.d.ts.map +1 -0
  29. package/dist/backend.js +63 -0
  30. package/dist/backend.js.map +1 -0
  31. package/dist/cache.d.ts +20 -0
  32. package/dist/cache.d.ts.map +1 -0
  33. package/dist/cache.js +84 -0
  34. package/dist/cache.js.map +1 -0
  35. package/dist/client.d.ts +147 -0
  36. package/dist/client.d.ts.map +1 -0
  37. package/dist/client.js +469 -0
  38. package/dist/client.js.map +1 -0
  39. package/dist/components.d.ts +235 -0
  40. package/dist/components.d.ts.map +1 -0
  41. package/dist/components.js +1491 -0
  42. package/dist/components.js.map +1 -0
  43. package/dist/context.d.ts +110 -0
  44. package/dist/context.d.ts.map +1 -0
  45. package/dist/context.js +126 -0
  46. package/dist/context.js.map +1 -0
  47. package/dist/data/crud.d.ts +74 -0
  48. package/dist/data/crud.d.ts.map +1 -0
  49. package/dist/data/crud.js +614 -0
  50. package/dist/data/crud.js.map +1 -0
  51. package/dist/data/ddl.d.ts +76 -0
  52. package/dist/data/ddl.d.ts.map +1 -0
  53. package/dist/data/ddl.js +362 -0
  54. package/dist/data/ddl.js.map +1 -0
  55. package/dist/data/fold.d.ts +14 -0
  56. package/dist/data/fold.d.ts.map +1 -0
  57. package/dist/data/fold.js +76 -0
  58. package/dist/data/fold.js.map +1 -0
  59. package/dist/data/model.d.ts +113 -0
  60. package/dist/data/model.d.ts.map +1 -0
  61. package/dist/data/model.js +408 -0
  62. package/dist/data/model.js.map +1 -0
  63. package/dist/data/values.d.ts +29 -0
  64. package/dist/data/values.d.ts.map +1 -0
  65. package/dist/data/values.js +152 -0
  66. package/dist/data/values.js.map +1 -0
  67. package/dist/dexa.d.ts +44 -0
  68. package/dist/dexa.d.ts.map +1 -0
  69. package/dist/dexa.js +74 -0
  70. package/dist/dexa.js.map +1 -0
  71. package/dist/dexaCommand.d.ts +116 -0
  72. package/dist/dexaCommand.d.ts.map +1 -0
  73. package/dist/dexaCommand.js +226 -0
  74. package/dist/dexaCommand.js.map +1 -0
  75. package/dist/export/columns.d.ts +62 -0
  76. package/dist/export/columns.d.ts.map +1 -0
  77. package/dist/export/columns.js +127 -0
  78. package/dist/export/columns.js.map +1 -0
  79. package/dist/export/csv.d.ts +10 -0
  80. package/dist/export/csv.d.ts.map +1 -0
  81. package/dist/export/csv.js +30 -0
  82. package/dist/export/csv.js.map +1 -0
  83. package/dist/export/report.d.ts +19 -0
  84. package/dist/export/report.d.ts.map +1 -0
  85. package/dist/export/report.js +91 -0
  86. package/dist/export/report.js.map +1 -0
  87. package/dist/export/response.d.ts +14 -0
  88. package/dist/export/response.d.ts.map +1 -0
  89. package/dist/export/response.js +70 -0
  90. package/dist/export/response.js.map +1 -0
  91. package/dist/export/xlsx.d.ts +15 -0
  92. package/dist/export/xlsx.d.ts.map +1 -0
  93. package/dist/export/xlsx.js +167 -0
  94. package/dist/export/xlsx.js.map +1 -0
  95. package/dist/export/zip.d.ts +7 -0
  96. package/dist/export/zip.d.ts.map +1 -0
  97. package/dist/export/zip.js +83 -0
  98. package/dist/export/zip.js.map +1 -0
  99. package/dist/files.d.ts +52 -0
  100. package/dist/files.d.ts.map +1 -0
  101. package/dist/files.js +137 -0
  102. package/dist/files.js.map +1 -0
  103. package/dist/index.d.ts +31 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +35 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/jobs.d.ts +57 -0
  108. package/dist/jobs.d.ts.map +1 -0
  109. package/dist/jobs.js +157 -0
  110. package/dist/jobs.js.map +1 -0
  111. package/dist/log.d.ts +22 -0
  112. package/dist/log.d.ts.map +1 -0
  113. package/dist/log.js +107 -0
  114. package/dist/log.js.map +1 -0
  115. package/dist/notify.d.ts +41 -0
  116. package/dist/notify.d.ts.map +1 -0
  117. package/dist/notify.js +11 -0
  118. package/dist/notify.js.map +1 -0
  119. package/dist/org.d.ts +184 -0
  120. package/dist/org.d.ts.map +1 -0
  121. package/dist/org.js +114 -0
  122. package/dist/org.js.map +1 -0
  123. package/dist/people.d.ts +39 -0
  124. package/dist/people.d.ts.map +1 -0
  125. package/dist/people.js +88 -0
  126. package/dist/people.js.map +1 -0
  127. package/dist/problem.d.ts +12 -0
  128. package/dist/problem.d.ts.map +1 -0
  129. package/dist/problem.js +33 -0
  130. package/dist/problem.js.map +1 -0
  131. package/dist/runtime.d.ts +92 -0
  132. package/dist/runtime.d.ts.map +1 -0
  133. package/dist/runtime.js +8 -0
  134. package/dist/runtime.js.map +1 -0
  135. package/dist/scenarios.d.ts +125 -0
  136. package/dist/scenarios.d.ts.map +1 -0
  137. package/dist/scenarios.js +251 -0
  138. package/dist/scenarios.js.map +1 -0
  139. package/package.json +55 -3
@@ -0,0 +1,96 @@
1
+ // accessRequest.mjs tipleri — Devoplus One MCP sunucusu ve TypeScript tüketicileri için. Davranış .mjs'tedir.
2
+
3
+ export declare class AccessRequestError extends Error {
4
+ readonly status: number | undefined
5
+ readonly code: string | undefined
6
+ constructor(message: string, details?: { status?: number; code?: string })
7
+ }
8
+
9
+ export type AccessRequestKindName =
10
+ | 'registration'
11
+ | 'installation'
12
+ | 'dexa-query'
13
+ | 'dexa-command'
14
+ | 'app-permission'
15
+ | 'scope'
16
+ | 'new-query'
17
+
18
+ export interface AccessRequestKind {
19
+ wire: string
20
+ label: string
21
+ required: readonly string[]
22
+ optional: readonly string[]
23
+ audience: 'platform' | 'company'
24
+ }
25
+
26
+ export declare const KINDS: Readonly<Record<AccessRequestKindName, AccessRequestKind>>
27
+ export declare const LIMITS: Readonly<{
28
+ justification: number
29
+ description: number
30
+ draftSql: number
31
+ title: number
32
+ permissionName: number
33
+ additionalPermissions: number
34
+ }>
35
+
36
+ /** Kayıt talebinin ek izni: `One.<Uygulama>.<Eylem>` kodu + Türkçe ad (zorunlu) + İngilizce ad. */
37
+ export interface AdditionalPermissionInput {
38
+ code: string
39
+ nameTr: string
40
+ nameEn?: string | undefined
41
+ }
42
+
43
+ export interface AccessRequestFields {
44
+ appSlug?: string | undefined
45
+ justification?: string | undefined
46
+ titleTr?: string | undefined
47
+ titleEn?: string | undefined
48
+ portalKey?: string | undefined
49
+ queryKey?: string | undefined
50
+ permissionCode?: string | undefined
51
+ permissionNameTr?: string | undefined
52
+ permissionNameEn?: string | undefined
53
+ userGroupId?: string | undefined
54
+ scope?: string | undefined
55
+ description?: string | undefined
56
+ draftSql?: string | undefined
57
+ /** registration: uygulama içi izinler (en çok 16). */
58
+ additionalPermissions?: readonly AdditionalPermissionInput[] | undefined
59
+ }
60
+
61
+ export type AccessRequestBody = { kind: string; appSlug: string } & Record<string, string | AdditionalPermissionInput[]>
62
+
63
+ /** `GET api/v1/One/access-requests/context` — oturum portalı. */
64
+ export interface PortalContext {
65
+ portalId: string
66
+ portalName: string
67
+ /** Portaldaki var olan bir kurulumun anahtarı; yoksa `null`. */
68
+ portalKey: string | null
69
+ }
70
+
71
+ /** Sunucunun talep satırı (backend `OneAccessRequestResponse`). */
72
+ export interface AccessRequestRow {
73
+ id: string
74
+ kind: string
75
+ audience: string
76
+ status: string
77
+ appSlug: string
78
+ [field: string]: unknown
79
+ }
80
+
81
+ export interface AccessRequestClientOptions {
82
+ apiBase: string
83
+ accessToken: string
84
+ fetch?: typeof fetch
85
+ }
86
+
87
+ export declare function resolveKind(value: unknown): AccessRequestKindName | undefined
88
+ export declare function buildAccessRequest(kind: string, fields?: AccessRequestFields): AccessRequestBody
89
+ export declare function submitAccessRequest(options: AccessRequestClientOptions, body: AccessRequestBody): Promise<AccessRequestRow>
90
+ export declare function listMyAccessRequests(options: AccessRequestClientOptions): Promise<AccessRequestRow[]>
91
+ export declare function getAccessRequest(options: AccessRequestClientOptions, id: string): Promise<AccessRequestRow>
92
+ export declare function describeAccessRequest(row: Partial<AccessRequestRow>): string
93
+ export declare function buildAdditionalPermissions(value: unknown): Array<{ code: string; nameTr: string; nameEn?: string }>
94
+ export declare function parsePermissionOptions(trValues: readonly string[], enValues?: readonly string[]): AdditionalPermissionInput[]
95
+ export declare function getPortalContext(options: AccessRequestClientOptions): Promise<PortalContext>
96
+ export declare function describePortalContext(context: Partial<PortalContext>): string
@@ -0,0 +1,340 @@
1
+ // Devoplus One ERİŞİM TALEBİ istemcisi (D-75). `one request` komutu ve Devoplus One MCP sunucusu AYNI modülü kullanır;
2
+ // ikisi aynı backend ucunu (`api/v1/One/access-requests`) çağırır.
3
+ //
4
+ // ⛔ Talep YENİ BİR YETKİ YOLU AÇMAZ: yalnız yöneticiye bir istek bırakır. Gönderenin kimliği ve portalı OTURUMDAN
5
+ // (kullanıcının kendi erişim belirtecinden) gelir; bu modül gövdeye portal ya da kişi YAZMAZ.
6
+ //
7
+ // Burada yalnız gövdenin kurulması, türe göre ZORUNLU alanların varlığı, uzunluk ve sayı sınırları denetlenir. Biçim
8
+ // kuralları (kısa ad, portal anahtarı, izin kodu, sorgu anahtarı, yetki alanı) sunucudadır; sunucunun reddi
9
+ // açıklamasıyla birlikte kullanıcıya taşınır. İki yerde tutulan biçim kuralı zamanla ayrışırdı.
10
+
11
+ export class AccessRequestError extends Error {
12
+ /**
13
+ * @param {string} message kullanıcıya gösterilecek Türkçe metin
14
+ * @param {{ status?: number, code?: string }} [details]
15
+ */
16
+ constructor(message, details = {}) {
17
+ super(message)
18
+ this.name = 'AccessRequestError'
19
+ this.status = details.status
20
+ this.code = details.code
21
+ }
22
+ }
23
+
24
+ /** Sunucu sınırları — backend `OneAccessRequest` / `OneApp` / `OneAppPermission` sabitleriyle aynı. */
25
+ export const LIMITS = {
26
+ justification: 2000,
27
+ description: 2000,
28
+ draftSql: 20000,
29
+ title: 120,
30
+ permissionName: 120,
31
+ additionalPermissions: 16,
32
+ }
33
+
34
+ /**
35
+ * Talep türleri: komut adı → tel adı (backend `OneAccessRequestNames`) + zorunlu alanlar + kime düşer.
36
+ * `audience: 'platform'` → platform yöneticisi; `'company'` → talebin portalının şirket yöneticisi (küresel yönetici de
37
+ * onaylayabilir). Kayıt talebi 19.10.2026'dan beri şirket yöneticisine düşer; yetki alanı platformda kalır.
38
+ */
39
+ export const KINDS = {
40
+ registration: {
41
+ wire: 'registration',
42
+ label: 'Yeni uygulama kaydı',
43
+ required: ['titleTr'],
44
+ // `additionalPermissions`: uygulama içi izinler kayıtla birlikte istenir; onayda kataloğa girer (19.10.2026).
45
+ optional: ['titleEn', 'additionalPermissions'],
46
+ audience: 'company',
47
+ },
48
+ installation: {
49
+ wire: 'installation',
50
+ label: 'Uygulamanın portala kurulması',
51
+ // Portal anahtarını sunucu portalın adından belirler (örn. "Süvari Portal" için suvari); elle seçilemez.
52
+ // `portalKey` yalnız eski istemcilerle uyumluluk için kabul edilir, sunucu onu yok sayar (19.10.2026).
53
+ required: [],
54
+ optional: ['portalKey'],
55
+ audience: 'company',
56
+ },
57
+ 'dexa-query': {
58
+ wire: 'dexaQuery',
59
+ label: 'DEXA okuma sorgusu izni',
60
+ required: ['queryKey'],
61
+ optional: [],
62
+ audience: 'company',
63
+ },
64
+ 'dexa-command': {
65
+ wire: 'dexaCommand',
66
+ label: 'ERP\'ye yazan DEXA işlemi izni',
67
+ required: ['queryKey'],
68
+ optional: [],
69
+ audience: 'company',
70
+ },
71
+ 'app-permission': {
72
+ wire: 'appPermission',
73
+ label: 'Uygulama izninin bir gruba atanması',
74
+ required: ['permissionCode'],
75
+ optional: ['permissionNameTr', 'permissionNameEn', 'userGroupId'],
76
+ audience: 'company',
77
+ },
78
+ scope: {
79
+ wire: 'scope',
80
+ label: 'Yetki alanı (scope)',
81
+ required: ['scope'],
82
+ optional: [],
83
+ audience: 'platform',
84
+ },
85
+ 'new-query': {
86
+ wire: 'newQuery',
87
+ label: 'Henüz olmayan bir sorgu için iş talebi',
88
+ required: ['description'],
89
+ optional: ['draftSql'],
90
+ audience: 'company',
91
+ },
92
+ }
93
+
94
+ /** Alanların kullanıcıya görünen adları (hata metinleri için). */
95
+ const FIELD_LABELS = {
96
+ appSlug: 'uygulamanın kısa adı',
97
+ justification: 'gerekçe',
98
+ titleTr: 'uygulamanın Türkçe adı',
99
+ titleEn: 'uygulamanın İngilizce adı',
100
+ portalKey: 'portal anahtarı',
101
+ queryKey: 'sorgu anahtarı',
102
+ permissionCode: 'izin kodu',
103
+ permissionNameTr: 'iznin Türkçe adı',
104
+ permissionNameEn: 'iznin İngilizce adı',
105
+ userGroupId: 'kullanıcı grubu kimliği',
106
+ scope: 'yetki alanı',
107
+ description: 'sorgu tarifi',
108
+ draftSql: 'SQL taslağı',
109
+ }
110
+
111
+ const LENGTH_OF = {
112
+ justification: LIMITS.justification,
113
+ description: LIMITS.description,
114
+ draftSql: LIMITS.draftSql,
115
+ titleTr: LIMITS.title,
116
+ titleEn: LIMITS.title,
117
+ permissionNameTr: LIMITS.permissionName,
118
+ permissionNameEn: LIMITS.permissionName,
119
+ }
120
+
121
+ /** Tel adı ya da komut adı → komut adı. Harf duyarsız (`dexaQuery` = `dexa-query`). */
122
+ export function resolveKind(value) {
123
+ const text = String(value ?? '').trim().toLowerCase().replace(/_/g, '-')
124
+ for (const [name, kind] of Object.entries(KINDS)) {
125
+ if (name === text || kind.wire.toLowerCase() === text) return name
126
+ }
127
+ return undefined
128
+ }
129
+
130
+ function clean(value) {
131
+ if (value === undefined || value === null) return undefined
132
+ const text = String(value).trim()
133
+ return text === '' ? undefined : text
134
+ }
135
+
136
+ /**
137
+ * Talep gövdesini kurar. İlgisiz alanlar gövdeye girmez (sunucu yok sayardı; göndermemek talebi okuyan yöneticiye
138
+ * gösterilen içeriği daraltır). Hata → `AccessRequestError`, ağ çağrısı YAPILMADAN.
139
+ *
140
+ * @param {string} kind komut adı ya da tel adı
141
+ * @param {Record<string, unknown>} fields `appSlug`, `justification` + türün alanları
142
+ */
143
+ export function buildAccessRequest(kind, fields = {}) {
144
+ const name = resolveKind(kind)
145
+ if (!name)
146
+ throw new AccessRequestError(`Talep türü tanınmadı: "${kind}". Geçerli türler: ${Object.keys(KINDS).join(', ')}.`)
147
+ const spec = KINDS[name]
148
+ const appSlug = clean(fields.appSlug)?.toLowerCase()
149
+ if (!appSlug) throw new AccessRequestError('Uygulamanın kısa adı zorunludur (one.manifest.json dosyasındaki app.slug).')
150
+
151
+ const body = { kind: spec.wire, appSlug }
152
+ for (const key of ['justification', ...spec.required, ...spec.optional]) {
153
+ if (key === 'additionalPermissions') {
154
+ const list = buildAdditionalPermissions(fields[key])
155
+ if (list.length > 0) body[key] = list
156
+ continue
157
+ }
158
+ const value = clean(fields[key])
159
+ if (value === undefined) {
160
+ if (spec.required.includes(key))
161
+ throw new AccessRequestError(`"${spec.label}" talebi için ${FIELD_LABELS[key]} zorunludur.`)
162
+ continue
163
+ }
164
+ const max = LENGTH_OF[key]
165
+ if (max !== undefined && value.length > max)
166
+ throw new AccessRequestError(`${capitalize(FIELD_LABELS[key])} en çok ${max} karakter olabilir (${value.length}).`)
167
+ body[key] = value
168
+ }
169
+ return body
170
+ }
171
+
172
+ /**
173
+ * Kayıt talebinin ek izinleri: `[{ code, nameTr, nameEn? }]`, en çok 16. Burada yalnız yapı, sayı, uzunluk ve birebir
174
+ * yinelenen kod denetlenir; kodun biçimi (`One.<Ad>.<Eylem>`) ve uygulamanın ad alanında olması SUNUCUDADIR.
175
+ *
176
+ * @param {unknown} value
177
+ * @returns {Array<{ code: string, nameTr: string, nameEn?: string }>}
178
+ */
179
+ export function buildAdditionalPermissions(value) {
180
+ if (value === undefined || value === null) return []
181
+ if (!Array.isArray(value)) throw new AccessRequestError('Ek izinler bir liste olmalı: [{ code, nameTr, nameEn? }].')
182
+ if (value.length > LIMITS.additionalPermissions)
183
+ throw new AccessRequestError(`En çok ${LIMITS.additionalPermissions} ek izin istenebilir (${value.length}).`)
184
+ const seen = new Set()
185
+ return value.map((item, i) => {
186
+ const code = clean(item?.code)
187
+ const nameTr = clean(item?.nameTr)
188
+ const nameEn = clean(item?.nameEn)
189
+ const at = `${i + 1}. ek izin`
190
+ if (!code) throw new AccessRequestError(`${at}: izin kodu zorunludur (One.<Uygulama>.<Eylem>).`)
191
+ if (!nameTr) throw new AccessRequestError(`${at} (${code}): iznin Türkçe adı zorunludur.`)
192
+ if (code.length > 200) throw new AccessRequestError(`${at}: izin kodu en çok 200 karakter olabilir.`)
193
+ for (const [label, name] of [['Türkçe', nameTr], ['İngilizce', nameEn]])
194
+ if (name !== undefined && name.length > LIMITS.permissionName)
195
+ throw new AccessRequestError(`${at} (${code}): iznin ${label} adı en çok ${LIMITS.permissionName} karakter olabilir.`)
196
+ if (seen.has(code)) throw new AccessRequestError(`Ek izin kodu iki kez yazılmış: ${code}.`)
197
+ seen.add(code)
198
+ return nameEn === undefined ? { code, nameTr } : { code, nameTr, nameEn }
199
+ })
200
+ }
201
+
202
+ /**
203
+ * Komut satırının `--permission <kod>=<Türkçe ad>` ve `--permission-en <kod>=<İngilizce ad>` değerlerini ek izin
204
+ * listesine çevirir. İngilizce ad yalnız `--permission` ile verilmiş bir koda eklenebilir.
205
+ *
206
+ * @param {readonly string[]} trValues
207
+ * @param {readonly string[]} [enValues]
208
+ */
209
+ export function parsePermissionOptions(trValues, enValues = []) {
210
+ const split = (raw, option) => {
211
+ const text = String(raw ?? '')
212
+ const at = text.indexOf('=')
213
+ if (at <= 0) throw new AccessRequestError(`${option} "<kod>=<ad>" biçiminde olmalı: ${text}`)
214
+ return [text.slice(0, at).trim(), text.slice(at + 1).trim()]
215
+ }
216
+ const list = trValues.map((raw) => {
217
+ const [code, nameTr] = split(raw, '--permission')
218
+ return { code, nameTr }
219
+ })
220
+ for (const raw of enValues) {
221
+ const [code, nameEn] = split(raw, '--permission-en')
222
+ const item = list.find((p) => p.code === code)
223
+ if (!item) throw new AccessRequestError(`--permission-en için önce aynı kodla --permission verin: ${code}`)
224
+ item.nameEn = nameEn
225
+ }
226
+ return list
227
+ }
228
+
229
+ function capitalize(text) {
230
+ return text.charAt(0).toLocaleUpperCase('tr-TR') + text.slice(1)
231
+ }
232
+
233
+ /** API tabanı `https://.../` biçiminde olmalı; uç yolu ona eklenir. */
234
+ function endpoint(apiBase, path) {
235
+ // Belirteç bu adrese gider: düz http yalnız yerel geliştirme adresinde (RFC 6750 §5.3).
236
+ const base = apiBase ?? ''
237
+ if (!/^https:\/\/[^\s/]+(\/[^\s]*)?\/$/.test(base) && !/^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?\/([^\s]*\/)?$/.test(base))
238
+ throw new AccessRequestError(`API tabanı "https://.../" biçiminde ve "/" ile bitmeli (http yalnız localhost): ${apiBase}`)
239
+ return new URL(`api/v1/One/access-requests${path}`, apiBase).toString()
240
+ }
241
+
242
+ /** Sunucunun ProblemDetails yanıtını kullanıcı metnine çevirir; gövde yoksa durum koduna göre sabit cümle. */
243
+ async function failure(response) {
244
+ let detail
245
+ let code
246
+ try {
247
+ const problem = await response.json()
248
+ detail = typeof problem?.detail === 'string' ? problem.detail : undefined
249
+ code = typeof problem?.code === 'string' ? problem.code : undefined
250
+ } catch {
251
+ // gövdesiz 401/403 — aşağıdaki sabit metin
252
+ }
253
+ const fallback =
254
+ response.status === 401
255
+ ? 'Oturumunuz geçersiz ya da süresi dolmuş; yeniden giriş yapın.'
256
+ : response.status === 403
257
+ ? 'Bu talebi gönderme yetkiniz yok.'
258
+ : response.status === 429
259
+ ? 'Çok fazla talep gönderdiniz; bir süre sonra yeniden deneyin.'
260
+ : `Devoplus isteği başarısız oldu (HTTP ${response.status}).`
261
+ return new AccessRequestError(detail ?? fallback, { status: response.status, code })
262
+ }
263
+
264
+ /**
265
+ * @typedef {{ apiBase: string, accessToken: string, fetch?: typeof fetch }} ClientOptions
266
+ */
267
+
268
+ async function call(options, path, init = {}) {
269
+ const doFetch = options.fetch ?? fetch
270
+ if (!options.accessToken) throw new AccessRequestError('Oturum yok; önce giriş yapın.', { status: 401 })
271
+ let response
272
+ try {
273
+ response = await doFetch(endpoint(options.apiBase, path), {
274
+ ...init,
275
+ headers: {
276
+ Accept: 'application/json',
277
+ Authorization: `Bearer ${options.accessToken}`,
278
+ ...(init.body ? { 'Content-Type': 'application/json' } : {}),
279
+ },
280
+ })
281
+ } catch (error) {
282
+ if (error instanceof AccessRequestError) throw error
283
+ throw new AccessRequestError('Devoplus API\'ye ulaşılamadı.')
284
+ }
285
+ if (!response.ok) throw await failure(response)
286
+ return response.json()
287
+ }
288
+
289
+ /** Talebi gönderir. Dönüş: sunucunun talep satırı (`id`, `status` …). */
290
+ export function submitAccessRequest(options, body) {
291
+ return call(options, '', { method: 'POST', body: JSON.stringify(body) })
292
+ }
293
+
294
+ /** Çağıranın kendi talepleri (en yeni önce). */
295
+ export function listMyAccessRequests(options) {
296
+ return call(options, '/mine')
297
+ }
298
+
299
+ /**
300
+ * Oturum portalının bağlamı: `{ portalId, portalName, portalKey | null }`. Kurulum talebinde kullanıcıya portal adresi
301
+ * sormamak için okunur; `portalKey` portaldaki var olan bir kurulumun anahtarıdır, yoksa `null`.
302
+ */
303
+ export function getPortalContext(options) {
304
+ return call(options, '/context')
305
+ }
306
+
307
+ /** Portal bağlamını tek satırlık Türkçe özete çevirir. */
308
+ export function describePortalContext(context) {
309
+ const name = context?.portalName ? String(context.portalName) : 'adı okunamadı'
310
+ const key =
311
+ typeof context?.portalKey === 'string' && context.portalKey
312
+ ? `kısa ad (portal anahtarı): ${context.portalKey}`
313
+ : 'bu portalda henüz kısa ad yok; kurulum onayında sunucu portalın adından belirler'
314
+ return `Portal: ${name} (kimlik ${context?.portalId ?? '?'}); ${key}`
315
+ }
316
+
317
+ /** Tek talep — çağıran talep sahibi değilse sunucu 404 döner. */
318
+ export function getAccessRequest(options, id) {
319
+ const text = String(id ?? '').trim()
320
+ if (!/^[0-9a-f]{24}$/i.test(text)) throw new AccessRequestError(`Talep kimliği 24 karakterlik onaltılık olmalı: ${id}`)
321
+ return call(options, `/${text}`)
322
+ }
323
+
324
+ const STATUS_LABELS = { pending: 'Bekliyor', approved: 'Onaylandı', rejected: 'Reddedildi' }
325
+
326
+ /** Talep satırını tek satırlık Türkçe özete çevirir (CLI listesi ve MCP yanıtı). */
327
+ export function describeAccessRequest(row) {
328
+ const name = resolveKind(row?.kind)
329
+ const label = name ? KINDS[name].label : String(row?.kind ?? '?')
330
+ const subject =
331
+ row?.portalKey ?? row?.queryKey ?? row?.permissionCode ?? row?.scope ?? row?.titleTr ?? row?.description ?? ''
332
+ const status = STATUS_LABELS[row?.status] ?? String(row?.status ?? '?')
333
+ const parts = [`${row?.id ?? '?'} ${status.padEnd(10)} ${row?.appSlug ?? '?'}, ${label}`]
334
+ if (subject) parts.push(`: ${String(subject).slice(0, 80)}`)
335
+ const extra = Array.isArray(row?.additionalPermissions) ? row.additionalPermissions.length : 0
336
+ if (extra > 0) parts.push(` (+${extra} ek izin)`)
337
+ if (row?.decisionNote) parts.push(`; not: ${row.decisionNote}`)
338
+ if (row?.resolvedQueryKey) parts.push(`; sorgu anahtarı: ${row.resolvedQueryKey}`)
339
+ return parts.join('')
340
+ }
@@ -0,0 +1,97 @@
1
+ // appOps.mjs tipleri — Devoplus One MCP sunucusu ve TypeScript tüketicileri için. Davranış .mjs'tedir.
2
+
3
+ export declare class AppOpsError extends Error {
4
+ readonly status: number | undefined
5
+ readonly code: string | undefined
6
+ constructor(message: string, details?: { status?: number; code?: string })
7
+ }
8
+
9
+ export declare const SLUG_RE: RegExp
10
+ export declare const SLUG_MAX: number
11
+ export declare const PORTAL_KEY_RE: RegExp
12
+ export declare const VERSION_RE: RegExp
13
+ export declare const DAYS_DEFAULT: number
14
+ export declare const DAYS_MAX: number
15
+ export declare const PREVIEW_HOST_BASE: string
16
+ export declare const NOT_CONFIGURED_MESSAGE: string
17
+ export declare const INSIGHTS_NOT_CONFIGURED_MESSAGE: string
18
+ export declare const ROLLBACK_WARNING: string
19
+
20
+ export type DeploymentAction = 'deploy' | 'promote' | 'rollback'
21
+ export declare const ACTIONS: Readonly<Record<DeploymentAction, string>>
22
+ export declare const COMMAND_ACTIONS: Readonly<{ publish: 'deploy'; promote: 'promote'; rollback: 'rollback' }>
23
+
24
+ export interface AppOpsClientOptions {
25
+ apiBase: string
26
+ accessToken: string
27
+ fetch?: typeof fetch
28
+ }
29
+
30
+ export interface DeploymentFields {
31
+ action?: string | undefined
32
+ portalKey?: string | undefined
33
+ toVersion?: string | undefined
34
+ }
35
+
36
+ export interface DeploymentRequestBody {
37
+ action: DeploymentAction
38
+ portalKey?: string
39
+ toVersion?: string
40
+ }
41
+
42
+ /** Backend yanıtı (C5): 202 `{ id, status, pipelineUrl? }`. */
43
+ export interface DeploymentResult {
44
+ id: string
45
+ status: 'queued' | 'not_configured' | (string & {})
46
+ pipelineUrl?: string
47
+ }
48
+
49
+ /** Liste satırı — C5 alanları; sunucu fazlasını taşıyabilir. */
50
+ export interface DeploymentRow extends Partial<DeploymentResult> {
51
+ action?: string
52
+ portalKey?: string
53
+ toVersion?: string
54
+ createdAt?: string
55
+ [field: string]: unknown
56
+ }
57
+
58
+ export interface AppInsights {
59
+ configured: boolean
60
+ from?: string
61
+ to?: string
62
+ totals?: { requests?: number; errors?: number; cpuP50Ms?: number; cpuP99Ms?: number }
63
+ daily?: Array<{ date: string; requests: number; errors: number }>
64
+ recentErrors?: Array<{ time: string; message: string; path?: string }>
65
+ jobs?: { failed?: number }
66
+ }
67
+
68
+ export type OpsCommand = 'publish' | 'promote' | 'rollback' | 'deployments' | 'status'
69
+
70
+ export interface OpsArgs {
71
+ json: boolean
72
+ portalKey: string | undefined
73
+ app: string | undefined
74
+ toVersion?: string | undefined
75
+ yes?: boolean
76
+ days?: number
77
+ }
78
+
79
+ export declare function checkSlug(value: unknown): string
80
+ export declare function checkPortalKey(value: unknown): string | undefined
81
+ export declare function checkDays(value: unknown): number
82
+ export declare function buildDeploymentRequest(fields?: DeploymentFields): DeploymentRequestBody
83
+ export declare function requestDeployment(options: AppOpsClientOptions, slug: string, body: DeploymentFields): Promise<DeploymentResult>
84
+ export declare function listDeployments(options: AppOpsClientOptions, slug: string, portalKey?: string): Promise<DeploymentRow[]>
85
+ export declare function getInsights(
86
+ options: AppOpsClientOptions,
87
+ slug: string,
88
+ query?: { portalKey?: string | undefined; days?: number | string | undefined },
89
+ ): Promise<AppInsights>
90
+ export declare function previewAddress(slug: string, portalKey: string | undefined): string | undefined
91
+ export declare function describeDeployment(row: Partial<DeploymentRow>): string
92
+ export declare function describeDeploymentResult(
93
+ result: Partial<DeploymentResult>,
94
+ request: { action: string; slug: string; portalKey?: string | undefined },
95
+ ): string
96
+ export declare function describeInsights(insights: Partial<AppInsights> | undefined): string
97
+ export declare function parseOpsArgs(command: OpsCommand, argv: readonly string[]): OpsArgs