aranea-sdk-cli 0.5.2 → 0.5.5
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.
- package/dist/commands/permission.d.ts +18 -0
- package/dist/commands/permission.js +412 -0
- package/dist/commands/type.d.ts +21 -0
- package/dist/commands/type.js +469 -0
- package/dist/index.js +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AraneaSDK CLI - Permission Command
|
|
3
|
+
*
|
|
4
|
+
* TypeDefaultPermissions management for AraneaDevice types
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* aranea-sdk permission list # List all typeDefaultPermissions
|
|
8
|
+
* aranea-sdk permission get <type> # Get permission for specific type
|
|
9
|
+
* aranea-sdk permission set <type> <level> # Set default permission level
|
|
10
|
+
* aranea-sdk permission delete <type> # Delete typeDefaultPermission
|
|
11
|
+
*
|
|
12
|
+
* Note: Requires System Authority Layer permission (71+)
|
|
13
|
+
*/
|
|
14
|
+
import { Command } from 'commander';
|
|
15
|
+
/**
|
|
16
|
+
* Permission command
|
|
17
|
+
*/
|
|
18
|
+
export declare const permissionCommand: Command;
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AraneaSDK CLI - Permission Command
|
|
4
|
+
*
|
|
5
|
+
* TypeDefaultPermissions management for AraneaDevice types
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* aranea-sdk permission list # List all typeDefaultPermissions
|
|
9
|
+
* aranea-sdk permission get <type> # Get permission for specific type
|
|
10
|
+
* aranea-sdk permission set <type> <level> # Set default permission level
|
|
11
|
+
* aranea-sdk permission delete <type> # Delete typeDefaultPermission
|
|
12
|
+
*
|
|
13
|
+
* Note: Requires System Authority Layer permission (71+)
|
|
14
|
+
*/
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.permissionCommand = void 0;
|
|
20
|
+
const commander_1 = require("commander");
|
|
21
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
22
|
+
const auth_1 = require("./auth");
|
|
23
|
+
const config_1 = require("../config");
|
|
24
|
+
// Firebase project configuration
|
|
25
|
+
const FIREBASE_PROJECTS = {
|
|
26
|
+
production: 'mobesorder',
|
|
27
|
+
staging: 'mobesorder-staging',
|
|
28
|
+
};
|
|
29
|
+
const FIREBASE_REGION = 'asia-northeast1';
|
|
30
|
+
/**
|
|
31
|
+
* Call Firebase Callable Function
|
|
32
|
+
*/
|
|
33
|
+
async function callFunction(functionName, data, token, env) {
|
|
34
|
+
const projectId = FIREBASE_PROJECTS[env];
|
|
35
|
+
const url = `https://${FIREBASE_REGION}-${projectId}.cloudfunctions.net/${functionName}`;
|
|
36
|
+
const response = await fetch(url, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
Authorization: `Bearer ${token}`,
|
|
41
|
+
},
|
|
42
|
+
body: JSON.stringify({ data }),
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
46
|
+
const errorMessage = errorBody.error?.message || `HTTP ${response.status}`;
|
|
47
|
+
throw new Error(errorMessage);
|
|
48
|
+
}
|
|
49
|
+
const result = await response.json();
|
|
50
|
+
return result.result;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Firestore REST API for direct reads
|
|
54
|
+
*/
|
|
55
|
+
async function firestoreGet(path, token, env) {
|
|
56
|
+
const projectId = FIREBASE_PROJECTS[env];
|
|
57
|
+
const url = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${path}`;
|
|
58
|
+
const response = await fetch(url, {
|
|
59
|
+
method: 'GET',
|
|
60
|
+
headers: {
|
|
61
|
+
Authorization: `Bearer ${token}`,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
if (response.status === 404) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
69
|
+
throw new Error(errorBody.error?.message || `HTTP ${response.status}`);
|
|
70
|
+
}
|
|
71
|
+
return response.json();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* List all typeDefaultPermissions
|
|
75
|
+
*/
|
|
76
|
+
async function firestoreListTypeDefaultPermissions(token, env) {
|
|
77
|
+
const projectId = FIREBASE_PROJECTS[env];
|
|
78
|
+
const collectionPath = 'LacisOathConfig/permissionConfig/typeDefaultPermissions';
|
|
79
|
+
const url = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${collectionPath}`;
|
|
80
|
+
const response = await fetch(url, {
|
|
81
|
+
method: 'GET',
|
|
82
|
+
headers: {
|
|
83
|
+
Authorization: `Bearer ${token}`,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
if (response.status === 404) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
91
|
+
throw new Error(errorBody.error?.message || `HTTP ${response.status}`);
|
|
92
|
+
}
|
|
93
|
+
const result = await response.json();
|
|
94
|
+
return result.documents || [];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Parse Firestore document fields to plain object
|
|
98
|
+
*/
|
|
99
|
+
function parseFirestoreFields(fields) {
|
|
100
|
+
const result = {};
|
|
101
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
102
|
+
if ('stringValue' in value) {
|
|
103
|
+
result[key] = value.stringValue;
|
|
104
|
+
}
|
|
105
|
+
else if ('integerValue' in value) {
|
|
106
|
+
result[key] = parseInt(value.integerValue, 10);
|
|
107
|
+
}
|
|
108
|
+
else if ('doubleValue' in value) {
|
|
109
|
+
result[key] = value.doubleValue;
|
|
110
|
+
}
|
|
111
|
+
else if ('booleanValue' in value) {
|
|
112
|
+
result[key] = value.booleanValue;
|
|
113
|
+
}
|
|
114
|
+
else if ('timestampValue' in value) {
|
|
115
|
+
result[key] = new Date(value.timestampValue);
|
|
116
|
+
}
|
|
117
|
+
else if ('mapValue' in value) {
|
|
118
|
+
result[key] = parseFirestoreFields(value.mapValue.fields || {});
|
|
119
|
+
}
|
|
120
|
+
else if ('arrayValue' in value) {
|
|
121
|
+
result[key] = (value.arrayValue.values || []).map((v) => parseFirestoreFields({ _: v })._);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Format permission level with description
|
|
128
|
+
*/
|
|
129
|
+
function formatPermissionLevel(level) {
|
|
130
|
+
if (level >= 100)
|
|
131
|
+
return chalk_1.default.magenta(`${level} (Lacis/SU)`);
|
|
132
|
+
if (level >= 71)
|
|
133
|
+
return chalk_1.default.red(`${level} (System Authority)`);
|
|
134
|
+
if (level >= 61)
|
|
135
|
+
return chalk_1.default.yellow(`${level} (Tenant Primary)`);
|
|
136
|
+
if (level >= 41)
|
|
137
|
+
return chalk_1.default.blue(`${level} (Management Authority)`);
|
|
138
|
+
if (level >= 21)
|
|
139
|
+
return chalk_1.default.cyan(`${level} (Standard User)`);
|
|
140
|
+
if (level >= 11)
|
|
141
|
+
return chalk_1.default.green(`${level} (Guest+)`);
|
|
142
|
+
if (level >= 3)
|
|
143
|
+
return chalk_1.default.gray(`${level} (Guest)`);
|
|
144
|
+
return chalk_1.default.red(`${level} (Reserved/BAN)`);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Permission command
|
|
148
|
+
*/
|
|
149
|
+
exports.permissionCommand = new commander_1.Command('permission')
|
|
150
|
+
.description('TypeDefaultPermissions management for AraneaDevice types')
|
|
151
|
+
.addHelpText('after', `
|
|
152
|
+
Permission Levels (Cathedral Orders):
|
|
153
|
+
100 : Lacis (System Super User)
|
|
154
|
+
71-99 : System Authority Layer (cross-tenant)
|
|
155
|
+
61-70 : Tenant Primary Layer
|
|
156
|
+
41-60 : Management Authority Layer
|
|
157
|
+
21-40 : Standard User Layer
|
|
158
|
+
11-20 : Guest+ Layer
|
|
159
|
+
3-10 : Guest Layer
|
|
160
|
+
0-2 : Reserved/BAN
|
|
161
|
+
|
|
162
|
+
Examples:
|
|
163
|
+
aranea-sdk permission list
|
|
164
|
+
aranea-sdk permission get aranea_ar-is22
|
|
165
|
+
aranea-sdk permission set aranea_ar-is22 21
|
|
166
|
+
aranea-sdk permission set aranea_ar-is22 21 --display-name "AR-IS22センサー"
|
|
167
|
+
aranea-sdk permission delete aranea_ar-is22
|
|
168
|
+
|
|
169
|
+
Note: Requires System Authority Layer permission (71+) for modifications.
|
|
170
|
+
`);
|
|
171
|
+
// permission list
|
|
172
|
+
exports.permissionCommand
|
|
173
|
+
.command('list')
|
|
174
|
+
.description('List all typeDefaultPermissions')
|
|
175
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
176
|
+
.option('--json', 'Output as JSON')
|
|
177
|
+
.action(async (options) => {
|
|
178
|
+
try {
|
|
179
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
180
|
+
(0, config_1.checkStagingAvailability)(env, 'permission list');
|
|
181
|
+
const token = await (0, auth_1.getValidToken)();
|
|
182
|
+
if (!token) {
|
|
183
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
if (!options.json) {
|
|
187
|
+
console.log(chalk_1.default.cyan('\n=== TypeDefaultPermissions List ===\n'));
|
|
188
|
+
console.log(`Environment: ${env === 'production' ? chalk_1.default.red('PRODUCTION') : chalk_1.default.yellow('staging')}`);
|
|
189
|
+
console.log('');
|
|
190
|
+
}
|
|
191
|
+
const documents = await firestoreListTypeDefaultPermissions(token, env);
|
|
192
|
+
if (documents.length === 0) {
|
|
193
|
+
if (options.json) {
|
|
194
|
+
console.log(JSON.stringify([], null, 2));
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
console.log(chalk_1.default.yellow('No typeDefaultPermissions configured.'));
|
|
198
|
+
console.log('\nTo add a permission, use:');
|
|
199
|
+
console.log(' aranea-sdk permission set <typeId> <level>');
|
|
200
|
+
}
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const permissions = documents.map((doc) => {
|
|
204
|
+
const name = doc.name.split('/').pop();
|
|
205
|
+
const fields = parseFirestoreFields(doc.fields || {});
|
|
206
|
+
return {
|
|
207
|
+
id: name,
|
|
208
|
+
typeDomainId: fields.typeDomainId,
|
|
209
|
+
typeId: fields.typeId,
|
|
210
|
+
defaultPermission: fields.defaultPermission,
|
|
211
|
+
displayName: fields.displayName,
|
|
212
|
+
...fields,
|
|
213
|
+
};
|
|
214
|
+
});
|
|
215
|
+
if (options.json) {
|
|
216
|
+
console.log(JSON.stringify(permissions, null, 2));
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
console.log(chalk_1.default.gray('─'.repeat(80)));
|
|
220
|
+
console.log(chalk_1.default.bold(`${'TypeDomain'.padEnd(20)} ${'TypeId'.padEnd(25)} ${'Permission'.padEnd(20)} DisplayName`));
|
|
221
|
+
console.log(chalk_1.default.gray('─'.repeat(80)));
|
|
222
|
+
for (const perm of permissions) {
|
|
223
|
+
const typeDomain = (perm.typeDomainId || '').padEnd(20);
|
|
224
|
+
const typeId = (perm.typeId || '').padEnd(25);
|
|
225
|
+
const level = formatPermissionLevel(perm.defaultPermission || 0).padEnd(30);
|
|
226
|
+
const displayName = perm.displayName || '-';
|
|
227
|
+
console.log(`${typeDomain} ${typeId} ${level} ${displayName}`);
|
|
228
|
+
}
|
|
229
|
+
console.log(chalk_1.default.gray('─'.repeat(80)));
|
|
230
|
+
console.log(`\nTotal: ${permissions.length} type(s)`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${error.message}`));
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
// permission get
|
|
239
|
+
exports.permissionCommand
|
|
240
|
+
.command('get <typeId>')
|
|
241
|
+
.description('Get typeDefaultPermission for specific type')
|
|
242
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
243
|
+
.option('--type-domain <domain>', 'TypeDomain ID (default: araneaDevice)')
|
|
244
|
+
.option('--json', 'Output as JSON')
|
|
245
|
+
.action(async (typeId, options) => {
|
|
246
|
+
try {
|
|
247
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
248
|
+
(0, config_1.checkStagingAvailability)(env, 'permission get');
|
|
249
|
+
const token = await (0, auth_1.getValidToken)();
|
|
250
|
+
if (!token) {
|
|
251
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
const typeDomainId = options.typeDomain || 'araneaDevice';
|
|
255
|
+
const docId = `${typeDomainId}_${typeId}`;
|
|
256
|
+
const path = `LacisOathConfig/permissionConfig/typeDefaultPermissions/${docId}`;
|
|
257
|
+
const doc = await firestoreGet(path, token, env);
|
|
258
|
+
if (!doc) {
|
|
259
|
+
if (options.json) {
|
|
260
|
+
console.log(JSON.stringify({ found: false, id: docId }, null, 2));
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
console.log(chalk_1.default.yellow(`\nNo typeDefaultPermission found for: ${docId}`));
|
|
264
|
+
console.log('\nThis type will use the fallback default permission (Guest: 3).');
|
|
265
|
+
console.log('\nTo set a permission, use:');
|
|
266
|
+
console.log(` aranea-sdk permission set ${typeId} <level>`);
|
|
267
|
+
}
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const fields = parseFirestoreFields(doc.fields || {});
|
|
271
|
+
if (options.json) {
|
|
272
|
+
console.log(JSON.stringify({ found: true, id: docId, ...fields }, null, 2));
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
console.log(chalk_1.default.cyan(`\n=== TypeDefaultPermission: ${docId} ===\n`));
|
|
276
|
+
console.log(` TypeDomain: ${fields.typeDomainId || '-'}`);
|
|
277
|
+
console.log(` TypeId: ${fields.typeId || '-'}`);
|
|
278
|
+
console.log(` Permission: ${formatPermissionLevel(fields.defaultPermission || 0)}`);
|
|
279
|
+
console.log(` DisplayName: ${fields.displayName || '-'}`);
|
|
280
|
+
if (fields.created_at) {
|
|
281
|
+
console.log(` Created: ${new Date(fields.created_at).toLocaleString('ja-JP')}`);
|
|
282
|
+
}
|
|
283
|
+
if (fields.updated_at) {
|
|
284
|
+
console.log(` Updated: ${new Date(fields.updated_at).toLocaleString('ja-JP')}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${error.message}`));
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
// permission set
|
|
294
|
+
exports.permissionCommand
|
|
295
|
+
.command('set <typeId> <level>')
|
|
296
|
+
.description('Set typeDefaultPermission for a type')
|
|
297
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
298
|
+
.option('--type-domain <domain>', 'TypeDomain ID (default: araneaDevice)')
|
|
299
|
+
.option('--display-name <name>', 'Display name for the type')
|
|
300
|
+
.action(async (typeId, level, options) => {
|
|
301
|
+
try {
|
|
302
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
303
|
+
(0, config_1.checkStagingAvailability)(env, 'permission set');
|
|
304
|
+
(0, config_1.warnIfProduction)(env, 'permission set');
|
|
305
|
+
const token = await (0, auth_1.getValidToken)();
|
|
306
|
+
if (!token) {
|
|
307
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
310
|
+
const permissionLevel = parseInt(level, 10);
|
|
311
|
+
if (isNaN(permissionLevel) || permissionLevel < 3 || permissionLevel > 100) {
|
|
312
|
+
console.error(chalk_1.default.red('\n✖ Permission level must be between 3 and 100.'));
|
|
313
|
+
console.error(' 0 = BAN, 1-2 = Reserved, 3-10 = Guest, 11-20 = Guest+, ...');
|
|
314
|
+
process.exit(1);
|
|
315
|
+
}
|
|
316
|
+
const typeDomainId = options.typeDomain || 'araneaDevice';
|
|
317
|
+
console.log(chalk_1.default.cyan('\n=== Setting TypeDefaultPermission ===\n'));
|
|
318
|
+
console.log(` Environment: ${env === 'production' ? chalk_1.default.red('PRODUCTION') : chalk_1.default.yellow('staging')}`);
|
|
319
|
+
console.log(` TypeDomain: ${typeDomainId}`);
|
|
320
|
+
console.log(` TypeId: ${typeId}`);
|
|
321
|
+
console.log(` Permission: ${formatPermissionLevel(permissionLevel)}`);
|
|
322
|
+
if (options.displayName) {
|
|
323
|
+
console.log(` DisplayName: ${options.displayName}`);
|
|
324
|
+
}
|
|
325
|
+
console.log('');
|
|
326
|
+
const requestData = {
|
|
327
|
+
typeDomainId,
|
|
328
|
+
typeId,
|
|
329
|
+
defaultPermission: permissionLevel,
|
|
330
|
+
};
|
|
331
|
+
if (options.displayName) {
|
|
332
|
+
requestData.displayName = options.displayName;
|
|
333
|
+
}
|
|
334
|
+
const result = await callFunction('upsertTypeDefaultPermission', requestData, token, env);
|
|
335
|
+
if (result.ok) {
|
|
336
|
+
console.log(chalk_1.default.green('✓ TypeDefaultPermission set successfully!'));
|
|
337
|
+
console.log(` Document ID: ${result.id}`);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
console.error(chalk_1.default.red('✖ Failed to set permission.'));
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
const message = error.message;
|
|
346
|
+
// Translate common error messages
|
|
347
|
+
if (message.includes('permission-denied') || message.includes('71')) {
|
|
348
|
+
console.error(chalk_1.default.red('\n✖ Permission denied.'));
|
|
349
|
+
console.error(' System Authority Layer permission (71+) is required.');
|
|
350
|
+
console.error(' Your account does not have sufficient privileges.');
|
|
351
|
+
}
|
|
352
|
+
else if (message.includes('not-found')) {
|
|
353
|
+
console.error(chalk_1.default.red(`\n✖ ${message}`));
|
|
354
|
+
console.error(' Make sure the typeDomain and type definitions exist.');
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${message}`));
|
|
358
|
+
}
|
|
359
|
+
process.exit(1);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
// permission delete
|
|
363
|
+
exports.permissionCommand
|
|
364
|
+
.command('delete <typeId>')
|
|
365
|
+
.description('Delete typeDefaultPermission for a type')
|
|
366
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
367
|
+
.option('--type-domain <domain>', 'TypeDomain ID (default: araneaDevice)')
|
|
368
|
+
.option('--force', 'Skip confirmation')
|
|
369
|
+
.action(async (typeId, options) => {
|
|
370
|
+
try {
|
|
371
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
372
|
+
(0, config_1.checkStagingAvailability)(env, 'permission delete');
|
|
373
|
+
(0, config_1.warnIfProduction)(env, 'permission delete');
|
|
374
|
+
const token = await (0, auth_1.getValidToken)();
|
|
375
|
+
if (!token) {
|
|
376
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
377
|
+
process.exit(1);
|
|
378
|
+
}
|
|
379
|
+
const typeDomainId = options.typeDomain || 'araneaDevice';
|
|
380
|
+
const docId = `${typeDomainId}_${typeId}`;
|
|
381
|
+
console.log(chalk_1.default.cyan('\n=== Delete TypeDefaultPermission ===\n'));
|
|
382
|
+
console.log(` Environment: ${env === 'production' ? chalk_1.default.red('PRODUCTION') : chalk_1.default.yellow('staging')}`);
|
|
383
|
+
console.log(` Document ID: ${docId}`);
|
|
384
|
+
if (!options.force) {
|
|
385
|
+
console.log(chalk_1.default.yellow('\n⚠ This will delete the typeDefaultPermission.'));
|
|
386
|
+
console.log(' The type will fall back to default permission (Guest: 3).');
|
|
387
|
+
console.log('\nUse --force to confirm deletion.');
|
|
388
|
+
process.exit(1);
|
|
389
|
+
}
|
|
390
|
+
// Use Firestore REST API to delete
|
|
391
|
+
const projectId = FIREBASE_PROJECTS[env];
|
|
392
|
+
const path = `LacisOathConfig/permissionConfig/typeDefaultPermissions/${docId}`;
|
|
393
|
+
const url = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${path}`;
|
|
394
|
+
const response = await fetch(url, {
|
|
395
|
+
method: 'DELETE',
|
|
396
|
+
headers: {
|
|
397
|
+
Authorization: `Bearer ${token}`,
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
if (response.ok || response.status === 404) {
|
|
401
|
+
console.log(chalk_1.default.green('\n✓ TypeDefaultPermission deleted.'));
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
405
|
+
throw new Error(errorBody.error?.message || `HTTP ${response.status}`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${error.message}`));
|
|
410
|
+
process.exit(1);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AraneaSDK CLI - Type Command
|
|
3
|
+
*
|
|
4
|
+
* UserTypeDefinitions management for AraneaDevice types
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* aranea-sdk type list # List all types
|
|
8
|
+
* aranea-sdk type get <typeId> # Get specific type
|
|
9
|
+
* aranea-sdk type create <typeId> # Create new type
|
|
10
|
+
* aranea-sdk type update <typeId> # Update type
|
|
11
|
+
* aranea-sdk type delete <typeId> # Delete type
|
|
12
|
+
*
|
|
13
|
+
* Note:
|
|
14
|
+
* - Read operations require System Authority Layer (71+)
|
|
15
|
+
* - Write operations require Super User (91+)
|
|
16
|
+
*/
|
|
17
|
+
import { Command } from 'commander';
|
|
18
|
+
/**
|
|
19
|
+
* Type command
|
|
20
|
+
*/
|
|
21
|
+
export declare const typeCommand: Command;
|
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AraneaSDK CLI - Type Command
|
|
4
|
+
*
|
|
5
|
+
* UserTypeDefinitions management for AraneaDevice types
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* aranea-sdk type list # List all types
|
|
9
|
+
* aranea-sdk type get <typeId> # Get specific type
|
|
10
|
+
* aranea-sdk type create <typeId> # Create new type
|
|
11
|
+
* aranea-sdk type update <typeId> # Update type
|
|
12
|
+
* aranea-sdk type delete <typeId> # Delete type
|
|
13
|
+
*
|
|
14
|
+
* Note:
|
|
15
|
+
* - Read operations require System Authority Layer (71+)
|
|
16
|
+
* - Write operations require Super User (91+)
|
|
17
|
+
*/
|
|
18
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(o, k2, desc);
|
|
25
|
+
}) : (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
o[k2] = m[k];
|
|
28
|
+
}));
|
|
29
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
+
}) : function(o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
+
var ownKeys = function(o) {
|
|
36
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
+
var ar = [];
|
|
38
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
+
return ar;
|
|
40
|
+
};
|
|
41
|
+
return ownKeys(o);
|
|
42
|
+
};
|
|
43
|
+
return function (mod) {
|
|
44
|
+
if (mod && mod.__esModule) return mod;
|
|
45
|
+
var result = {};
|
|
46
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
+
__setModuleDefault(result, mod);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
52
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
53
|
+
};
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.typeCommand = void 0;
|
|
56
|
+
const commander_1 = require("commander");
|
|
57
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
58
|
+
const auth_1 = require("./auth");
|
|
59
|
+
const config_1 = require("../config");
|
|
60
|
+
// Firebase project configuration
|
|
61
|
+
const FIREBASE_PROJECTS = {
|
|
62
|
+
production: 'mobesorder',
|
|
63
|
+
staging: 'mobesorder-staging',
|
|
64
|
+
};
|
|
65
|
+
const FIREBASE_REGION = 'asia-northeast1';
|
|
66
|
+
/**
|
|
67
|
+
* Call araneaTypeDefinitionHTTP API
|
|
68
|
+
*/
|
|
69
|
+
async function callTypeDefinitionAPI(request, token, env) {
|
|
70
|
+
const projectId = FIREBASE_PROJECTS[env];
|
|
71
|
+
const url = `https://${FIREBASE_REGION}-${projectId}.cloudfunctions.net/araneaTypeDefinitionHTTP`;
|
|
72
|
+
const response = await fetch(url, {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: {
|
|
75
|
+
'Content-Type': 'application/json',
|
|
76
|
+
Authorization: `Bearer ${token}`,
|
|
77
|
+
},
|
|
78
|
+
body: JSON.stringify(request),
|
|
79
|
+
});
|
|
80
|
+
const result = await response.json();
|
|
81
|
+
if (!response.ok || !result.ok) {
|
|
82
|
+
throw new Error(result.error || `HTTP ${response.status}`);
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Format permission level with Cathedral Order name
|
|
88
|
+
*/
|
|
89
|
+
function formatPermissionLevel(level) {
|
|
90
|
+
if (level >= 100)
|
|
91
|
+
return chalk_1.default.magenta(`${level} (Lacis)`);
|
|
92
|
+
if (level >= 91)
|
|
93
|
+
return chalk_1.default.red(`${level} (SU)`);
|
|
94
|
+
if (level >= 71)
|
|
95
|
+
return chalk_1.default.yellow(`${level} (System)`);
|
|
96
|
+
if (level >= 61)
|
|
97
|
+
return chalk_1.default.blue(`${level} (Tenant Primary)`);
|
|
98
|
+
if (level >= 41)
|
|
99
|
+
return chalk_1.default.cyan(`${level} (Management)`);
|
|
100
|
+
if (level >= 21)
|
|
101
|
+
return chalk_1.default.green(`${level} (Standard)`);
|
|
102
|
+
if (level >= 11)
|
|
103
|
+
return chalk_1.default.gray(`${level} (Guest+)`);
|
|
104
|
+
return chalk_1.default.gray(`${level} (Guest)`);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Load credentials for LacisOath
|
|
108
|
+
*/
|
|
109
|
+
async function loadLacisCredentials() {
|
|
110
|
+
// For now, we'll prompt for these or read from config
|
|
111
|
+
// In production, these should come from stored credentials
|
|
112
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
113
|
+
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
114
|
+
const os = await Promise.resolve().then(() => __importStar(require('os')));
|
|
115
|
+
const credFile = path.join(os.homedir(), '.aranea-sdk', 'lacis-credentials.json');
|
|
116
|
+
if (fs.existsSync(credFile)) {
|
|
117
|
+
try {
|
|
118
|
+
const data = JSON.parse(fs.readFileSync(credFile, 'utf8'));
|
|
119
|
+
if (data.lacisId && data.cic && data.tid) {
|
|
120
|
+
return data;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Ignore parse errors
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Prompt for LacisOath credentials
|
|
131
|
+
*/
|
|
132
|
+
async function promptLacisCredentials() {
|
|
133
|
+
const readline = await Promise.resolve().then(() => __importStar(require('readline')));
|
|
134
|
+
const rl = readline.createInterface({
|
|
135
|
+
input: process.stdin,
|
|
136
|
+
output: process.stdout,
|
|
137
|
+
});
|
|
138
|
+
const question = (prompt) => new Promise((resolve) => rl.question(prompt, resolve));
|
|
139
|
+
console.log(chalk_1.default.cyan('\n=== LacisOath Authentication ===\n'));
|
|
140
|
+
console.log('Type definition management requires LacisOath credentials.');
|
|
141
|
+
console.log('(Save to ~/.aranea-sdk/lacis-credentials.json for future use)\n');
|
|
142
|
+
const lacisId = await question('LacisID (20 digits): ');
|
|
143
|
+
const cic = await question('CIC (6 digits): ');
|
|
144
|
+
const tid = await question('TID (20 chars): ');
|
|
145
|
+
rl.close();
|
|
146
|
+
return { lacisId: lacisId.trim(), cic: cic.trim(), tid: tid.trim() };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Type command
|
|
150
|
+
*/
|
|
151
|
+
exports.typeCommand = new commander_1.Command('type')
|
|
152
|
+
.description('UserTypeDefinitions management for AraneaDevice types')
|
|
153
|
+
.addHelpText('after', `
|
|
154
|
+
Permission Requirements:
|
|
155
|
+
- list, get: System Authority Layer (71+)
|
|
156
|
+
- create, update, delete: Super User (91+)
|
|
157
|
+
|
|
158
|
+
LacisOath Authentication:
|
|
159
|
+
This command uses LacisOath (lacisId + cic + tid) for authentication.
|
|
160
|
+
Store credentials in ~/.aranea-sdk/lacis-credentials.json:
|
|
161
|
+
{
|
|
162
|
+
"lacisId": "17347487748391988274",
|
|
163
|
+
"cic": "123456",
|
|
164
|
+
"tid": "T9999999999999999999"
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
Examples:
|
|
168
|
+
aranea-sdk type list
|
|
169
|
+
aranea-sdk type list --type-domain araneaDevice
|
|
170
|
+
aranea-sdk type get aranea_ar-is22
|
|
171
|
+
aranea-sdk type create aranea_ar-is22 --display-name "AR-IS22 Sensor" --permission 21
|
|
172
|
+
aranea-sdk type update aranea_ar-is22 --permission 31
|
|
173
|
+
aranea-sdk type delete aranea_ar-is22 --force
|
|
174
|
+
`);
|
|
175
|
+
// type list
|
|
176
|
+
exports.typeCommand
|
|
177
|
+
.command('list')
|
|
178
|
+
.description('List all type definitions')
|
|
179
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
180
|
+
.option('--type-domain <domain>', 'Filter by TypeDomain (default: araneaDevice)')
|
|
181
|
+
.option('--json', 'Output as JSON')
|
|
182
|
+
.action(async (options) => {
|
|
183
|
+
try {
|
|
184
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
185
|
+
(0, config_1.checkStagingAvailability)(env, 'type list');
|
|
186
|
+
const token = await (0, auth_1.getValidToken)();
|
|
187
|
+
if (!token) {
|
|
188
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
let credentials = await loadLacisCredentials();
|
|
192
|
+
if (!credentials) {
|
|
193
|
+
credentials = await promptLacisCredentials();
|
|
194
|
+
}
|
|
195
|
+
if (!options.json) {
|
|
196
|
+
console.log(chalk_1.default.cyan('\n=== UserTypeDefinitions List ===\n'));
|
|
197
|
+
console.log(`Environment: ${env === 'production' ? chalk_1.default.red('PRODUCTION') : chalk_1.default.yellow('staging')}`);
|
|
198
|
+
console.log('');
|
|
199
|
+
}
|
|
200
|
+
const typeDomainId = options.typeDomain || 'araneaDevice';
|
|
201
|
+
const result = await callTypeDefinitionAPI({
|
|
202
|
+
auth: credentials,
|
|
203
|
+
method: 'list',
|
|
204
|
+
params: { typeDomainId },
|
|
205
|
+
}, token, env);
|
|
206
|
+
if (options.json) {
|
|
207
|
+
console.log(JSON.stringify(result.definitions, null, 2));
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
if (result.definitions.length === 0) {
|
|
211
|
+
console.log(chalk_1.default.yellow(`No types found for TypeDomain: ${typeDomainId}`));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
console.log(chalk_1.default.gray('─'.repeat(90)));
|
|
215
|
+
console.log(chalk_1.default.bold(`${'TypeId'.padEnd(25)} ${'DisplayName'.padEnd(25)} ${'Permission'.padEnd(20)} Status`));
|
|
216
|
+
console.log(chalk_1.default.gray('─'.repeat(90)));
|
|
217
|
+
for (const def of result.definitions) {
|
|
218
|
+
const typeId = def.typeId.padEnd(25);
|
|
219
|
+
const displayName = (def.displayName || '-').substring(0, 24).padEnd(25);
|
|
220
|
+
const permission = formatPermissionLevel(def.defaultCathedralOrder).padEnd(30);
|
|
221
|
+
const status = def.status === 'deprecated' ? chalk_1.default.red('deprecated') : chalk_1.default.green('active');
|
|
222
|
+
console.log(`${typeId} ${displayName} ${permission} ${status}`);
|
|
223
|
+
}
|
|
224
|
+
console.log(chalk_1.default.gray('─'.repeat(90)));
|
|
225
|
+
console.log(`\nTotal: ${result.count} type(s) in ${typeDomainId}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${error.message}`));
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
// type get
|
|
234
|
+
exports.typeCommand
|
|
235
|
+
.command('get <typeId>')
|
|
236
|
+
.description('Get specific type definition')
|
|
237
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
238
|
+
.option('--type-domain <domain>', 'TypeDomain ID (default: araneaDevice)')
|
|
239
|
+
.option('--json', 'Output as JSON')
|
|
240
|
+
.action(async (typeId, options) => {
|
|
241
|
+
try {
|
|
242
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
243
|
+
(0, config_1.checkStagingAvailability)(env, 'type get');
|
|
244
|
+
const token = await (0, auth_1.getValidToken)();
|
|
245
|
+
if (!token) {
|
|
246
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
let credentials = await loadLacisCredentials();
|
|
250
|
+
if (!credentials) {
|
|
251
|
+
credentials = await promptLacisCredentials();
|
|
252
|
+
}
|
|
253
|
+
const typeDomainId = options.typeDomain || 'araneaDevice';
|
|
254
|
+
const result = await callTypeDefinitionAPI({
|
|
255
|
+
auth: credentials,
|
|
256
|
+
method: 'get',
|
|
257
|
+
params: { typeDomainId, typeId },
|
|
258
|
+
}, token, env);
|
|
259
|
+
if (options.json) {
|
|
260
|
+
console.log(JSON.stringify(result.definition, null, 2));
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const def = result.definition;
|
|
264
|
+
console.log(chalk_1.default.cyan(`\n=== TypeDefinition: ${def.id} ===\n`));
|
|
265
|
+
console.log(` TypeDomain: ${def.typeDomainId}`);
|
|
266
|
+
console.log(` TypeId: ${def.typeId}`);
|
|
267
|
+
console.log(` DisplayName: ${def.displayName}`);
|
|
268
|
+
console.log(` Description: ${def.description || '-'}`);
|
|
269
|
+
console.log(` Permission: ${formatPermissionLevel(def.defaultCathedralOrder)}`);
|
|
270
|
+
console.log(` Status: ${def.status === 'deprecated' ? chalk_1.default.red('deprecated') : chalk_1.default.green('active')}`);
|
|
271
|
+
console.log(` Created: ${def.metadata.createdAt}`);
|
|
272
|
+
console.log(` Updated: ${def.metadata.updatedAt}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${error.message}`));
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
// type create
|
|
281
|
+
exports.typeCommand
|
|
282
|
+
.command('create <typeId>')
|
|
283
|
+
.description('Create new type definition')
|
|
284
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
285
|
+
.option('--type-domain <domain>', 'TypeDomain ID (default: araneaDevice)')
|
|
286
|
+
.option('--display-name <name>', 'Display name for the type (required)')
|
|
287
|
+
.option('--description <desc>', 'Description of the type')
|
|
288
|
+
.option('--permission <level>', 'Default permission level (required)', parseInt)
|
|
289
|
+
.action(async (typeId, options) => {
|
|
290
|
+
try {
|
|
291
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
292
|
+
(0, config_1.checkStagingAvailability)(env, 'type create');
|
|
293
|
+
(0, config_1.warnIfProduction)(env, 'type create');
|
|
294
|
+
if (!options.displayName) {
|
|
295
|
+
console.error(chalk_1.default.red('\n✖ --display-name is required'));
|
|
296
|
+
process.exit(1);
|
|
297
|
+
}
|
|
298
|
+
if (options.permission === undefined || isNaN(options.permission)) {
|
|
299
|
+
console.error(chalk_1.default.red('\n✖ --permission is required (e.g., --permission 21)'));
|
|
300
|
+
process.exit(1);
|
|
301
|
+
}
|
|
302
|
+
const token = await (0, auth_1.getValidToken)();
|
|
303
|
+
if (!token) {
|
|
304
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
let credentials = await loadLacisCredentials();
|
|
308
|
+
if (!credentials) {
|
|
309
|
+
credentials = await promptLacisCredentials();
|
|
310
|
+
}
|
|
311
|
+
const typeDomainId = options.typeDomain || 'araneaDevice';
|
|
312
|
+
console.log(chalk_1.default.cyan('\n=== Creating TypeDefinition ===\n'));
|
|
313
|
+
console.log(` Environment: ${env === 'production' ? chalk_1.default.red('PRODUCTION') : chalk_1.default.yellow('staging')}`);
|
|
314
|
+
console.log(` TypeDomain: ${typeDomainId}`);
|
|
315
|
+
console.log(` TypeId: ${typeId}`);
|
|
316
|
+
console.log(` DisplayName: ${options.displayName}`);
|
|
317
|
+
console.log(` Description: ${options.description || '-'}`);
|
|
318
|
+
console.log(` Permission: ${formatPermissionLevel(options.permission)}`);
|
|
319
|
+
console.log('');
|
|
320
|
+
const result = await callTypeDefinitionAPI({
|
|
321
|
+
auth: credentials,
|
|
322
|
+
method: 'create',
|
|
323
|
+
params: {
|
|
324
|
+
typeDomainId,
|
|
325
|
+
typeId,
|
|
326
|
+
displayName: options.displayName,
|
|
327
|
+
description: options.description,
|
|
328
|
+
defaultCathedralOrder: options.permission,
|
|
329
|
+
},
|
|
330
|
+
}, token, env);
|
|
331
|
+
console.log(chalk_1.default.green('✓ TypeDefinition created successfully!'));
|
|
332
|
+
console.log(` Document ID: ${result.id}`);
|
|
333
|
+
console.log('');
|
|
334
|
+
console.log(chalk_1.default.yellow('Note: To set typeDefaultPermissions separately, use:'));
|
|
335
|
+
console.log(` aranea-sdk permission set ${typeId} ${options.permission} --endpoint ${env}`);
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
const message = error.message;
|
|
339
|
+
if (message.includes('91')) {
|
|
340
|
+
console.error(chalk_1.default.red('\n✖ Permission denied. Super User (91+) is required for create operations.'));
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${message}`));
|
|
344
|
+
}
|
|
345
|
+
process.exit(1);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
// type update
|
|
349
|
+
exports.typeCommand
|
|
350
|
+
.command('update <typeId>')
|
|
351
|
+
.description('Update existing type definition')
|
|
352
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
353
|
+
.option('--type-domain <domain>', 'TypeDomain ID (default: araneaDevice)')
|
|
354
|
+
.option('--display-name <name>', 'New display name')
|
|
355
|
+
.option('--description <desc>', 'New description')
|
|
356
|
+
.option('--permission <level>', 'New default permission level', parseInt)
|
|
357
|
+
.option('--status <status>', 'Status (active|deprecated)')
|
|
358
|
+
.action(async (typeId, options) => {
|
|
359
|
+
try {
|
|
360
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
361
|
+
(0, config_1.checkStagingAvailability)(env, 'type update');
|
|
362
|
+
(0, config_1.warnIfProduction)(env, 'type update');
|
|
363
|
+
const token = await (0, auth_1.getValidToken)();
|
|
364
|
+
if (!token) {
|
|
365
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
366
|
+
process.exit(1);
|
|
367
|
+
}
|
|
368
|
+
let credentials = await loadLacisCredentials();
|
|
369
|
+
if (!credentials) {
|
|
370
|
+
credentials = await promptLacisCredentials();
|
|
371
|
+
}
|
|
372
|
+
const typeDomainId = options.typeDomain || 'araneaDevice';
|
|
373
|
+
const params = {
|
|
374
|
+
typeDomainId,
|
|
375
|
+
typeId,
|
|
376
|
+
};
|
|
377
|
+
if (options.displayName)
|
|
378
|
+
params.displayName = options.displayName;
|
|
379
|
+
if (options.description)
|
|
380
|
+
params.description = options.description;
|
|
381
|
+
if (options.permission !== undefined)
|
|
382
|
+
params.defaultCathedralOrder = options.permission;
|
|
383
|
+
if (options.status === 'active' || options.status === 'deprecated') {
|
|
384
|
+
params.status = options.status;
|
|
385
|
+
}
|
|
386
|
+
console.log(chalk_1.default.cyan('\n=== Updating TypeDefinition ===\n'));
|
|
387
|
+
console.log(` Environment: ${env === 'production' ? chalk_1.default.red('PRODUCTION') : chalk_1.default.yellow('staging')}`);
|
|
388
|
+
console.log(` TypeDomain: ${typeDomainId}`);
|
|
389
|
+
console.log(` TypeId: ${typeId}`);
|
|
390
|
+
if (options.displayName)
|
|
391
|
+
console.log(` DisplayName: ${options.displayName}`);
|
|
392
|
+
if (options.permission !== undefined)
|
|
393
|
+
console.log(` Permission: ${formatPermissionLevel(options.permission)}`);
|
|
394
|
+
if (options.status)
|
|
395
|
+
console.log(` Status: ${options.status}`);
|
|
396
|
+
console.log('');
|
|
397
|
+
const result = await callTypeDefinitionAPI({
|
|
398
|
+
auth: credentials,
|
|
399
|
+
method: 'update',
|
|
400
|
+
params,
|
|
401
|
+
}, token, env);
|
|
402
|
+
console.log(chalk_1.default.green('✓ TypeDefinition updated successfully!'));
|
|
403
|
+
console.log(` Document ID: ${result.id}`);
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
const message = error.message;
|
|
407
|
+
if (message.includes('91')) {
|
|
408
|
+
console.error(chalk_1.default.red('\n✖ Permission denied. Super User (91+) is required for update operations.'));
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${message}`));
|
|
412
|
+
}
|
|
413
|
+
process.exit(1);
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
// type delete
|
|
417
|
+
exports.typeCommand
|
|
418
|
+
.command('delete <typeId>')
|
|
419
|
+
.description('Delete type definition')
|
|
420
|
+
.option('--endpoint <env>', 'Target environment (production|staging)')
|
|
421
|
+
.option('--type-domain <domain>', 'TypeDomain ID (default: araneaDevice)')
|
|
422
|
+
.option('--force', 'Skip confirmation')
|
|
423
|
+
.action(async (typeId, options) => {
|
|
424
|
+
try {
|
|
425
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
426
|
+
(0, config_1.checkStagingAvailability)(env, 'type delete');
|
|
427
|
+
(0, config_1.warnIfProduction)(env, 'type delete');
|
|
428
|
+
const token = await (0, auth_1.getValidToken)();
|
|
429
|
+
if (!token) {
|
|
430
|
+
console.error(chalk_1.default.red('\n✖ Not authenticated. Run "aranea-sdk auth login" first.'));
|
|
431
|
+
process.exit(1);
|
|
432
|
+
}
|
|
433
|
+
let credentials = await loadLacisCredentials();
|
|
434
|
+
if (!credentials) {
|
|
435
|
+
credentials = await promptLacisCredentials();
|
|
436
|
+
}
|
|
437
|
+
const typeDomainId = options.typeDomain || 'araneaDevice';
|
|
438
|
+
console.log(chalk_1.default.cyan('\n=== Delete TypeDefinition ===\n'));
|
|
439
|
+
console.log(` Environment: ${env === 'production' ? chalk_1.default.red('PRODUCTION') : chalk_1.default.yellow('staging')}`);
|
|
440
|
+
console.log(` TypeDomain: ${typeDomainId}`);
|
|
441
|
+
console.log(` TypeId: ${typeId}`);
|
|
442
|
+
if (!options.force) {
|
|
443
|
+
console.log(chalk_1.default.yellow('\n⚠ This will permanently delete the type definition.'));
|
|
444
|
+
console.log(' Existing devices of this type will remain but may have issues.');
|
|
445
|
+
console.log('\nUse --force to confirm deletion.');
|
|
446
|
+
process.exit(1);
|
|
447
|
+
}
|
|
448
|
+
const result = await callTypeDefinitionAPI({
|
|
449
|
+
auth: credentials,
|
|
450
|
+
method: 'delete',
|
|
451
|
+
params: { typeDomainId, typeId },
|
|
452
|
+
}, token, env);
|
|
453
|
+
console.log(chalk_1.default.green('\n✓ TypeDefinition deleted.'));
|
|
454
|
+
console.log(` Document ID: ${result.id}`);
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
const message = error.message;
|
|
458
|
+
if (message.includes('reserved')) {
|
|
459
|
+
console.error(chalk_1.default.red(`\n✖ Cannot delete: ${message}`));
|
|
460
|
+
}
|
|
461
|
+
else if (message.includes('91')) {
|
|
462
|
+
console.error(chalk_1.default.red('\n✖ Permission denied. Super User (91+) is required for delete operations.'));
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
console.error(chalk_1.default.red(`\n✖ Error: ${message}`));
|
|
466
|
+
}
|
|
467
|
+
process.exit(1);
|
|
468
|
+
}
|
|
469
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -63,6 +63,8 @@ const auth_1 = require("./commands/auth");
|
|
|
63
63
|
const backlog_1 = require("./commands/backlog");
|
|
64
64
|
const registry_1 = require("./commands/registry");
|
|
65
65
|
const control_1 = require("./commands/control");
|
|
66
|
+
const permission_1 = require("./commands/permission");
|
|
67
|
+
const type_1 = require("./commands/type");
|
|
66
68
|
// package.json からバージョンを動的に取得
|
|
67
69
|
const packageJsonPath = path.resolve(__dirname, '../package.json');
|
|
68
70
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
@@ -99,4 +101,8 @@ program.addCommand(registry_1.registryCommand);
|
|
|
99
101
|
// control コマンド (v0.4.1) - Control型管理(安全機構付き)
|
|
100
102
|
// @see doc/APPS/araneaSDK/headDesign/59_METATRON_CONTROL_SUGGESTION.md Section 8
|
|
101
103
|
program.addCommand(control_1.controlCommand);
|
|
104
|
+
// permission コマンド (v0.5.4) - TypeDefaultPermissions管理
|
|
105
|
+
program.addCommand(permission_1.permissionCommand);
|
|
106
|
+
// type コマンド (v0.5.5) - UserTypeDefinitions管理
|
|
107
|
+
program.addCommand(type_1.typeCommand);
|
|
102
108
|
program.parse(process.argv);
|