Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stdout standardization with output formatter #56

Merged
merged 48 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
6c8a4ad
fix: changed `identities/CommandAuthenticate`, `identities/CommandCla…
amydevs Nov 10, 2023
92e105a
fix: `agent/CommandStatus` will now be more accurate to RPC call retu…
amydevs Feb 29, 2024
efc6b88
fix: `bootstrap/CommandBootstrap` now has a more verbose recoveryCode…
amydevs Feb 29, 2024
6747b8c
fix: `identities/CommandAuthenticate` now has more concise formatting…
amydevs Feb 29, 2024
4177998
fix `identities/CommandInvite` now logs the feedback to `stderr` instead
amydevs Feb 29, 2024
dbe1bf0
fix: `keys/CommandCert` now uses dict format
amydevs Feb 29, 2024
d1b92b3
fix: `keys/CommandCertchain` made more concise
amydevs Feb 29, 2024
f47d75a
fix: `keys/CommandDecrypt` and `keys/CommandEncrypt` now use raw outp…
amydevs Feb 29, 2024
e1f938e
fix: `keys/CommandSign` now uses camelcase for non-json formats
amydevs Feb 29, 2024
bd22f1f
fix: `keys/CommandVerify` now uses camelCase for non-json formats
amydevs Feb 29, 2024
c15b7e9
fix: `nodes/CommandClaim` now logs feedback to stderr, and the respon…
amydevs Mar 1, 2024
5ebc923
fix: replaced usage of `this.info.log` with `process.stderr.write` fo…
amydevs Mar 1, 2024
b33a3fb
fix: `tests/agent` tests
amydevs Mar 1, 2024
aa67d09
fix: `nodes/CommandConnections` has the json format check switched ar…
amydevs Mar 1, 2024
c2d6e86
fix: `nodes/CommandFind` now outputs a dict rather than a message
amydevs Mar 1, 2024
bb00f46
fix: `nodes/CommandGetAll` now uses table format
amydevs Mar 1, 2024
23e98ae
fix: `nodes/CommandPing` output
amydevs Mar 1, 2024
e08d131
feat: `identities/CommandList` now uses dict and list formats
amydevs Mar 4, 2024
f2366b9
feat: `secrets/CommandGet` now returns JSON with json format
amydevs Mar 7, 2024
e87f40c
fix: `secrets/CommandList` now returns array of objects on json format
amydevs Mar 7, 2024
afb4e50
fix: `secrets/CommandStat` now uses dict format
amydevs Mar 7, 2024
c98d50d
fix: `vaults/CommandCreate` feedback is now in stderr
amydevs Mar 14, 2024
11493aa
feat: `vaults/CommandLog` now uses dict format
amydevs Mar 14, 2024
6f5034b
fix: `vaults/CommandPermissions` now uses dict format
amydevs Mar 14, 2024
4ddf8b8
fix: `notifications/CommandRead` now responds with array in case of JSON
amydevs Mar 14, 2024
9aacee3
fix: `identities/CommandPermissions` now uses `actionsList` and `vaul…
amydevs Mar 14, 2024
11afb51
fix: `identities/CommandSearch` now has whitespace to separate each d…
amydevs Mar 15, 2024
f545322
fix: `nodes/CommandGetAll` now does not leak authentication metadata
amydevs Mar 15, 2024
a9eb4bd
fix: `nodes/CommandGetAll` now has `nodeAddress` instead of `address`
amydevs Mar 15, 2024
e5754d7
fix: `nodes/CommandFind` now has scopes displayed as a CSV
amydevs Mar 15, 2024
1cb2d0b
fix: `keys/CommandVerify` output follows RPC response better
amydevs Mar 15, 2024
a7faffe
fix: `keys/CommandPair` is now more similar to RPC sresponse
amydevs Mar 15, 2024
e56e0de
fix: `tests/notifications` tests
amydevs Mar 15, 2024
47091e2
fix: `tests/identities`
amydevs Mar 15, 2024
39a25f8
fix: `keys/CommandCertchain` now outputs array directly on JSON format
amydevs Mar 15, 2024
a4f468a
fix: `keys/CommandCert` will now output raw format
amydevs Mar 15, 2024
d02db44
fix: `keys/CommandCertchain` and `notifications/CommandRead` now bett…
amydevs Mar 15, 2024
b521b50
fix: `identities/CommandList` now only has newline separators for eac…
amydevs Mar 15, 2024
5be1fae
fix: `identities/CommandGet` is now closer to RPC output
amydevs Mar 15, 2024
1d10aa2
fix: `identities/CommandPermissions` now shows CSV permissions
amydevs Mar 15, 2024
56654ca
fix: `identities/CommandAuthenticate` is logic now more concise
amydevs Mar 15, 2024
3fda9b4
fix: `identities/CommandList` now more closely follows RPC response
amydevs Mar 18, 2024
1462efc
feat: nested objects on `outputFormatterDict`
amydevs Mar 21, 2024
aa9306b
fix: `identities/CommandList` now uses nested `dict` format
amydevs Mar 21, 2024
2aae8bf
fix: `identities/CommandList` and `identities/CommandSearch` have had…
amydevs Mar 21, 2024
0c74fe6
fix: `vaults/CommandPermissions` output now correctly iterates over each
amydevs Mar 21, 2024
b5c3e58
feat: `notifications/CommandRead` uses nesting to be better different…
amydevs Mar 21, 2024
18d223c
feat: `identities/CommandList` now uses nesting to represent each ele…
amydevs Mar 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/agent/CommandStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ class CommandStatus extends CommandPolykey {
agentHost: response.agentHost,
agentPort: response.agentPort,
upTime: getUnixtime() - response.startTime,
startTime: response.startTime,
connectionsActive: response.connectionsActive,
nodesTotal: response.nodesTotal,
version: response.version,
sourceVersion: response.sourceVersion,
stateVersion: response.stateVersion,
networkVersion: response.networkVersion,
...response.versionMetadata,
versionMetadata: response.versionMetadata,
},
}),
);
Expand Down
8 changes: 4 additions & 4 deletions src/agent/CommandStop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ class CommandStop extends CommandPolykey {
);
const statusInfo = clientStatus.statusInfo;
if (statusInfo?.status === 'DEAD') {
this.logger.info('Agent is already dead');
process.stderr.write('Agent is already dead\n');
return;
} else if (statusInfo?.status === 'STOPPING') {
this.logger.info('Agent is already stopping');
process.stderr.write('Agent is already stopping\n');
return;
} else if (statusInfo?.status === 'STARTING') {
throw new errors.ErrorPolykeyCLIAgentStatus('agent is starting');
throw new errors.ErrorPolykeyCLIAgentStatus('Agent is starting');
}
const auth = await binProcessors.processAuthentication(
options.passwordFile,
Expand Down Expand Up @@ -62,7 +62,7 @@ class CommandStop extends CommandPolykey {
}),
auth,
);
this.logger.info('Stopping Agent');
process.stderr.write('Stopping Agent\n');
} finally {
if (pkClient! != null) await pkClient.stop();
}
Expand Down
10 changes: 9 additions & 1 deletion src/bootstrap/CommandBootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import process from 'process';
import CommandPolykey from '../CommandPolykey';
import * as binUtils from '../utils';
import * as binOptions from '../utils/options';
import * as binProcessors from '../utils/processors';

Expand Down Expand Up @@ -36,7 +37,14 @@ class CommandBootstrap extends CommandPolykey {
logger: this.logger,
});
this.logger.info(`Bootstrapped ${options.nodePath}`);
if (recoveryCodeOut != null) process.stdout.write(recoveryCodeOut + '\n');
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'dict',
data: {
recoveryCode: recoveryCodeOut,
},
}),
);
});
}
}
Expand Down
46 changes: 30 additions & 16 deletions src/identities/CommandAuthenticate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,33 +68,47 @@ class CommandAuthenticate extends CommandPolykey {
);
for await (const message of genReadable) {
if (message.request != null) {
this.logger.info(`Navigate to the URL in order to authenticate`);
this.logger.info(
'Use any additional additional properties to complete authentication',
process.stderr.write(
`Navigate to the URL in order to authenticate\n`,
);
process.stderr.write(
'Use any additional additional properties to complete authentication\n',
);
try {
await identitiesUtils.browser(message.request.url);
} catch (e) {
if (e.code !== 'ENOENT') throw e;
// Otherwise we ignore `ENOENT` as a failure to spawn a browser
}
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'dict',
data: {
url: message.request.url,
...message.request.dataMap,
},
}),
);
if (options.format === 'json') {
process.stdout.write(
binUtils.outputFormatter({
type: 'json',
data: {
url: message.request.url,
dataMap: message.request.dataMap,
},
}),
);
} else {
process.stdout.write(
binUtils.outputFormatter({
type: 'dict',
data: {
url: message.request.url,
...message.request.dataMap,
},
}),
);
}
} else if (message.response != null) {
this.logger.info(
`Authenticated digital identity provider ${providerId}`,
process.stderr.write(
`Authenticated digital identity provider ${providerId}\n`,
);
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'list',
data: [message.response.identityId],
type: options.format === 'json' ? 'json' : 'dict',
data: { identityId: message.response.identityId },
}),
);
} else {
Expand Down
10 changes: 6 additions & 4 deletions src/identities/CommandClaim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,16 @@ class CommandClaim extends CommandPolykey {
}),
auth,
);
const output = [`Claim Id: ${claimMessage.claimId}`];
const data: { claimId: string; url?: string } = {
claimId: claimMessage.claimId,
};
if (claimMessage.url) {
output.push(`Url: ${claimMessage.url}`);
data.url = claimMessage.url;
}
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'list',
data: output,
type: options.format === 'json' ? 'json' : 'dict',
data,
}),
);
} finally {
Expand Down
27 changes: 17 additions & 10 deletions src/identities/CommandGet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,17 @@ class CommandGet extends CommandPolykey {
utils.never();
}
const gestalt = res!.gestalt;
let output: any = gestalt;
if (options.format !== 'json') {
// Creating a list.
output = [];
if (options.format === 'json') {
process.stdout.write(
binUtils.outputFormatter({
type: 'json',
data: {
gestalt,
},
}),
);
} else {
const output: Array<string> = [];
// Listing nodes.
for (const nodeKey of Object.keys(gestalt.nodes)) {
const node = gestalt.nodes[nodeKey];
Expand All @@ -102,13 +109,13 @@ class CommandGet extends CommandPolykey {
const identity = gestalt.identities[identityKey];
output.push(`${identity.providerId}:${identity.identityId}`);
}
process.stdout.write(
binUtils.outputFormatter({
type: 'list',
data: output,
}),
);
}
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'list',
data: output,
}),
);
} finally {
if (pkClient! != null) await pkClient.stop();
}
Expand Down
13 changes: 4 additions & 9 deletions src/identities/CommandInvite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,10 @@ class CommandClaim extends CommandPolykey {
}),
auth,
);
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'list',
data: [
`Successfully sent Gestalt Invite notification to Keynode with ID ${nodesUtils.encodeNodeId(
nodeId,
)}`,
],
}),
process.stderr.write(
`Successfully sent Gestalt Invite notification to Keynode with ID ${nodesUtils.encodeNodeId(
nodeId,
)}\n`,
);
} finally {
if (pkClient! != null) await pkClient.stop();
Expand Down
122 changes: 61 additions & 61 deletions src/identities/CommandList.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type PolykeyClient from 'polykey/dist/PolykeyClient';
import type { GestaltMessage } from 'polykey/dist/client/types';
import CommandPolykey from '../CommandPolykey';
import * as binOptions from '../utils/options';
import * as binUtils from '../utils';
Expand Down Expand Up @@ -42,72 +43,71 @@ class CommandList extends CommandPolykey {
},
logger: this.logger.getChild(PolykeyClient.name),
});
let output: any;
const gestalts = await binUtils.retryAuthentication(async (auth) => {
const gestalts: Array<any> = [];
const stream = await pkClient.rpcClient.methods.gestaltsGestaltList({
metadata: auth,
});
for await (const gestaltMessage of stream) {
const gestalt = gestaltMessage.gestalt;
const newGestalt: any = {
permissions: [],
nodes: [],
identities: [],
};
for (const node of Object.keys(gestalt.nodes)) {
const nodeInfo = gestalt.nodes[node];
newGestalt.nodes.push({ nodeId: nodeInfo.nodeId });
}
for (const identity of Object.keys(gestalt.identities)) {
const identityInfo = gestalt.identities[identity];
newGestalt.identities.push({
providerId: identityInfo.providerId,
identityId: identityInfo.identityId,
const gestaltMessages = await binUtils.retryAuthentication(
async (auth) => {
const gestaltMessages: Array<
GestaltMessage & { gestalt: { actionsList: Array<string> } }
> = [];
const stream = await pkClient.rpcClient.methods.gestaltsGestaltList(
{
metadata: auth,
},
);
for await (const gestaltMessage of stream) {
// Getting the permissions for the gestalt.
const actionsMessage = await binUtils.retryAuthentication(
(auth) =>
pkClient.rpcClient.methods.gestaltsActionsGetByNode({
metadata: auth,
nodeIdEncoded: Object.values(
gestaltMessage.gestalt.nodes,
)[0].nodeId,
}),
auth,
);
const actionsList = actionsMessage.actionsList;
gestaltMessages.push({
gestalt: {
...gestaltMessage.gestalt,
actionsList,
},
});
}
// Getting the permissions for the gestalt.
const actionsMessage = await binUtils.retryAuthentication(
(auth) =>
pkClient.rpcClient.methods.gestaltsActionsGetByNode({
metadata: auth,
nodeIdEncoded: newGestalt.nodes[0].nodeId,
}),
auth,
);
const actionList = actionsMessage.actionsList;
if (actionList.length === 0) newGestalt.permissions = null;
else newGestalt.permissions = actionList;
gestalts.push(newGestalt);
}
return gestalts;
}, auth);
output = gestalts;
if (options.format !== 'json') {
return gestaltMessages;
},
auth,
);
if (options.format === 'json') {
process.stdout.write(
binUtils.outputFormatter({
type: 'json',
data: gestaltMessages,
}),
);
} else {
// Convert to a human-readable list.
output = [];
let count = 1;
for (const gestalt of gestalts) {
output.push(`gestalt ${count}`);
output.push(`permissions: ${gestalt.permissions ?? 'None'}`);
// Listing nodes
for (const node of gestalt.nodes) {
output.push(`${node.nodeId}`);
}
// Listing identities
for (const identity of gestalt.identities) {
output.push(`${identity.providerId}:${identity.identityId}`);
}
output.push('');
count++;
for (const gestaltMessage of gestaltMessages) {
const gestalt = gestaltMessage.gestalt;
const nodeIds = Object.values(gestalt.nodes).map(
(node) => node.nodeId as string,
);
const identities = Object.values(gestalt.identities).map(
(identity) => `${identity.providerId}:${identity.identityId}`,
);
process.stdout.write(
binUtils.outputFormatter({
type: 'dict',
data: {
gestalt: {
actionsList: gestalt.actionsList.join(','),
identities,
nodeIds,
},
},
}),
);
}
}
process.stdout.write(
binUtils.outputFormatter({
type: options.format === 'json' ? 'json' : 'list',
data: output,
}),
);
} finally {
if (pkClient! != null) await pkClient.stop();
}
Expand Down
Loading