@promakeai/eslint 0.1.0
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/commands/init.js +200 -0
- package/dist/index.js +65 -0
- package/dist/utils/detect.js +39 -0
- package/dist/utils/exec.js +21 -0
- package/dist/utils/log.js +8 -0
- package/dist/utils/pm.js +29 -0
- package/dist/utils/templates.js +45 -0
- package/package.json +45 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { select, confirm } from "@inquirer/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import { detectProjectType } from "../utils/detect.js";
|
|
7
|
+
import { detectPackageManager, getInstallCommand, } from "../utils/pm.js";
|
|
8
|
+
import { exec } from "../utils/exec.js";
|
|
9
|
+
import { getEditorSettingsContent, getEslintConfigContent, getPrettierRcContent, getScripts, } from "../utils/templates.js";
|
|
10
|
+
import { log } from "../utils/log.js";
|
|
11
|
+
export async function init(options = {}) {
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const yes = options.yes ?? false;
|
|
14
|
+
const allowPrettier = options.prettier ?? true;
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(pc.bold("@promakeai/eslint") + " " + pc.dim("- ESLint + Prettier setup"));
|
|
17
|
+
console.log();
|
|
18
|
+
// Step 1: Verify package.json exists
|
|
19
|
+
const pkgPath = resolve(cwd, "package.json");
|
|
20
|
+
if (!existsSync(pkgPath)) {
|
|
21
|
+
log.error("No package.json found. Run this command from a project root.");
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
// Step 2: Detect or ask project type
|
|
25
|
+
let projectType;
|
|
26
|
+
if (options.projectType) {
|
|
27
|
+
const allowed = ["react-vite", "react-lib", "node"];
|
|
28
|
+
if (!allowed.includes(options.projectType)) {
|
|
29
|
+
log.error(`Invalid --project value: ${pc.bold(options.projectType)}. ` +
|
|
30
|
+
"Use react-vite, react-lib, or node.");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
projectType = options.projectType;
|
|
34
|
+
log.info(`Project type: ${pc.bold(projectType)} (via --project)`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const detection = await detectProjectType(cwd);
|
|
38
|
+
if (detection.detected) {
|
|
39
|
+
log.info(`Detected: ${pc.bold(detection.detected)} (${detection.confidence})`);
|
|
40
|
+
const useDetected = yes
|
|
41
|
+
? true
|
|
42
|
+
: await confirm({
|
|
43
|
+
message: `Set up as ${pc.bold(detection.detected)} project?`,
|
|
44
|
+
default: true,
|
|
45
|
+
});
|
|
46
|
+
projectType = useDetected ? detection.detected : await askProjectType();
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
log.warn("Could not auto-detect project type.");
|
|
50
|
+
projectType = yes ? "node" : await askProjectType();
|
|
51
|
+
if (yes) {
|
|
52
|
+
log.info(`Defaulting to ${pc.bold(projectType)}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Step 3: Detect package manager
|
|
57
|
+
const pm = detectPackageManager(cwd);
|
|
58
|
+
log.info(`Package manager: ${pc.bold(pm)}`);
|
|
59
|
+
// Step 4: Create eslint.config.mts
|
|
60
|
+
const eslintConfigPath = resolve(cwd, "eslint.config.mts");
|
|
61
|
+
if (existsSync(eslintConfigPath)) {
|
|
62
|
+
const overwrite = yes
|
|
63
|
+
? true
|
|
64
|
+
: await confirm({
|
|
65
|
+
message: "eslint.config.mts already exists. Overwrite?",
|
|
66
|
+
default: false,
|
|
67
|
+
});
|
|
68
|
+
if (!overwrite) {
|
|
69
|
+
log.warn("Skipping eslint.config.mts");
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
await writeFile(eslintConfigPath, getEslintConfigContent(projectType));
|
|
73
|
+
log.success("Created eslint.config.mts");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
await writeFile(eslintConfigPath, getEslintConfigContent(projectType));
|
|
78
|
+
log.success("Created eslint.config.mts");
|
|
79
|
+
}
|
|
80
|
+
// Step 5: Optionally create .prettierrc.json
|
|
81
|
+
const prettierRcPath = resolve(cwd, ".prettierrc.json");
|
|
82
|
+
if (allowPrettier) {
|
|
83
|
+
if (!existsSync(prettierRcPath)) {
|
|
84
|
+
const createPrettierRc = yes
|
|
85
|
+
? true
|
|
86
|
+
: await confirm({
|
|
87
|
+
message: "Create .prettierrc.json? (mirrors config defaults)",
|
|
88
|
+
default: true,
|
|
89
|
+
});
|
|
90
|
+
if (createPrettierRc) {
|
|
91
|
+
await writeFile(prettierRcPath, getPrettierRcContent());
|
|
92
|
+
log.success("Created .prettierrc.json");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
log.info(".prettierrc.json already exists, skipping.");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
log.info("Skipping .prettierrc.json (--no-prettier)");
|
|
101
|
+
}
|
|
102
|
+
// Step 6: Optionally create editor settings for VSCode
|
|
103
|
+
const vscodeDir = resolve(cwd, ".vscode");
|
|
104
|
+
const vscodeSettingsPath = resolve(vscodeDir, "settings.json");
|
|
105
|
+
const ensureVscodeSettings = async () => {
|
|
106
|
+
try {
|
|
107
|
+
await mkdir(vscodeDir, { recursive: true });
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// ignore
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
if (!existsSync(vscodeSettingsPath)) {
|
|
114
|
+
await ensureVscodeSettings();
|
|
115
|
+
await writeFile(vscodeSettingsPath, getEditorSettingsContent());
|
|
116
|
+
log.success("Created .vscode/settings.json (format on save)");
|
|
117
|
+
}
|
|
118
|
+
else if (yes) {
|
|
119
|
+
await ensureVscodeSettings();
|
|
120
|
+
await writeFile(vscodeSettingsPath, getEditorSettingsContent());
|
|
121
|
+
log.success("Overwrote .vscode/settings.json with default editor preferences");
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
log.info(".vscode/settings.json already exists, skipping editor config");
|
|
125
|
+
}
|
|
126
|
+
// Step 6: Update package.json scripts
|
|
127
|
+
const pkgRaw = await readFile(pkgPath, "utf-8");
|
|
128
|
+
const pkg = JSON.parse(pkgRaw);
|
|
129
|
+
const newScripts = getScripts();
|
|
130
|
+
const existingScripts = pkg.scripts ?? {};
|
|
131
|
+
let scriptsAdded = 0;
|
|
132
|
+
for (const [key, value] of Object.entries(newScripts)) {
|
|
133
|
+
if (!(key in existingScripts)) {
|
|
134
|
+
existingScripts[key] = value;
|
|
135
|
+
scriptsAdded++;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (scriptsAdded > 0) {
|
|
139
|
+
pkg.scripts = existingScripts;
|
|
140
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
141
|
+
log.success(`Added ${scriptsAdded} script(s) to package.json`);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
log.info("All lint/format scripts already exist in package.json");
|
|
145
|
+
}
|
|
146
|
+
// Step 7: Install dependencies
|
|
147
|
+
const depsToInstall = getDependencies();
|
|
148
|
+
console.log();
|
|
149
|
+
log.step("Installing dependencies...");
|
|
150
|
+
log.info(pc.dim(depsToInstall.join(", ")));
|
|
151
|
+
const installCmd = getInstallCommand(pm, depsToInstall, true);
|
|
152
|
+
log.info(pc.dim(`$ ${installCmd}`));
|
|
153
|
+
const result = await exec(installCmd, cwd);
|
|
154
|
+
if (result.code !== 0) {
|
|
155
|
+
log.error("Installation failed:");
|
|
156
|
+
console.error(result.stderr);
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
log.success("Dependencies installed");
|
|
160
|
+
// Done
|
|
161
|
+
console.log();
|
|
162
|
+
log.success(pc.bold("ESLint + Prettier configured!"));
|
|
163
|
+
console.log();
|
|
164
|
+
const runPrefix = pm === "npm" ? "npm run" : pm;
|
|
165
|
+
console.log(` ${pc.dim("$")} ${runPrefix} lint`);
|
|
166
|
+
console.log(` ${pc.dim("$")} ${runPrefix} lint:fix`);
|
|
167
|
+
console.log(` ${pc.dim("$")} ${runPrefix} format`);
|
|
168
|
+
console.log();
|
|
169
|
+
}
|
|
170
|
+
async function askProjectType() {
|
|
171
|
+
return select({
|
|
172
|
+
message: "What type of project is this?",
|
|
173
|
+
choices: [
|
|
174
|
+
{
|
|
175
|
+
name: "React + Vite (SPA)",
|
|
176
|
+
value: "react-vite",
|
|
177
|
+
description: "Browser app with React and Vite",
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "React Library",
|
|
181
|
+
value: "react-lib",
|
|
182
|
+
description: "Publishable React component library",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: "Node.js / CLI",
|
|
186
|
+
value: "node",
|
|
187
|
+
description: "Server, API, CLI tool, or library",
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function getDependencies() {
|
|
193
|
+
return [
|
|
194
|
+
"@promakeai/eslint-config",
|
|
195
|
+
"eslint",
|
|
196
|
+
"prettier",
|
|
197
|
+
"typescript",
|
|
198
|
+
"jiti",
|
|
199
|
+
];
|
|
200
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { init } from "./commands/init.js";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
const args = process.argv.slice(2);
|
|
5
|
+
const command = args[0];
|
|
6
|
+
function parseInitOptions(argv) {
|
|
7
|
+
const options = {
|
|
8
|
+
yes: false,
|
|
9
|
+
prettier: true,
|
|
10
|
+
};
|
|
11
|
+
for (let i = 0; i < argv.length; i++) {
|
|
12
|
+
const arg = argv[i];
|
|
13
|
+
if (arg === "--yes" || arg === "-y") {
|
|
14
|
+
options.yes = true;
|
|
15
|
+
}
|
|
16
|
+
else if (arg === "--no-prettier") {
|
|
17
|
+
options.prettier = false;
|
|
18
|
+
}
|
|
19
|
+
else if (arg === "--project" || arg === "-p") {
|
|
20
|
+
const value = argv[i + 1];
|
|
21
|
+
if (!value) {
|
|
22
|
+
throw new Error("Missing value for --project");
|
|
23
|
+
}
|
|
24
|
+
options.projectType = value;
|
|
25
|
+
i++;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return options;
|
|
29
|
+
}
|
|
30
|
+
async function main() {
|
|
31
|
+
if (!command || command === "init") {
|
|
32
|
+
const opts = parseInitOptions(args.slice(command ? 1 : 0));
|
|
33
|
+
await init(opts);
|
|
34
|
+
}
|
|
35
|
+
else if (command === "--help" || command === "-h") {
|
|
36
|
+
printHelp();
|
|
37
|
+
}
|
|
38
|
+
else if (command === "--version" || command === "-v") {
|
|
39
|
+
console.log("0.1.0");
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.error(pc.red(`Unknown command: ${command}`));
|
|
43
|
+
printHelp();
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function printHelp() {
|
|
48
|
+
console.log(`
|
|
49
|
+
${pc.bold("@promakeai/eslint")} - ESLint + Prettier scaffolding tool
|
|
50
|
+
|
|
51
|
+
${pc.bold("Usage:")}
|
|
52
|
+
npx @promakeai/eslint init [options] Set up ESLint + Prettier in your project
|
|
53
|
+
|
|
54
|
+
${pc.bold("Options:")}
|
|
55
|
+
-y, --yes Accept all prompts (overwrite files, create .prettierrc)
|
|
56
|
+
-p, --project <type> One of: react-vite | react-lib | node
|
|
57
|
+
--no-prettier Skip creating .prettierrc.json
|
|
58
|
+
-h, --help Show this help message
|
|
59
|
+
-v, --version Show version number
|
|
60
|
+
`);
|
|
61
|
+
}
|
|
62
|
+
main().catch((err) => {
|
|
63
|
+
console.error(pc.red("Error:"), err.message);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
export async function detectProjectType(cwd) {
|
|
5
|
+
const viteConfigExists = existsSync(resolve(cwd, "vite.config.ts")) ||
|
|
6
|
+
existsSync(resolve(cwd, "vite.config.js")) ||
|
|
7
|
+
existsSync(resolve(cwd, "vite.config.mts"));
|
|
8
|
+
let pkg = {};
|
|
9
|
+
try {
|
|
10
|
+
const raw = await readFile(resolve(cwd, "package.json"), "utf-8");
|
|
11
|
+
pkg = JSON.parse(raw);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return { detected: null, confidence: "No package.json found" };
|
|
15
|
+
}
|
|
16
|
+
const allDeps = {
|
|
17
|
+
...(pkg.dependencies ?? {}),
|
|
18
|
+
...(pkg.devDependencies ?? {}),
|
|
19
|
+
};
|
|
20
|
+
const hasReact = "react" in allDeps;
|
|
21
|
+
const hasVite = "vite" in allDeps;
|
|
22
|
+
const hasNext = "next" in allDeps;
|
|
23
|
+
if (hasReact && (hasVite || viteConfigExists)) {
|
|
24
|
+
return { detected: "react-vite", confidence: "Found react + vite" };
|
|
25
|
+
}
|
|
26
|
+
if (hasReact && !hasVite && !hasNext) {
|
|
27
|
+
return {
|
|
28
|
+
detected: "react-lib",
|
|
29
|
+
confidence: "Found react without vite/next",
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (!hasReact) {
|
|
33
|
+
return {
|
|
34
|
+
detected: "node",
|
|
35
|
+
confidence: "No browser framework detected",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return { detected: null, confidence: "Could not determine project type" };
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export function exec(command, cwd) {
|
|
3
|
+
return new Promise((resolve) => {
|
|
4
|
+
const child = spawn(command, {
|
|
5
|
+
cwd,
|
|
6
|
+
shell: true,
|
|
7
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
8
|
+
});
|
|
9
|
+
let stdout = "";
|
|
10
|
+
let stderr = "";
|
|
11
|
+
child.stdout.on("data", (data) => {
|
|
12
|
+
stdout += data.toString();
|
|
13
|
+
});
|
|
14
|
+
child.stderr.on("data", (data) => {
|
|
15
|
+
stderr += data.toString();
|
|
16
|
+
});
|
|
17
|
+
child.on("close", (code) => {
|
|
18
|
+
resolve({ code: code ?? 1, stdout, stderr });
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
export const log = {
|
|
3
|
+
info: (msg) => console.log(pc.cyan("i"), msg),
|
|
4
|
+
success: (msg) => console.log(pc.green("\u2713"), msg),
|
|
5
|
+
warn: (msg) => console.log(pc.yellow("!"), msg),
|
|
6
|
+
error: (msg) => console.error(pc.red("\u2717"), msg),
|
|
7
|
+
step: (msg) => console.log(pc.bold(pc.blue(">")), msg),
|
|
8
|
+
};
|
package/dist/utils/pm.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
export function detectPackageManager(cwd) {
|
|
4
|
+
if (existsSync(resolve(cwd, "bun.lock")) ||
|
|
5
|
+
existsSync(resolve(cwd, "bun.lockb"))) {
|
|
6
|
+
return "bun";
|
|
7
|
+
}
|
|
8
|
+
if (existsSync(resolve(cwd, "pnpm-lock.yaml"))) {
|
|
9
|
+
return "pnpm";
|
|
10
|
+
}
|
|
11
|
+
if (existsSync(resolve(cwd, "yarn.lock"))) {
|
|
12
|
+
return "yarn";
|
|
13
|
+
}
|
|
14
|
+
return "npm";
|
|
15
|
+
}
|
|
16
|
+
export function getInstallCommand(pm, packages, dev) {
|
|
17
|
+
const pkgs = packages.join(" ");
|
|
18
|
+
switch (pm) {
|
|
19
|
+
case "bun":
|
|
20
|
+
return `bun add${dev ? " -D" : ""} ${pkgs}`;
|
|
21
|
+
case "pnpm":
|
|
22
|
+
return `pnpm add${dev ? " -D" : ""} ${pkgs}`;
|
|
23
|
+
case "yarn":
|
|
24
|
+
return `yarn add${dev ? " -D" : ""} ${pkgs}`;
|
|
25
|
+
case "npm":
|
|
26
|
+
default:
|
|
27
|
+
return `npm install${dev ? " --save-dev" : ""} ${pkgs}`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export function getEslintConfigContent(projectType) {
|
|
2
|
+
switch (projectType) {
|
|
3
|
+
case "react-vite":
|
|
4
|
+
case "react-lib":
|
|
5
|
+
return `import config from "@promakeai/eslint-config/react";
|
|
6
|
+
|
|
7
|
+
export default config;
|
|
8
|
+
`;
|
|
9
|
+
case "node":
|
|
10
|
+
return `import config from "@promakeai/eslint-config/node";
|
|
11
|
+
|
|
12
|
+
export default config;
|
|
13
|
+
`;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function getPrettierRcContent() {
|
|
17
|
+
return (JSON.stringify({
|
|
18
|
+
semi: true,
|
|
19
|
+
singleQuote: false,
|
|
20
|
+
tabWidth: 2,
|
|
21
|
+
trailingComma: "all",
|
|
22
|
+
printWidth: 80,
|
|
23
|
+
bracketSpacing: true,
|
|
24
|
+
arrowParens: "always",
|
|
25
|
+
endOfLine: "auto",
|
|
26
|
+
}, null, 2) + "\n");
|
|
27
|
+
}
|
|
28
|
+
export function getScripts() {
|
|
29
|
+
return {
|
|
30
|
+
lint: "eslint .",
|
|
31
|
+
"lint:fix": "eslint . --fix",
|
|
32
|
+
format: "prettier --write .",
|
|
33
|
+
"format:check": "prettier --check .",
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function getEditorSettingsContent() {
|
|
37
|
+
return JSON.stringify({
|
|
38
|
+
"editor.formatOnSave": true,
|
|
39
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
40
|
+
"editor.codeActionsOnSave": {
|
|
41
|
+
"source.fixAll.eslint": true,
|
|
42
|
+
},
|
|
43
|
+
"files.autoSave": "off",
|
|
44
|
+
}, null, 2) + "\n";
|
|
45
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@promakeai/eslint",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI to scaffold ESLint + Prettier with @promakeai/eslint-config",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"@promakeai/eslint": "./dist/index.js",
|
|
8
|
+
"promake-eslint": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc --project tsconfig.build.json",
|
|
15
|
+
"clean": "rm -rf dist",
|
|
16
|
+
"dev": "bun run src/index.ts",
|
|
17
|
+
"pack": "bun run clean && bun run build && npm pack --dry-run",
|
|
18
|
+
"publish": "bun run clean && bun run build && npm publish --access public",
|
|
19
|
+
"release": "npm run publish",
|
|
20
|
+
"prepublishOnly": "bun run clean && bun run build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"eslint",
|
|
24
|
+
"prettier",
|
|
25
|
+
"cli",
|
|
26
|
+
"scaffolding",
|
|
27
|
+
"typescript"
|
|
28
|
+
],
|
|
29
|
+
"author": "Promake",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": "^20.19.0 || ^22.13.0 || >=24"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@inquirer/prompts": "^8.2.0",
|
|
36
|
+
"picocolors": "^1.1.1"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^25.2.3",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
}
|
|
45
|
+
}
|