@drupal-canvas/cli 0.5.1 → 0.6.1
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/README.md +0 -1
- package/dist/index.js +132 -104
- package/package.json +2 -2
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -40,7 +40,6 @@ to get started.
|
|
|
40
40
|
| `--client-id` | `CANVAS_CLIENT_ID` | OAuth client ID. |
|
|
41
41
|
| `--client-secret` | `CANVAS_CLIENT_SECRET` | OAuth client secret. |
|
|
42
42
|
| `--dir` | `CANVAS_COMPONENT_DIR` | Directory where code components are stored in the filesystem. |
|
|
43
|
-
| `--verbose` | `CANVAS_VERBOSE` | Verbose CLI output for troubleshooting. Defaults to `false`. |
|
|
44
43
|
| `--scope` | `CANVAS_SCOPE` | (Optional) Space-separated list of OAuth scopes to request. |
|
|
45
44
|
|
|
46
45
|
**Note:** The `--scope` parameter defaults to
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import { parse } from '@babel/parser';
|
|
|
25
25
|
|
|
26
26
|
// package.json
|
|
27
27
|
var package_default = {
|
|
28
|
-
|
|
28
|
+
};
|
|
29
29
|
function loadEnvFiles() {
|
|
30
30
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
31
31
|
if (homeDir) {
|
|
@@ -46,7 +46,6 @@ var config = {
|
|
|
46
46
|
clientSecret: process.env.CANVAS_CLIENT_SECRET || "",
|
|
47
47
|
scope: process.env.CANVAS_SCOPE || "canvas:js_component canvas:asset_library",
|
|
48
48
|
componentDir: process.env.CANVAS_COMPONENT_DIR || "./components",
|
|
49
|
-
verbose: process.env.CANVAS_VERBOSE === "true",
|
|
50
49
|
userAgent: process.env.CANVAS_USER_AGENT || ""
|
|
51
50
|
};
|
|
52
51
|
function getConfig() {
|
|
@@ -10672,107 +10671,138 @@ var ApiService = class _ApiService {
|
|
|
10672
10671
|
throw new Error("Failed to update global asset library");
|
|
10673
10672
|
}
|
|
10674
10673
|
}
|
|
10675
|
-
|
|
10676
|
-
|
|
10677
|
-
|
|
10678
|
-
|
|
10679
|
-
|
|
10680
|
-
|
|
10681
|
-
|
|
10682
|
-
if (
|
|
10683
|
-
|
|
10684
|
-
console.error(`- Status: ${status}`);
|
|
10685
|
-
console.error(`- URL: ${error.config?.url || "unknown"}`);
|
|
10686
|
-
console.error(
|
|
10687
|
-
`- Method: ${error.config?.method?.toUpperCase() || "unknown"}`
|
|
10688
|
-
);
|
|
10689
|
-
console.error("- Response data:", JSON.stringify(data, null, 2));
|
|
10690
|
-
const safeHeaders = { ...error.config?.headers };
|
|
10691
|
-
if (safeHeaders && safeHeaders.Authorization) {
|
|
10692
|
-
safeHeaders.Authorization = "Bearer ********";
|
|
10693
|
-
}
|
|
10694
|
-
console.error(
|
|
10695
|
-
"- Request headers:",
|
|
10696
|
-
JSON.stringify(safeHeaders, null, 2)
|
|
10697
|
-
);
|
|
10698
|
-
}
|
|
10699
|
-
if (status === 401) {
|
|
10700
|
-
throw new Error(
|
|
10701
|
-
"Authentication failed. Please check your client ID and secret."
|
|
10702
|
-
);
|
|
10703
|
-
} else if (status === 403) {
|
|
10704
|
-
throw new Error(
|
|
10705
|
-
"You do not have permission to perform this action. Check your configured scope."
|
|
10706
|
-
);
|
|
10707
|
-
} else if (data && (data.error || data.error_description || data.hint)) {
|
|
10708
|
-
throw new Error(
|
|
10709
|
-
`API Error (${status}): ${[
|
|
10710
|
-
data.error,
|
|
10711
|
-
data.error_description,
|
|
10712
|
-
data.hint
|
|
10713
|
-
].filter(Boolean).join(" | ")}`
|
|
10714
|
-
);
|
|
10715
|
-
} else {
|
|
10716
|
-
throw new Error(`API Error (${status}): ${error.message}`);
|
|
10674
|
+
/**
|
|
10675
|
+
* Parse Canvas API error responses into user-friendly messages.
|
|
10676
|
+
* Handles both structured validation errors and simple string errors.
|
|
10677
|
+
*/
|
|
10678
|
+
parseCanvasErrors(data) {
|
|
10679
|
+
if (data && typeof data === "object" && "errors" in data && Array.isArray(data.errors)) {
|
|
10680
|
+
return data.errors.map((err) => {
|
|
10681
|
+
if (typeof err === "string") {
|
|
10682
|
+
return err.trim();
|
|
10717
10683
|
}
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
console.error(
|
|
10724
|
-
`- Method: ${error.config?.method?.toUpperCase() || "unknown"}`
|
|
10725
|
-
);
|
|
10726
|
-
const safeHeaders = { ...error.config?.headers };
|
|
10727
|
-
if (safeHeaders && safeHeaders.Authorization) {
|
|
10728
|
-
safeHeaders.Authorization = "Bearer ********";
|
|
10684
|
+
if (err && typeof err === "object" && "detail" in err) {
|
|
10685
|
+
let message = typeof err.detail === "string" ? err.detail : String(err.detail);
|
|
10686
|
+
message = message.replace(/<[^>]*>/g, "").replace(/"/g, '"').replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").trim();
|
|
10687
|
+
if (!message) {
|
|
10688
|
+
return "";
|
|
10729
10689
|
}
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
JSON.stringify(safeHeaders, null, 2)
|
|
10733
|
-
);
|
|
10734
|
-
if (this.siteUrl.includes("ddev.site")) {
|
|
10735
|
-
console.error("\nDDEV Local Development Troubleshooting Tips:");
|
|
10736
|
-
console.error('1. Make sure DDEV is running: try "ddev status"');
|
|
10737
|
-
console.error(
|
|
10738
|
-
'2. Try using HTTP instead of HTTPS: use "http://drupal-dev.ddev.site" as URL'
|
|
10739
|
-
);
|
|
10740
|
-
console.error("3. Check if the site is accessible in your browser");
|
|
10741
|
-
console.error(
|
|
10742
|
-
'4. For HTTPS issues: Try "ddev auth ssl" to set up local SSL certificates'
|
|
10743
|
-
);
|
|
10690
|
+
if ("source" in err && err.source && typeof err.source === "object" && "pointer" in err.source && typeof err.source.pointer === "string" && err.source.pointer !== "") {
|
|
10691
|
+
message = `[${err.source.pointer}] ${message}`;
|
|
10744
10692
|
}
|
|
10693
|
+
return message;
|
|
10745
10694
|
}
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
|
|
10695
|
+
return "";
|
|
10696
|
+
}).filter((msg) => msg !== "");
|
|
10697
|
+
}
|
|
10698
|
+
return [];
|
|
10699
|
+
}
|
|
10700
|
+
/**
|
|
10701
|
+
* Throws an appropriate error based on the API response.
|
|
10702
|
+
*/
|
|
10703
|
+
throwApiError(status, data, error, canvasErrors) {
|
|
10704
|
+
if (canvasErrors.length > 0) {
|
|
10705
|
+
const errorList = canvasErrors.join("\n\n").trim();
|
|
10706
|
+
if (errorList) {
|
|
10707
|
+
throw new Error(errorList);
|
|
10708
|
+
}
|
|
10709
|
+
}
|
|
10710
|
+
if (status === 401) {
|
|
10711
|
+
let message = "Authentication failed. Please check your client ID and secret.";
|
|
10712
|
+
if (data && typeof data === "object" && "error_description" in data && typeof data.error_description === "string") {
|
|
10713
|
+
message = `Authentication Error: ${data.error_description}
|
|
10714
|
+
|
|
10715
|
+
${message}`;
|
|
10716
|
+
}
|
|
10717
|
+
throw new Error(message);
|
|
10718
|
+
}
|
|
10719
|
+
if (status === 403) {
|
|
10720
|
+
throw new Error(
|
|
10721
|
+
"You do not have permission to perform this action. Check your configured scope."
|
|
10722
|
+
);
|
|
10723
|
+
}
|
|
10724
|
+
if (status === 404) {
|
|
10725
|
+
const url2 = error.config?.url || "unknown";
|
|
10726
|
+
let message = `API endpoint not found: ${url2}
|
|
10727
|
+
|
|
10728
|
+
`;
|
|
10729
|
+
if (this.siteUrl.includes("ddev.site")) {
|
|
10730
|
+
message += "Possible causes:\n";
|
|
10731
|
+
message += " \u2022 DDEV is not running (run: ddev start)\n";
|
|
10732
|
+
message += " \u2022 Canvas module is not enabled (run: ddev drush en canvas -y)\n";
|
|
10733
|
+
message += " \u2022 Site URL is incorrect";
|
|
10755
10734
|
} else {
|
|
10756
|
-
|
|
10757
|
-
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
|
|
10761
|
-
|
|
10735
|
+
message += "Possible causes:\n";
|
|
10736
|
+
message += " \u2022 Canvas module is not enabled\n";
|
|
10737
|
+
message += " \u2022 Site URL is incorrect\n";
|
|
10738
|
+
message += " \u2022 Server is not responding correctly";
|
|
10739
|
+
}
|
|
10740
|
+
throw new Error(message);
|
|
10741
|
+
}
|
|
10742
|
+
if (data && typeof data === "object" && "message" in data && typeof data.message === "string") {
|
|
10743
|
+
throw new Error(data.message);
|
|
10744
|
+
}
|
|
10745
|
+
if (data && typeof data === "object") {
|
|
10746
|
+
const errorParts = [];
|
|
10747
|
+
if ("error" in data && typeof data.error === "string") {
|
|
10748
|
+
errorParts.push(data.error);
|
|
10762
10749
|
}
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
console.error("General Error:");
|
|
10766
|
-
console.error(`- Message: ${error.message}`);
|
|
10767
|
-
console.error("- Stack:", error.stack);
|
|
10750
|
+
if ("error_description" in data && typeof data.error_description === "string") {
|
|
10751
|
+
errorParts.push(data.error_description);
|
|
10768
10752
|
}
|
|
10769
|
-
|
|
10753
|
+
if ("hint" in data && typeof data.hint === "string") {
|
|
10754
|
+
errorParts.push(data.hint);
|
|
10755
|
+
}
|
|
10756
|
+
if (errorParts.length > 0) {
|
|
10757
|
+
throw new Error(`API Error (${status}): ${errorParts.join(" | ")}`);
|
|
10758
|
+
}
|
|
10759
|
+
}
|
|
10760
|
+
const url = error.config?.url || "unknown";
|
|
10761
|
+
const method = error.config?.method?.toUpperCase() || "unknown";
|
|
10762
|
+
throw new Error(
|
|
10763
|
+
`API Error (${status}): ${error.message}
|
|
10764
|
+
|
|
10765
|
+
URL: ${url}
|
|
10766
|
+
Method: ${method}`
|
|
10767
|
+
);
|
|
10768
|
+
}
|
|
10769
|
+
/**
|
|
10770
|
+
* Handles network errors (no response from server).
|
|
10771
|
+
*/
|
|
10772
|
+
handleNetworkError() {
|
|
10773
|
+
let message = `No response from: ${this.siteUrl}
|
|
10774
|
+
|
|
10775
|
+
`;
|
|
10776
|
+
if (this.siteUrl.includes("ddev.site")) {
|
|
10777
|
+
message += "Troubleshooting tips:\n";
|
|
10778
|
+
message += " \u2022 Check if DDEV is running: ddev status\n";
|
|
10779
|
+
message += " \u2022 Try HTTP instead of HTTPS\n";
|
|
10780
|
+
message += " \u2022 Verify site is accessible in browser\n";
|
|
10781
|
+
message += " \u2022 For HTTPS issues, try: ddev auth ssl";
|
|
10770
10782
|
} else {
|
|
10771
|
-
|
|
10772
|
-
|
|
10783
|
+
message += "Check your site URL and internet connection.";
|
|
10784
|
+
}
|
|
10785
|
+
throw new Error(message);
|
|
10786
|
+
}
|
|
10787
|
+
/**
|
|
10788
|
+
* Main error handler for API requests.
|
|
10789
|
+
*/
|
|
10790
|
+
handleApiError(error) {
|
|
10791
|
+
if (!axios.isAxiosError(error)) {
|
|
10792
|
+
if (error instanceof Error) {
|
|
10793
|
+
throw error;
|
|
10773
10794
|
}
|
|
10774
10795
|
throw new Error("Unknown API error occurred");
|
|
10775
10796
|
}
|
|
10797
|
+
if (error.response) {
|
|
10798
|
+
const { status, data } = error.response;
|
|
10799
|
+
const canvasErrors = this.parseCanvasErrors(data);
|
|
10800
|
+
this.throwApiError(status, data, error, canvasErrors);
|
|
10801
|
+
}
|
|
10802
|
+
if (error.request) {
|
|
10803
|
+
this.handleNetworkError();
|
|
10804
|
+
}
|
|
10805
|
+
throw new Error(`Request setup error: ${error.message}`);
|
|
10776
10806
|
}
|
|
10777
10807
|
};
|
|
10778
10808
|
function createApiService() {
|
|
@@ -11114,7 +11144,6 @@ function updateConfigFromOptions(options) {
|
|
|
11114
11144
|
if (options.dir) setConfig({ componentDir: options.dir });
|
|
11115
11145
|
if (options.scope) setConfig({ scope: options.scope });
|
|
11116
11146
|
if (options.all) setConfig({ all: options.all });
|
|
11117
|
-
if (options.verbose) setConfig({ verbose: true });
|
|
11118
11147
|
}
|
|
11119
11148
|
function pluralizeComponent(count) {
|
|
11120
11149
|
return count === 1 ? "component" : "components";
|
|
@@ -18091,7 +18120,7 @@ function buildCommand(program2) {
|
|
|
18091
18120
|
).option("--all", "Build all components").option(
|
|
18092
18121
|
"-c, --components <names>",
|
|
18093
18122
|
"Specific component(s) to build (comma-separated)"
|
|
18094
|
-
).option("--no-tailwind", "Skip Tailwind CSS building").option("-y, --yes", "Skip confirmation prompts").option("--client-id <id>", "Client ID").option("--client-secret <secret>", "Client Secret").option("--site-url <url>", "Site URL").
|
|
18123
|
+
).option("--no-tailwind", "Skip Tailwind CSS building").option("-y, --yes", "Skip confirmation prompts").option("--client-id <id>", "Client ID").option("--client-secret <secret>", "Client Secret").option("--site-url <url>", "Site URL").action(async (options) => {
|
|
18095
18124
|
try {
|
|
18096
18125
|
p.intro(chalk2.bold("Drupal Canvas CLI: build"));
|
|
18097
18126
|
validateComponentOptions(options);
|
|
@@ -18161,7 +18190,7 @@ function downloadCommand(program2) {
|
|
|
18161
18190
|
).option("--all", "Download all components").option("-y, --yes", "Skip all confirmation prompts").option(
|
|
18162
18191
|
"--skip-overwrite",
|
|
18163
18192
|
"Skip downloading components that already exist locally"
|
|
18164
|
-
).option("--skip-css", "Skip downloading global CSS").option("--css-only", "Download only global CSS (skip components)").
|
|
18193
|
+
).option("--skip-css", "Skip downloading global CSS").option("--css-only", "Download only global CSS (skip components)").action(async (options) => {
|
|
18165
18194
|
p.intro(chalk2.bold("Drupal Canvas CLI: download"));
|
|
18166
18195
|
try {
|
|
18167
18196
|
validateComponentOptions(options);
|
|
@@ -18351,11 +18380,10 @@ function scaffoldCommand(program2) {
|
|
|
18351
18380
|
).option(
|
|
18352
18381
|
"-d, --dir <directory>",
|
|
18353
18382
|
"Component directory to create component in"
|
|
18354
|
-
).
|
|
18383
|
+
).action(async (options) => {
|
|
18355
18384
|
p.intro(chalk2.bold("Drupal Canvas CLI: scaffold"));
|
|
18356
18385
|
try {
|
|
18357
18386
|
if (options.dir) setConfig({ componentDir: options.dir });
|
|
18358
|
-
if (options.verbose) setConfig({ verbose: options.verbose });
|
|
18359
18387
|
const config2 = getConfig();
|
|
18360
18388
|
const baseDir = config2.componentDir;
|
|
18361
18389
|
let componentName = options.name;
|
|
@@ -18450,7 +18478,7 @@ var getDataDependenciesFromAst = (ast) => ast.program.body.filter((d2) => d2.typ
|
|
|
18450
18478
|
const source = d2.source.value;
|
|
18451
18479
|
if (
|
|
18452
18480
|
// Only consider imports from these two modules.
|
|
18453
|
-
source !== "@/lib/drupal-utils" && source !== "@drupal-api-client/json-api-client"
|
|
18481
|
+
source !== "@/lib/drupal-utils" && source !== "@drupal-api-client/json-api-client" && source !== "drupal-canvas"
|
|
18454
18482
|
) {
|
|
18455
18483
|
return carry;
|
|
18456
18484
|
}
|
|
@@ -18707,7 +18735,7 @@ function uploadCommand(program2) {
|
|
|
18707
18735
|
program2.command("upload").description("build and upload local components and global CSS assets").option("--client-id <id>", "Client ID").option("--client-secret <secret>", "Client Secret").option("--site-url <url>", "Site URL").option("--scope <scope>", "Scope").option("-d, --dir <directory>", "Component directory").option(
|
|
18708
18736
|
"-c, --components <names>",
|
|
18709
18737
|
"Specific component(s) to upload (comma-separated)"
|
|
18710
|
-
).option("--all", "Upload all components").option("-y, --yes", "Skip confirmation prompts").option("--
|
|
18738
|
+
).option("--all", "Upload all components").option("-y, --yes", "Skip confirmation prompts").option("--no-tailwind", "Skip Tailwind CSS building").option("--skip-css", "Skip global CSS upload").option("--css-only", "Upload only global CSS (skip components)").action(async (options) => {
|
|
18711
18739
|
const allFlag = options.all || options.yes && !options.components || false;
|
|
18712
18740
|
const skipTailwind = !options.tailwind;
|
|
18713
18741
|
try {
|
|
@@ -18738,6 +18766,7 @@ function uploadCommand(program2) {
|
|
|
18738
18766
|
selectMessage: "Select items to upload"
|
|
18739
18767
|
});
|
|
18740
18768
|
const apiService = await createApiService();
|
|
18769
|
+
await apiService.listComponents();
|
|
18741
18770
|
let componentResults = [];
|
|
18742
18771
|
if (!options.cssOnly && componentsToUpload.length > 0) {
|
|
18743
18772
|
componentResults = await getBuildAndUploadResults(
|
|
@@ -18924,12 +18953,13 @@ async function getBuildAndUploadResults(componentsToUpload, apiService, includeG
|
|
|
18924
18953
|
]
|
|
18925
18954
|
});
|
|
18926
18955
|
} else {
|
|
18956
|
+
const errorMessage = uploadResult.error?.message || "Unknown upload error";
|
|
18927
18957
|
results.push({
|
|
18928
18958
|
itemName: component.componentName,
|
|
18929
18959
|
success: false,
|
|
18930
18960
|
details: [
|
|
18931
18961
|
{
|
|
18932
|
-
content:
|
|
18962
|
+
content: errorMessage.trim() || "Unknown upload error"
|
|
18933
18963
|
}
|
|
18934
18964
|
]
|
|
18935
18965
|
});
|
|
@@ -19009,7 +19039,7 @@ function validateCommand(program2) {
|
|
|
19009
19039
|
).option(
|
|
19010
19040
|
"-c, --components <names>",
|
|
19011
19041
|
"Specific component(s) to validate (comma-separated)"
|
|
19012
|
-
).option("--all", "Validate all components").option("-y, --yes", "Skip confirmation prompts").option(
|
|
19042
|
+
).option("--all", "Validate all components").option("-y, --yes", "Skip confirmation prompts").option(
|
|
19013
19043
|
"--fix",
|
|
19014
19044
|
"Apply available automatic fixes for linting issues",
|
|
19015
19045
|
false
|
|
@@ -19060,7 +19090,7 @@ function validateCommand(program2) {
|
|
|
19060
19090
|
// src/index.ts
|
|
19061
19091
|
var version = package_default.version;
|
|
19062
19092
|
var program = new Command();
|
|
19063
|
-
program.name("canvas").description("CLI tool for managing Drupal Canvas code components").version(version);
|
|
19093
|
+
program.name("canvas").description("CLI tool for managing Drupal Canvas code components").version(version ?? "0.0.0");
|
|
19064
19094
|
downloadCommand(program);
|
|
19065
19095
|
scaffoldCommand(program);
|
|
19066
19096
|
uploadCommand(program);
|
|
@@ -19076,5 +19106,3 @@ try {
|
|
|
19076
19106
|
process.exit(1);
|
|
19077
19107
|
}
|
|
19078
19108
|
}
|
|
19079
|
-
//# sourceMappingURL=index.js.map
|
|
19080
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drupal-canvas/cli",
|
|
3
|
-
"version": "0.5.1",
|
|
4
3
|
"description": "CLI tool for managing Drupal Canvas code components",
|
|
4
|
+
"version": "0.6.1",
|
|
5
5
|
"license": "GPL-2.0-or-later",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@babel/parser": "^7.26.9",
|
|
53
53
|
"@clack/prompts": "^0.11.0",
|
|
54
|
-
"@drupal-canvas/eslint-config": "^0.0
|
|
54
|
+
"@drupal-canvas/eslint-config": "^0.1.0",
|
|
55
55
|
"@swc/wasm": "^1.12.1",
|
|
56
56
|
"axios": "^1.9.0",
|
|
57
57
|
"chalk": "^5.4.1",
|