@hypequery/cli 1.1.1 → 1.2.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/README.md +71 -149
- package/dist/bin/cli.js +21 -81
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +74 -105
- package/dist/commands/dev.d.ts +1 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +180 -255
- package/dist/commands/generate-datasets.d.ts +14 -0
- package/dist/commands/generate-datasets.d.ts.map +1 -0
- package/dist/commands/generate-datasets.js +96 -0
- package/dist/commands/generate.d.ts +2 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +112 -167
- package/dist/commands/init.d.ts +7 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +337 -390
- package/dist/generators/clickhouse.d.ts +1 -1
- package/dist/generators/clickhouse.d.ts.map +1 -1
- package/dist/generators/clickhouse.js +10 -269
- package/dist/generators/dataset-generator.d.ts +16 -0
- package/dist/generators/dataset-generator.d.ts.map +1 -0
- package/dist/generators/dataset-generator.js +213 -0
- package/dist/generators/index.js +4 -4
- package/dist/templates/api.d.ts +9 -0
- package/dist/templates/api.d.ts.map +1 -0
- package/dist/templates/api.js +26 -0
- package/dist/templates/auth-scaffold.d.ts +17 -0
- package/dist/templates/auth-scaffold.d.ts.map +1 -0
- package/dist/templates/auth-scaffold.js +41 -0
- package/dist/templates/client.js +10 -1
- package/dist/templates/datasets.d.ts +5 -0
- package/dist/templates/datasets.d.ts.map +1 -0
- package/dist/templates/datasets.js +23 -0
- package/dist/templates/env.d.ts +2 -1
- package/dist/templates/env.d.ts.map +1 -1
- package/dist/templates/env.js +19 -6
- package/dist/templates/gitignore.js +4 -1
- package/dist/templates/queries.d.ts +3 -0
- package/dist/templates/queries.d.ts.map +1 -1
- package/dist/templates/queries.js +66 -9
- package/dist/test-utils.d.ts +0 -72
- package/dist/test-utils.d.ts.map +1 -1
- package/dist/test-utils.js +12 -138
- package/dist/utils/clickhouse-client.js +11 -58
- package/dist/utils/clickhouse-sql.d.ts +6 -0
- package/dist/utils/clickhouse-sql.d.ts.map +1 -0
- package/dist/utils/clickhouse-sql.js +18 -0
- package/dist/utils/clickhouse-type-utils.d.ts +6 -0
- package/dist/utils/clickhouse-type-utils.d.ts.map +1 -0
- package/dist/utils/clickhouse-type-utils.js +59 -0
- package/dist/utils/dependency-installer.d.ts +5 -1
- package/dist/utils/dependency-installer.d.ts.map +1 -1
- package/dist/utils/dependency-installer.js +117 -134
- package/dist/utils/detect-database.js +84 -195
- package/dist/utils/find-files.d.ts +3 -1
- package/dist/utils/find-files.d.ts.map +1 -1
- package/dist/utils/find-files.js +82 -148
- package/dist/utils/load-api.d.ts.map +1 -1
- package/dist/utils/load-api.js +207 -396
- package/dist/utils/logger.js +38 -42
- package/dist/utils/prompts.d.ts +14 -5
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +170 -244
- package/dist/utils/runtime-guards.d.ts +4 -0
- package/dist/utils/runtime-guards.d.ts.map +1 -0
- package/dist/utils/runtime-guards.js +9 -0
- package/dist/utils/sha256.d.ts +2 -0
- package/dist/utils/sha256.d.ts.map +1 -0
- package/dist/utils/sha256.js +4 -0
- package/package.json +4 -4
- package/dist/utils/error-messages.d.ts +0 -6
- package/dist/utils/error-messages.d.ts.map +0 -1
- package/dist/utils/error-messages.js +0 -19
- package/dist/utils/load-hypequery-config.d.ts +0 -7
- package/dist/utils/load-hypequery-config.d.ts.map +0 -1
- package/dist/utils/load-hypequery-config.js +0 -89
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export function splitTopLevelArgs(value) {
|
|
2
|
+
const parts = [];
|
|
3
|
+
let current = '';
|
|
4
|
+
let depth = 0;
|
|
5
|
+
let quote = null;
|
|
6
|
+
for (const char of value) {
|
|
7
|
+
if (quote) {
|
|
8
|
+
current += char;
|
|
9
|
+
if (char === quote) {
|
|
10
|
+
quote = null;
|
|
11
|
+
}
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
15
|
+
quote = char;
|
|
16
|
+
current += char;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (char === '(') {
|
|
20
|
+
depth += 1;
|
|
21
|
+
current += char;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (char === ')') {
|
|
25
|
+
depth -= 1;
|
|
26
|
+
current += char;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (char === ',' && depth === 0) {
|
|
30
|
+
parts.push(current.trim());
|
|
31
|
+
current = '';
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
current += char;
|
|
35
|
+
}
|
|
36
|
+
if (current.trim()) {
|
|
37
|
+
parts.push(current.trim());
|
|
38
|
+
}
|
|
39
|
+
return parts;
|
|
40
|
+
}
|
|
41
|
+
export function unwrapType(type, wrapperName) {
|
|
42
|
+
const prefix = `${wrapperName}(`;
|
|
43
|
+
return type.startsWith(prefix) && type.endsWith(')') ? type.slice(prefix.length, -1) : null;
|
|
44
|
+
}
|
|
45
|
+
export function matchTypeCall(type, name) {
|
|
46
|
+
const inner = unwrapType(type, name);
|
|
47
|
+
return inner === null ? null : splitTopLevelArgs(inner);
|
|
48
|
+
}
|
|
49
|
+
export function unquoteClickHouseString(value) {
|
|
50
|
+
const trimmed = value.trim();
|
|
51
|
+
if ((trimmed.startsWith("'") && trimmed.endsWith("'")) ||
|
|
52
|
+
(trimmed.startsWith('"') && trimmed.endsWith('"'))) {
|
|
53
|
+
return trimmed.slice(1, -1);
|
|
54
|
+
}
|
|
55
|
+
return trimmed;
|
|
56
|
+
}
|
|
57
|
+
export function isIntegerLiteral(value) {
|
|
58
|
+
return /^\d+$/.test(value.trim());
|
|
59
|
+
}
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
type ScaffoldStyle = 'queries' | 'datasets';
|
|
2
|
+
export declare function resolveScaffoldPackages(cliVersion: string | undefined, style?: ScaffoldStyle): string[];
|
|
3
|
+
export declare function installScaffoldDependencies(style?: ScaffoldStyle): Promise<void>;
|
|
4
|
+
export declare const installServeDependencies: typeof installScaffoldDependencies;
|
|
5
|
+
export {};
|
|
2
6
|
//# sourceMappingURL=dependency-installer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-installer.d.ts","sourceRoot":"","sources":["../../src/utils/dependency-installer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dependency-installer.d.ts","sourceRoot":"","sources":["../../src/utils/dependency-installer.ts"],"names":[],"mappings":"AASA,KAAK,aAAa,GAAG,SAAS,GAAG,UAAU,CAAC;AA0F5C,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,GAAE,aAAyB,GAAG,MAAM,EAAE,CAgBlH;AAsBD,wBAAsB,2BAA2B,CAAC,KAAK,GAAE,aAAyB,iBAiDjF;AAED,eAAO,MAAM,wBAAwB,oCAA8B,CAAC"}
|
|
@@ -1,100 +1,63 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
12
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
-
function step(op) {
|
|
15
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
-
switch (op[0]) {
|
|
20
|
-
case 0: case 1: t = op; break;
|
|
21
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
-
default:
|
|
25
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
-
if (t[2]) _.ops.pop();
|
|
30
|
-
_.trys.pop(); continue;
|
|
31
|
-
}
|
|
32
|
-
op = body.call(thisArg, _);
|
|
33
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
38
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
39
|
-
if (ar || !(i in from)) {
|
|
40
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
41
|
-
ar[i] = from[i];
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
45
|
-
};
|
|
46
1
|
import { existsSync } from 'node:fs';
|
|
47
2
|
import { readFile } from 'node:fs/promises';
|
|
48
3
|
import path from 'node:path';
|
|
49
4
|
import { spawn } from 'node:child_process';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
50
6
|
import { logger } from './logger.js';
|
|
51
|
-
|
|
52
|
-
|
|
7
|
+
const ZOD_SCAFFOLD_VERSION = '^3.23.8';
|
|
8
|
+
const STABLE_SCAFFOLD_PACKAGES = ['@hypequery/clickhouse', '@hypequery/serve', `zod@${ZOD_SCAFFOLD_VERSION}`];
|
|
9
|
+
const CLI_PACKAGE_PATH = fileURLToPath(new URL('../../package.json', import.meta.url));
|
|
10
|
+
const MANUAL_COMMANDS = {
|
|
53
11
|
pnpm: 'pnpm add',
|
|
54
12
|
yarn: 'yarn add',
|
|
55
13
|
npm: 'npm install',
|
|
56
14
|
bun: 'bun add',
|
|
57
15
|
};
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
return Boolean((_b = (_a = pkg.dependencies) === null || _a === void 0 ? void 0 : _a[name]) !== null && _b !== void 0 ? _b : (_c = pkg.devDependencies) === null || _c === void 0 ? void 0 : _c[name]);
|
|
16
|
+
function getDependencyVersion(pkg, name) {
|
|
17
|
+
return pkg.dependencies?.[name] ?? pkg.devDependencies?.[name];
|
|
61
18
|
}
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
19
|
+
function packageNameFromSpecifier(specifier) {
|
|
20
|
+
if (!specifier.startsWith('@')) {
|
|
21
|
+
const atIndex = specifier.lastIndexOf('@');
|
|
22
|
+
return atIndex > 0 ? specifier.slice(0, atIndex) : specifier;
|
|
23
|
+
}
|
|
24
|
+
const separatorIndex = specifier.indexOf('@', specifier.indexOf('/') + 1);
|
|
25
|
+
return separatorIndex === -1 ? specifier : specifier.slice(0, separatorIndex);
|
|
26
|
+
}
|
|
27
|
+
async function readProjectPackageJson() {
|
|
28
|
+
try {
|
|
29
|
+
const file = await readFile(path.join(process.cwd(), 'package.json'), 'utf8');
|
|
30
|
+
return JSON.parse(file);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function readCliPackageJson() {
|
|
37
|
+
try {
|
|
38
|
+
const file = await readFile(CLI_PACKAGE_PATH, 'utf8');
|
|
39
|
+
return JSON.parse(file);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
80
44
|
}
|
|
81
45
|
function detectPackageManager(pkgJson) {
|
|
82
|
-
|
|
83
|
-
var userAgent = (_a = process.env.npm_config_user_agent) !== null && _a !== void 0 ? _a : '';
|
|
46
|
+
const userAgent = process.env.npm_config_user_agent ?? '';
|
|
84
47
|
if (userAgent.includes('pnpm'))
|
|
85
48
|
return 'pnpm';
|
|
86
49
|
if (userAgent.includes('yarn'))
|
|
87
50
|
return 'yarn';
|
|
88
51
|
if (userAgent.includes('bun'))
|
|
89
52
|
return 'bun';
|
|
90
|
-
|
|
53
|
+
const declared = pkgJson?.packageManager ?? '';
|
|
91
54
|
if (declared.startsWith('pnpm'))
|
|
92
55
|
return 'pnpm';
|
|
93
56
|
if (declared.startsWith('yarn'))
|
|
94
57
|
return 'yarn';
|
|
95
58
|
if (declared.startsWith('bun'))
|
|
96
59
|
return 'bun';
|
|
97
|
-
|
|
60
|
+
const cwd = process.cwd();
|
|
98
61
|
if (existsSync(path.join(cwd, 'pnpm-lock.yaml')))
|
|
99
62
|
return 'pnpm';
|
|
100
63
|
if (existsSync(path.join(cwd, 'yarn.lock')))
|
|
@@ -106,75 +69,95 @@ function detectPackageManager(pkgJson) {
|
|
|
106
69
|
function getInstallArgs(manager, packages) {
|
|
107
70
|
switch (manager) {
|
|
108
71
|
case 'pnpm':
|
|
109
|
-
return
|
|
72
|
+
return ['add', ...packages];
|
|
110
73
|
case 'yarn':
|
|
111
|
-
return
|
|
74
|
+
return ['add', ...packages];
|
|
112
75
|
case 'bun':
|
|
113
|
-
return
|
|
76
|
+
return ['add', ...packages];
|
|
114
77
|
case 'npm':
|
|
115
78
|
default:
|
|
116
|
-
return
|
|
79
|
+
return ['install', ...packages];
|
|
117
80
|
}
|
|
118
81
|
}
|
|
119
82
|
function formatManualCommand(manager, packages) {
|
|
120
|
-
return
|
|
83
|
+
return `${MANUAL_COMMANDS[manager]} ${packages.join(' ')}`;
|
|
84
|
+
}
|
|
85
|
+
export function resolveScaffoldPackages(cliVersion, style = 'queries') {
|
|
86
|
+
const includeDatasets = style === 'datasets';
|
|
87
|
+
if (cliVersion?.includes('canary')) {
|
|
88
|
+
return [
|
|
89
|
+
`@hypequery/clickhouse@${cliVersion}`,
|
|
90
|
+
`@hypequery/serve@${cliVersion}`,
|
|
91
|
+
...(includeDatasets ? [`@hypequery/datasets@${cliVersion}`] : []),
|
|
92
|
+
`zod@${ZOD_SCAFFOLD_VERSION}`,
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
return [
|
|
96
|
+
...STABLE_SCAFFOLD_PACKAGES,
|
|
97
|
+
...(includeDatasets ? ['@hypequery/datasets'] : []),
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
function shouldInstallPackage(pkgJson, specifier) {
|
|
101
|
+
const name = packageNameFromSpecifier(specifier);
|
|
102
|
+
const existingVersion = getDependencyVersion(pkgJson, name);
|
|
103
|
+
if (!existingVersion) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
const desiredHasPinnedVersion = specifier.startsWith('@')
|
|
107
|
+
? specifier.indexOf('@', specifier.indexOf('/') + 1) !== -1
|
|
108
|
+
: specifier.includes('@');
|
|
109
|
+
if (!desiredHasPinnedVersion) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
const desiredVersion = specifier.slice(name.length + 1);
|
|
113
|
+
return existingVersion !== desiredVersion;
|
|
121
114
|
}
|
|
122
|
-
export function
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
else {
|
|
160
|
-
reject(new Error("".concat(command, " exited with code ").concat(code)));
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
})];
|
|
164
|
-
case 3:
|
|
165
|
-
_a.sent();
|
|
166
|
-
logger.success("Installed ".concat(missing.join(', ')));
|
|
167
|
-
return [3 /*break*/, 5];
|
|
168
|
-
case 4:
|
|
169
|
-
error_1 = _a.sent();
|
|
170
|
-
logger.warn('Failed to install hypequery packages automatically.');
|
|
171
|
-
logger.info("Run manually: ".concat(formatManualCommand(manager, missing)));
|
|
172
|
-
if (error_1 instanceof Error && error_1.message) {
|
|
173
|
-
logger.info(error_1.message);
|
|
174
|
-
}
|
|
175
|
-
return [3 /*break*/, 5];
|
|
176
|
-
case 5: return [2 /*return*/];
|
|
177
|
-
}
|
|
115
|
+
export async function installScaffoldDependencies(style = 'queries') {
|
|
116
|
+
if (process.env.HYPEQUERY_SKIP_INSTALL === '1') {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const [pkgJson, cliPkgJson] = await Promise.all([
|
|
120
|
+
readProjectPackageJson(),
|
|
121
|
+
readCliPackageJson(),
|
|
122
|
+
]);
|
|
123
|
+
if (!pkgJson) {
|
|
124
|
+
const extra = style === 'datasets' ? ', @hypequery/datasets' : '';
|
|
125
|
+
logger.warn(`package.json not found. Install @hypequery/clickhouse, @hypequery/serve${extra}, and zod manually.`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const requestedPackages = resolveScaffoldPackages(cliPkgJson?.version, style);
|
|
129
|
+
const missing = requestedPackages.filter(pkg => shouldInstallPackage(pkgJson, pkg));
|
|
130
|
+
if (missing.length === 0) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const manager = detectPackageManager(pkgJson);
|
|
134
|
+
const command = manager === 'npm' ? 'npm' : manager;
|
|
135
|
+
const args = getInstallArgs(manager, missing);
|
|
136
|
+
logger.info(`Installing ${missing.join(', ')} with ${manager}...`);
|
|
137
|
+
try {
|
|
138
|
+
await new Promise((resolve, reject) => {
|
|
139
|
+
const child = spawn(command, args, {
|
|
140
|
+
cwd: process.cwd(),
|
|
141
|
+
stdio: 'inherit',
|
|
142
|
+
});
|
|
143
|
+
child.on('error', reject);
|
|
144
|
+
child.on('close', code => {
|
|
145
|
+
if (code === 0) {
|
|
146
|
+
resolve();
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
reject(new Error(`${command} exited with code ${code}`));
|
|
150
|
+
}
|
|
151
|
+
});
|
|
178
152
|
});
|
|
179
|
-
|
|
153
|
+
logger.success(`Installed ${missing.join(', ')}`);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
logger.warn('Failed to install hypequery packages automatically.');
|
|
157
|
+
logger.info(`Run manually: ${formatManualCommand(manager, missing)}`);
|
|
158
|
+
if (error instanceof Error && error.message) {
|
|
159
|
+
logger.info(error.message);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
180
162
|
}
|
|
163
|
+
export const installServeDependencies = installScaffoldDependencies;
|