dart-fss-cli 0.4.1

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.
@@ -0,0 +1,1715 @@
1
+ // src/cli.ts
2
+ import { Command } from "commander";
3
+
4
+ // src/config.ts
5
+ import { homedir } from "os";
6
+ import { join as join2 } from "path";
7
+
8
+ // src/env.ts
9
+ import { existsSync, readFileSync } from "fs";
10
+ import { join, resolve } from "path";
11
+ var loaded = false;
12
+ function loadEnv() {
13
+ if (loaded) return;
14
+ loaded = true;
15
+ const candidates = [
16
+ process.cwd(),
17
+ resolve(process.cwd(), ".."),
18
+ resolve(import.meta.dirname, "..")
19
+ ];
20
+ for (const base of candidates) {
21
+ const envPath = join(base, ".env");
22
+ if (existsSync(envPath)) {
23
+ const content = readFileSync(envPath, "utf-8");
24
+ for (const line of content.split("\n")) {
25
+ const trimmed = line.trim();
26
+ if (!trimmed || trimmed.startsWith("#")) continue;
27
+ const eqIdx = trimmed.indexOf("=");
28
+ if (eqIdx === -1) continue;
29
+ const key = trimmed.slice(0, eqIdx).trim();
30
+ const val = trimmed.slice(eqIdx + 1).trim();
31
+ if (!process.env[key]) {
32
+ process.env[key] = val;
33
+ }
34
+ }
35
+ break;
36
+ }
37
+ }
38
+ }
39
+
40
+ // src/config.ts
41
+ loadEnv();
42
+ var DART_BASE_URL = "https://opendart.fss.or.kr/api/";
43
+ var CACHE_DIR = join2(homedir(), ".dart-fss");
44
+ var CORP_CODE_CACHE_PATH = join2(CACHE_DIR, "corp-codes.json");
45
+ var CORP_CODE_CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
46
+ function getApiKey(optionKey) {
47
+ const key = optionKey || process.env.DART_API_KEY;
48
+ if (!key) {
49
+ throw new Error("Set the DART_API_KEY environment variable or use the --api-key option. Get a key at https://opendart.fss.or.kr");
50
+ }
51
+ return key;
52
+ }
53
+
54
+ // src/errors.ts
55
+ var DART_STATUS_MESSAGES = {
56
+ "000": "OK",
57
+ "010": "Unregistered API key",
58
+ "011": "Disabled API key",
59
+ "012": "IP not allowed",
60
+ "013": "No data found",
61
+ "014": "File not found",
62
+ "020": "Request limit exceeded",
63
+ "021": "Max company count exceeded (limit: 100)",
64
+ "100": "Invalid field value",
65
+ "101": "Unauthorized access",
66
+ "800": "System maintenance",
67
+ "900": "Undefined error",
68
+ "901": "Personal data retention period expired"
69
+ };
70
+ var DartApiError = class extends Error {
71
+ constructor(statusCode, dartMessage) {
72
+ const description = DART_STATUS_MESSAGES[statusCode] || "Unknown error";
73
+ super(`DART API error [${statusCode}]: ${description} \u2014 ${dartMessage}`);
74
+ this.statusCode = statusCode;
75
+ this.dartMessage = dartMessage;
76
+ this.name = "DartApiError";
77
+ }
78
+ statusCode;
79
+ dartMessage;
80
+ toJSON() {
81
+ return {
82
+ error: true,
83
+ code: this.statusCode,
84
+ description: DART_STATUS_MESSAGES[this.statusCode] || "Unknown error",
85
+ message: this.dartMessage
86
+ };
87
+ }
88
+ };
89
+ function formatErrorJson(err) {
90
+ if (err instanceof DartApiError) {
91
+ return JSON.stringify(err.toJSON());
92
+ }
93
+ const message = err instanceof Error ? err.message : String(err);
94
+ return JSON.stringify({ error: true, code: "CLI_ERROR", message });
95
+ }
96
+ function checkDartStatus(data) {
97
+ if (data.status && data.status !== "000") {
98
+ throw new DartApiError(data.status, data.message || "");
99
+ }
100
+ }
101
+
102
+ // src/client.ts
103
+ function buildUrl(path) {
104
+ const cleanPath = path.replace(/^\//, "");
105
+ return new URL(cleanPath, DART_BASE_URL);
106
+ }
107
+ async function dartFetch(opts) {
108
+ const url = buildUrl(opts.path);
109
+ url.searchParams.set("crtfc_key", opts.apiKey);
110
+ if (opts.params) {
111
+ for (const [k, v] of Object.entries(opts.params)) {
112
+ if (v !== void 0 && v !== "") {
113
+ url.searchParams.set(k, v);
114
+ }
115
+ }
116
+ }
117
+ const res = await fetch(url.toString());
118
+ if (!res.ok) {
119
+ throw new Error(`HTTP ${res.status}: ${res.statusText} \u2014 ${url.pathname}`);
120
+ }
121
+ const contentType = res.headers.get("content-type") || "";
122
+ if (contentType.includes("application/json")) {
123
+ const data = await res.json();
124
+ checkDartStatus(data);
125
+ return data;
126
+ }
127
+ throw new Error(`Unexpected content-type: ${contentType}. Binary endpoints should use dartFetchBinary().`);
128
+ }
129
+ async function dartFetchBinary(opts) {
130
+ const url = buildUrl(opts.path);
131
+ url.searchParams.set("crtfc_key", opts.apiKey);
132
+ if (opts.params) {
133
+ for (const [k, v] of Object.entries(opts.params)) {
134
+ if (v !== void 0 && v !== "") {
135
+ url.searchParams.set(k, v);
136
+ }
137
+ }
138
+ }
139
+ const res = await fetch(url.toString());
140
+ if (!res.ok) {
141
+ throw new Error(`HTTP ${res.status}: ${res.statusText} \u2014 ${url.pathname}`);
142
+ }
143
+ const buf = await res.arrayBuffer();
144
+ const header = new Uint8Array(buf.slice(0, 4));
145
+ const isZip = header[0] === 80 && header[1] === 75 && header[2] === 3 && header[3] === 4;
146
+ if (!isZip) {
147
+ const text = new TextDecoder().decode(buf);
148
+ try {
149
+ const data = JSON.parse(text);
150
+ checkDartStatus(data);
151
+ } catch {
152
+ }
153
+ throw new Error(`DART API error: expected ZIP file but got: ${text.slice(0, 200)}`);
154
+ }
155
+ return buf;
156
+ }
157
+
158
+ // src/corp-code.ts
159
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync, statSync } from "fs";
160
+ import { inflateRawSync } from "zlib";
161
+ import { XMLParser } from "fast-xml-parser";
162
+ function isNonKoreanName(name) {
163
+ return !/[\uAC00-\uD7AF]/.test(name);
164
+ }
165
+ function ensureCacheDir() {
166
+ if (!existsSync2(CACHE_DIR)) {
167
+ mkdirSync(CACHE_DIR, { recursive: true });
168
+ }
169
+ }
170
+ function isCacheValid() {
171
+ if (!existsSync2(CORP_CODE_CACHE_PATH)) return false;
172
+ const stat = statSync(CORP_CODE_CACHE_PATH);
173
+ return Date.now() - stat.mtimeMs < CORP_CODE_CACHE_MAX_AGE_MS;
174
+ }
175
+ function extractXmlFromZip(zipBuffer) {
176
+ const buf = Buffer.from(zipBuffer);
177
+ const sig = buf.indexOf(Buffer.from([80, 75, 3, 4]));
178
+ if (sig === -1) throw new Error("Invalid ZIP: no local file header found");
179
+ let compressedSize = buf.readUInt32LE(sig + 18);
180
+ const fileNameLength = buf.readUInt16LE(sig + 26);
181
+ const extraFieldLength = buf.readUInt16LE(sig + 28);
182
+ const compressionMethod = buf.readUInt16LE(sig + 8);
183
+ const dataStart = sig + 30 + fileNameLength + extraFieldLength;
184
+ if (compressedSize === 0) {
185
+ const centralDirSig = buf.indexOf(Buffer.from([80, 75, 1, 2]), dataStart);
186
+ if (centralDirSig !== -1) {
187
+ compressedSize = centralDirSig - dataStart;
188
+ } else {
189
+ compressedSize = buf.length - dataStart;
190
+ }
191
+ }
192
+ const compressedData = buf.subarray(dataStart, dataStart + compressedSize);
193
+ if (compressionMethod === 0) {
194
+ return compressedData.toString("utf-8");
195
+ } else if (compressionMethod === 8) {
196
+ const decompressed = inflateRawSync(compressedData);
197
+ return decompressed.toString("utf-8");
198
+ } else {
199
+ throw new Error(`Unsupported ZIP compression method: ${compressionMethod}`);
200
+ }
201
+ }
202
+ function parseCorpCodeXml(xml) {
203
+ const parser = new XMLParser({
204
+ ignoreAttributes: false,
205
+ isArray: (name) => name === "list"
206
+ });
207
+ const parsed = parser.parse(xml);
208
+ const items = parsed?.result?.list || [];
209
+ return items.map((item) => ({
210
+ corp_code: String(item.corp_code || "").padStart(8, "0"),
211
+ corp_name: String(item.corp_name || ""),
212
+ stock_code: String(item.stock_code || ""),
213
+ modify_date: String(item.modify_date || "")
214
+ }));
215
+ }
216
+ async function refreshCorpCodeCache(apiKey) {
217
+ console.error("Refreshing corp_code cache... (downloading ZIP)");
218
+ const zipData = await dartFetchBinary({ apiKey, path: "/corpCode.xml" });
219
+ console.error(`ZIP downloaded (${(zipData.byteLength / 1024 / 1024).toFixed(1)} MB)`);
220
+ const xml = extractXmlFromZip(zipData);
221
+ const entries = parseCorpCodeXml(xml);
222
+ const needsEnrichment = entries.filter(
223
+ (e) => e.stock_code && e.stock_code.trim() !== "" && isNonKoreanName(e.corp_name)
224
+ );
225
+ if (needsEnrichment.length > 0) {
226
+ console.error(`Enriching ${needsEnrichment.length} listed companies with Korean names...`);
227
+ for (const entry of needsEnrichment) {
228
+ try {
229
+ const data = await dartFetch({ apiKey, path: "/company.json", params: { corp_code: entry.corp_code } });
230
+ entry.korean_name = String(data.corp_name || "");
231
+ entry.stock_name = String(data.stock_name || "");
232
+ } catch {
233
+ }
234
+ }
235
+ console.error("Enrichment complete.");
236
+ }
237
+ ensureCacheDir();
238
+ writeFileSync(CORP_CODE_CACHE_PATH, JSON.stringify(entries), "utf-8");
239
+ console.error(`Cache saved: ${entries.length} corporations`);
240
+ return entries;
241
+ }
242
+ async function getCorpCodes(apiKey) {
243
+ if (isCacheValid()) {
244
+ const data = readFileSync2(CORP_CODE_CACHE_PATH, "utf-8");
245
+ return JSON.parse(data);
246
+ }
247
+ return refreshCorpCodeCache(apiKey);
248
+ }
249
+ async function resolveCorpCode(nameOrCode, apiKey) {
250
+ if (/^\d{8}$/.test(nameOrCode)) return nameOrCode;
251
+ const entries = await getCorpCodes(apiKey);
252
+ const term = nameOrCode.trim();
253
+ const exact = entries.find(
254
+ (e) => e.corp_name === term || e.stock_code === term || e.korean_name === term || e.stock_name === term
255
+ );
256
+ if (exact) return exact.corp_code;
257
+ const partial = entries.filter(
258
+ (e) => e.corp_name.includes(term) || e.korean_name && e.korean_name.includes(term)
259
+ );
260
+ if (partial.length === 1) return partial[0].corp_code;
261
+ if (partial.length > 1) {
262
+ const listed = partial.filter((e) => e.stock_code && e.stock_code.length > 0);
263
+ if (listed.length === 1) return listed[0].corp_code;
264
+ const displayName = (e) => e.korean_name || e.corp_name;
265
+ const matches = partial.slice(0, 10).map((e) => `${e.corp_code} \u2014 ${displayName(e)} (${e.stock_code || "unlisted"})`);
266
+ throw new Error(`Multiple matches for "${term}": ${matches.join(", ")}${partial.length > 10 ? ` ... and ${partial.length - 10} more` : ""}`);
267
+ }
268
+ throw new Error(`No corporation found for "${term}".`);
269
+ }
270
+ async function lookupCorpCode(term, apiKey) {
271
+ const entries = await getCorpCodes(apiKey);
272
+ return entries.filter(
273
+ (e) => e.corp_name.includes(term) || e.corp_code === term || e.stock_code === term || e.korean_name && e.korean_name.includes(term) || e.stock_name && e.stock_name.includes(term)
274
+ );
275
+ }
276
+
277
+ // src/json-params.ts
278
+ function parseJsonParams(jsonStr) {
279
+ try {
280
+ return JSON.parse(jsonStr);
281
+ } catch {
282
+ throw new Error("Invalid JSON in --json parameter");
283
+ }
284
+ }
285
+
286
+ // src/output.ts
287
+ import { writeFileSync as writeFileSync2 } from "fs";
288
+ function pickFields(data, fields) {
289
+ if (Array.isArray(data)) {
290
+ return data.map((item) => pickFields(item, fields));
291
+ }
292
+ if (data !== null && typeof data === "object") {
293
+ const record = data;
294
+ if (Array.isArray(record.list)) {
295
+ return { ...record, list: record.list.map((item) => pickFields(item, fields)) };
296
+ }
297
+ const result = {};
298
+ for (const f of fields) {
299
+ if (f in record) {
300
+ result[f] = record[f];
301
+ }
302
+ }
303
+ return result;
304
+ }
305
+ return data;
306
+ }
307
+ function formatOutput(data, opts) {
308
+ let out = data;
309
+ if (opts.fields) {
310
+ const fields = opts.fields.split(",").map((f) => f.trim());
311
+ out = pickFields(data, fields);
312
+ }
313
+ if (opts.pretty) {
314
+ return JSON.stringify(out, null, 2);
315
+ }
316
+ return JSON.stringify(out);
317
+ }
318
+ function writeDryRun(path, params, opts) {
319
+ const cleanPath = path.replace(/^\//, "");
320
+ const url = new URL(cleanPath, DART_BASE_URL);
321
+ for (const [k, v] of Object.entries(params)) {
322
+ url.searchParams.set(k, v);
323
+ }
324
+ const info = {
325
+ endpoint: cleanPath,
326
+ method: "GET",
327
+ url: url.toString(),
328
+ params
329
+ };
330
+ const text = JSON.stringify(info, null, 2);
331
+ console.log(text);
332
+ }
333
+ function writeOutput(data, opts) {
334
+ const text = formatOutput(data, opts);
335
+ if (opts.output) {
336
+ writeFileSync2(opts.output, text, "utf-8");
337
+ console.error(`Saved to ${opts.output}`);
338
+ } else {
339
+ console.log(text);
340
+ }
341
+ }
342
+
343
+ // src/registry.ts
344
+ var REGISTRY = [
345
+ {
346
+ path: "list.json",
347
+ cliName: "list",
348
+ summary: "\uACF5\uC2DC \uAC80\uC0C9",
349
+ pattern: "special",
350
+ group: "disclosure",
351
+ tag: "\uACF5\uC2DC\uC815\uBCF4",
352
+ extraParams: [
353
+ {
354
+ "name": "corp_code",
355
+ "description": "\uACE0\uC720\uBC88\uD638 (8\uC790\uB9AC). \uBBF8\uC785\uB825 \uC2DC \uC804\uCCB4 \uAC80\uC0C9",
356
+ "required": false
357
+ },
358
+ {
359
+ "name": "bgn_de",
360
+ "description": "\uC2DC\uC791\uC77C (YYYYMMDD). \uAE30\uBCF8\uAC12\uC740 end_de\uC640 \uB3D9\uC77C",
361
+ "required": false
362
+ },
363
+ {
364
+ "name": "end_de",
365
+ "description": "\uC885\uB8CC\uC77C (YYYYMMDD). \uAE30\uBCF8\uAC12\uC740 \uB2F9\uC77C",
366
+ "required": false
367
+ },
368
+ {
369
+ "name": "last_reprt_at",
370
+ "description": "\uCD5C\uC885\uBCF4\uACE0\uC11C\uB9CC \uAC80\uC0C9 \uC5EC\uBD80. \uAE30\uBCF8\uAC12 N",
371
+ "required": false,
372
+ "enum": [
373
+ "Y",
374
+ "N"
375
+ ]
376
+ },
377
+ {
378
+ "name": "pblntf_ty",
379
+ "description": "\uACF5\uC2DC\uC720\uD615:",
380
+ "required": false,
381
+ "enum": [
382
+ "A",
383
+ "B",
384
+ "C",
385
+ "D",
386
+ "E",
387
+ "F",
388
+ "G",
389
+ "H",
390
+ "I",
391
+ "J"
392
+ ]
393
+ },
394
+ {
395
+ "name": "pblntf_detail_ty",
396
+ "description": "\uACF5\uC2DC\uC0C1\uC138\uC720\uD615 \uCF54\uB4DC (4\uC790\uB9AC)",
397
+ "required": false
398
+ },
399
+ {
400
+ "name": "corp_cls",
401
+ "description": "\uBC95\uC778\uAD6C\uBD84: Y(\uC720\uAC00), K(\uCF54\uC2A4\uB2E5), N(\uCF54\uB125\uC2A4), E(\uAE30\uD0C0)",
402
+ "required": false,
403
+ "enum": [
404
+ "Y",
405
+ "K",
406
+ "N",
407
+ "E"
408
+ ]
409
+ },
410
+ {
411
+ "name": "sort",
412
+ "description": "\uC815\uB82C\uAE30\uC900: date(\uC811\uC218\uC77C), crp(\uD68C\uC0AC\uBA85), rpt(\uBCF4\uACE0\uC11C\uBA85). \uAE30\uBCF8\uAC12 date",
413
+ "required": false,
414
+ "enum": [
415
+ "date",
416
+ "crp",
417
+ "rpt"
418
+ ]
419
+ },
420
+ {
421
+ "name": "sort_mth",
422
+ "description": "\uC815\uB82C\uBC29\uC2DD: asc(\uC624\uB984\uCC28\uC21C), desc(\uB0B4\uB9BC\uCC28\uC21C). \uAE30\uBCF8\uAC12 desc",
423
+ "required": false,
424
+ "enum": [
425
+ "asc",
426
+ "desc"
427
+ ]
428
+ },
429
+ {
430
+ "name": "page_no",
431
+ "description": "\uD398\uC774\uC9C0 \uBC88\uD638 (1~n). \uAE30\uBCF8\uAC12 1",
432
+ "required": false
433
+ },
434
+ {
435
+ "name": "page_count",
436
+ "description": "\uD398\uC774\uC9C0\uB2F9 \uAC74\uC218 (1~100). \uAE30\uBCF8\uAC12 10",
437
+ "required": false
438
+ }
439
+ ]
440
+ },
441
+ {
442
+ path: "company.json",
443
+ cliName: "company",
444
+ summary: "\uAE30\uC5C5 \uAC1C\uD669",
445
+ pattern: "corpOnly",
446
+ group: "disclosure",
447
+ tag: "\uACF5\uC2DC\uC815\uBCF4"
448
+ },
449
+ {
450
+ path: "document.xml",
451
+ cliName: "document",
452
+ summary: "\uACF5\uC2DC\uC11C\uB958 \uC6D0\uBCF8\uD30C\uC77C",
453
+ pattern: "special",
454
+ group: "disclosure",
455
+ tag: "\uACF5\uC2DC\uC815\uBCF4",
456
+ extraParams: [
457
+ {
458
+ "name": "rcept_no",
459
+ "description": "\uC811\uC218\uBC88\uD638 (14\uC790\uB9AC)",
460
+ "required": true
461
+ }
462
+ ]
463
+ },
464
+ {
465
+ path: "corpCode.xml",
466
+ cliName: "corp-code",
467
+ summary: "\uACE0\uC720\uBC88\uD638 \uC804\uCCB4 \uBAA9\uB85D",
468
+ pattern: "special",
469
+ group: "disclosure",
470
+ tag: "\uACF5\uC2DC\uC815\uBCF4"
471
+ },
472
+ {
473
+ path: "irdsSttus.json",
474
+ cliName: "capital-change",
475
+ summary: "\uC99D\uC790(\uAC10\uC790) \uD604\uD669",
476
+ pattern: "periodic",
477
+ group: "report",
478
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
479
+ },
480
+ {
481
+ path: "alotMatter.json",
482
+ cliName: "dividend",
483
+ summary: "\uBC30\uB2F9\uC5D0 \uAD00\uD55C \uC0AC\uD56D",
484
+ pattern: "periodic",
485
+ group: "report",
486
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
487
+ },
488
+ {
489
+ path: "tesstkAcqsDspsSttus.json",
490
+ cliName: "treasury-stock",
491
+ summary: "\uC790\uAE30\uC8FC\uC2DD \uCDE8\uB4DD \uBC0F \uCC98\uBD84 \uD604\uD669",
492
+ pattern: "periodic",
493
+ group: "report",
494
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
495
+ },
496
+ {
497
+ path: "stockTotqySttus.json",
498
+ cliName: "stock-total",
499
+ summary: "\uC8FC\uC2DD\uC758 \uCD1D\uC218 \uD604\uD669",
500
+ pattern: "periodic",
501
+ group: "report",
502
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
503
+ },
504
+ {
505
+ path: "hyslrSttus.json",
506
+ cliName: "shareholder",
507
+ summary: "\uCD5C\uB300\uC8FC\uC8FC \uD604\uD669",
508
+ pattern: "periodic",
509
+ group: "report",
510
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
511
+ },
512
+ {
513
+ path: "hyslrChgSttus.json",
514
+ cliName: "shareholder-change",
515
+ summary: "\uCD5C\uB300\uC8FC\uC8FC \uBCC0\uB3D9\uD604\uD669",
516
+ pattern: "periodic",
517
+ group: "report",
518
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
519
+ },
520
+ {
521
+ path: "mrhlSttus.json",
522
+ cliName: "minority-shareholder",
523
+ summary: "\uC18C\uC561\uC8FC\uC8FC \uD604\uD669",
524
+ pattern: "periodic",
525
+ group: "report",
526
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
527
+ },
528
+ {
529
+ path: "exctvSttus.json",
530
+ cliName: "executive",
531
+ summary: "\uC784\uC6D0 \uD604\uD669",
532
+ pattern: "periodic",
533
+ group: "report",
534
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
535
+ },
536
+ {
537
+ path: "empSttus.json",
538
+ cliName: "employee",
539
+ summary: "\uC9C1\uC6D0 \uD604\uD669",
540
+ pattern: "periodic",
541
+ group: "report",
542
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
543
+ },
544
+ {
545
+ path: "hmvAuditIndvdlBySttus.json",
546
+ cliName: "exec-pay-individual",
547
+ summary: "\uC774\uC0AC\xB7\uAC10\uC0AC\uC758 \uAC1C\uC778\uBCC4 \uBCF4\uC218\uD604\uD669",
548
+ pattern: "periodic",
549
+ group: "report",
550
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
551
+ },
552
+ {
553
+ path: "hmvAuditAllSttus.json",
554
+ cliName: "exec-pay-total",
555
+ summary: "\uC774\uC0AC\xB7\uAC10\uC0AC \uC804\uCCB4\uC758 \uBCF4\uC218\uD604\uD669 (\uBCF4\uC218\uC9C0\uAE09\uAE08\uC561 - \uC774\uC0AC\xB7\uAC10\uC0AC \uC804\uCCB4)",
556
+ pattern: "periodic",
557
+ group: "report",
558
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
559
+ },
560
+ {
561
+ path: "indvdlByPay.json",
562
+ cliName: "top-pay",
563
+ summary: "\uAC1C\uC778\uBCC4 \uBCF4\uC218\uC9C0\uAE09 \uAE08\uC561 (5\uC5B5\uC774\uC0C1 \uC0C1\uC7045\uC778)",
564
+ pattern: "periodic",
565
+ group: "report",
566
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
567
+ },
568
+ {
569
+ path: "unrstExctvMendngSttus.json",
570
+ cliName: "unregistered-exec-pay",
571
+ summary: "\uBBF8\uB4F1\uAE30\uC784\uC6D0 \uBCF4\uC218\uD604\uD669",
572
+ pattern: "periodic",
573
+ group: "report",
574
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
575
+ },
576
+ {
577
+ path: "drctrAdtAllMendngSttusGmtsckConfmAmount.json",
578
+ cliName: "director-pay-approved",
579
+ summary: "\uC774\uC0AC\xB7\uAC10\uC0AC \uC804\uCCB4\uC758 \uBCF4\uC218\uD604\uD669 (\uC8FC\uC8FC\uCD1D\uD68C \uC2B9\uC778\uAE08\uC561)",
580
+ pattern: "periodic",
581
+ group: "report",
582
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
583
+ },
584
+ {
585
+ path: "drctrAdtAllMendngSttusMendngPymntamtTyCl.json",
586
+ cliName: "director-pay-type",
587
+ summary: "\uC774\uC0AC\xB7\uAC10\uC0AC \uC804\uCCB4\uC758 \uBCF4\uC218\uD604\uD669 (\uBCF4\uC218\uC9C0\uAE09\uAE08\uC561 - \uC720\uD615\uBCC4)",
588
+ pattern: "periodic",
589
+ group: "report",
590
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
591
+ },
592
+ {
593
+ path: "detScritsIsuAcmslt.json",
594
+ cliName: "debt-securities",
595
+ summary: "\uCC44\uBB34\uC99D\uAD8C \uBC1C\uD589\uC2E4\uC801",
596
+ pattern: "periodic",
597
+ group: "report",
598
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
599
+ },
600
+ {
601
+ path: "entrprsBilScritsNrdmpBlce.json",
602
+ cliName: "commercial-paper",
603
+ summary: "\uAE30\uC5C5\uC5B4\uC74C\uC99D\uAD8C \uBBF8\uC0C1\uD658 \uC794\uC561",
604
+ pattern: "periodic",
605
+ group: "report",
606
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
607
+ },
608
+ {
609
+ path: "srtpdPsndbtNrdmpBlce.json",
610
+ cliName: "short-term-bond",
611
+ summary: "\uB2E8\uAE30\uC0AC\uCC44 \uBBF8\uC0C1\uD658 \uC794\uC561",
612
+ pattern: "periodic",
613
+ group: "report",
614
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
615
+ },
616
+ {
617
+ path: "cprndNrdmpBlce.json",
618
+ cliName: "contingent-bond",
619
+ summary: "\uD68C\uC0AC\uCC44 \uBBF8\uC0C1\uD658 \uC794\uC561",
620
+ pattern: "periodic",
621
+ group: "report",
622
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
623
+ },
624
+ {
625
+ path: "newCaplScritsNrdmpBlce.json",
626
+ cliName: "new-capital-securities",
627
+ summary: "\uC2E0\uC885\uC790\uBCF8\uC99D\uAD8C \uBBF8\uC0C1\uD658 \uC794\uC561",
628
+ pattern: "periodic",
629
+ group: "report",
630
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
631
+ },
632
+ {
633
+ path: "cndlCaplScritsNrdmpBlce.json",
634
+ cliName: "conditional-capital-securities",
635
+ summary: "\uC870\uAC74\uBD80 \uC790\uBCF8\uC99D\uAD8C \uBBF8\uC0C1\uD658 \uC794\uC561",
636
+ pattern: "periodic",
637
+ group: "report",
638
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
639
+ },
640
+ {
641
+ path: "accnutAdtorNmNdAdtOpinion.json",
642
+ cliName: "auditor-opinion",
643
+ summary: "\uD68C\uACC4\uAC10\uC0AC\uC778\uC758 \uBA85\uCE6D \uBC0F \uAC10\uC0AC\uC758\uACAC",
644
+ pattern: "periodic",
645
+ group: "report",
646
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
647
+ },
648
+ {
649
+ path: "adtServcCnclsSttus.json",
650
+ cliName: "audit-service",
651
+ summary: "\uAC10\uC0AC\uC6A9\uC5ED\uCCB4\uACB0\uD604\uD669",
652
+ pattern: "periodic",
653
+ group: "report",
654
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
655
+ },
656
+ {
657
+ path: "accnutAdtorNonAdtServcCnclsSttus.json",
658
+ cliName: "non-audit-service",
659
+ summary: "\uD68C\uACC4\uAC10\uC0AC\uC778\uACFC\uC758 \uBE44\uAC10\uC0AC\uC6A9\uC5ED \uACC4\uC57D\uCCB4\uACB0 \uD604\uD669",
660
+ pattern: "periodic",
661
+ group: "report",
662
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
663
+ },
664
+ {
665
+ path: "outcmpnyDrctrNdChangeSttus.json",
666
+ cliName: "outside-director",
667
+ summary: "\uC0AC\uC678\uC774\uC0AC \uBC0F \uADF8 \uBCC0\uB3D9\uD604\uD669",
668
+ pattern: "periodic",
669
+ group: "report",
670
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
671
+ },
672
+ {
673
+ path: "otrCprInvstmntSttus.json",
674
+ cliName: "other-corp-investment",
675
+ summary: "\uD0C0\uBC95\uC778 \uCD9C\uC790\uD604\uD669",
676
+ pattern: "periodic",
677
+ group: "report",
678
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
679
+ },
680
+ {
681
+ path: "pssrpCptalUseDtls.json",
682
+ cliName: "public-fund-usage",
683
+ summary: "\uACF5\uBAA8\uC790\uAE08\uC758 \uC0AC\uC6A9\uB0B4\uC5ED",
684
+ pattern: "periodic",
685
+ group: "report",
686
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
687
+ },
688
+ {
689
+ path: "prvsrpCptalUseDtls.json",
690
+ cliName: "private-fund-usage",
691
+ summary: "\uC0AC\uBAA8\uC790\uAE08\uC758 \uC0AC\uC6A9\uB0B4\uC5ED",
692
+ pattern: "periodic",
693
+ group: "report",
694
+ tag: "\uC815\uAE30\uBCF4\uACE0\uC11C"
695
+ },
696
+ {
697
+ path: "fnlttSinglAcnt.json",
698
+ cliName: "single-account",
699
+ summary: "\uB2E8\uC77C\uD68C\uC0AC \uC8FC\uC694\uACC4\uC815",
700
+ pattern: "periodic",
701
+ group: "financial",
702
+ tag: "\uC7AC\uBB34\uC815\uBCF4"
703
+ },
704
+ {
705
+ path: "fnlttMultiAcnt.json",
706
+ cliName: "multi-account",
707
+ summary: "\uB2E4\uC911\uD68C\uC0AC \uC8FC\uC694\uACC4\uC815",
708
+ pattern: "special",
709
+ group: "financial",
710
+ tag: "\uC7AC\uBB34\uC815\uBCF4",
711
+ extraParams: [
712
+ {
713
+ "name": "corp_code",
714
+ "description": "\uACE0\uC720\uBC88\uD638 (\uC27C\uD45C \uAD6C\uBD84, \uCD5C\uB300 100\uAC1C)",
715
+ "required": true
716
+ }
717
+ ]
718
+ },
719
+ {
720
+ path: "fnlttSinglAcntAll.json",
721
+ cliName: "full-statement",
722
+ summary: "\uB2E8\uC77C\uD68C\uC0AC \uC804\uCCB4 \uC7AC\uBB34\uC81C\uD45C",
723
+ pattern: "periodic",
724
+ group: "financial",
725
+ tag: "\uC7AC\uBB34\uC815\uBCF4",
726
+ extraParams: [
727
+ {
728
+ "name": "fs_div",
729
+ "description": "\uAC1C\uBCC4/\uC5F0\uACB0 \uAD6C\uBD84: OFS(\uC7AC\uBB34\uC81C\uD45C), CFS(\uC5F0\uACB0\uC7AC\uBB34\uC81C\uD45C)",
730
+ "required": true,
731
+ "enum": [
732
+ "OFS",
733
+ "CFS"
734
+ ]
735
+ }
736
+ ]
737
+ },
738
+ {
739
+ path: "fnlttSinglIndx.json",
740
+ cliName: "single-index",
741
+ summary: "\uB2E8\uC77C\uD68C\uC0AC \uC8FC\uC694 \uC7AC\uBB34\uC9C0\uD45C",
742
+ pattern: "periodic",
743
+ group: "financial",
744
+ tag: "\uC7AC\uBB34\uC815\uBCF4"
745
+ },
746
+ {
747
+ path: "fnlttCmpnyIndx.json",
748
+ cliName: "multi-index",
749
+ summary: "\uB2E4\uC911\uD68C\uC0AC \uC8FC\uC694 \uC7AC\uBB34\uC9C0\uD45C",
750
+ pattern: "special",
751
+ group: "financial",
752
+ tag: "\uC7AC\uBB34\uC815\uBCF4",
753
+ extraParams: [
754
+ {
755
+ "name": "corp_code",
756
+ "description": "\uACE0\uC720\uBC88\uD638 (\uC27C\uD45C \uAD6C\uBD84, \uCD5C\uB300 100\uAC1C)",
757
+ "required": true
758
+ }
759
+ ]
760
+ },
761
+ {
762
+ path: "fnlttXbrl.xml",
763
+ cliName: "xbrl",
764
+ summary: "XBRL \uC7AC\uBB34\uC81C\uD45C \uC6D0\uBCF8\uD30C\uC77C",
765
+ pattern: "special",
766
+ group: "financial",
767
+ tag: "\uC7AC\uBB34\uC815\uBCF4",
768
+ extraParams: [
769
+ {
770
+ "name": "rcept_no",
771
+ "description": "\uC811\uC218\uBC88\uD638 (14\uC790\uB9AC)",
772
+ "required": true
773
+ }
774
+ ]
775
+ },
776
+ {
777
+ path: "xbrlTaxonomy.json",
778
+ cliName: "taxonomy",
779
+ summary: "XBRL \uD0DD\uC0AC\uB178\uBBF8 \uC7AC\uBB34\uC81C\uD45C \uC591\uC2DD",
780
+ pattern: "special",
781
+ group: "financial",
782
+ tag: "\uC7AC\uBB34\uC815\uBCF4",
783
+ extraParams: [
784
+ {
785
+ "name": "sj_div",
786
+ "description": "\uC7AC\uBB34\uC81C\uD45C\uAD6C\uBD84:",
787
+ "required": true,
788
+ "enum": [
789
+ "BS1",
790
+ "BS2",
791
+ "BS3",
792
+ "BS4",
793
+ "IS1",
794
+ "IS2",
795
+ "IS3",
796
+ "IS4",
797
+ "CIS1",
798
+ "CIS2",
799
+ "CF1",
800
+ "CF2",
801
+ "SCE"
802
+ ]
803
+ }
804
+ ]
805
+ },
806
+ {
807
+ path: "majorstock.json",
808
+ cliName: "major-stock",
809
+ summary: "\uB300\uB7C9\uBCF4\uC720 \uC0C1\uD669\uBCF4\uACE0",
810
+ pattern: "corpOnly",
811
+ group: "equity",
812
+ tag: "\uC9C0\uBD84\uACF5\uC2DC"
813
+ },
814
+ {
815
+ path: "elestock.json",
816
+ cliName: "executive-stock",
817
+ summary: "\uC784\uC6D0\xB7\uC8FC\uC694\uC8FC\uC8FC \uC18C\uC720\uBCF4\uACE0",
818
+ pattern: "corpOnly",
819
+ group: "equity",
820
+ tag: "\uC9C0\uBD84\uACF5\uC2DC"
821
+ },
822
+ {
823
+ path: "astInhtrfEtcPtbkOpt.json",
824
+ cliName: "asset-transfer",
825
+ summary: "\uC790\uC0B0\uC591\uC218\uB3C4(\uAE30\uD0C0), \uD48B\uBC31\uC635\uC158",
826
+ pattern: "dateRange",
827
+ group: "major",
828
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
829
+ },
830
+ {
831
+ path: "dfOcr.json",
832
+ cliName: "default",
833
+ summary: "\uBD80\uB3C4\uBC1C\uC0DD",
834
+ pattern: "dateRange",
835
+ group: "major",
836
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
837
+ },
838
+ {
839
+ path: "bsnSp.json",
840
+ cliName: "business-suspension",
841
+ summary: "\uC601\uC5C5\uC815\uC9C0",
842
+ pattern: "dateRange",
843
+ group: "major",
844
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
845
+ },
846
+ {
847
+ path: "ctrcvsBgrq.json",
848
+ cliName: "rehabilitation",
849
+ summary: "\uD68C\uC0DD\uC808\uCC28 \uAC1C\uC2DC\uC2E0\uCCAD",
850
+ pattern: "dateRange",
851
+ group: "major",
852
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
853
+ },
854
+ {
855
+ path: "dsRsOcr.json",
856
+ cliName: "dissolution",
857
+ summary: "\uD574\uC0B0\uC0AC\uC720 \uBC1C\uC0DD",
858
+ pattern: "dateRange",
859
+ group: "major",
860
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
861
+ },
862
+ {
863
+ path: "piicDecsn.json",
864
+ cliName: "paid-increase",
865
+ summary: "\uC720\uC0C1\uC99D\uC790 \uACB0\uC815",
866
+ pattern: "dateRange",
867
+ group: "major",
868
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
869
+ },
870
+ {
871
+ path: "fricDecsn.json",
872
+ cliName: "free-increase",
873
+ summary: "\uBB34\uC0C1\uC99D\uC790 \uACB0\uC815",
874
+ pattern: "dateRange",
875
+ group: "major",
876
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
877
+ },
878
+ {
879
+ path: "pifricDecsn.json",
880
+ cliName: "paid-free-increase",
881
+ summary: "\uC720\uBB34\uC0C1\uC99D\uC790 \uACB0\uC815",
882
+ pattern: "dateRange",
883
+ group: "major",
884
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
885
+ },
886
+ {
887
+ path: "crDecsn.json",
888
+ cliName: "capital-reduction",
889
+ summary: "\uAC10\uC790 \uACB0\uC815",
890
+ pattern: "dateRange",
891
+ group: "major",
892
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
893
+ },
894
+ {
895
+ path: "bnkMngtPcbg.json",
896
+ cliName: "creditor-mgmt-start",
897
+ summary: "\uCC44\uAD8C\uC740\uD589 \uB4F1\uC758 \uAD00\uB9AC\uC808\uCC28 \uAC1C\uC2DC",
898
+ pattern: "dateRange",
899
+ group: "major",
900
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
901
+ },
902
+ {
903
+ path: "lwstLg.json",
904
+ cliName: "lawsuit",
905
+ summary: "\uC18C\uC1A1 \uB4F1\uC758 \uC81C\uAE30",
906
+ pattern: "dateRange",
907
+ group: "major",
908
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
909
+ },
910
+ {
911
+ path: "ovLstDecsn.json",
912
+ cliName: "overseas-listing-decision",
913
+ summary: "\uD574\uC678 \uC99D\uAD8C\uC2DC\uC7A5 \uC8FC\uAD8C\uB4F1 \uC0C1\uC7A5 \uACB0\uC815",
914
+ pattern: "dateRange",
915
+ group: "major",
916
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
917
+ },
918
+ {
919
+ path: "ovDlstDecsn.json",
920
+ cliName: "overseas-delisting-decision",
921
+ summary: "\uD574\uC678 \uC99D\uAD8C\uC2DC\uC7A5 \uC8FC\uAD8C\uB4F1 \uC0C1\uC7A5\uD3D0\uC9C0 \uACB0\uC815",
922
+ pattern: "dateRange",
923
+ group: "major",
924
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
925
+ },
926
+ {
927
+ path: "ovLst.json",
928
+ cliName: "overseas-listing",
929
+ summary: "\uD574\uC678 \uC99D\uAD8C\uC2DC\uC7A5 \uC8FC\uAD8C\uB4F1 \uC0C1\uC7A5",
930
+ pattern: "dateRange",
931
+ group: "major",
932
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
933
+ },
934
+ {
935
+ path: "ovDlst.json",
936
+ cliName: "overseas-delisting",
937
+ summary: "\uD574\uC678 \uC99D\uAD8C\uC2DC\uC7A5 \uC8FC\uAD8C\uB4F1 \uC0C1\uC7A5\uD3D0\uC9C0",
938
+ pattern: "dateRange",
939
+ group: "major",
940
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
941
+ },
942
+ {
943
+ path: "cvbdIsDecsn.json",
944
+ cliName: "convertible-bond",
945
+ summary: "\uC804\uD658\uC0AC\uCC44\uAD8C \uBC1C\uD589\uACB0\uC815",
946
+ pattern: "dateRange",
947
+ group: "major",
948
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
949
+ },
950
+ {
951
+ path: "bdwtIsDecsn.json",
952
+ cliName: "bond-with-warrant",
953
+ summary: "\uC2E0\uC8FC\uC778\uC218\uAD8C\uBD80\uC0AC\uCC44\uAD8C \uBC1C\uD589\uACB0\uC815",
954
+ pattern: "dateRange",
955
+ group: "major",
956
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
957
+ },
958
+ {
959
+ path: "exbdIsDecsn.json",
960
+ cliName: "exchangeable-bond",
961
+ summary: "\uAD50\uD658\uC0AC\uCC44\uAD8C \uBC1C\uD589\uACB0\uC815",
962
+ pattern: "dateRange",
963
+ group: "major",
964
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
965
+ },
966
+ {
967
+ path: "bnkMngtPcsp.json",
968
+ cliName: "creditor-mgmt-stop",
969
+ summary: "\uCC44\uAD8C\uC740\uD589 \uB4F1\uC758 \uAD00\uB9AC\uC808\uCC28 \uC911\uB2E8",
970
+ pattern: "dateRange",
971
+ group: "major",
972
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
973
+ },
974
+ {
975
+ path: "wdCocobdIsDecsn.json",
976
+ cliName: "contingent-convertible",
977
+ summary: "\uC0C1\uAC01\uD615 \uC870\uAC74\uBD80\uC790\uBCF8\uC99D\uAD8C \uBC1C\uD589\uACB0\uC815",
978
+ pattern: "dateRange",
979
+ group: "major",
980
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
981
+ },
982
+ {
983
+ path: "tsstkAqDecsn.json",
984
+ cliName: "treasury-acquire",
985
+ summary: "\uC790\uAE30\uC8FC\uC2DD \uCDE8\uB4DD \uACB0\uC815",
986
+ pattern: "dateRange",
987
+ group: "major",
988
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
989
+ },
990
+ {
991
+ path: "tsstkDpDecsn.json",
992
+ cliName: "treasury-dispose",
993
+ summary: "\uC790\uAE30\uC8FC\uC2DD \uCC98\uBD84 \uACB0\uC815",
994
+ pattern: "dateRange",
995
+ group: "major",
996
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
997
+ },
998
+ {
999
+ path: "tsstkAqTrctrCnsDecsn.json",
1000
+ cliName: "treasury-trust-start",
1001
+ summary: "\uC790\uAE30\uC8FC\uC2DD\uCDE8\uB4DD \uC2E0\uD0C1\uACC4\uC57D \uCCB4\uACB0 \uACB0\uC815",
1002
+ pattern: "dateRange",
1003
+ group: "major",
1004
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1005
+ },
1006
+ {
1007
+ path: "tsstkAqTrctrCcDecsn.json",
1008
+ cliName: "treasury-trust-end",
1009
+ summary: "\uC790\uAE30\uC8FC\uC2DD\uCDE8\uB4DD \uC2E0\uD0C1\uACC4\uC57D \uD574\uC9C0 \uACB0\uC815",
1010
+ pattern: "dateRange",
1011
+ group: "major",
1012
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1013
+ },
1014
+ {
1015
+ path: "bsnInhDecsn.json",
1016
+ cliName: "business-acquire",
1017
+ summary: "\uC601\uC5C5\uC591\uC218 \uACB0\uC815",
1018
+ pattern: "dateRange",
1019
+ group: "major",
1020
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1021
+ },
1022
+ {
1023
+ path: "bsnTrfDecsn.json",
1024
+ cliName: "business-transfer",
1025
+ summary: "\uC601\uC5C5\uC591\uB3C4 \uACB0\uC815",
1026
+ pattern: "dateRange",
1027
+ group: "major",
1028
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1029
+ },
1030
+ {
1031
+ path: "tgastInhDecsn.json",
1032
+ cliName: "tangible-asset-acquire",
1033
+ summary: "\uC720\uD615\uC790\uC0B0 \uC591\uC218 \uACB0\uC815",
1034
+ pattern: "dateRange",
1035
+ group: "major",
1036
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1037
+ },
1038
+ {
1039
+ path: "tgastTrfDecsn.json",
1040
+ cliName: "tangible-asset-transfer",
1041
+ summary: "\uC720\uD615\uC790\uC0B0 \uC591\uB3C4 \uACB0\uC815",
1042
+ pattern: "dateRange",
1043
+ group: "major",
1044
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1045
+ },
1046
+ {
1047
+ path: "otcprStkInvscrInhDecsn.json",
1048
+ cliName: "other-stock-acquire",
1049
+ summary: "\uD0C0\uBC95\uC778 \uC8FC\uC2DD \uBC0F \uCD9C\uC790\uC99D\uAD8C \uC591\uC218\uACB0\uC815",
1050
+ pattern: "dateRange",
1051
+ group: "major",
1052
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1053
+ },
1054
+ {
1055
+ path: "otcprStkInvscrTrfDecsn.json",
1056
+ cliName: "other-stock-transfer",
1057
+ summary: "\uD0C0\uBC95\uC778 \uC8FC\uC2DD \uBC0F \uCD9C\uC790\uC99D\uAD8C \uC591\uB3C4\uACB0\uC815",
1058
+ pattern: "dateRange",
1059
+ group: "major",
1060
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1061
+ },
1062
+ {
1063
+ path: "stkrtbdInhDecsn.json",
1064
+ cliName: "stock-bond-acquire",
1065
+ summary: "\uC8FC\uAD8C \uAD00\uB828 \uC0AC\uCC44\uAD8C \uC591\uC218 \uACB0\uC815",
1066
+ pattern: "dateRange",
1067
+ group: "major",
1068
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1069
+ },
1070
+ {
1071
+ path: "stkrtbdTrfDecsn.json",
1072
+ cliName: "stock-bond-transfer",
1073
+ summary: "\uC8FC\uAD8C \uAD00\uB828 \uC0AC\uCC44\uAD8C \uC591\uB3C4 \uACB0\uC815",
1074
+ pattern: "dateRange",
1075
+ group: "major",
1076
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1077
+ },
1078
+ {
1079
+ path: "cmpMgDecsn.json",
1080
+ cliName: "merger-decision",
1081
+ summary: "\uD68C\uC0AC\uD569\uBCD1 \uACB0\uC815",
1082
+ pattern: "dateRange",
1083
+ group: "major",
1084
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1085
+ },
1086
+ {
1087
+ path: "cmpDvDecsn.json",
1088
+ cliName: "split-decision",
1089
+ summary: "\uD68C\uC0AC\uBD84\uD560 \uACB0\uC815",
1090
+ pattern: "dateRange",
1091
+ group: "major",
1092
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1093
+ },
1094
+ {
1095
+ path: "cmpDvmgDecsn.json",
1096
+ cliName: "split-merger-decision",
1097
+ summary: "\uD68C\uC0AC\uBD84\uD560\uD569\uBCD1 \uACB0\uC815",
1098
+ pattern: "dateRange",
1099
+ group: "major",
1100
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1101
+ },
1102
+ {
1103
+ path: "stkExtrDecsn.json",
1104
+ cliName: "stock-exchange-decision",
1105
+ summary: "\uC8FC\uC2DD\uAD50\uD658\xB7\uC774\uC804 \uACB0\uC815",
1106
+ pattern: "dateRange",
1107
+ group: "major",
1108
+ tag: "\uC8FC\uC694\uC0AC\uD56D\uBCF4\uACE0\uC11C"
1109
+ },
1110
+ {
1111
+ path: "estkRs.json",
1112
+ cliName: "equity-securities",
1113
+ summary: "\uC9C0\uBD84\uC99D\uAD8C",
1114
+ pattern: "dateRange",
1115
+ group: "securities",
1116
+ tag: "\uC99D\uAD8C\uC2E0\uACE0\uC11C"
1117
+ },
1118
+ {
1119
+ path: "bdRs.json",
1120
+ cliName: "debt-registration",
1121
+ summary: "\uCC44\uBB34\uC99D\uAD8C",
1122
+ pattern: "dateRange",
1123
+ group: "securities",
1124
+ tag: "\uC99D\uAD8C\uC2E0\uACE0\uC11C"
1125
+ },
1126
+ {
1127
+ path: "stkdpRs.json",
1128
+ cliName: "depository-receipt",
1129
+ summary: "\uC99D\uAD8C\uC608\uD0C1\uC99D\uAD8C",
1130
+ pattern: "dateRange",
1131
+ group: "securities",
1132
+ tag: "\uC99D\uAD8C\uC2E0\uACE0\uC11C"
1133
+ },
1134
+ {
1135
+ path: "mgRs.json",
1136
+ cliName: "merger-registration",
1137
+ summary: "\uD569\uBCD1",
1138
+ pattern: "dateRange",
1139
+ group: "securities",
1140
+ tag: "\uC99D\uAD8C\uC2E0\uACE0\uC11C"
1141
+ },
1142
+ {
1143
+ path: "extrRs.json",
1144
+ cliName: "exchange-registration",
1145
+ summary: "\uC8FC\uC2DD\uC758\uD3EC\uAD04\uC801\uAD50\uD658\xB7\uC774\uC804",
1146
+ pattern: "dateRange",
1147
+ group: "securities",
1148
+ tag: "\uC99D\uAD8C\uC2E0\uACE0\uC11C"
1149
+ },
1150
+ {
1151
+ path: "dvRs.json",
1152
+ cliName: "split-registration",
1153
+ summary: "\uBD84\uD560",
1154
+ pattern: "dateRange",
1155
+ group: "securities",
1156
+ tag: "\uC99D\uAD8C\uC2E0\uACE0\uC11C"
1157
+ }
1158
+ ];
1159
+ var REGISTRY_BY_CLI_NAME = /* @__PURE__ */ new Map();
1160
+ var REGISTRY_BY_GROUP = /* @__PURE__ */ new Map();
1161
+ for (const entry of REGISTRY) {
1162
+ REGISTRY_BY_CLI_NAME.set(entry.cliName, entry);
1163
+ const group = REGISTRY_BY_GROUP.get(entry.group) || [];
1164
+ group.push(entry);
1165
+ REGISTRY_BY_GROUP.set(entry.group, group);
1166
+ }
1167
+
1168
+ // src/commands/disclosure.ts
1169
+ function getGlobalOpts(cmd) {
1170
+ return cmd.optsWithGlobals();
1171
+ }
1172
+ function registerDisclosureCommands(program) {
1173
+ const group = program.command("disclosure").description(
1174
+ 'DS001: Disclosure info \u2014 search filings, company overview, original documents, corp codes.\nUse "disclosure list" to search filings by company/date/type.\nUse "disclosure company" to get company profile (CEO, address, industry code).'
1175
+ );
1176
+ group.command("list").description(
1177
+ "Search DART disclosure filings. Returns paginated results with report name, filing date, receipt number.\nWithout --corp, searches ALL companies (date range limited to 3 months).\nWith --corp, searches specific company with no date limit.\nDisclosure types: A=Regular, B=Major events, C=Issuance, D=Equity, E=Other, F=Audit, G=Fund, H=ABS, I=Exchange, J=FTC"
1178
+ ).option("--corp <name-or-code>", 'Company name (e.g. "\uC0BC\uC131\uC804\uC790") or 8-digit corp_code').option("--from <YYYYMMDD>", "Start date in YYYYMMDD format (e.g. 20240101)").option("--to <YYYYMMDD>", "End date in YYYYMMDD format (e.g. 20241231)").option("--type <code>", "Disclosure type: A=Regular, B=Major events, C=Issuance, D=Equity, E=Other, F=Audit, G=Fund, H=ABS, I=Exchange, J=FTC").option("--corp-cls <cls>", "Corp class filter: Y=KOSPI, K=KOSDAQ, N=KONEX, E=Other").option("--page <n>", "Page number, starting from 1 (default: 1)", "1").option("--count <n>", "Items per page, 1-100 (default: 10)", "10").action(async (opts) => {
1179
+ const globalOpts = getGlobalOpts(group);
1180
+ const apiKey = getApiKey(globalOpts.apiKey);
1181
+ if (globalOpts.json) {
1182
+ const params2 = parseJsonParams(globalOpts.json);
1183
+ const data2 = await dartFetch({ apiKey, path: "/list.json", params: params2 });
1184
+ writeOutput(data2, globalOpts);
1185
+ return;
1186
+ }
1187
+ const params = {};
1188
+ if (opts.corp) params.corp_code = await resolveCorpCode(opts.corp, apiKey);
1189
+ if (opts.from) params.bgn_de = opts.from;
1190
+ if (opts.to) params.end_de = opts.to;
1191
+ if (opts.type) params.pblntf_ty = opts.type;
1192
+ if (opts.corpCls) params.corp_cls = opts.corpCls;
1193
+ params.page_no = opts.page;
1194
+ params.page_count = opts.count;
1195
+ if (globalOpts.dryRun) {
1196
+ writeDryRun("/list.json", params, globalOpts);
1197
+ return;
1198
+ }
1199
+ const data = await dartFetch({ apiKey, path: "/list.json", params });
1200
+ writeOutput(data, globalOpts);
1201
+ });
1202
+ group.command("company").description(
1203
+ 'Get company profile from DART. Returns corp name, CEO, address, stock code, industry code, incorporation date, fiscal month.\nAccepts company name (e.g. "\uC0BC\uC131\uC804\uC790") or 8-digit corp_code.'
1204
+ ).requiredOption("--corp <name-or-code>", 'Company name (e.g. "\uC0BC\uC131\uC804\uC790") or 8-digit corp_code').action(async (opts) => {
1205
+ const globalOpts = getGlobalOpts(group);
1206
+ const apiKey = getApiKey(globalOpts.apiKey);
1207
+ if (globalOpts.json) {
1208
+ const params2 = parseJsonParams(globalOpts.json);
1209
+ const data2 = await dartFetch({ apiKey, path: "/company.json", params: params2 });
1210
+ writeOutput(data2, globalOpts);
1211
+ return;
1212
+ }
1213
+ const corpCode = await resolveCorpCode(opts.corp, apiKey);
1214
+ const params = { corp_code: corpCode };
1215
+ if (globalOpts.dryRun) {
1216
+ writeDryRun("/company.json", params, globalOpts);
1217
+ return;
1218
+ }
1219
+ const data = await dartFetch({ apiKey, path: "/company.json", params });
1220
+ writeOutput(data, globalOpts);
1221
+ });
1222
+ const ds001Endpoints = REGISTRY_BY_GROUP.get("disclosure") || [];
1223
+ for (const ep of ds001Endpoints) {
1224
+ if (["list", "company", "document", "corp-code"].includes(ep.cliName)) continue;
1225
+ if (ep.pattern === "corpOnly") {
1226
+ group.command(ep.cliName).description(ep.summary).requiredOption("--corp <name-or-code>", "Company name or corp_code").action(async (opts) => {
1227
+ const globalOpts = getGlobalOpts(group);
1228
+ const apiKey = getApiKey(globalOpts.apiKey);
1229
+ if (globalOpts.json) {
1230
+ const params2 = parseJsonParams(globalOpts.json);
1231
+ const data2 = await dartFetch({ apiKey, path: `/${ep.path}`, params: params2 });
1232
+ writeOutput(data2, globalOpts);
1233
+ return;
1234
+ }
1235
+ const corpCode = await resolveCorpCode(opts.corp, apiKey);
1236
+ const params = { corp_code: corpCode };
1237
+ if (globalOpts.dryRun) {
1238
+ writeDryRun(`/${ep.path}`, params, globalOpts);
1239
+ return;
1240
+ }
1241
+ const data = await dartFetch({ apiKey, path: `/${ep.path}`, params });
1242
+ writeOutput(data, globalOpts);
1243
+ });
1244
+ }
1245
+ }
1246
+ }
1247
+ function registerLookupCommand(program) {
1248
+ program.command("lookup <term>").description(
1249
+ "Look up corp_code by company name. Use this to find the 8-digit corp_code needed by other commands.\nSearches by exact and partial match. If multiple matches, lists all with stock codes."
1250
+ ).action(async (term) => {
1251
+ const globalOpts = program.opts();
1252
+ const apiKey = getApiKey(globalOpts.apiKey);
1253
+ const results = await lookupCorpCode(term, apiKey);
1254
+ if (results.length === 0) {
1255
+ throw new Error(`No corporation found for "${term}".`);
1256
+ }
1257
+ writeOutput(results, globalOpts);
1258
+ });
1259
+ }
1260
+ function registerCorpCacheCommand(program) {
1261
+ const cache = program.command("corp-cache").description("Manage the local corp_code cache (~/.dart-fss/corp-codes.json). Auto-refreshes every 7 days.");
1262
+ cache.command("refresh").description("Force refresh corp_code cache").action(async () => {
1263
+ const globalOpts = program.opts();
1264
+ const apiKey = getApiKey(globalOpts.apiKey);
1265
+ const entries = await refreshCorpCodeCache(apiKey);
1266
+ console.error(`Refreshed: ${entries.length} corporations`);
1267
+ });
1268
+ }
1269
+
1270
+ // src/types.ts
1271
+ var REPRT_CODE_MAP = {
1272
+ "q1": "11013",
1273
+ "half": "11012",
1274
+ "q3": "11014",
1275
+ "annual": "11011"
1276
+ };
1277
+ var IDX_CL_CODE_MAP = {
1278
+ "profitability": "M210000",
1279
+ "stability": "M220000",
1280
+ "growth": "M230000",
1281
+ "activity": "M240000"
1282
+ };
1283
+
1284
+ // src/commands/periodic-report.ts
1285
+ function getGlobalOpts2(cmd) {
1286
+ return cmd.optsWithGlobals();
1287
+ }
1288
+ function registerPeriodicReportCommands(program) {
1289
+ const group = program.command("report").description(
1290
+ "DS002: Periodic report key information \u2014 28 APIs extracting data from annual/quarterly reports.\nCovers: capital changes, dividends, treasury stock, shareholders, executives, employees,\ncompensation, debt securities, audit info, outside directors, investments, fund usage.\nData available from 2015 onward."
1291
+ );
1292
+ const endpoints = (REGISTRY_BY_GROUP.get("report") || []).filter(
1293
+ (ep) => ep.pattern === "periodic"
1294
+ );
1295
+ for (const ep of endpoints) {
1296
+ group.command(ep.cliName).description(ep.summary).requiredOption("--corp <name-or-code>", 'Company name (e.g. "\uC0BC\uC131\uC804\uC790") or 8-digit corp_code').requiredOption("--year <YYYY>", "Business year in YYYY format (e.g. 2024). Data from 2015 onward").requiredOption("--quarter <q1|half|q3|annual>", "Report quarter: q1 (Q1), half (semi-annual), q3 (Q3), annual (full year)").action(async (opts) => {
1297
+ const globalOpts = getGlobalOpts2(group);
1298
+ const apiKey = getApiKey(globalOpts.apiKey);
1299
+ if (globalOpts.json) {
1300
+ const params2 = parseJsonParams(globalOpts.json);
1301
+ const data2 = await dartFetch({ apiKey, path: `/${ep.path}`, params: params2 });
1302
+ writeOutput(data2, globalOpts);
1303
+ return;
1304
+ }
1305
+ const corpCode = await resolveCorpCode(opts.corp, apiKey);
1306
+ const reprtCode = REPRT_CODE_MAP[opts.quarter];
1307
+ if (!reprtCode) {
1308
+ throw new Error(`Invalid quarter: ${opts.quarter} (must be one of: q1, half, q3, annual)`);
1309
+ }
1310
+ const params = { corp_code: corpCode, bsns_year: opts.year, reprt_code: reprtCode };
1311
+ if (globalOpts.dryRun) {
1312
+ writeDryRun(`/${ep.path}`, params, globalOpts);
1313
+ return;
1314
+ }
1315
+ const data = await dartFetch({ apiKey, path: `/${ep.path}`, params });
1316
+ writeOutput(data, globalOpts);
1317
+ });
1318
+ }
1319
+ }
1320
+
1321
+ // src/commands/financial.ts
1322
+ function getGlobalOpts3(cmd) {
1323
+ return cmd.optsWithGlobals();
1324
+ }
1325
+ function registerFinancialCommands(program) {
1326
+ const group = program.command("financial").description(
1327
+ "DS003: Financial data \u2014 statements, indices, and XBRL for listed companies (KOSPI/KOSDAQ).\nIncludes key accounts (assets, liabilities, revenue), full financial statements,\nfinancial indices (profitability, stability, growth, activity), and XBRL taxonomy."
1328
+ );
1329
+ const endpoints = REGISTRY_BY_GROUP.get("financial") || [];
1330
+ for (const ep of endpoints) {
1331
+ const cmd = group.command(ep.cliName).description(ep.summary);
1332
+ if (ep.pattern === "periodic") {
1333
+ cmd.requiredOption("--corp <name-or-code>", 'Company name (e.g. "\uC0BC\uC131\uC804\uC790") or 8-digit corp_code').requiredOption("--year <YYYY>", "Business year in YYYY format (e.g. 2024). Data from 2015 onward").requiredOption("--quarter <q1|half|q3|annual>", "Report quarter: q1 (Q1), half (semi-annual), q3 (Q3), annual (full year)");
1334
+ const needsIdxClCode = ep.cliName === "single-index";
1335
+ if (needsIdxClCode) {
1336
+ cmd.requiredOption("--idx-cl-code <code>", "Index classification: profitability (M210000), stability (M220000), growth (M230000), activity (M240000). Accepts aliases or raw codes");
1337
+ }
1338
+ if (ep.extraParams) {
1339
+ for (const p of ep.extraParams) {
1340
+ const flag = `--${p.name.replace(/_/g, "-")} <value>`;
1341
+ if (p.required) {
1342
+ cmd.requiredOption(flag, p.description);
1343
+ } else {
1344
+ cmd.option(flag, p.description);
1345
+ }
1346
+ }
1347
+ }
1348
+ cmd.action(async (opts) => {
1349
+ const globalOpts = getGlobalOpts3(group);
1350
+ const apiKey = getApiKey(globalOpts.apiKey);
1351
+ if (globalOpts.json) {
1352
+ const params2 = parseJsonParams(globalOpts.json);
1353
+ const data2 = await dartFetch({ apiKey, path: `/${ep.path}`, params: params2 });
1354
+ writeOutput(data2, globalOpts);
1355
+ return;
1356
+ }
1357
+ const corpCode = await resolveCorpCode(opts.corp, apiKey);
1358
+ const reprtCode = REPRT_CODE_MAP[opts.quarter];
1359
+ if (!reprtCode) {
1360
+ throw new Error(`Invalid quarter: ${opts.quarter} (must be one of: q1, half, q3, annual)`);
1361
+ }
1362
+ const params = {
1363
+ corp_code: corpCode,
1364
+ bsns_year: opts.year,
1365
+ reprt_code: reprtCode
1366
+ };
1367
+ if (needsIdxClCode && opts.idxClCode) {
1368
+ params.idx_cl_code = IDX_CL_CODE_MAP[opts.idxClCode] || opts.idxClCode;
1369
+ }
1370
+ if (ep.extraParams) {
1371
+ for (const p of ep.extraParams) {
1372
+ const optKey = p.name.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
1373
+ if (opts[optKey]) {
1374
+ params[p.name] = opts[optKey];
1375
+ }
1376
+ }
1377
+ }
1378
+ if (globalOpts.dryRun) {
1379
+ writeDryRun(`/${ep.path}`, params, globalOpts);
1380
+ return;
1381
+ }
1382
+ const data = await dartFetch({ apiKey, path: `/${ep.path}`, params });
1383
+ writeOutput(data, globalOpts);
1384
+ });
1385
+ } else if (ep.cliName === "multi-account" || ep.cliName === "multi-index") {
1386
+ cmd.requiredOption("--corp <codes>", 'Corp codes, comma-separated, max 100 (e.g. "00126380,00258801")').requiredOption("--year <YYYY>", "Business year in YYYY format (e.g. 2024). Data from 2015 onward").requiredOption("--quarter <q1|half|q3|annual>", "Report quarter: q1 (Q1), half (semi-annual), q3 (Q3), annual (full year)");
1387
+ if (ep.cliName === "multi-index") {
1388
+ cmd.requiredOption("--idx-cl-code <code>", "Index classification: profitability (M210000), stability (M220000), growth (M230000), activity (M240000). Accepts aliases or raw codes");
1389
+ }
1390
+ cmd.action(async (opts) => {
1391
+ const globalOpts = getGlobalOpts3(group);
1392
+ const apiKey = getApiKey(globalOpts.apiKey);
1393
+ if (globalOpts.json) {
1394
+ const params2 = parseJsonParams(globalOpts.json);
1395
+ const data2 = await dartFetch({ apiKey, path: `/${ep.path}`, params: params2 });
1396
+ writeOutput(data2, globalOpts);
1397
+ return;
1398
+ }
1399
+ const reprtCode = REPRT_CODE_MAP[opts.quarter];
1400
+ if (!reprtCode) {
1401
+ throw new Error(`Invalid quarter: ${opts.quarter} (must be one of: q1, half, q3, annual)`);
1402
+ }
1403
+ const params = {
1404
+ corp_code: opts.corp,
1405
+ bsns_year: opts.year,
1406
+ reprt_code: reprtCode
1407
+ };
1408
+ if (opts.idxClCode) {
1409
+ params.idx_cl_code = IDX_CL_CODE_MAP[opts.idxClCode] || opts.idxClCode;
1410
+ }
1411
+ if (globalOpts.dryRun) {
1412
+ writeDryRun(`/${ep.path}`, params, globalOpts);
1413
+ return;
1414
+ }
1415
+ const data = await dartFetch({ apiKey, path: `/${ep.path}`, params });
1416
+ writeOutput(data, globalOpts);
1417
+ });
1418
+ } else if (ep.cliName === "taxonomy") {
1419
+ cmd.requiredOption("--sj-div <code>", "Statement type code: BS1=Balance sheet, IS1=Income statement, CIS1=Comprehensive income, CF1/CF2=Cash flow, SCE=Equity changes").action(async (opts) => {
1420
+ const globalOpts = getGlobalOpts3(group);
1421
+ const apiKey = getApiKey(globalOpts.apiKey);
1422
+ if (globalOpts.json) {
1423
+ const params2 = parseJsonParams(globalOpts.json);
1424
+ const data2 = await dartFetch({ apiKey, path: `/${ep.path}`, params: params2 });
1425
+ writeOutput(data2, globalOpts);
1426
+ return;
1427
+ }
1428
+ const params = { sj_div: opts.sjDiv };
1429
+ if (globalOpts.dryRun) {
1430
+ writeDryRun(`/${ep.path}`, params, globalOpts);
1431
+ return;
1432
+ }
1433
+ const data = await dartFetch({ apiKey, path: `/${ep.path}`, params });
1434
+ writeOutput(data, globalOpts);
1435
+ });
1436
+ }
1437
+ }
1438
+ }
1439
+
1440
+ // src/commands/equity-disclosure.ts
1441
+ function getGlobalOpts4(cmd) {
1442
+ return cmd.optsWithGlobals();
1443
+ }
1444
+ function registerEquityDisclosureCommands(program) {
1445
+ const group = program.command("equity").description(
1446
+ 'DS004: Equity disclosure \u2014 major shareholding reports and executive/major shareholder ownership.\nUse "equity major-stock" for large shareholding (5%+ ownership) status reports.\nUse "equity executive-stock" for executive and major shareholder ownership reports.'
1447
+ );
1448
+ const endpoints = (REGISTRY_BY_GROUP.get("equity") || []).filter(
1449
+ (ep) => ep.pattern === "corpOnly"
1450
+ );
1451
+ for (const ep of endpoints) {
1452
+ group.command(ep.cliName).description(ep.summary).requiredOption("--corp <name-or-code>", "Company name or corp_code").action(async (opts) => {
1453
+ const globalOpts = getGlobalOpts4(group);
1454
+ const apiKey = getApiKey(globalOpts.apiKey);
1455
+ if (globalOpts.json) {
1456
+ const params2 = parseJsonParams(globalOpts.json);
1457
+ const data2 = await dartFetch({ apiKey, path: `/${ep.path}`, params: params2 });
1458
+ writeOutput(data2, globalOpts);
1459
+ return;
1460
+ }
1461
+ const corpCode = await resolveCorpCode(opts.corp, apiKey);
1462
+ const params = { corp_code: corpCode };
1463
+ if (globalOpts.dryRun) {
1464
+ writeDryRun(`/${ep.path}`, params, globalOpts);
1465
+ return;
1466
+ }
1467
+ const data = await dartFetch({ apiKey, path: `/${ep.path}`, params });
1468
+ writeOutput(data, globalOpts);
1469
+ });
1470
+ }
1471
+ }
1472
+
1473
+ // src/commands/major-report.ts
1474
+ function getGlobalOpts5(cmd) {
1475
+ return cmd.optsWithGlobals();
1476
+ }
1477
+ function registerMajorReportCommands(program) {
1478
+ const group = program.command("major").description(
1479
+ "DS005: Major event reports \u2014 36 APIs for significant corporate events.\nCovers: capital increases/reductions, bond issuances (convertible, exchangeable, warrant),\ntreasury stock, M&A (mergers, splits, business/asset transfers), lawsuits,\noverseas listings, defaults, business suspension, rehabilitation.\nData available from 2015 onward. Requires date range."
1480
+ );
1481
+ const endpoints = (REGISTRY_BY_GROUP.get("major") || []).filter(
1482
+ (ep) => ep.pattern === "dateRange"
1483
+ );
1484
+ for (const ep of endpoints) {
1485
+ group.command(ep.cliName).description(ep.summary).requiredOption("--corp <name-or-code>", 'Company name (e.g. "\uC0BC\uC131\uC804\uC790") or 8-digit corp_code').requiredOption("--from <YYYYMMDD>", "Start date in YYYYMMDD format (filing date). Data from 2015 onward").requiredOption("--to <YYYYMMDD>", "End date in YYYYMMDD format (filing date)").action(async (opts) => {
1486
+ const globalOpts = getGlobalOpts5(group);
1487
+ const apiKey = getApiKey(globalOpts.apiKey);
1488
+ if (globalOpts.json) {
1489
+ const params2 = parseJsonParams(globalOpts.json);
1490
+ const data2 = await dartFetch({ apiKey, path: `/${ep.path}`, params: params2 });
1491
+ writeOutput(data2, globalOpts);
1492
+ return;
1493
+ }
1494
+ const corpCode = await resolveCorpCode(opts.corp, apiKey);
1495
+ const params = { corp_code: corpCode, bgn_de: opts.from, end_de: opts.to };
1496
+ if (globalOpts.dryRun) {
1497
+ writeDryRun(`/${ep.path}`, params, globalOpts);
1498
+ return;
1499
+ }
1500
+ const data = await dartFetch({ apiKey, path: `/${ep.path}`, params });
1501
+ writeOutput(data, globalOpts);
1502
+ });
1503
+ }
1504
+ }
1505
+
1506
+ // src/commands/securities-filing.ts
1507
+ function getGlobalOpts6(cmd) {
1508
+ return cmd.optsWithGlobals();
1509
+ }
1510
+ function registerSecuritiesFilingCommands(program) {
1511
+ const group = program.command("securities").description(
1512
+ "DS006: Securities registration statements \u2014 6 APIs for securities filings.\nCovers: equity securities, debt securities, depository receipts,\nmergers, comprehensive stock exchange/transfer, and splits.\nData available from 2015 onward. Requires date range."
1513
+ );
1514
+ const endpoints = (REGISTRY_BY_GROUP.get("securities") || []).filter(
1515
+ (ep) => ep.pattern === "dateRange"
1516
+ );
1517
+ for (const ep of endpoints) {
1518
+ group.command(ep.cliName).description(ep.summary).requiredOption("--corp <name-or-code>", 'Company name (e.g. "\uC0BC\uC131\uC804\uC790") or 8-digit corp_code').requiredOption("--from <YYYYMMDD>", "Start date in YYYYMMDD format (filing date). Data from 2015 onward").requiredOption("--to <YYYYMMDD>", "End date in YYYYMMDD format (filing date)").action(async (opts) => {
1519
+ const globalOpts = getGlobalOpts6(group);
1520
+ const apiKey = getApiKey(globalOpts.apiKey);
1521
+ if (globalOpts.json) {
1522
+ const params2 = parseJsonParams(globalOpts.json);
1523
+ const data2 = await dartFetch({ apiKey, path: `/${ep.path}`, params: params2 });
1524
+ writeOutput(data2, globalOpts);
1525
+ return;
1526
+ }
1527
+ const corpCode = await resolveCorpCode(opts.corp, apiKey);
1528
+ const params = { corp_code: corpCode, bgn_de: opts.from, end_de: opts.to };
1529
+ if (globalOpts.dryRun) {
1530
+ writeDryRun(`/${ep.path}`, params, globalOpts);
1531
+ return;
1532
+ }
1533
+ const data = await dartFetch({ apiKey, path: `/${ep.path}`, params });
1534
+ writeOutput(data, globalOpts);
1535
+ });
1536
+ }
1537
+ }
1538
+
1539
+ // src/commands/schema.ts
1540
+ function getPeriodicParams() {
1541
+ return [
1542
+ {
1543
+ name: "corp_code",
1544
+ type: "STRING(8)",
1545
+ required: true,
1546
+ description: "Company unique code (8 digits)"
1547
+ },
1548
+ {
1549
+ name: "bsns_year",
1550
+ type: "STRING(4)",
1551
+ required: true,
1552
+ description: "Business year (e.g. 2024). Data from 2015 onward"
1553
+ },
1554
+ {
1555
+ name: "reprt_code",
1556
+ type: "STRING(5)",
1557
+ required: true,
1558
+ description: "Report code",
1559
+ enum: { "11013": "Q1", "11012": "Semi-annual", "11014": "Q3", "11011": "Annual" }
1560
+ }
1561
+ ];
1562
+ }
1563
+ function getDateRangeParams() {
1564
+ return [
1565
+ {
1566
+ name: "corp_code",
1567
+ type: "STRING(8)",
1568
+ required: true,
1569
+ description: "Company unique code (8 digits)"
1570
+ },
1571
+ {
1572
+ name: "bgn_de",
1573
+ type: "STRING(8)",
1574
+ required: true,
1575
+ description: "Start date",
1576
+ format: "YYYYMMDD"
1577
+ },
1578
+ {
1579
+ name: "end_de",
1580
+ type: "STRING(8)",
1581
+ required: true,
1582
+ description: "End date",
1583
+ format: "YYYYMMDD"
1584
+ }
1585
+ ];
1586
+ }
1587
+ function getCorpOnlyParams() {
1588
+ return [
1589
+ {
1590
+ name: "corp_code",
1591
+ type: "STRING(8)",
1592
+ required: true,
1593
+ description: "Company unique code (8 digits)"
1594
+ }
1595
+ ];
1596
+ }
1597
+ function extraParamToSchema(p) {
1598
+ const schema = {
1599
+ name: p.name,
1600
+ type: "STRING",
1601
+ required: p.required,
1602
+ description: p.description
1603
+ };
1604
+ if (p.enum) {
1605
+ schema.enum = p.enum;
1606
+ }
1607
+ return schema;
1608
+ }
1609
+ function buildSchema(ep) {
1610
+ let parameters;
1611
+ switch (ep.pattern) {
1612
+ case "periodic":
1613
+ parameters = getPeriodicParams();
1614
+ break;
1615
+ case "dateRange":
1616
+ parameters = getDateRangeParams();
1617
+ break;
1618
+ case "corpOnly":
1619
+ parameters = getCorpOnlyParams();
1620
+ break;
1621
+ case "special":
1622
+ parameters = [];
1623
+ break;
1624
+ }
1625
+ if (ep.extraParams) {
1626
+ for (const p of ep.extraParams) {
1627
+ if (!parameters.find((existing) => existing.name === p.name)) {
1628
+ parameters.push(extraParamToSchema(p));
1629
+ }
1630
+ }
1631
+ }
1632
+ return {
1633
+ endpoint: ep.cliName,
1634
+ path: `/api/${ep.path}`,
1635
+ group: ep.group,
1636
+ pattern: ep.pattern,
1637
+ description: ep.summary,
1638
+ parameters
1639
+ };
1640
+ }
1641
+ function registerSchemaCommand(program) {
1642
+ program.command("schema [endpoint]").description(
1643
+ "Dump parameter schema for an endpoint (for AI agent introspection).\nWithout argument, lists all endpoint names grouped by group."
1644
+ ).action((endpoint) => {
1645
+ if (!endpoint) {
1646
+ const output = {};
1647
+ for (const [groupName, eps] of REGISTRY_BY_GROUP) {
1648
+ output[groupName] = eps.map((ep2) => ep2.cliName);
1649
+ }
1650
+ console.log(JSON.stringify(output, null, 2));
1651
+ return;
1652
+ }
1653
+ const ep = REGISTRY_BY_CLI_NAME.get(endpoint);
1654
+ if (!ep) {
1655
+ throw new Error(`Unknown endpoint: "${endpoint}". Run "dart-fss schema" to list all.`);
1656
+ }
1657
+ const schema = buildSchema(ep);
1658
+ console.log(JSON.stringify(schema, null, 2));
1659
+ });
1660
+ }
1661
+
1662
+ // src/cli.ts
1663
+ function createDartProgram() {
1664
+ const program = new Command();
1665
+ program.name("dart-fss").description(
1666
+ 'DART Open API CLI \u2014 access Korea Financial Supervisory Service (FSS) electronic disclosure system.\nProvides 83 API endpoints for company filings, financial statements, equity disclosures, and more.\nAuthentication: set DART_API_KEY env var or pass --api-key. Get a key at https://opendart.fss.or.kr\nCompanies are identified by 8-digit corp_code or company name. Use "dart-fss lookup <name>" to find corp_code.\nOutput is JSON by default (compact single-line). Use --pretty for formatted output.\nRate limit: approximately 20,000 requests per day per API key.'
1667
+ ).version("0.4.1").option("--api-key <key>", "DART API key (default: DART_API_KEY env). Get one at https://opendart.fss.or.kr").option("--pretty", "Pretty-print JSON output (default: compact single-line JSON)").option("--output <file>", "Save result to file instead of stdout").option("--json <params>", "Pass raw API parameters as JSON string, bypassing flag parsing").option("--fields <f1,f2,...>", "Comma-separated field names to include in output (reduces response size for agents)").option("--dry-run", "Validate parameters and print the resolved API request without calling the API");
1668
+ registerDisclosureCommands(program);
1669
+ registerPeriodicReportCommands(program);
1670
+ registerFinancialCommands(program);
1671
+ registerEquityDisclosureCommands(program);
1672
+ registerMajorReportCommands(program);
1673
+ registerSecuritiesFilingCommands(program);
1674
+ registerLookupCommand(program);
1675
+ registerCorpCacheCommand(program);
1676
+ registerSchemaCommand(program);
1677
+ program.command("endpoints").description("List all registered API endpoints. Outputs JSON when stdout is not a TTY or --json-output is used.").option("--group <group>", "disclosure, report, financial, equity, major, securities").option("--json-output", "Force JSON output").action((opts) => {
1678
+ let endpoints = REGISTRY;
1679
+ if (opts.group) {
1680
+ endpoints = endpoints.filter((ep) => ep.group === opts.group);
1681
+ }
1682
+ const useJson = opts.jsonOutput || !process.stdout.isTTY;
1683
+ if (useJson) {
1684
+ const data = endpoints.map((ep) => ({
1685
+ name: ep.cliName,
1686
+ group: ep.group,
1687
+ pattern: ep.pattern,
1688
+ description: ep.summary
1689
+ }));
1690
+ console.log(JSON.stringify(data));
1691
+ return;
1692
+ }
1693
+ console.log(`${endpoints.length} endpoints:
1694
+ `);
1695
+ const groups = /* @__PURE__ */ new Map();
1696
+ for (const ep of endpoints) {
1697
+ const g = groups.get(ep.group) || [];
1698
+ g.push(ep);
1699
+ groups.set(ep.group, g);
1700
+ }
1701
+ for (const [groupName, eps] of groups) {
1702
+ console.log(`[${groupName}] (${eps.length})`);
1703
+ for (const ep of eps) {
1704
+ console.log(` ${ep.cliName.padEnd(35)} ${ep.pattern.padEnd(10)} ${ep.summary}`);
1705
+ }
1706
+ console.log();
1707
+ }
1708
+ });
1709
+ return program;
1710
+ }
1711
+
1712
+ export {
1713
+ formatErrorJson,
1714
+ createDartProgram
1715
+ };