Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export {
PLC_DIRECTORY_URL,
FAIR_SERVICE_TYPE,
FAIR_SERVICE_ID,
updateDID,
setFairServiceUrl,
addVerificationKey,
addRotationKey,
revokeVerificationKey,
Expand Down
4 changes: 2 additions & 2 deletions src/cli/did-service-add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { parseArgs } from 'node:util';
import { PlcClientError } from '@did-plc/lib';
import { importRotationKeyPair } from '../keys.js';
import { updateDID } from '../plc.js';
import { setFairServiceUrl } from '../plc.js';
import { loadRotationKey, SigningKeyError } from '../signing.js';
import { logPlcError } from './lib/plc-error.js';
import { rotationKeyHelp } from './lib/help.js';
Expand Down Expand Up @@ -88,7 +88,7 @@ const { keypair, publicKey: signerPublicKey } = await importRotationKeyPair(priv
console.log(`Updating DID ${did}...`);

try {
await updateDID({
await setFairServiceUrl({
did,
serviceUrl: url,
signer: keypair,
Expand Down
16 changes: 10 additions & 6 deletions src/cli/lib/plc-error.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { PlcClientError } from '@did-plc/lib';

const useColor = process.stderr.isTTY && !process.env.NO_COLOR;
const red = useColor ? '\x1b[31m' : '';
const yellow = useColor ? '\x1b[33m' : '';
const reset = useColor ? '\x1b[0m' : '';

interface PlcErrorOptions {
includeData?: boolean;
}
Expand All @@ -14,17 +19,16 @@ interface PlcErrorContext {
* The @did-plc/lib library throws PlcClientError which has:
* - status: HTTP status code
* - data: Response body from PLC server (often contains error details)
* - message: Generic axios error message
* - message: Generic axios error message (e.g. "Request failed with status code 400")
*/
export function formatPlcError(err: PlcClientError, { includeData = true }: PlcErrorOptions = {}): string {
// Check if this is a PlcClientError with additional data
const data = err.data as string | { message?: string; error?: string } | undefined;
if (err.status && data && includeData) {
const details = typeof data === 'string' ? data : data.message || data.error || JSON.stringify(data);
return `${err.message} (${err.status}): ${details}`;
return `(${err.status}) ${details}`;
}
if (err.status) {
return `${err.message} (${err.status})`;
return `(${err.status})`;
}
return err.message;
}
Expand All @@ -34,9 +38,9 @@ export function formatPlcError(err: PlcClientError, { includeData = true }: PlcE
*/
export function logPlcError(prefix: string, err: PlcClientError, context: PlcErrorContext = {}): void {
const hints = diagnosePlcError(err, context);
console.error(`\x1b[31m${prefix}: ${formatPlcError(err, { includeData: hints.length === 0 })}\x1b[0m`);
console.error(`${red}${prefix}: ${formatPlcError(err, { includeData: hints.length === 0 })}${reset}`);
for (const hint of hints) {
console.error(`\x1b[33m - ${hint}\x1b[0m`);
console.error(`${yellow} - ${hint}${reset}`);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/did.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function createGenesisOperation({ verificationKey, rotationKeys }: GenesisOperat
*
* This creates the initial operation for a new PLC DID for a FAIR package.
* The operation does NOT include the FAIR service - this should be
* added in a subsequent updateDID() operation after the DID is created.
* added in a subsequent setFairServiceUrl() operation after the DID is created.
*/
interface GenerateDIDOptions {
verificationKey: string;
Expand Down Expand Up @@ -66,7 +66,7 @@ interface CreateDIDOptions {
/**
* Creates a new FAIR package DID and submits it to the PLC directory.
*
* This creates the DID without a FAIR service initially. Use updateDID()
* This creates the DID without a FAIR service initially. Use setFairServiceUrl()
* to add the service URL after the DID is created.
*/
export async function createDID({
Expand Down
8 changes: 5 additions & 3 deletions src/plc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ export const FAIR_SERVICE_ID = 'fairpm_repo';

/**
* Default PLC directory URL.
*
* Can be overridden via the PLC_DIRECTORY_URL environment variable (for testing).
*/
export const PLC_DIRECTORY_URL = 'https://plc.directory';
export const PLC_DIRECTORY_URL = process.env.PLC_DIRECTORY_URL ?? 'https://plc.directory';

/**
* Creates a PLC directory client.
Expand Down Expand Up @@ -101,12 +103,12 @@ export async function submitDID({ op, did, plcUrl = PLC_DIRECTORY_URL }: SubmitD
}

/**
* Updates the FAIR service URL for an existing DID.
* Sets the FAIR service URL for an existing DID.
*
* This adds or updates the FAIR package management service endpoint
* in the DID document.
*/
export async function updateDID({
export async function setFairServiceUrl({
did,
serviceUrl,
signer,
Expand Down
15 changes: 6 additions & 9 deletions test/cli/plc-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,41 @@ describe('formatPlcError', () => {
const err = new Error('Request failed with status code 400');
err.status = 400;
err.data = 'Invalid signature on op';
assert.strictEqual(formatPlcError(err), 'Request failed with status code 400 (400): Invalid signature on op');
assert.strictEqual(formatPlcError(err), '(400) Invalid signature on op');
});

it('formats PlcClientError with object data containing message', () => {
const err = new Error('Request failed with status code 400');
err.status = 400;
err.data = { message: 'Key not found' };
assert.strictEqual(formatPlcError(err), 'Request failed with status code 400 (400): Key not found');
assert.strictEqual(formatPlcError(err), '(400) Key not found');
});

it('formats PlcClientError with object data containing error', () => {
const err = new Error('Request failed with status code 500');
err.status = 500;
err.data = { error: 'Internal server error' };
assert.strictEqual(formatPlcError(err), 'Request failed with status code 500 (500): Internal server error');
assert.strictEqual(formatPlcError(err), '(500) Internal server error');
});

it('JSON stringifies object data without message or error', () => {
const err = new Error('Request failed with status code 400');
err.status = 400;
err.data = { code: 'INVALID_OP', details: 'bad' };
assert.strictEqual(
formatPlcError(err),
'Request failed with status code 400 (400): {"code":"INVALID_OP","details":"bad"}',
);
assert.strictEqual(formatPlcError(err), '(400) {"code":"INVALID_OP","details":"bad"}');
});

it('excludes data when includeData is false', () => {
const err = new Error('Request failed with status code 400');
err.status = 400;
err.data = 'Some detailed error message';
assert.strictEqual(formatPlcError(err, { includeData: false }), 'Request failed with status code 400 (400)');
assert.strictEqual(formatPlcError(err, { includeData: false }), '(400)');
});

it('returns status without data when error has status but no data', () => {
const err = new Error('Request failed with status code 404');
err.status = 404;
assert.strictEqual(formatPlcError(err), 'Request failed with status code 404 (404)');
assert.strictEqual(formatPlcError(err), '(404)');
});
});

Expand Down