@newpeak/barista-cli 0.1.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 (82) hide show
  1. package/.eslintrc.json +23 -0
  2. package/.prettierrc +9 -0
  3. package/.sisyphus/notepads/liberica-employees/learnings.md +73 -0
  4. package/AGENTS.md +270 -0
  5. package/CONTRIBUTING.md +291 -0
  6. package/README.md +707 -0
  7. package/bin/barista +6 -0
  8. package/bin/barista.js +3 -0
  9. package/docs/ARCHITECTURE.md +184 -0
  10. package/docs/COMMANDS.md +352 -0
  11. package/docs/COMMAND_DESIGN_SPEC.md +811 -0
  12. package/docs/INTEGRATION_NOTES.md +270 -0
  13. package/docs/commands/REFERENCE.md +297 -0
  14. package/docs/commands/arabica/auth/index.md +296 -0
  15. package/docs/commands/liberica/auth/index.md +133 -0
  16. package/docs/commands/liberica/context/index.md +60 -0
  17. package/docs/commands/liberica/employees/create.md +185 -0
  18. package/docs/commands/liberica/employees/disable.md +138 -0
  19. package/docs/commands/liberica/employees/enable.md +137 -0
  20. package/docs/commands/liberica/employees/get.md +153 -0
  21. package/docs/commands/liberica/employees/list.md +168 -0
  22. package/docs/commands/liberica/employees/update.md +180 -0
  23. package/docs/commands/liberica/orgs/list.md +62 -0
  24. package/docs/commands/liberica/positions/list.md +61 -0
  25. package/docs/commands/liberica/roles/list.md +67 -0
  26. package/docs/commands/liberica/users/create.md +170 -0
  27. package/docs/commands/liberica/users/get.md +151 -0
  28. package/docs/commands/liberica/users/list.md +175 -0
  29. package/package.json +37 -0
  30. package/src/commands/arabica/auth/index.ts +277 -0
  31. package/src/commands/arabica/auth/login.ts +5 -0
  32. package/src/commands/arabica/auth/logout.ts +5 -0
  33. package/src/commands/arabica/auth/register.ts +5 -0
  34. package/src/commands/arabica/auth/status.ts +5 -0
  35. package/src/commands/arabica/index.ts +23 -0
  36. package/src/commands/auth.ts +107 -0
  37. package/src/commands/context.ts +60 -0
  38. package/src/commands/liberica/auth/index.ts +170 -0
  39. package/src/commands/liberica/context/index.ts +43 -0
  40. package/src/commands/liberica/employees/create.ts +275 -0
  41. package/src/commands/liberica/employees/delete.ts +122 -0
  42. package/src/commands/liberica/employees/disable.ts +97 -0
  43. package/src/commands/liberica/employees/enable.ts +97 -0
  44. package/src/commands/liberica/employees/get.ts +115 -0
  45. package/src/commands/liberica/employees/index.ts +23 -0
  46. package/src/commands/liberica/employees/list.ts +131 -0
  47. package/src/commands/liberica/employees/update.ts +157 -0
  48. package/src/commands/liberica/index.ts +36 -0
  49. package/src/commands/liberica/orgs/index.ts +35 -0
  50. package/src/commands/liberica/positions/index.ts +30 -0
  51. package/src/commands/liberica/roles/index.ts +59 -0
  52. package/src/commands/liberica/users/create.ts +132 -0
  53. package/src/commands/liberica/users/delete.ts +49 -0
  54. package/src/commands/liberica/users/disable.ts +41 -0
  55. package/src/commands/liberica/users/enable.ts +30 -0
  56. package/src/commands/liberica/users/get.ts +46 -0
  57. package/src/commands/liberica/users/index.ts +27 -0
  58. package/src/commands/liberica/users/list.ts +68 -0
  59. package/src/commands/liberica/users/me.ts +42 -0
  60. package/src/commands/liberica/users/reset-password.ts +42 -0
  61. package/src/commands/liberica/users/update.ts +48 -0
  62. package/src/core/api/client.ts +825 -0
  63. package/src/core/auth/token-manager.ts +183 -0
  64. package/src/core/config/manager.ts +164 -0
  65. package/src/index.ts +37 -0
  66. package/src/types/employee.ts +102 -0
  67. package/src/types/index.ts +75 -0
  68. package/src/types/org.ts +25 -0
  69. package/src/types/position.ts +24 -0
  70. package/src/types/user.ts +64 -0
  71. package/tests/unit/commands/arabica/auth.test.ts +230 -0
  72. package/tests/unit/commands/liberica/auth.test.ts +175 -0
  73. package/tests/unit/commands/liberica/context.test.ts +98 -0
  74. package/tests/unit/commands/liberica/employees/create.test.ts +463 -0
  75. package/tests/unit/commands/liberica/employees/disable.test.ts +82 -0
  76. package/tests/unit/commands/liberica/employees/enable.test.ts +82 -0
  77. package/tests/unit/commands/liberica/employees/get.test.ts +111 -0
  78. package/tests/unit/commands/liberica/employees/list.test.ts +294 -0
  79. package/tests/unit/commands/liberica/employees/update.test.ts +210 -0
  80. package/tests/unit/config.test.ts +141 -0
  81. package/tests/unit/types.test.ts +195 -0
  82. package/tsconfig.json +20 -0
@@ -0,0 +1,183 @@
1
+ import keytar from 'keytar';
2
+ import * as crypto from 'crypto';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import * as os from 'os';
6
+ import { TokenContext } from '../../types/index.js';
7
+
8
+ const SERVICE_NAME = 'barista-cli';
9
+ const ENCRYPTION_ALGORITHM = 'aes-256-gcm';
10
+ const FALLBACK_FILE_NAME = '.barista-tokens';
11
+
12
+ interface StoredToken {
13
+ service: string;
14
+ environment: string;
15
+ tenant?: string;
16
+ token: string;
17
+ updatedAt: string;
18
+ }
19
+
20
+ class TokenManager {
21
+ private fallbackDir: string;
22
+ private fallbackFilePath: string;
23
+
24
+ constructor() {
25
+ this.fallbackDir = path.join(os.homedir(), '.barista');
26
+ this.fallbackFilePath = path.join(this.fallbackDir, FALLBACK_FILE_NAME);
27
+ }
28
+
29
+ async getToken(context: TokenContext): Promise<string | null> {
30
+ const account = this.buildAccount(context);
31
+
32
+ try {
33
+ const token = await keytar.getPassword(SERVICE_NAME, account);
34
+ if (token) return token;
35
+ } catch (keytarError) {
36
+ console.warn('[TokenManager] Keytar not available, using fallback storage');
37
+ }
38
+
39
+ return this.getTokenFromFallback(context);
40
+ }
41
+
42
+ async setToken(context: TokenContext, token: string): Promise<void> {
43
+ const account = this.buildAccount(context);
44
+
45
+ try {
46
+ await keytar.setPassword(SERVICE_NAME, account, token);
47
+ await this.removeFromFallback(context);
48
+ return;
49
+ } catch (keytarError) {
50
+ console.warn('[TokenManager] Keytar failed, using fallback storage');
51
+ }
52
+
53
+ await this.setTokenToFallback(context, token);
54
+ }
55
+
56
+ async deleteToken(context: TokenContext): Promise<boolean> {
57
+ const account = this.buildAccount(context);
58
+
59
+ let deleted = false;
60
+ try {
61
+ deleted = await keytar.deletePassword(SERVICE_NAME, account);
62
+ } catch (keytarError) {
63
+ // Ignore keytar errors, try fallback
64
+ }
65
+
66
+ const fallbackDeleted = await this.removeFromFallback(context);
67
+ return deleted || fallbackDeleted;
68
+ }
69
+
70
+ async findAllTokens(): Promise<Array<{ account: string; password: string }>> {
71
+ try {
72
+ const credentials = await keytar.findCredentials(SERVICE_NAME);
73
+ if (credentials.length > 0) return credentials;
74
+ } catch (keytarError) {
75
+ // Ignore keytar errors
76
+ }
77
+
78
+ return this.getAllFromFallback();
79
+ }
80
+
81
+ private buildAccount(context: TokenContext): string {
82
+ const parts: string[] = [context.service, context.environment];
83
+ if (context.tenant) {
84
+ parts.push(context.tenant);
85
+ }
86
+ return parts.join(':');
87
+ }
88
+
89
+ private getMachineId(): Buffer {
90
+ const machineId = os.hostname() + os.platform() + os.arch() + os.homedir();
91
+ return crypto.createHash('sha256').update(machineId).digest();
92
+ }
93
+
94
+ private encrypt(text: string): string {
95
+ const key = this.getMachineId();
96
+ const iv = crypto.randomBytes(16);
97
+ const cipher = crypto.createCipheriv(ENCRYPTION_ALGORITHM, key, iv);
98
+ let encrypted = cipher.update(text, 'utf8', 'hex');
99
+ encrypted += cipher.final('hex');
100
+ const authTag = cipher.getAuthTag();
101
+ return iv.toString('hex') + ':' + authTag.toString('hex') + ':' + encrypted;
102
+ }
103
+
104
+ private decrypt(encryptedText: string): string {
105
+ const parts = encryptedText.split(':');
106
+ if (parts.length !== 3) throw new Error('Invalid encrypted data format');
107
+ const iv = Buffer.from(parts[0], 'hex');
108
+ const authTag = Buffer.from(parts[1], 'hex');
109
+ const encrypted = parts[2];
110
+ const key = this.getMachineId();
111
+ const decipher = crypto.createDecipheriv(ENCRYPTION_ALGORITHM, key, iv);
112
+ decipher.setAuthTag(authTag);
113
+ let decrypted = decipher.update(encrypted, 'hex', 'utf8');
114
+ decrypted += decipher.final('utf8');
115
+ return decrypted;
116
+ }
117
+
118
+ private async getFallbackTokens(): Promise<Record<string, StoredToken>> {
119
+ try {
120
+ if (!fs.existsSync(this.fallbackFilePath)) {
121
+ return {};
122
+ }
123
+ const encryptedData = fs.readFileSync(this.fallbackFilePath, 'utf8');
124
+ const decrypted = this.decrypt(encryptedData);
125
+ return JSON.parse(decrypted);
126
+ } catch {
127
+ return {};
128
+ }
129
+ }
130
+
131
+ private async saveFallbackTokens(tokens: Record<string, StoredToken>): Promise<void> {
132
+ if (!fs.existsSync(this.fallbackDir)) {
133
+ fs.mkdirSync(this.fallbackDir, { recursive: true });
134
+ }
135
+ const json = JSON.stringify(tokens);
136
+ const encrypted = this.encrypt(json);
137
+ fs.writeFileSync(this.fallbackFilePath, encrypted, { mode: 0o600 });
138
+ }
139
+
140
+ private async getTokenFromFallback(context: TokenContext): Promise<string | null> {
141
+ const tokens = await this.getFallbackTokens();
142
+ const key = this.buildAccount(context);
143
+ const stored = tokens[key];
144
+ if (stored) {
145
+ return stored.token;
146
+ }
147
+ return null;
148
+ }
149
+
150
+ private async setTokenToFallback(context: TokenContext, token: string): Promise<void> {
151
+ const tokens = await this.getFallbackTokens();
152
+ const key = this.buildAccount(context);
153
+ tokens[key] = {
154
+ service: context.service,
155
+ environment: context.environment,
156
+ tenant: context.tenant,
157
+ token,
158
+ updatedAt: new Date().toISOString(),
159
+ };
160
+ await this.saveFallbackTokens(tokens);
161
+ }
162
+
163
+ private async removeFromFallback(context: TokenContext): Promise<boolean> {
164
+ const tokens = await this.getFallbackTokens();
165
+ const key = this.buildAccount(context);
166
+ if (tokens[key]) {
167
+ delete tokens[key];
168
+ await this.saveFallbackTokens(tokens);
169
+ return true;
170
+ }
171
+ return false;
172
+ }
173
+
174
+ private async getAllFromFallback(): Promise<Array<{ account: string; password: string }>> {
175
+ const tokens = await this.getFallbackTokens();
176
+ return Object.entries(tokens).map(([account, stored]) => ({
177
+ account,
178
+ password: stored.token,
179
+ }));
180
+ }
181
+ }
182
+
183
+ export const tokenManager = new TokenManager();
@@ -0,0 +1,164 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import yaml from 'yaml';
5
+ import { Config, Context, Environment, Service } from '../../types/index.js';
6
+
7
+ const DEFAULT_CONFIG: Config = {
8
+ defaults: {
9
+ env: 'dev',
10
+ tenant: 'default',
11
+ service: 'liberica',
12
+ },
13
+ environments: {
14
+ dev: {
15
+ liberica: {
16
+ baseUrl: 'https://{tenant}-dev.newpeaksh.com',
17
+ timeout: 30000,
18
+ },
19
+ arabica: {
20
+ baseUrl: 'https://arabica-dev.newpeaksh.com',
21
+ timeout: 30000,
22
+ },
23
+ },
24
+ test: {
25
+ liberica: {
26
+ baseUrl: 'https://{tenant}-test.newpeaksh.com',
27
+ timeout: 30000,
28
+ },
29
+ arabica: {
30
+ baseUrl: 'https://arabica-test.newpeaksh.com',
31
+ timeout: 30000,
32
+ },
33
+ },
34
+ 'prod-cn': {
35
+ liberica: {
36
+ baseUrl: 'https://{tenant}.newpeaksh.com',
37
+ timeout: 60000,
38
+ },
39
+ arabica: {
40
+ baseUrl: 'https://www.newpeaksh.com',
41
+ timeout: 60000,
42
+ },
43
+ },
44
+ 'prod-jp': {
45
+ liberica: {
46
+ baseUrl: 'https://{tenant}.newpeakjp.com',
47
+ timeout: 60000,
48
+ },
49
+ arabica: {
50
+ baseUrl: 'https://members.newpeakjp.com',
51
+ timeout: 60000,
52
+ },
53
+ },
54
+ },
55
+ output: {
56
+ format: 'table',
57
+ color: true,
58
+ timestamp: true,
59
+ },
60
+ };
61
+
62
+ class ConfigManager {
63
+ private config: Config | null = null;
64
+ private configPath: string;
65
+
66
+ constructor() {
67
+ const homeDir = os.homedir();
68
+ const baristaDir = path.join(homeDir, '.barista');
69
+ this.configPath = path.join(baristaDir, 'config.yaml');
70
+ }
71
+
72
+ async load(): Promise<void> {
73
+ try {
74
+ const configDir = path.dirname(this.configPath);
75
+ if (!fs.existsSync(configDir)) {
76
+ fs.mkdirSync(configDir, { recursive: true });
77
+ }
78
+
79
+ if (fs.existsSync(this.configPath)) {
80
+ const content = fs.readFileSync(this.configPath, 'utf-8');
81
+ this.config = yaml.parse(content) as Config;
82
+ } else {
83
+ this.config = { ...DEFAULT_CONFIG };
84
+ await this.save();
85
+ }
86
+ } catch (error) {
87
+ this.config = { ...DEFAULT_CONFIG };
88
+ }
89
+ }
90
+
91
+ async save(): Promise<void> {
92
+ if (!this.config) {
93
+ throw new Error('Config not loaded');
94
+ }
95
+ const configDir = path.dirname(this.configPath);
96
+ if (!fs.existsSync(configDir)) {
97
+ fs.mkdirSync(configDir, { recursive: true });
98
+ }
99
+ const content = yaml.stringify(this.config);
100
+ fs.writeFileSync(this.configPath, content, 'utf-8');
101
+ }
102
+
103
+ getConfig(): Config {
104
+ if (!this.config) {
105
+ throw new Error('Config not loaded');
106
+ }
107
+ return this.config;
108
+ }
109
+
110
+ getCurrentContext(): Context {
111
+ if (!this.config) {
112
+ throw new Error('Config not loaded');
113
+ }
114
+ return {
115
+ environment: this.config.defaults.env,
116
+ service: this.config.defaults.service,
117
+ tenant: this.config.defaults.tenant,
118
+ };
119
+ }
120
+
121
+ async setEnvironment(env: Environment): Promise<void> {
122
+ if (!this.config) {
123
+ throw new Error('Config not loaded');
124
+ }
125
+ if (!['dev', 'test', 'prod-cn', 'prod-jp'].includes(env)) {
126
+ throw new Error(`Invalid environment: ${env}`);
127
+ }
128
+ this.config.defaults.env = env;
129
+ await this.save();
130
+ }
131
+
132
+ async setTenant(tenant: string): Promise<void> {
133
+ if (!this.config) {
134
+ throw new Error('Config not loaded');
135
+ }
136
+ this.config.defaults.tenant = tenant;
137
+ await this.save();
138
+ }
139
+
140
+ async setService(service: Service): Promise<void> {
141
+ if (!this.config) {
142
+ throw new Error('Config not loaded');
143
+ }
144
+ this.config.defaults.service = service;
145
+ await this.save();
146
+ }
147
+
148
+ getEnvironmentUrl(service: Service, environment: Environment, tenant?: string): string {
149
+ if (!this.config) {
150
+ throw new Error('Config not loaded');
151
+ }
152
+ const envConfig = this.config.environments[environment];
153
+ if (!envConfig) {
154
+ throw new Error(`Environment not found: ${environment}`);
155
+ }
156
+ let url = service === 'liberica' ? envConfig.liberica.baseUrl : envConfig.arabica.baseUrl;
157
+ if (service === 'liberica') {
158
+ url = url.replace('{tenant}', tenant || this.config.defaults.tenant);
159
+ }
160
+ return url;
161
+ }
162
+ }
163
+
164
+ export const configManager = new ConfigManager();
package/src/index.ts ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { configManager } from './core/config/manager.js';
5
+ import { createContextCommand } from './commands/context.js';
6
+ import { createAuthCommand } from './commands/auth.js';
7
+ import { createLibericaCommand } from './commands/liberica/index.js';
8
+ import { createArabicaCommand } from './commands/arabica/index.js';
9
+
10
+ async function main(): Promise<void> {
11
+ try {
12
+ await configManager.load();
13
+
14
+ const program = new Command();
15
+ program
16
+ .name('barista')
17
+ .description('Barista CLI - Bridge between AI agents and Liberica/Arabica')
18
+ .version('0.1.0')
19
+ .option('-e, --env <environment>', 'Target environment (dev|test|prod-cn|prod-jp)')
20
+ .option('-t, --tenant <tenant>', 'Target tenant (for Liberica)')
21
+ .option('--dry-run', 'Execute in dry-run mode')
22
+ .option('--json', 'Output as JSON')
23
+ .option('--debug', 'Enable debug mode');
24
+
25
+ program.addCommand(createContextCommand());
26
+ program.addCommand(createAuthCommand());
27
+ program.addCommand(createLibericaCommand());
28
+ program.addCommand(createArabicaCommand());
29
+
30
+ await program.parseAsync();
31
+ } catch (error) {
32
+ console.error('Error:', error instanceof Error ? error.message : error);
33
+ process.exit(1);
34
+ }
35
+ }
36
+
37
+ main();
@@ -0,0 +1,102 @@
1
+ // Employee sex literal type
2
+ export type EmployeeSex = 'M' | 'F';
3
+
4
+ // Status flag literal type
5
+ export type StatusFlag = 1 | 2;
6
+
7
+ // Full Employee entity (from MasterEmployeeResponse)
8
+ export interface Employee {
9
+ employeeId: string;
10
+ employeeCode: string;
11
+ employeeName: string;
12
+ employeeNo: string;
13
+ employeePhone?: string;
14
+ employeeEmail?: string;
15
+ employeeSex?: EmployeeSex;
16
+ employeeIdType?: string;
17
+ employeeIdNo?: string;
18
+ employeeJoinedDate?: string;
19
+ employeeLeaveDate?: string;
20
+ employeeBirthday?: string;
21
+ organizationId?: string;
22
+ orgCode?: string;
23
+ orgName?: string;
24
+ organizationManagerFlag?: string;
25
+ positionId?: string;
26
+ positionName?: string;
27
+ jobType?: string;
28
+ jobLevelNo?: string;
29
+ evaluator1?: string;
30
+ evaluator2?: string;
31
+ coach?: string;
32
+ employeeStatus?: string;
33
+ statusFlag: StatusFlag;
34
+ employeeBankAccount?: string;
35
+ employeeDepositBank?: string;
36
+ account?: string;
37
+ encryptPassword?: string;
38
+ showQrCode?: boolean;
39
+ qrCode?: string;
40
+ }
41
+
42
+ // Request for creating employee (add endpoint)
43
+ export interface CreateEmployeeRequest {
44
+ employeeCode?: string;
45
+ employeeName: string;
46
+ employeeNo: string;
47
+ employeePhone?: string;
48
+ employeeEmail?: string;
49
+ employeeSex?: EmployeeSex;
50
+ employeeIdType?: string;
51
+ employeeIdNo?: string;
52
+ employeeJoinedDate?: string;
53
+ employeeLeaveDate?: string;
54
+ employeeBirthday?: string;
55
+ organizationId?: string;
56
+ positionId?: string;
57
+ jobType?: string;
58
+ jobLevelNo?: string;
59
+ }
60
+
61
+ // Request for updating employee (edit endpoint)
62
+ export interface UpdateEmployeeRequest {
63
+ employeeId: string;
64
+ employeeName?: string;
65
+ employeePhone?: string;
66
+ employeeEmail?: string;
67
+ employeeJoinedDate?: string;
68
+ employeeLeaveDate?: string;
69
+ organizationId?: string;
70
+ positionId?: string;
71
+ }
72
+
73
+ // Query params for list/pagination
74
+ export interface EmployeeQueryParams {
75
+ pageNo?: number;
76
+ pageSize?: number;
77
+ status?: StatusFlag;
78
+ organizationId?: number;
79
+ employeeCode?: string;
80
+ employeeName?: string;
81
+ }
82
+
83
+ // Paginated response wrapper (PageResult from Roses framework)
84
+ export interface PageResult<T> {
85
+ totalRows: number;
86
+ pageSize: number;
87
+ pageNo: number;
88
+ rows: T[];
89
+ }
90
+
91
+ // List response type
92
+ export interface EmployeeListResponse extends PageResult<Employee> {}
93
+
94
+ // API response wrapper
95
+ export interface EmployeeApiResponse {
96
+ success: boolean;
97
+ data?: Employee | EmployeeListResponse;
98
+ error?: {
99
+ code: string;
100
+ message: string;
101
+ };
102
+ }
@@ -0,0 +1,75 @@
1
+ export interface APIResponse<T = unknown> {
2
+ success: boolean;
3
+ data?: T;
4
+ error?: {
5
+ code: string;
6
+ message: string;
7
+ details?: unknown;
8
+ };
9
+ // Backend error format (direct fields instead of nested error object)
10
+ code?: string;
11
+ message?: string;
12
+ meta?: {
13
+ requestId?: string;
14
+ timestamp?: string;
15
+ pagination?: {
16
+ page: number;
17
+ size: number;
18
+ total: number;
19
+ totalPages: number;
20
+ };
21
+ };
22
+ }
23
+
24
+ export interface CommandOptions {
25
+ env?: string;
26
+ tenant?: string;
27
+ dryRun?: boolean;
28
+ json?: boolean;
29
+ debug?: boolean;
30
+ }
31
+
32
+ export interface Context {
33
+ environment: Environment;
34
+ service: Service;
35
+ tenant: string;
36
+ }
37
+
38
+ export type Environment = 'dev' | 'test' | 'prod-cn' | 'prod-jp';
39
+ export type Service = 'liberica' | 'arabica';
40
+
41
+ export interface Config {
42
+ defaults: {
43
+ env: Environment;
44
+ tenant: string;
45
+ service: Service;
46
+ };
47
+ environments: Record<
48
+ Environment,
49
+ {
50
+ liberica: {
51
+ baseUrl: string;
52
+ timeout: number;
53
+ };
54
+ arabica: {
55
+ baseUrl: string;
56
+ timeout: number;
57
+ };
58
+ }
59
+ >;
60
+ output: {
61
+ format: 'table' | 'json';
62
+ color: boolean;
63
+ timestamp: boolean;
64
+ };
65
+ }
66
+
67
+ export interface TokenContext {
68
+ service: Service;
69
+ environment: Environment;
70
+ tenant?: string;
71
+ }
72
+
73
+ export * from './employee.js';
74
+ export * from './org.js';
75
+ export * from './position.js';
@@ -0,0 +1,25 @@
1
+ // Organization entity
2
+ export interface Organization {
3
+ organizationId: number;
4
+ orgCode?: string;
5
+ orgName?: string;
6
+ parentId?: number;
7
+ orgLevel?: number;
8
+ sortNo?: number;
9
+ statusFlag?: number;
10
+ }
11
+
12
+ // API response for org list (generic id+name for reuse)
13
+ export interface OrgListItem {
14
+ id: string;
15
+ name: string;
16
+ }
17
+
18
+ export interface OrgListResponse {
19
+ success: boolean;
20
+ data?: OrgListItem[];
21
+ error?: {
22
+ code: string;
23
+ message: string;
24
+ };
25
+ }
@@ -0,0 +1,24 @@
1
+ // Position entity
2
+ export interface Position {
3
+ positionId: string;
4
+ positionCode?: string;
5
+ positionName?: string;
6
+ jobType?: string;
7
+ jobLevelNo?: string;
8
+ statusFlag?: number;
9
+ }
10
+
11
+ // API response for position list (generic id+name for reuse)
12
+ export interface PositionListItem {
13
+ id: string;
14
+ name: string;
15
+ }
16
+
17
+ export interface PositionListResponse {
18
+ success: boolean;
19
+ data?: PositionListItem[];
20
+ error?: {
21
+ code: string;
22
+ message: string;
23
+ };
24
+ }
@@ -0,0 +1,64 @@
1
+ export type UserStatusFlag = 1 | 2;
2
+
3
+ export interface User {
4
+ userId: string;
5
+ realName: string;
6
+ account: string;
7
+ email?: string;
8
+ employeeId?: string;
9
+ employeeNumber?: string;
10
+ employeeName?: string;
11
+ roleNameList?: string[];
12
+ statusFlag: UserStatusFlag;
13
+ createTime?: string;
14
+ readOnly?: boolean;
15
+ }
16
+
17
+ export interface CreateUserRequest {
18
+ realName: string;
19
+ account: string;
20
+ email?: string;
21
+ roleIdList: string[];
22
+ employeeId?: string;
23
+ employeeNumber?: string;
24
+ employeeCode?: string;
25
+ orgId?: string;
26
+ positionId?: string;
27
+ mainFlag?: boolean;
28
+ }
29
+
30
+ export interface UpdateUserRequest {
31
+ userId: string;
32
+ realName?: string;
33
+ email?: string;
34
+ roleIdList?: string[];
35
+ employeeId?: string;
36
+ statusFlag?: UserStatusFlag;
37
+ }
38
+
39
+ export interface UserQueryParams {
40
+ pageNo?: number;
41
+ pageSize?: number;
42
+ status?: UserStatusFlag;
43
+ account?: string;
44
+ realName?: string;
45
+ employeeId?: string;
46
+ }
47
+
48
+ export interface PageResult<T> {
49
+ totalRows: number;
50
+ pageSize: number;
51
+ pageNo: number;
52
+ rows: T[];
53
+ }
54
+
55
+ export interface UserListResponse extends PageResult<User> {}
56
+
57
+ export interface UserApiResponse {
58
+ success: boolean;
59
+ data?: User | UserListResponse;
60
+ error?: {
61
+ code: string;
62
+ message: string;
63
+ };
64
+ }