blockprotocol
Advanced tools
Comparing version 0.1.0 to 0.1.1
# blockprotocol | ||
## 0.1.1 | ||
### Patch Changes | ||
- [#584](https://github.com/blockprotocol/blockprotocol/pull/584) [`33ac788`](https://github.com/blockprotocol/blockprotocol/commit/33ac788c6f1ce38b9868e182f261e331ec118988) Thanks [@kachkaev](https://github.com/kachkaev)! - Check typings, fix potential edge case bugs | ||
## 0.1.0 | ||
@@ -4,0 +10,0 @@ |
28
cli.js
@@ -8,6 +8,8 @@ #!/usr/bin/env node | ||
import { commandLookup } from "./cli/commands.js"; | ||
import { run as printHelp } from "./cli/commands/help.js"; | ||
import { printSpacer } from "./cli/print-spacer.js"; | ||
const availableCommands = Object.keys(commandLookup); | ||
/** | ||
* @param {string} errorMessage | ||
*/ | ||
const printErrorMessage = (errorMessage) => { | ||
@@ -21,7 +23,9 @@ console.log(chalk.red(`${errorMessage}. Please check usage.`)); | ||
const { _unknown: optionsArgv, command } = commandLineArgs( | ||
[ | ||
{ | ||
name: "command", | ||
defaultOption: true, | ||
}, | ||
], | ||
{ | ||
name: "command", | ||
defaultOption: true, | ||
}, | ||
{ | ||
stopAtFirstUnknown: true, | ||
@@ -32,3 +36,2 @@ }, | ||
// print help for the CLI if requested or if the command is unknown | ||
const printHelp = commandLookup.help.run; | ||
if (command === "help" || !command) { | ||
@@ -38,3 +41,6 @@ printHelp(); | ||
} | ||
if (!availableCommands.includes(command)) { | ||
const foundCommand = commandLookup[command]; | ||
if (!foundCommand) { | ||
printHelp(); | ||
@@ -47,3 +53,3 @@ printErrorMessage(`Unknown command '${command ?? ""}'`); | ||
const { _unknown: unknownOption, ...options } = commandLineArgs( | ||
commandLookup[command].options, | ||
foundCommand.options ?? [], | ||
{ | ||
@@ -56,3 +62,3 @@ argv: optionsArgv ?? [], | ||
// print help for the given command if requested or usage is incorrect | ||
const commandManual = commandLineUsage(commandLookup[command].manual); | ||
const commandManual = commandLineUsage(foundCommand.manual ?? []); | ||
if (options.help) { | ||
@@ -69,3 +75,3 @@ console.log(commandManual); | ||
// execute the requested command with the given options, if any | ||
commandLookup[command].run(options); | ||
foundCommand.run(options); | ||
})(); |
import * as help from "./commands/help.js"; | ||
import * as publish from "./commands/publish.js"; | ||
/** @type {Record<string, { run: (options?: import("command-line-args").CommandLineOptions) => void; options?: import("command-line-args").OptionDefinition[]; manual?: import("command-line-usage").Section[]}>} */ | ||
export const commandLookup = { | ||
@@ -5,0 +6,0 @@ help, |
@@ -17,3 +17,3 @@ import chalk from "chalk"; | ||
/** | ||
* @type {[{header: string, content: string},{optionList: [{name: string, alias: string, description: string, typeLabel: string, type: BooleanConstructor},{name: string, alias: string, description: string, type: BooleanConstructor},{name: string, alias: string, description: string, typeLabel: string, type: StringConstructor},{name: string, alias: string, description: string, typeLabel: string, type: StringConstructor},{name: string, alias: string, description: string, type: BooleanConstructor}], header: string}]} | ||
* @type {[import("command-line-usage").Content, import("command-line-usage").OptionList]} | ||
*/ | ||
@@ -71,4 +71,3 @@ const manual = [ | ||
const optionsGuide = manual.find(({ header }) => header === "Options"); | ||
const options = optionsGuide.optionList; | ||
const options = manual[1].optionList; | ||
@@ -79,9 +78,7 @@ // *********************** RUN *********************** // | ||
* Publishes to the Block Protocol hub | ||
* @param {object} [providedOptions] | ||
* @param {string} [providedOptions.path] | ||
* @param {boolean} [providedOptions.dry] | ||
* @param {import("command-line-args").CommandLineOptions | undefined} providedOptions | ||
*/ | ||
const run = async (providedOptions) => { | ||
const { path: providedPath, tmp: tmpDir, yes } = providedOptions ?? {}; | ||
const dryRun = providedOptions["dry-run"]; | ||
const dryRun = providedOptions?.["dry-run"]; | ||
@@ -111,5 +108,7 @@ const apiKey = await findApiKey(); | ||
metadataJson = await fs.readJson(metadataPath); | ||
} catch (err) { | ||
} catch (error) { | ||
console.log( | ||
`Could not parse block-metadata.json: ${chalk.red(err.message)}`, | ||
`Could not parse block-metadata.json: ${chalk.red( | ||
error instanceof Error ? error.message : error, | ||
)}`, | ||
); | ||
@@ -173,4 +172,4 @@ process.exit(); | ||
if (errors) { | ||
const errorMsg = errors[0].msg; | ||
if (errors || !block) { | ||
const errorMsg = errors?.[0]?.msg; | ||
console.log(chalk.red(errorMsg)); | ||
@@ -177,0 +176,0 @@ process.exit(); |
@@ -6,7 +6,7 @@ import chalk from "chalk"; | ||
* Prompts a user to confirm or deny an action | ||
* @param message The yes/no question to ask the user | ||
* @param {string} message The yes/no question to ask the user | ||
* @returns {Promise<boolean>} | ||
*/ | ||
export const doesUserAgree = async (message) => { | ||
prompt.colors = ""; | ||
prompt.colors = false; | ||
prompt.message = ""; | ||
@@ -21,3 +21,3 @@ prompt.start(); | ||
required: true, | ||
before: (value) => value.trim()[0].toLowerCase(), | ||
before: (value) => value.trim().slice(0, 1).toLowerCase(), | ||
}, | ||
@@ -24,0 +24,0 @@ }, |
@@ -18,2 +18,3 @@ import chalk from "chalk"; | ||
* @param {string} filePath | ||
* @return {string} | ||
*/ | ||
@@ -25,3 +26,3 @@ const extractKeyFromRcFile = (filePath) => { | ||
const [key, value] = line.split("="); | ||
if (key === configFileKey) { | ||
if (key === configFileKey && value) { | ||
console.log(chalk.green(`Found API key in configuration file.`)); | ||
@@ -39,2 +40,5 @@ return value; | ||
/** | ||
* @returns {Promise<string>} | ||
*/ | ||
export const findApiKey = async () => { | ||
@@ -41,0 +45,0 @@ const keyInEnvironment = process.env[environmentVariableName]; |
@@ -12,3 +12,3 @@ import chalk from "chalk"; | ||
* 1. Look in the current working directory and its subfolders | ||
* 2. If none found, search up for a folder containing package.json, adn then search within | ||
* 2. If none found, search up for a folder containing package.json, and then search within | ||
* | ||
@@ -30,14 +30,12 @@ * If multiple block-metadata.json are found, a path containing 'dist' is preferred | ||
const projectRootPath = await findProjectRoot(); | ||
if (!projectRootPath) { | ||
return; | ||
if (projectRootPath) { | ||
metadataJsonPaths = await globby("**/block-metadata.json", { | ||
absolute: true, | ||
cwd: projectRootPath, | ||
caseSensitiveMatch: false, | ||
}); | ||
} | ||
metadataJsonPaths = await globby("**/block-metadata.json", { | ||
absolute: true, | ||
cwd: projectRootPath, | ||
caseSensitiveMatch: false, | ||
}); | ||
} | ||
if (!metadataJsonPaths?.length) { | ||
if (!metadataJsonPaths[0]) { | ||
console.log(chalk.red("Could not find block folder")); | ||
@@ -44,0 +42,0 @@ console.log( |
@@ -8,6 +8,8 @@ import { FormData } from "formdata-node"; | ||
* Posts to the Block Protocol API /blocks/publish endpoint | ||
* @param {string} blockProtocolSiteHost | ||
* @param {String} tarballFilePath | ||
* @param {String} blockName | ||
* @param {String} apiKey | ||
* @param {object} payload | ||
* @param {string} payload.blockProtocolSiteHost | ||
* @param {string} payload.tarballFilePath | ||
* @param {string} payload.blockName | ||
* @param {string} payload.apiKey | ||
* @return { Promise<{ errors?: { msg: string }[], block?: { blockSitePath: string }}> } | ||
*/ | ||
@@ -22,2 +24,3 @@ export const postPublishForm = async ({ | ||
/** @type {import("node-fetch").FormData} -- https://github.com/node-fetch/node-fetch/issues/900#issuecomment-716342574 */ | ||
const form = new FormData(); | ||
@@ -30,2 +33,3 @@ | ||
/** @type {import("node-fetch").RequestInit} */ | ||
const options = { | ||
@@ -41,15 +45,19 @@ body: form, | ||
return fetch(url, options) | ||
.then(async (resp) => { | ||
.then(async (response) => { | ||
try { | ||
return await resp.json(); | ||
} catch (err) { | ||
return /** @type {{ block: { blockSitePath: string }}} */ ( | ||
await response.json() | ||
); | ||
} catch (error) { | ||
// if the JSON parsing failed, the user is probably trying to contact a host that doesn't implement the endpoint | ||
const errorMsg = | ||
resp.status !== 200 | ||
? `Request to ${blockProtocolSiteHost} errored: ${resp.status} ${resp.statusText}` | ||
: `Malformed JSON response: ${err.message}`; // a non-parseable 200 status response should not happen | ||
const errorMessage = | ||
response.status !== 200 | ||
? `Request to ${blockProtocolSiteHost} errored: ${response.status} ${response.statusText}` | ||
: `Malformed JSON response: ${ | ||
error instanceof Error ? error.message : error | ||
}`; // a non-parsable 200 status response should not happen | ||
return { | ||
errors: [ | ||
{ | ||
msg: errorMsg, | ||
msg: errorMessage, | ||
}, | ||
@@ -60,13 +68,22 @@ ], | ||
}) | ||
.catch((err) => { | ||
if (err.code === "ENOTFOUND" || err.code === "ECONNREFUSED") { | ||
// the host is not contactable at all – probably a network issue or non-running dev/staging instance | ||
return { | ||
errors: [ | ||
{ msg: `Could not connect to host ${blockProtocolSiteHost}` }, | ||
], | ||
}; | ||
.catch((/** @type unknown */ error) => { | ||
if (typeof error === "object" && error) { | ||
// @ts-expect-error -- code can be a property on the error object | ||
const errorCode = error.code; | ||
if (errorCode === "ENOTFOUND" || errorCode === "ECONNREFUSED") { | ||
// the host is not contactable at all – probably a network issue or non-running dev/staging instance | ||
return { | ||
errors: [ | ||
{ msg: `Could not connect to host ${blockProtocolSiteHost}` }, | ||
], | ||
}; | ||
} | ||
if ("errors" in error) { | ||
// should be a meaningful error provided by the API about why the request failed, e.g. bad API key | ||
return error; | ||
} | ||
} | ||
return err; // should be a meaningful error provided by the API about why the request failed, e.g. bad API key | ||
return { errors: [{ msg: `Unknown error: ${error}` }] }; | ||
}); | ||
}; |
{ | ||
"name": "blockprotocol", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "Command Line Interface (CLI) for the Block Protocol API", | ||
@@ -24,3 +24,4 @@ "keywords": [ | ||
"scripts": { | ||
"dev": "BLOCK_PROTOCOL_SITE_HOST=http://localhost:3000 node cli.js" | ||
"dev": "BLOCK_PROTOCOL_SITE_HOST=http://localhost:3000 node cli.js", | ||
"lint:tsc": "tsc --noEmit" | ||
}, | ||
@@ -40,3 +41,11 @@ "dependencies": { | ||
"tmp-promise": "3.0.3" | ||
}, | ||
"devDependencies": { | ||
"@local/tsconfig": "0.0.0-private", | ||
"@types/command-line-args": "^5.2.0", | ||
"@types/command-line-usage": "^5.0.2", | ||
"@types/prompt": "^1.1.3", | ||
"@types/react": "^18.0.15", | ||
"typescript": "4.8.2" | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
19423
14
497
1
6