faces-cli 1.6.2 → 1.6.4
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/catalog.d.ts +13 -1
- package/dist/catalog.js +78 -9
- package/dist/commands/catalog/backup.js +12 -31
- package/dist/commands/catalog/doctor.js +69 -19
- package/dist/commands/face/create.js +16 -7
- package/dist/commands/face/get.d.ts +1 -0
- package/dist/commands/face/get.js +13 -9
- package/dist/commands/face/list.d.ts +2 -0
- package/dist/commands/face/list.js +16 -11
- package/dist/commands/face/tag/add.js +12 -1
- package/dist/commands/face/tag/all.d.ts +10 -0
- package/dist/commands/face/tag/all.js +31 -0
- package/dist/commands/face/tag/remove.js +12 -1
- package/dist/commands/face/tag/set.js +12 -1
- package/dist/commands/face/teams.d.ts +14 -0
- package/dist/commands/face/teams.js +29 -0
- package/dist/commands/face/update.js +18 -6
- package/dist/commands/team/add.js +17 -0
- package/dist/commands/team/create.js +18 -2
- package/dist/commands/team/list.js +5 -14
- package/dist/commands/team/remove.js +14 -0
- package/dist/commands/team/update.js +30 -0
- package/dist/team-catalog.d.ts +1 -0
- package/dist/team-catalog.js +6 -1
- package/dist/utils.d.ts +9 -2
- package/dist/utils.js +17 -2
- package/oclif.manifest.json +746 -604
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import { BaseCommand } from '../../../base.js';
|
|
3
3
|
import { FacesAPIError } from '../../../client.js';
|
|
4
|
+
import { CatalogService } from '../../../catalog.js';
|
|
4
5
|
export default class FaceTagAdd extends BaseCommand {
|
|
5
6
|
static description = 'Add tags to a face (appends, idempotent)';
|
|
6
7
|
static flags = {
|
|
@@ -18,10 +19,20 @@ export default class FaceTagAdd extends BaseCommand {
|
|
|
18
19
|
data = await client.post(`/v1/iam/${args.alias}/tags`, { body: { tags: flags.tag } });
|
|
19
20
|
}
|
|
20
21
|
catch (err) {
|
|
21
|
-
if (err instanceof FacesAPIError)
|
|
22
|
+
if (err instanceof FacesAPIError) {
|
|
23
|
+
if (err.statusCode === 403) {
|
|
24
|
+
this.error(`Forbidden: face '${args.alias}' is not owned by the current account. Run \`faces catalog:doctor --fix\` to sync.`);
|
|
25
|
+
}
|
|
22
26
|
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
27
|
+
}
|
|
23
28
|
throw err;
|
|
24
29
|
}
|
|
30
|
+
// Sync tags to local catalog
|
|
31
|
+
const tags = data.tags ?? [];
|
|
32
|
+
try {
|
|
33
|
+
new CatalogService().updateTags(args.alias, tags);
|
|
34
|
+
}
|
|
35
|
+
catch { /* non-fatal */ }
|
|
25
36
|
if (!this.jsonEnabled())
|
|
26
37
|
this.printHuman(data);
|
|
27
38
|
return data;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base.js';
|
|
2
|
+
export default class FaceTagAll extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static flags: {
|
|
5
|
+
'base-url': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<unknown>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base.js';
|
|
2
|
+
import { FacesAPIError } from '../../../client.js';
|
|
3
|
+
export default class FaceTagAll extends BaseCommand {
|
|
4
|
+
static description = 'List all tags across all your faces';
|
|
5
|
+
static flags = {
|
|
6
|
+
...BaseCommand.baseFlags,
|
|
7
|
+
};
|
|
8
|
+
async run() {
|
|
9
|
+
const { flags } = await this.parse(FaceTagAll);
|
|
10
|
+
const client = this.makeClient(flags);
|
|
11
|
+
let data;
|
|
12
|
+
try {
|
|
13
|
+
data = await client.get('/v1/me/tags');
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err instanceof FacesAPIError)
|
|
17
|
+
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
|
20
|
+
if (!this.jsonEnabled()) {
|
|
21
|
+
const tags = data.tags ?? [];
|
|
22
|
+
if (tags.length === 0) {
|
|
23
|
+
this.log('(no tags)');
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.log(tags.join(', '));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return data;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
2
|
import { BaseCommand } from '../../../base.js';
|
|
3
3
|
import { FacesAPIError } from '../../../client.js';
|
|
4
|
+
import { CatalogService } from '../../../catalog.js';
|
|
4
5
|
export default class FaceTagRemove extends BaseCommand {
|
|
5
6
|
static description = 'Remove a tag from a face';
|
|
6
7
|
static flags = {
|
|
@@ -18,10 +19,20 @@ export default class FaceTagRemove extends BaseCommand {
|
|
|
18
19
|
data = await client.delete(`/v1/iam/${args.alias}/tags/${encodeURIComponent(args.tag)}`);
|
|
19
20
|
}
|
|
20
21
|
catch (err) {
|
|
21
|
-
if (err instanceof FacesAPIError)
|
|
22
|
+
if (err instanceof FacesAPIError) {
|
|
23
|
+
if (err.statusCode === 403) {
|
|
24
|
+
this.error(`Forbidden: face '${args.alias}' is not owned by the current account. Run \`faces catalog:doctor --fix\` to sync.`);
|
|
25
|
+
}
|
|
22
26
|
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
27
|
+
}
|
|
23
28
|
throw err;
|
|
24
29
|
}
|
|
30
|
+
// Refresh tags in local catalog
|
|
31
|
+
try {
|
|
32
|
+
const tagResp = await client.get(`/v1/iam/${args.alias}/tags`);
|
|
33
|
+
new CatalogService().updateTags(args.alias, tagResp.tags ?? []);
|
|
34
|
+
}
|
|
35
|
+
catch { /* non-fatal */ }
|
|
25
36
|
if (!this.jsonEnabled())
|
|
26
37
|
this.log(`Removed tag '${args.tag}' from ${args.alias}`);
|
|
27
38
|
return data;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import { BaseCommand } from '../../../base.js';
|
|
3
3
|
import { FacesAPIError } from '../../../client.js';
|
|
4
|
+
import { CatalogService } from '../../../catalog.js';
|
|
4
5
|
export default class FaceTagSet extends BaseCommand {
|
|
5
6
|
static description = 'Replace all tags on a face';
|
|
6
7
|
static flags = {
|
|
@@ -18,10 +19,20 @@ export default class FaceTagSet extends BaseCommand {
|
|
|
18
19
|
data = await client.put(`/v1/iam/${args.alias}/tags`, { body: { tags: flags.tag } });
|
|
19
20
|
}
|
|
20
21
|
catch (err) {
|
|
21
|
-
if (err instanceof FacesAPIError)
|
|
22
|
+
if (err instanceof FacesAPIError) {
|
|
23
|
+
if (err.statusCode === 403) {
|
|
24
|
+
this.error(`Forbidden: face '${args.alias}' is not owned by the current account. Run \`faces catalog:doctor --fix\` to sync.`);
|
|
25
|
+
}
|
|
22
26
|
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
27
|
+
}
|
|
23
28
|
throw err;
|
|
24
29
|
}
|
|
30
|
+
// Sync tags to local catalog
|
|
31
|
+
const tags = data.tags ?? [];
|
|
32
|
+
try {
|
|
33
|
+
new CatalogService().updateTags(args.alias, tags);
|
|
34
|
+
}
|
|
35
|
+
catch { /* non-fatal */ }
|
|
25
36
|
if (!this.jsonEnabled())
|
|
26
37
|
this.printHuman(data);
|
|
27
38
|
return data;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base.js';
|
|
2
|
+
export default class FaceTeams extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static flags: {
|
|
5
|
+
team: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
6
|
+
'base-url': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
static args: {
|
|
11
|
+
alias: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<unknown>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base.js';
|
|
3
|
+
import { FacesAPIError } from '../../client.js';
|
|
4
|
+
export default class FaceTeams extends BaseCommand {
|
|
5
|
+
static description = "Set a face's team memberships (replaces all)";
|
|
6
|
+
static flags = {
|
|
7
|
+
...BaseCommand.baseFlags,
|
|
8
|
+
team: Flags.string({ description: 'Team ID (repeatable, replaces all memberships)', multiple: true, required: true }),
|
|
9
|
+
};
|
|
10
|
+
static args = {
|
|
11
|
+
alias: Args.string({ description: 'Face alias', required: true }),
|
|
12
|
+
};
|
|
13
|
+
async run() {
|
|
14
|
+
const { args, flags } = await this.parse(FaceTeams);
|
|
15
|
+
const client = this.makeClient(flags);
|
|
16
|
+
let data;
|
|
17
|
+
try {
|
|
18
|
+
data = await client.put(`/v1/faces/${args.alias}/teams`, { body: { team_ids: flags.team } });
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
if (err instanceof FacesAPIError)
|
|
22
|
+
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
if (!this.jsonEnabled())
|
|
26
|
+
this.printHuman(data);
|
|
27
|
+
return data;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -2,7 +2,7 @@ import { Args, Flags } from '@oclif/core';
|
|
|
2
2
|
import { BaseCommand } from '../../base.js';
|
|
3
3
|
import { FacesAPIError } from '../../client.js';
|
|
4
4
|
import { CatalogService } from '../../catalog.js';
|
|
5
|
-
import {
|
|
5
|
+
import { renameFaceFields } from '../../utils.js';
|
|
6
6
|
export default class FaceUpdate extends BaseCommand {
|
|
7
7
|
static description = "Update a face's metadata";
|
|
8
8
|
static flags = {
|
|
@@ -67,9 +67,11 @@ export default class FaceUpdate extends BaseCommand {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
// Replace tags if provided
|
|
70
|
+
let currentTags;
|
|
70
71
|
if (hasTags) {
|
|
71
72
|
try {
|
|
72
|
-
await client.put(`/v1/iam/${args.face_id}/tags`, { body: { tags: flags.tag } });
|
|
73
|
+
const tagResp = await client.put(`/v1/iam/${args.face_id}/tags`, { body: { tags: flags.tag } });
|
|
74
|
+
currentTags = tagResp.tags ?? flags.tag;
|
|
73
75
|
}
|
|
74
76
|
catch (err) {
|
|
75
77
|
if (err instanceof FacesAPIError)
|
|
@@ -81,12 +83,22 @@ export default class FaceUpdate extends BaseCommand {
|
|
|
81
83
|
for (const w of face.warnings)
|
|
82
84
|
this.warn(w);
|
|
83
85
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
// Add tags to response if we set them
|
|
87
|
+
if (currentTags)
|
|
88
|
+
face.tags = currentTags;
|
|
89
|
+
// Rename basic_facts → attributes
|
|
90
|
+
renameFaceFields(face);
|
|
91
|
+
// Write to local catalog
|
|
87
92
|
try {
|
|
88
93
|
const catalog = new CatalogService();
|
|
89
|
-
catalog.writeFace(
|
|
94
|
+
catalog.writeFace({
|
|
95
|
+
...face,
|
|
96
|
+
basic_facts: face.attributes,
|
|
97
|
+
tags: face.tags ?? undefined,
|
|
98
|
+
description: face.description ?? undefined,
|
|
99
|
+
default_model: face.default_model,
|
|
100
|
+
formula: face.formula,
|
|
101
|
+
});
|
|
90
102
|
}
|
|
91
103
|
catch { /* catalog errors are non-fatal */ }
|
|
92
104
|
if (!this.jsonEnabled())
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import { BaseCommand } from '../../base.js';
|
|
3
3
|
import { FacesAPIError } from '../../client.js';
|
|
4
|
+
import { TeamCatalogService } from '../../team-catalog.js';
|
|
4
5
|
export default class TeamAdd extends BaseCommand {
|
|
5
6
|
static description = 'Add face(s) to a team';
|
|
6
7
|
static flags = {
|
|
@@ -43,6 +44,22 @@ export default class TeamAdd extends BaseCommand {
|
|
|
43
44
|
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
44
45
|
throw err;
|
|
45
46
|
}
|
|
47
|
+
// Update local TEAM.md — find by team ID and add aliases
|
|
48
|
+
try {
|
|
49
|
+
const teamCatalog = new TeamCatalogService();
|
|
50
|
+
for (const name of teamCatalog.listTeams()) {
|
|
51
|
+
const team = teamCatalog.readTeam(name);
|
|
52
|
+
if (team?.frontmatter.id === args.team_id) {
|
|
53
|
+
const members = new Set(team.frontmatter.members ?? []);
|
|
54
|
+
for (const alias of flags.face)
|
|
55
|
+
members.add(alias);
|
|
56
|
+
team.frontmatter.members = [...members];
|
|
57
|
+
teamCatalog.writeTeam(name, team.frontmatter, team.body || undefined);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch { /* non-fatal */ }
|
|
46
63
|
if (!this.jsonEnabled()) {
|
|
47
64
|
this.log(`Added ${flags.face.join(', ')} to team.`);
|
|
48
65
|
}
|
|
@@ -2,6 +2,7 @@ import { Flags } from '@oclif/core';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import { BaseCommand } from '../../base.js';
|
|
4
4
|
import { FacesAPIError } from '../../client.js';
|
|
5
|
+
import { TeamCatalogService } from '../../team-catalog.js';
|
|
5
6
|
export default class TeamCreate extends BaseCommand {
|
|
6
7
|
static description = 'Create a new team';
|
|
7
8
|
static flags = {
|
|
@@ -37,15 +38,30 @@ export default class TeamCreate extends BaseCommand {
|
|
|
37
38
|
}
|
|
38
39
|
const team = data;
|
|
39
40
|
// Post tags if provided
|
|
40
|
-
|
|
41
|
+
const tags = flags.tag ?? [];
|
|
42
|
+
if (tags.length > 0) {
|
|
41
43
|
try {
|
|
42
|
-
await client.post(`/v1/teams/${team.id}/tags`, { body: { tags
|
|
44
|
+
await client.post(`/v1/teams/${team.id}/tags`, { body: { tags } });
|
|
45
|
+
team.tags = tags;
|
|
43
46
|
}
|
|
44
47
|
catch (err) {
|
|
45
48
|
if (err instanceof FacesAPIError)
|
|
46
49
|
this.warn(`Tags failed (${err.statusCode}): ${err.message}`);
|
|
47
50
|
}
|
|
48
51
|
}
|
|
52
|
+
// Write local TEAM.md
|
|
53
|
+
try {
|
|
54
|
+
const teamCatalog = new TeamCatalogService();
|
|
55
|
+
const slug = String(team.name).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
56
|
+
teamCatalog.writeTeam(slug, {
|
|
57
|
+
id: team.id,
|
|
58
|
+
name: team.name,
|
|
59
|
+
description: team.description ?? undefined,
|
|
60
|
+
tags: team.tags ?? undefined,
|
|
61
|
+
members: [],
|
|
62
|
+
}, team.protocol ?? protocol ?? undefined);
|
|
63
|
+
}
|
|
64
|
+
catch { /* non-fatal */ }
|
|
49
65
|
if (!this.jsonEnabled())
|
|
50
66
|
this.printHuman(data);
|
|
51
67
|
return data;
|
|
@@ -8,14 +8,6 @@ export default class TeamList extends BaseCommand {
|
|
|
8
8
|
async run() {
|
|
9
9
|
const { flags } = await this.parse(TeamList);
|
|
10
10
|
const client = this.makeClient(flags);
|
|
11
|
-
// Get current username to filter out personal Guild
|
|
12
|
-
let username;
|
|
13
|
-
try {
|
|
14
|
-
const resp = await client.get('/auth/me');
|
|
15
|
-
const whoami = (resp.data ?? resp);
|
|
16
|
-
username = whoami.username ?? undefined;
|
|
17
|
-
}
|
|
18
|
-
catch { /* proceed without filtering */ }
|
|
19
11
|
let data;
|
|
20
12
|
try {
|
|
21
13
|
data = await client.get('/v1/me/teams');
|
|
@@ -27,10 +19,8 @@ export default class TeamList extends BaseCommand {
|
|
|
27
19
|
}
|
|
28
20
|
const resp = data;
|
|
29
21
|
let teams = resp.data ?? data;
|
|
30
|
-
// Filter out personal Guild
|
|
31
|
-
|
|
32
|
-
teams = teams.filter(t => t.name !== username);
|
|
33
|
-
}
|
|
22
|
+
// Filter out personal Guild using kind field
|
|
23
|
+
teams = teams.filter(t => t.kind !== 'personal');
|
|
34
24
|
if (this.jsonEnabled())
|
|
35
25
|
return teams;
|
|
36
26
|
if (teams.length === 0) {
|
|
@@ -40,8 +30,9 @@ export default class TeamList extends BaseCommand {
|
|
|
40
30
|
const nameWidth = Math.max(...teams.map(t => String(t.name ?? '').length));
|
|
41
31
|
for (const t of teams) {
|
|
42
32
|
const name = String(t.name ?? '').padEnd(nameWidth);
|
|
43
|
-
const
|
|
44
|
-
|
|
33
|
+
const members = t.member_count != null ? ` [${t.member_count} members]` : '';
|
|
34
|
+
const desc = t.description ? ` ${String(t.description).slice(0, 50)}` : '';
|
|
35
|
+
this.log(`${t.id} ${name}${members}${desc}`);
|
|
45
36
|
}
|
|
46
37
|
}
|
|
47
38
|
return teams;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
2
|
import { BaseCommand } from '../../base.js';
|
|
3
3
|
import { FacesAPIError } from '../../client.js';
|
|
4
|
+
import { TeamCatalogService } from '../../team-catalog.js';
|
|
4
5
|
export default class TeamRemove extends BaseCommand {
|
|
5
6
|
static description = 'Remove a face from a team';
|
|
6
7
|
static flags = {
|
|
@@ -35,6 +36,19 @@ export default class TeamRemove extends BaseCommand {
|
|
|
35
36
|
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
36
37
|
throw err;
|
|
37
38
|
}
|
|
39
|
+
// Update local TEAM.md — find by team ID and remove alias
|
|
40
|
+
try {
|
|
41
|
+
const teamCatalog = new TeamCatalogService();
|
|
42
|
+
for (const name of teamCatalog.listTeams()) {
|
|
43
|
+
const team = teamCatalog.readTeam(name);
|
|
44
|
+
if (team?.frontmatter.id === args.team_id) {
|
|
45
|
+
team.frontmatter.members = (team.frontmatter.members ?? []).filter(m => m !== args.alias);
|
|
46
|
+
teamCatalog.writeTeam(name, team.frontmatter, team.body || undefined);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch { /* non-fatal */ }
|
|
38
52
|
if (!this.jsonEnabled())
|
|
39
53
|
this.log(`Removed ${args.alias} from team.`);
|
|
40
54
|
return data;
|
|
@@ -2,6 +2,7 @@ import { Args, Flags } from '@oclif/core';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import { BaseCommand } from '../../base.js';
|
|
4
4
|
import { FacesAPIError } from '../../client.js';
|
|
5
|
+
import { TeamCatalogService } from '../../team-catalog.js';
|
|
5
6
|
export default class TeamUpdate extends BaseCommand {
|
|
6
7
|
static description = 'Update a team';
|
|
7
8
|
static flags = {
|
|
@@ -41,6 +42,35 @@ export default class TeamUpdate extends BaseCommand {
|
|
|
41
42
|
this.error(`Error (${err.statusCode}): ${err.message}`);
|
|
42
43
|
throw err;
|
|
43
44
|
}
|
|
45
|
+
// Update local TEAM.md
|
|
46
|
+
try {
|
|
47
|
+
const team = data;
|
|
48
|
+
const teamCatalog = new TeamCatalogService();
|
|
49
|
+
const slug = String(team.name).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
50
|
+
// Fetch members for the local file
|
|
51
|
+
let members = [];
|
|
52
|
+
try {
|
|
53
|
+
const membersResp = await client.get(`/v1/teams/${args.team_id}/members`);
|
|
54
|
+
// Members come as iam_ids — we'd need to resolve, but for now store what we have
|
|
55
|
+
members = (membersResp.data ?? []).map(m => m.iam_id);
|
|
56
|
+
}
|
|
57
|
+
catch { /* proceed without members */ }
|
|
58
|
+
// Fetch tags
|
|
59
|
+
let tags = [];
|
|
60
|
+
try {
|
|
61
|
+
const tagResp = await client.get(`/v1/teams/${args.team_id}/tags`);
|
|
62
|
+
tags = tagResp.tags ?? [];
|
|
63
|
+
}
|
|
64
|
+
catch { /* proceed */ }
|
|
65
|
+
teamCatalog.writeTeam(slug, {
|
|
66
|
+
id: args.team_id,
|
|
67
|
+
name: team.name,
|
|
68
|
+
description: team.description ?? undefined,
|
|
69
|
+
tags,
|
|
70
|
+
members,
|
|
71
|
+
}, team.protocol ?? undefined);
|
|
72
|
+
}
|
|
73
|
+
catch { /* non-fatal */ }
|
|
44
74
|
if (!this.jsonEnabled())
|
|
45
75
|
this.printHuman(data);
|
|
46
76
|
return data;
|
package/dist/team-catalog.d.ts
CHANGED
package/dist/team-catalog.js
CHANGED
|
@@ -10,6 +10,8 @@ function quoteYaml(value) {
|
|
|
10
10
|
}
|
|
11
11
|
function serializeFrontmatter(fm) {
|
|
12
12
|
const lines = ['---'];
|
|
13
|
+
if (fm.id)
|
|
14
|
+
lines.push(`id: ${fm.id}`);
|
|
13
15
|
lines.push(`name: ${quoteYaml(fm.name)}`);
|
|
14
16
|
if (fm.description)
|
|
15
17
|
lines.push(`description: ${quoteYaml(fm.description)}`);
|
|
@@ -35,7 +37,10 @@ function parseFrontmatter(content) {
|
|
|
35
37
|
continue;
|
|
36
38
|
const key = line.slice(0, colonIdx).trim();
|
|
37
39
|
const val = line.slice(colonIdx + 1).trim();
|
|
38
|
-
if (key === '
|
|
40
|
+
if (key === 'id') {
|
|
41
|
+
fm.id = val.replace(/^"(.*)"$/, '$1');
|
|
42
|
+
}
|
|
43
|
+
else if (key === 'name') {
|
|
39
44
|
fm.name = val.replace(/^"(.*)"$/, '$1');
|
|
40
45
|
}
|
|
41
46
|
else if (key === 'description') {
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Flatten basic_facts from API's nested {value, status, identification} format
|
|
2
|
+
* Flatten basic_facts/attributes from API's nested {value, status, identification} format
|
|
3
3
|
* to simple {key: value} strings.
|
|
4
4
|
*/
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function flattenAttributes(facts: Record<string, unknown>): Record<string, string>;
|
|
6
|
+
/** @deprecated Use flattenAttributes */
|
|
7
|
+
export declare const flattenBasicFacts: typeof flattenAttributes;
|
|
8
|
+
/**
|
|
9
|
+
* Rename basic_facts → attributes in a face response object.
|
|
10
|
+
* Mutates the object in place and returns it.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renameFaceFields(face: Record<string, unknown>): Record<string, unknown>;
|
package/dist/utils.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Flatten basic_facts from API's nested {value, status, identification} format
|
|
2
|
+
* Flatten basic_facts/attributes from API's nested {value, status, identification} format
|
|
3
3
|
* to simple {key: value} strings.
|
|
4
4
|
*/
|
|
5
|
-
export function
|
|
5
|
+
export function flattenAttributes(facts) {
|
|
6
6
|
const flat = {};
|
|
7
7
|
for (const [k, v] of Object.entries(facts)) {
|
|
8
8
|
if (typeof v === 'object' && v !== null && 'value' in v) {
|
|
@@ -14,3 +14,18 @@ export function flattenBasicFacts(facts) {
|
|
|
14
14
|
}
|
|
15
15
|
return flat;
|
|
16
16
|
}
|
|
17
|
+
/** @deprecated Use flattenAttributes */
|
|
18
|
+
export const flattenBasicFacts = flattenAttributes;
|
|
19
|
+
/**
|
|
20
|
+
* Rename basic_facts → attributes in a face response object.
|
|
21
|
+
* Mutates the object in place and returns it.
|
|
22
|
+
*/
|
|
23
|
+
export function renameFaceFields(face) {
|
|
24
|
+
if (face.basic_facts !== undefined) {
|
|
25
|
+
face.attributes = typeof face.basic_facts === 'object' && face.basic_facts !== null
|
|
26
|
+
? flattenAttributes(face.basic_facts)
|
|
27
|
+
: face.basic_facts;
|
|
28
|
+
delete face.basic_facts;
|
|
29
|
+
}
|
|
30
|
+
return face;
|
|
31
|
+
}
|