@linkup-ai/abap-ai 2.0.0

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 (114) hide show
  1. package/README.md +384 -0
  2. package/dist/adt-client.js +364 -0
  3. package/dist/cli/activate.js +113 -0
  4. package/dist/cli/init.js +333 -0
  5. package/dist/cli/remove.js +80 -0
  6. package/dist/cli/status.js +229 -0
  7. package/dist/cli/systems.js +68 -0
  8. package/dist/cli.js +81 -0
  9. package/dist/index.js +1318 -0
  10. package/dist/knowledge/abap/abap-dictionary.md +199 -0
  11. package/dist/knowledge/abap/abap-sql.md +296 -0
  12. package/dist/knowledge/abap/amdp.md +273 -0
  13. package/dist/knowledge/abap/clean-code.md +293 -0
  14. package/dist/knowledge/abap/cloud-background-processing.md +250 -0
  15. package/dist/knowledge/abap/cloud-communication.md +265 -0
  16. package/dist/knowledge/abap/cloud-development.md +176 -0
  17. package/dist/knowledge/abap/cloud-extensibility.md +252 -0
  18. package/dist/knowledge/abap/cloud-released-apis.md +261 -0
  19. package/dist/knowledge/abap/constructor-expressions.md +289 -0
  20. package/dist/knowledge/abap/enhancements.md +232 -0
  21. package/dist/knowledge/abap/exceptions.md +271 -0
  22. package/dist/knowledge/abap/internal-tables.md +205 -0
  23. package/dist/knowledge/abap/object-orientation.md +298 -0
  24. package/dist/knowledge/abap/performance.md +216 -0
  25. package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
  26. package/dist/knowledge/abap/rap-business-events.md +216 -0
  27. package/dist/knowledge/abap/rap-draft.md +191 -0
  28. package/dist/knowledge/abap/rap-eml.md +453 -0
  29. package/dist/knowledge/abap/rap-end-to-end.md +486 -0
  30. package/dist/knowledge/abap/rap-feature-control.md +185 -0
  31. package/dist/knowledge/abap/rap-numbering.md +280 -0
  32. package/dist/knowledge/abap/rap-service-exposure.md +163 -0
  33. package/dist/knowledge/abap/rap-unmanaged.md +468 -0
  34. package/dist/knowledge/abap/string-processing.md +180 -0
  35. package/dist/knowledge/abap/unit-testing.md +303 -0
  36. package/dist/knowledge/abap-cds/access-control.md +241 -0
  37. package/dist/knowledge/abap-cds/annotations.md +331 -0
  38. package/dist/knowledge/abap-cds/associations.md +254 -0
  39. package/dist/knowledge/abap-cds/expressions.md +230 -0
  40. package/dist/knowledge/abap-cds/functions.md +245 -0
  41. package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
  42. package/dist/knowledge/cap/authentication.md +278 -0
  43. package/dist/knowledge/cap/cdl-syntax.md +247 -0
  44. package/dist/knowledge/cap/cql-queries.md +266 -0
  45. package/dist/knowledge/cap/deployment.md +343 -0
  46. package/dist/knowledge/cap/event-handlers.md +287 -0
  47. package/dist/knowledge/cap/fiori-integration.md +303 -0
  48. package/dist/knowledge/cap/service-definitions.md +287 -0
  49. package/dist/knowledge/fiori/annotations.md +347 -0
  50. package/dist/knowledge/fiori/deployment.md +340 -0
  51. package/dist/knowledge/fiori/fiori-elements.md +332 -0
  52. package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
  53. package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
  54. package/dist/knowledge/fiori/ui5-controllers.md +358 -0
  55. package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
  56. package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
  57. package/dist/knowledge/fiori/ui5-manifest.md +411 -0
  58. package/dist/knowledge/fiori/ui5-routing.md +303 -0
  59. package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
  60. package/dist/logger.js +114 -0
  61. package/dist/system-profile.js +207 -0
  62. package/dist/tools/abap-doc.js +72 -0
  63. package/dist/tools/abapgit.js +161 -0
  64. package/dist/tools/activate.js +68 -0
  65. package/dist/tools/atc-check.js +117 -0
  66. package/dist/tools/auth-object.js +56 -0
  67. package/dist/tools/breakpoints.js +76 -0
  68. package/dist/tools/call-hierarchy.js +84 -0
  69. package/dist/tools/cds-annotations.js +98 -0
  70. package/dist/tools/cds-dependencies.js +65 -0
  71. package/dist/tools/check.js +47 -0
  72. package/dist/tools/code-completion.js +70 -0
  73. package/dist/tools/code-coverage.js +111 -0
  74. package/dist/tools/create-amdp.js +111 -0
  75. package/dist/tools/create-dcl.js +81 -0
  76. package/dist/tools/create-transport.js +38 -0
  77. package/dist/tools/create.js +285 -0
  78. package/dist/tools/data-preview.js +37 -0
  79. package/dist/tools/delete.js +45 -0
  80. package/dist/tools/deploy-bsp.js +298 -0
  81. package/dist/tools/discovery.js +59 -0
  82. package/dist/tools/element-info.js +93 -0
  83. package/dist/tools/enhancements.js +186 -0
  84. package/dist/tools/extract-method.js +44 -0
  85. package/dist/tools/function-group.js +59 -0
  86. package/dist/tools/knowledge.js +275 -0
  87. package/dist/tools/lock-object.js +75 -0
  88. package/dist/tools/message-class.js +67 -0
  89. package/dist/tools/navigate.js +80 -0
  90. package/dist/tools/number-range.js +57 -0
  91. package/dist/tools/object-documentation.js +43 -0
  92. package/dist/tools/object-structure.js +78 -0
  93. package/dist/tools/object-versions.js +57 -0
  94. package/dist/tools/package-contents.js +60 -0
  95. package/dist/tools/pretty-printer.js +35 -0
  96. package/dist/tools/publish-binding.js +49 -0
  97. package/dist/tools/quick-fix.js +69 -0
  98. package/dist/tools/read.js +167 -0
  99. package/dist/tools/refactor-rename.js +60 -0
  100. package/dist/tools/release-transport.js +24 -0
  101. package/dist/tools/released-apis.js +51 -0
  102. package/dist/tools/repository-tree.js +90 -0
  103. package/dist/tools/scaffold-rap.js +642 -0
  104. package/dist/tools/search.js +73 -0
  105. package/dist/tools/shared/data-format.js +101 -0
  106. package/dist/tools/sql-console.js +17 -0
  107. package/dist/tools/system-info.js +270 -0
  108. package/dist/tools/traces.js +66 -0
  109. package/dist/tools/transport-contents.js +83 -0
  110. package/dist/tools/transports.js +67 -0
  111. package/dist/tools/unit-test.js +135 -0
  112. package/dist/tools/where-used.js +59 -0
  113. package/dist/tools/write.js +101 -0
  114. package/package.json +49 -0
@@ -0,0 +1,364 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.http = exports.SUPPORTED_OBJECT_TYPES = exports.AdtError = exports.SAP_LANGUAGE = exports.SAP_USER = void 0;
7
+ exports.resolveAdtPath = resolveAdtPath;
8
+ exports.adtGet = adtGet;
9
+ exports.adtGetXml = adtGetXml;
10
+ exports.adtGetWithEtag = adtGetWithEtag;
11
+ exports.adtPut = adtPut;
12
+ exports.adtLock = adtLock;
13
+ exports.adtUnlock = adtUnlock;
14
+ exports.adtDelete = adtDelete;
15
+ exports.adtPostXml = adtPostXml;
16
+ exports.adtGetXmlWithParams = adtGetXmlWithParams;
17
+ exports.adtPostText = adtPostText;
18
+ exports.ensureSession = ensureSession;
19
+ exports.resetSession = resetSession;
20
+ const axios_1 = __importDefault(require("axios"));
21
+ const axios_cookiejar_support_1 = require("axios-cookiejar-support");
22
+ const tough_cookie_1 = require("tough-cookie");
23
+ const logger_js_1 = require("./logger.js");
24
+ // ─── Configuração via env ─────────────────────────────────────────
25
+ const SAP_URL = process.env.SAP_URL ?? "";
26
+ exports.SAP_USER = process.env.SAP_USER ?? "";
27
+ const SAP_PASS = process.env.SAP_PASS ?? "";
28
+ const SAP_CLIENT = process.env.SAP_CLIENT ?? "100";
29
+ exports.SAP_LANGUAGE = process.env.SAP_LANGUAGE ?? "PT";
30
+ /** Timeout em ms para chamadas ADT (padrão: 60s, configurável via SAP_TIMEOUT) */
31
+ const SAP_TIMEOUT = parseInt(process.env.SAP_TIMEOUT ?? "60000", 10);
32
+ /** Número máximo de retries em 401 (sessão expirada) */
33
+ const MAX_RETRIES = 1;
34
+ let session = null;
35
+ // ─── HTTP Client ──────────────────────────────────────────────────
36
+ function createHttpClient() {
37
+ const jar = new tough_cookie_1.CookieJar();
38
+ // NODE_TLS_REJECT_UNAUTHORIZED=0 já está definido no mcp.json para ignorar certs self-signed.
39
+ // axios-cookiejar-support@4 é incompatível com httpsAgent customizado — não usar.
40
+ return (0, axios_cookiejar_support_1.wrapper)(axios_1.default.create({
41
+ baseURL: `${SAP_URL}/sap/bc/adt`,
42
+ jar,
43
+ withCredentials: true,
44
+ auth: { username: exports.SAP_USER, password: SAP_PASS },
45
+ params: { "sap-client": SAP_CLIENT, "sap-language": exports.SAP_LANGUAGE },
46
+ timeout: SAP_TIMEOUT,
47
+ }));
48
+ }
49
+ const http = createHttpClient();
50
+ exports.http = http;
51
+ // ─── Sessão CSRF ──────────────────────────────────────────────────
52
+ async function ensureSession() {
53
+ if (session)
54
+ return session.csrfToken;
55
+ const response = await http.get("/discovery", {
56
+ headers: { "X-CSRF-Token": "Fetch", Accept: "application/xml" },
57
+ validateStatus: (status) => status < 500, // 406 é esperado mas traz o CSRF token
58
+ });
59
+ const token = response.headers["x-csrf-token"];
60
+ if (!token) {
61
+ throw new AdtError("Falha ao obter CSRF token do SAP ADT. Verifique se o serviço /sap/bc/adt/discovery está ativo.", 0, "/discovery");
62
+ }
63
+ session = { csrfToken: token };
64
+ return token;
65
+ }
66
+ function resetSession() {
67
+ session = null;
68
+ }
69
+ // ─── Erros tipados ────────────────────────────────────────────────
70
+ class AdtError extends Error {
71
+ statusCode;
72
+ path;
73
+ sapMessage;
74
+ constructor(message, statusCode, path, sapMessage) {
75
+ super(message);
76
+ this.statusCode = statusCode;
77
+ this.path = path;
78
+ this.sapMessage = sapMessage;
79
+ this.name = "AdtError";
80
+ }
81
+ }
82
+ exports.AdtError = AdtError;
83
+ function isAxiosError(error) {
84
+ return typeof error === "object" && error !== null && ("response" in error || "code" in error);
85
+ }
86
+ // ─── Mensagens de erro em português ───────────────────────────────
87
+ function translateError(error, path) {
88
+ if (error instanceof AdtError)
89
+ return error;
90
+ if (isAxiosError(error)) {
91
+ const status = error.response?.status ?? 0;
92
+ const sapMsg = typeof error.response?.data === "string"
93
+ ? extractSapMessage(error.response.data)
94
+ : undefined;
95
+ switch (status) {
96
+ case 401:
97
+ return new AdtError("Credenciais inválidas ou sessão expirada. Verifique SAP_USER e SAP_PASS.", 401, path, sapMsg);
98
+ case 403:
99
+ return new AdtError(`Sem autorização para acessar ${path}. Verifique as autorizações do usuário ${exports.SAP_USER} no SAP.`, 403, path, sapMsg);
100
+ case 404:
101
+ return new AdtError(`Objeto não encontrado: ${path}. Verifique o nome e tipo do objeto.`, 404, path, sapMsg);
102
+ case 409:
103
+ return new AdtError(`Conflito ao acessar ${path}. O objeto pode estar bloqueado por outro usuário.`, 409, path, sapMsg);
104
+ case 412:
105
+ return new AdtError(`ETag desatualizado para ${path}. O objeto foi modificado por outro processo. Tente novamente.`, 412, path, sapMsg);
106
+ case 422:
107
+ return new AdtError(sapMsg || `Erro de validação em ${path}. Verifique os dados enviados.`, 422, path, sapMsg);
108
+ default:
109
+ if (status >= 400) {
110
+ return new AdtError(sapMsg || `Erro HTTP ${status} ao acessar ${path}: ${error.response?.statusText ?? "erro desconhecido"}`, status, path, sapMsg);
111
+ }
112
+ }
113
+ // Erros de rede (sem response)
114
+ if (error.code === "ECONNREFUSED") {
115
+ return new AdtError(`Conexão recusada: ${SAP_URL}. Verifique se o SAP está acessível e a VPN está conectada.`, 0, path);
116
+ }
117
+ if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") {
118
+ return new AdtError(`Timeout ao acessar ${path} (limite: ${SAP_TIMEOUT / 1000}s). O servidor SAP pode estar lento ou inacessível.`, 0, path);
119
+ }
120
+ if (error.code === "ENOTFOUND") {
121
+ return new AdtError(`Host não encontrado: ${SAP_URL}. Verifique a URL do SAP e a resolução DNS.`, 0, path);
122
+ }
123
+ if (error.code === "UNABLE_TO_VERIFY_LEAF_SIGNATURE" || error.code === "DEPTH_ZERO_SELF_SIGNED_CERT") {
124
+ return new AdtError(`Certificado SSL inválido para ${SAP_URL}. Defina NODE_TLS_REJECT_UNAUTHORIZED=0 no mcp.json.`, 0, path);
125
+ }
126
+ }
127
+ const msg = error instanceof Error ? error.message : String(error);
128
+ return new AdtError(`Erro inesperado em ${path}: ${msg}`, 0, path);
129
+ }
130
+ /** Extrai mensagem de erro do XML de resposta SAP */
131
+ function extractSapMessage(xml) {
132
+ // SAP retorna erros em <exc:exception><exc:message>
133
+ const match = xml.match(/<(?:exc:)?message[^>]*>([^<]+)<\/(?:exc:)?message>/i)
134
+ || xml.match(/<msg[^>]*>([^<]+)<\/msg>/i)
135
+ || xml.match(/<shortText>([^<]+)<\/shortText>/i);
136
+ return match?.[1]?.trim();
137
+ }
138
+ // ─── Retry com logging ────────────────────────────────────────────
139
+ /**
140
+ * Wrapper central: executa uma operação ADT com retry automático em 401
141
+ * e logging de cada chamada.
142
+ */
143
+ async function withRetry(method, path, fn) {
144
+ let lastError;
145
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
146
+ const elapsed = (0, logger_js_1.startTimer)();
147
+ try {
148
+ const result = await fn();
149
+ (0, logger_js_1.logCall)({
150
+ timestamp: new Date().toISOString(),
151
+ method,
152
+ path,
153
+ status: 200,
154
+ duration_ms: elapsed(),
155
+ });
156
+ return result;
157
+ }
158
+ catch (error) {
159
+ const duration = elapsed();
160
+ lastError = error;
161
+ const status = isAxiosError(error) ? (error.response?.status ?? 0) : 0;
162
+ (0, logger_js_1.logCall)({
163
+ timestamp: new Date().toISOString(),
164
+ method,
165
+ path,
166
+ status,
167
+ duration_ms: duration,
168
+ error: error instanceof Error ? error.message : String(error),
169
+ });
170
+ // 401 = sessão expirada → reseta e tenta de novo (apenas 1x)
171
+ if (status === 401 && attempt < MAX_RETRIES) {
172
+ resetSession();
173
+ continue;
174
+ }
175
+ // Timeout → tenta de novo (apenas 1x)
176
+ if (isAxiosError(error) && (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") && attempt < MAX_RETRIES) {
177
+ continue;
178
+ }
179
+ break;
180
+ }
181
+ }
182
+ throw translateError(lastError, path);
183
+ }
184
+ // ─── Mapeamento de tipo SAP para caminho ADT ─────────────────────
185
+ const TYPE_TO_PATH = {
186
+ // Objetos ABAP clássicos
187
+ "PROG/P": "programs/programs",
188
+ "CLAS/OC": "oo/classes",
189
+ "FUGR/FF": "functions/functionmodules",
190
+ "DOMA/D": "ddic/domains",
191
+ "DTEL/D": "ddic/dataelements",
192
+ "TABL/DT": "ddic/tables",
193
+ "TABL/DS": "ddic/structures",
194
+ "INTF/OI": "oo/interfaces",
195
+ // Objetos RAP / Fiori
196
+ "DDLS/DF": "ddic/ddl/sources",
197
+ "DDLX/MX": "ddic/ddlx/sources",
198
+ "SRVD/SRV": "ddic/srvd/sources",
199
+ "BDEF/BDO": "bo/behaviordefinitions",
200
+ "SRVB/SVB": "businessservices/bindings",
201
+ // Objetos adicionais
202
+ "FUGR/F": "functions/groups",
203
+ "TTYP/TT": "ddic/tabletypes",
204
+ "MSAG/N": "messageclass",
205
+ // Transformações
206
+ "XSLT/XT": "transformations/xslt",
207
+ "XSLT/ST": "transformations/simple",
208
+ // Enhancements
209
+ "ENHS/ES": "enhancements/spots",
210
+ "ENHO/EO": "enhancements/implementations",
211
+ // DDIC adicional
212
+ "ENQU/DL": "ddic/lockobjects/sources",
213
+ "NROB/NR": "numberranges/objects",
214
+ "SUSO/B": "authorization/authorizationobjects",
215
+ };
216
+ function resolveAdtPath(objectType) {
217
+ const path = TYPE_TO_PATH[objectType];
218
+ if (!path)
219
+ throw new AdtError(`Tipo de objeto não suportado: ${objectType}. Tipos válidos: ${Object.keys(TYPE_TO_PATH).join(", ")}`, 0, "");
220
+ return path;
221
+ }
222
+ // ─── Funções ADT com retry e logging ──────────────────────────────
223
+ async function adtGet(path) {
224
+ return withRetry("GET", path, async () => {
225
+ await ensureSession();
226
+ const response = await http.get(path, {
227
+ headers: { Accept: "text/plain" },
228
+ responseType: "text",
229
+ });
230
+ return response.data;
231
+ });
232
+ }
233
+ async function adtGetXml(path) {
234
+ return withRetry("GET_XML", path, async () => {
235
+ await ensureSession();
236
+ const response = await http.get(path, {
237
+ headers: { Accept: "application/xml" },
238
+ responseType: "text",
239
+ });
240
+ return response.data;
241
+ });
242
+ }
243
+ async function adtGetWithEtag(path) {
244
+ return withRetry("GET_ETAG", path, async () => {
245
+ await ensureSession();
246
+ const response = await http.get(path, {
247
+ headers: { Accept: "text/plain" },
248
+ responseType: "text",
249
+ });
250
+ const etag = response.headers["etag"];
251
+ if (!etag)
252
+ throw new AdtError("ETag não retornado pelo servidor — impossível gravar com segurança. Verifique se o objeto suporta edição via ADT.", 0, path);
253
+ return { source: response.data, etag };
254
+ });
255
+ }
256
+ async function adtPut(path, source, etag, transportRequest) {
257
+ await withRetry("PUT", path, async () => {
258
+ const csrf = await ensureSession();
259
+ const params = {};
260
+ if (transportRequest)
261
+ params.corrNr = transportRequest;
262
+ await http.put(path, source, {
263
+ headers: {
264
+ "Content-Type": "text/plain",
265
+ "X-CSRF-Token": csrf,
266
+ "If-Match": etag,
267
+ },
268
+ params,
269
+ });
270
+ });
271
+ }
272
+ async function adtLock(objectPath) {
273
+ return withRetry("LOCK", objectPath, async () => {
274
+ const csrf = await ensureSession();
275
+ const resp = await http.post(objectPath, "", {
276
+ headers: { "X-CSRF-Token": csrf },
277
+ params: { _action: "LOCK", accessMode: "MODIFY" },
278
+ validateStatus: (status) => status < 500,
279
+ responseType: "text",
280
+ });
281
+ if (resp.status >= 300) {
282
+ throw new AdtError(`Falha ao bloquear objeto ${objectPath} (status ${resp.status}). O objeto pode estar bloqueado por outro usuário.`, resp.status, objectPath);
283
+ }
284
+ // Extrair lockHandle do XML de resposta
285
+ const data = typeof resp.data === "string" ? resp.data : "";
286
+ const handleMatch = data.match(/<LOCK_HANDLE>([^<]+)<\/LOCK_HANDLE>/);
287
+ return handleMatch?.[1] ?? "";
288
+ });
289
+ }
290
+ async function adtUnlock(objectPath) {
291
+ await withRetry("UNLOCK", objectPath, async () => {
292
+ const csrf = await ensureSession();
293
+ await http.post(objectPath, "", {
294
+ headers: { "X-CSRF-Token": csrf },
295
+ params: { _action: "UNLOCK" },
296
+ validateStatus: (status) => status < 500,
297
+ });
298
+ });
299
+ }
300
+ async function adtDelete(path, transportRequest) {
301
+ await withRetry("DELETE", path, async () => {
302
+ const csrf = await ensureSession();
303
+ const params = {};
304
+ if (transportRequest)
305
+ params.corrNr = transportRequest;
306
+ await http.delete(path, {
307
+ headers: { "X-CSRF-Token": csrf },
308
+ params,
309
+ });
310
+ });
311
+ }
312
+ async function adtPostXml(path, body, params, accept = "application/xml") {
313
+ return withRetry("POST_XML", path, async () => {
314
+ const csrf = await ensureSession();
315
+ const response = await http.post(path, body, {
316
+ headers: {
317
+ "Content-Type": "application/xml",
318
+ Accept: accept,
319
+ "X-CSRF-Token": csrf,
320
+ },
321
+ params,
322
+ responseType: "text",
323
+ validateStatus: (status) => status < 500,
324
+ });
325
+ return {
326
+ data: response.data,
327
+ status: response.status,
328
+ headers: response.headers,
329
+ };
330
+ });
331
+ }
332
+ async function adtGetXmlWithParams(path, params) {
333
+ return withRetry("GET_XML", path, async () => {
334
+ await ensureSession();
335
+ const response = await http.get(path, {
336
+ headers: { Accept: "application/xml" },
337
+ params,
338
+ responseType: "text",
339
+ });
340
+ return response.data;
341
+ });
342
+ }
343
+ async function adtPostText(path, body, params, accept = "application/xml") {
344
+ return withRetry("POST_TEXT", path, async () => {
345
+ const csrf = await ensureSession();
346
+ const response = await http.post(path, body, {
347
+ headers: {
348
+ "Content-Type": "text/plain",
349
+ Accept: accept,
350
+ "X-CSRF-Token": csrf,
351
+ },
352
+ params,
353
+ responseType: "text",
354
+ validateStatus: (status) => status < 500,
355
+ });
356
+ return {
357
+ data: response.data,
358
+ status: response.status,
359
+ headers: response.headers,
360
+ };
361
+ });
362
+ }
363
+ // ─── Exports ──────────────────────────────────────────────────────
364
+ exports.SUPPORTED_OBJECT_TYPES = Object.keys(TYPE_TO_PATH);
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.readLicense = readLicense;
37
+ exports.activate = activate;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const LICENSE_DIR = path.join(process.env.HOME || "~", ".abap-ai");
41
+ const LICENSE_PATH = path.join(LICENSE_DIR, "license.json");
42
+ // TODO: Substituir pela URL real quando o license server existir
43
+ const LICENSE_API_URL = "https://api.lkpabap.ai/v1/license/validate";
44
+ function saveLicense(license) {
45
+ if (!fs.existsSync(LICENSE_DIR)) {
46
+ fs.mkdirSync(LICENSE_DIR, { recursive: true });
47
+ }
48
+ fs.writeFileSync(LICENSE_PATH, JSON.stringify(license, null, 2) + "\n", "utf-8");
49
+ }
50
+ function readLicense() {
51
+ try {
52
+ const raw = fs.readFileSync(LICENSE_PATH, "utf-8");
53
+ return JSON.parse(raw);
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ async function activate(key) {
60
+ console.log("\n ⏳ Validando licença...");
61
+ // -----------------------------------------------------------------
62
+ // STUB: Enquanto o license server não existe, simula validação local
63
+ // Aceita qualquer chave no formato LK-XXXX-XXXX-XXXX
64
+ // -----------------------------------------------------------------
65
+ const keyPattern = /^LK-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/i;
66
+ if (!keyPattern.test(key)) {
67
+ console.log(` ✗ Formato de chave inválido.`);
68
+ console.log(` Formato esperado: LK-XXXX-XXXX-XXXX`);
69
+ console.log(` Adquira em: https://lkpabap.ai\n`);
70
+ process.exit(1);
71
+ }
72
+ // Simular chamada ao license server
73
+ // TODO: Substituir por fetch real ao LICENSE_API_URL
74
+ const isAllInOne = key.toUpperCase().startsWith("LK-A");
75
+ const plan = key.toUpperCase().includes("ENT") ? "enterprise" : key.toUpperCase().includes("STA") ? "starter" : "pro";
76
+ const license = {
77
+ key: key.toUpperCase(),
78
+ plan,
79
+ mode: isAllInOne ? "allinone" : "byok",
80
+ limits: {
81
+ systems: plan === "starter" ? 1 : plan === "pro" ? 3 : -1,
82
+ calls_per_day: plan === "starter" ? 200 : -1,
83
+ tokens_per_month: isAllInOne ? (plan === "starter" ? 500000 : plan === "pro" ? 5000000 : 20000000) : undefined,
84
+ },
85
+ expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString().split("T")[0],
86
+ validated_at: new Date().toISOString(),
87
+ proxy_url: isAllInOne ? "https://proxy.lkpabap.ai/v1" : null,
88
+ };
89
+ saveLicense(license);
90
+ const planLabel = `${plan.charAt(0).toUpperCase() + plan.slice(1)} (${license.mode === "byok" ? "BYOK" : "All-in-One"})`;
91
+ const systemsLabel = license.limits.systems === -1 ? "Ilimitado" : `até ${license.limits.systems}`;
92
+ const callsLabel = license.limits.calls_per_day === -1 ? "Ilimitado" : `${license.limits.calls_per_day}/dia`;
93
+ console.log(` ✓ Licença válida!`);
94
+ console.log(`
95
+ ╭──────────────────────────────────────────╮
96
+ │ Plano: ${planLabel.padEnd(25)}│
97
+ │ Válido até: ${license.expires.padEnd(25)}│
98
+ │ Sistemas: ${systemsLabel.padEnd(25)}│
99
+ │ Chamadas/dia: ${callsLabel.padEnd(25)}│`);
100
+ if (license.mode === "allinone") {
101
+ const tokensLabel = license.limits.tokens_per_month
102
+ ? `${(license.limits.tokens_per_month / 1000000).toFixed(0)}M`
103
+ : "N/A";
104
+ console.log(` │ Tokens/mês: ${tokensLabel.padEnd(25)}│`);
105
+ console.log(` │${" ".repeat(42)}│`);
106
+ console.log(` │ ✓ Claude proxy configurado${" ".repeat(13)}│`);
107
+ console.log(` │ URL: ${(license.proxy_url || "").padEnd(32)}│`);
108
+ }
109
+ console.log(` │${" ".repeat(42)}│`);
110
+ console.log(` │ Licença salva em ~/.abap-ai/license${" ".repeat(4)}│`);
111
+ console.log(` ╰──────────────────────────────────────────╯`);
112
+ console.log(`\n Próximo passo: abap-ai init\n`);
113
+ }