empuno 1.1.0 → 1.2.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 (3) hide show
  1. package/README.md +4 -0
  2. package/empuno.mjs +42 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -38,6 +38,7 @@ empuno leave-requests.approve 123
38
38
  empuno leave-requests.reject 124 --rejection_reason "Yoğun dönem"
39
39
  empuno employees.documents.store 45 --document_type is_sozlesmesi --file file=./sozlesme.pdf
40
40
  empuno leave-reports.download 12 --output ./rapor.pdf
41
+ empuno reference sgk_exit_codes # bir alanın geçerli değerleri
41
42
  empuno call POST /manager/leave-requests/123/approve # ham çağrı
42
43
  empuno api leaves --status approved # salt-okuma Company API
43
44
  ```
@@ -50,6 +51,9 @@ komutu CLI güncellemesi olmadan görünür.
50
51
  - `--alan @dosya` ya da `--file alan=dosya` → multipart yükleme.
51
52
  - `--json '{…}'` / `--json @govde.json`, `--dry-run`, `--output yol`,
52
53
  `--profile ad` (birden çok firma).
54
+ - Listeler `--per_page` (≤100) ve `--page` alır; yeni kaydın kimliği yanıtta
55
+ `flash.created` ya da `redirect.params` içindedir.
56
+ - Geçmiş veri aktarımı (`data-migration.*`) davet/e-posta/bildirim göndermez.
53
57
 
54
58
  ## Talepler (empuno ekibine)
55
59
 
package/empuno.mjs CHANGED
@@ -21,7 +21,7 @@ import os from 'node:os';
21
21
  import path from 'node:path';
22
22
  import crypto from 'node:crypto';
23
23
 
24
- const VERSION = '1.1.0'; // EMPUNO_CLI_VERSION — config/agent_api.php cli_version + package.json ile aynı tutulur
24
+ const VERSION = '1.2.0'; // EMPUNO_CLI_VERSION — config/agent_api.php cli_version + package.json ile aynı tutulur
25
25
  const NPM_PACKAGE = 'empuno';
26
26
  const DEFAULT_URL = 'https://empuno.com';
27
27
  const CATALOG_TTL_MS = 10 * 60 * 1000;
@@ -95,7 +95,7 @@ function resolveAuth(flags) {
95
95
 
96
96
  function requireKey(auth) {
97
97
  if (!auth.key) {
98
- throw new UsageError('API anahtarı yok. `empuno login` çalıştırın ya da EMPUNO_API_KEY ortam değişkenini ayarlayın. Anahtar: empuno paneli → Firma Ayarları → API → "Ajan" türünde anahtar.');
98
+ throw new UsageError('API anahtarı yok. `empuno login` çalıştırın ya da EMPUNO_API_KEY ortam değişkenini ayarlayın. Anahtar: empuno paneli → Firma Ayarları → API & Ajan → "Ajan" türünde anahtar.');
99
99
  }
100
100
  if (!auth.key.startsWith('emp_live_')) {
101
101
  throw new UsageError('Geçersiz anahtar biçimi (emp_live_ ile başlamalı).');
@@ -234,7 +234,7 @@ function compareVersions(a, b) {
234
234
  return 0;
235
235
  }
236
236
 
237
- async function request(auth, method, urlPath, { query = {}, body = null, files = [], output = null, dryRun = false } = {}) {
237
+ async function request(auth, method, urlPath, { query = {}, body = null, files = [], output = null, dryRun = false, headers: extraHeaders = {} } = {}) {
238
238
  const url = new URL(urlPath.startsWith('http') ? urlPath : auth.url + urlPath);
239
239
  for (const [k, v] of Object.entries(query)) {
240
240
  if (Array.isArray(v)) v.forEach((item) => url.searchParams.append(`${k}[]`, String(item)));
@@ -246,6 +246,7 @@ async function request(auth, method, urlPath, { query = {}, body = null, files =
246
246
  Accept: 'application/json',
247
247
  'User-Agent': `empuno-cli/${VERSION} node/${process.versions.node}`,
248
248
  'X-Empuno-Cli': VERSION,
249
+ ...extraHeaders,
249
250
  };
250
251
 
251
252
  let sendMethod = method;
@@ -382,7 +383,7 @@ async function findCommand(auth, name, flags) {
382
383
  if (cmd) return cmd;
383
384
 
384
385
  if (catalog.access === 'read') {
385
- const err = new UsageError('bu anahtar salt-okuma ("read") türünde: panel komutlarını çalıştıramaz, yalnız `empuno api …`. Firma Ayarları → API sekmesinden "Ajan" anahtarı oluşturun.');
386
+ const err = new UsageError('bu anahtar salt-okuma ("read") türünde: panel komutlarını çalıştıramaz, yalnız `empuno api …`. Firma Ayarları → API & Ajan sekmesinden "Ajan" anahtarı oluşturun.');
386
387
  err.payload = { ok: false, error: 'read_only_key' };
387
388
  throw err;
388
389
  }
@@ -394,7 +395,7 @@ async function findCommand(auth, name, flags) {
394
395
 
395
396
  if (cmd) {
396
397
  const need = cmd.requires_company_admin ? ['company_admin'] : cmd.permissions;
397
- const err = new UsageError(`"${name}" bu anahtarın kapsamında değil. Gereken yetki: ${need.join(', ') || '—'}. Anahtar kapsamını panelden genişletin (Firma Ayarları → API).`);
398
+ const err = new UsageError(`"${name}" bu anahtarın kapsamında değil. Gereken yetki: ${need.join(', ') || '—'}. Anahtar kapsamını panelden genişletin (Firma Ayarları → API & Ajan).`);
398
399
  err.payload = { ok: false, error: 'scope_required', command: name, required: need, hint: 'Kapsamı anahtar sahibi panelden genişletir; kullanıcıya bildirin.' };
399
400
  throw err;
400
401
  }
@@ -647,6 +648,23 @@ function installedViaNpm() {
647
648
  }
648
649
  }
649
650
 
651
+ async function cmdReference(args) {
652
+ const auth = resolveAuth(args.flags);
653
+ requireKey(auth);
654
+ const name = args.positional[0];
655
+ const { ok, result } = await request(auth, 'GET', `/api/company/v1/reference${name ? `/${encodeURIComponent(name)}` : ''}`);
656
+ if (wantsText() && ok && name && Array.isArray(result?.data)) {
657
+ for (const row of result.data) {
658
+ const key = row.code ?? row.value ?? row.id;
659
+ const label = row.label ?? row.name ?? '';
660
+ process.stdout.write(`${String(key).padEnd(24)} ${label}\n`);
661
+ }
662
+ return 0;
663
+ }
664
+ print(result);
665
+ return ok ? 0 : 1;
666
+ }
667
+
650
668
  async function cmdUpdate(args) {
651
669
  if (installedViaNpm()) {
652
670
  // npm'in yönettiği dosyanın üzerine yazmak sürüm kaydını bozar.
@@ -748,14 +766,20 @@ function printTicket(result) {
748
766
 
749
767
  async function cmdTickets(args) {
750
768
  const { flags, fields, positional } = args;
751
- const auth = resolveAuth(flags);
752
- requireKey(auth);
753
769
  const opts = fieldMap(fields);
754
770
  const [action = 'list', ...rest] = positional;
755
771
  const base = '/api/company/v1/tickets';
756
772
 
757
- const send = async (method, urlPath, body = null, query = {}) => {
758
- const response = await request(auth, method, urlPath, { body, query, dryRun: flags['dry-run'] });
773
+ if (action === 'kinds') {
774
+ print({ kinds: TICKET_KINDS, priorities: ['low', 'normal', 'high'] });
775
+ return 0;
776
+ }
777
+
778
+ const auth = resolveAuth(flags);
779
+ requireKey(auth);
780
+
781
+ const send = async (method, urlPath, body = null, query = {}, headers = {}) => {
782
+ const response = await request(auth, method, urlPath, { body, query, headers, dryRun: flags['dry-run'] });
759
783
  return response;
760
784
  };
761
785
 
@@ -783,7 +807,10 @@ async function cmdTickets(args) {
783
807
  }
784
808
  let context = opts.context ? readJsonArg(String(opts.context)) : {};
785
809
  if (opts.command) context = { ...context, command: String(opts.command) };
786
- const r = await send('POST', base, { title: String(title), kind, body, priority: opts.priority, context: Object.keys(context).length ? context : undefined });
810
+ // Aynı içerik → aynı anahtar: betik yeniden denese de ikinci talep açılmaz
811
+ // (sunucu mevcut talebi duplicate=true ile döner).
812
+ const idem = crypto.createHash('sha256').update(`${title}|${kind}|${body}`).digest('hex').slice(0, 40);
813
+ const r = await send('POST', base, { title: String(title), kind, body, priority: opts.priority, context: Object.keys(context).length ? context : undefined }, {}, { 'Idempotency-Key': opts['idempotency-key'] ? String(opts['idempotency-key']) : idem });
787
814
  if (r.dryRun) return print(r.result), 0;
788
815
  print(r.result);
789
816
  return r.ok ? 0 : 1;
@@ -808,9 +835,6 @@ async function cmdTickets(args) {
808
835
  print(r.result);
809
836
  return r.ok || r.dryRun ? 0 : 1;
810
837
  }
811
- case 'kinds':
812
- print({ kinds: TICKET_KINDS, priorities: ['low', 'normal', 'high'] });
813
- return 0;
814
838
  default:
815
839
  throw new UsageError(`bilinmeyen tickets işlemi "${action}". Kullanım: empuno tickets [list|open|show|reply|close|kinds]`);
816
840
  }
@@ -925,7 +949,8 @@ KURULUM
925
949
  KEŞİF
926
950
  empuno whoami # firma, anahtar türü, kimin adına çalıştığı
927
951
  empuno commands [ara] [--module leaves] [--writes|--reads] [--all] [--full]
928
- empuno describe <komut> # yöntem, yol, yol parametreleri, alanlar/kurallar, gereken yetki
952
+ empuno describe <komut> # yöntem, yol, yol parametreleri, alanlar/kurallar, gereken yetki, hız sınırı
953
+ empuno reference [ad] # geçerli değerler: sgk_exit_codes, employee_document_types, departments, branches, leave_types…
929
954
 
930
955
  ÇALIŞTIRMA (komut = panel rotası; listeden)
931
956
  empuno leave-requests.index --status pending --per_page 50
@@ -1013,6 +1038,9 @@ async function main() {
1013
1038
  case 'tickets':
1014
1039
  case 'ticket':
1015
1040
  return cmdTickets(args);
1041
+ case 'reference':
1042
+ case 'ref':
1043
+ return cmdReference(args);
1016
1044
  case 'support':
1017
1045
  return cmdSupport(args);
1018
1046
  case 'run':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "empuno",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "empuno İK platformunun komut satırı: yönetim panelindeki tüm işlemleri (izin, bordro, vardiya, PDKS, zimmet, masraf, işe alım) yapay zekâ ajanlarına ve otomasyonlara açar.",
5
5
  "type": "module",
6
6
  "bin": {