vovk-cli 0.0.1-draft.340 → 0.0.1-draft.341
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/client-templates/cjs/index.cjs.ejs +2 -2
- package/client-templates/ts/index.ts.ejs +1 -1
- package/dist/bundle/index.mjs +12 -0
- package/dist/generate/generate.mjs +5 -1
- package/dist/generate/getTemplateClientImports.mjs +11 -1
- package/dist/generate/writeOneClientFile.d.mts +2 -1
- package/dist/generate/writeOneClientFile.mjs +3 -3
- package/dist/getProjectInfo/getConfig/index.mjs +0 -12
- package/dist/getProjectInfo/getMetaSchema.mjs +1 -1
- package/dist/index.mjs +3 -3
- package/dist/init/createStandardSchemaValidatorFile.d.mts +2 -2
- package/dist/init/createStandardSchemaValidatorFile.mjs +6 -5
- package/dist/init/index.mjs +9 -9
- package/dist/types.d.mts +2 -1
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%- t.getFirstLineBanner() %>
|
|
2
2
|
const { createRPC } = require('<%= t.commonImports.createRPC %>');
|
|
3
3
|
const { schema } = require('./schema.cjs');
|
|
4
|
-
const openapi = require('./openapi.cjs');
|
|
4
|
+
const { openapi } = require('./openapi.cjs');
|
|
5
5
|
const { validateOnClient = null } = <%- t.imports.validateOnClient ? `require('${t.imports.validateOnClient}')` : '{}'%>;
|
|
6
6
|
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment) => { %>
|
|
7
7
|
<% Object.entries(t.segmentMeta[segment.segmentName].reExports).forEach(([reExportWhatCommaDivisible, reExportFrom]) => {
|
|
@@ -12,7 +12,7 @@ exports['<%= reExportWhat.split(/\s+as\s+/)[1] ?? reExportWhat %>'] = require('<
|
|
|
12
12
|
<% Object.keys(segment.controllers).forEach((rpcModuleName) => { %>
|
|
13
13
|
exports.<%= rpcModuleName %> = createRPC(
|
|
14
14
|
schema, '<%= segment.segmentName %>', '<%= rpcModuleName %>', require('<%= t.segmentImports[segment.segmentName].fetcher %>').fetcher,
|
|
15
|
-
{ validateOnClient:
|
|
15
|
+
{ validateOnClient: <%- t.segmentImports[segment.segmentName].validateOnClient ? `require('${t.segmentImports[segment.segmentName].validateOnClient}').validateOnClient` : 'undefined' %>, <%- typeof t.segmentMeta[segment.segmentName].segmentNameOverride === 'string' ? `segmentNameOverride: '${t.segmentMeta[segment.segmentName].segmentNameOverride}', ` : '' %><%- segment.segmentType === 'mixin' ? '' : `apiRoot: '${t.segmentMeta[segment.segmentName].forceApiRoot ?? t.apiRoot}'` %> }
|
|
16
16
|
);
|
|
17
17
|
<% })
|
|
18
18
|
}) %>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { VovkClientFetcher } from 'vovk';
|
|
3
3
|
import { createRPC } from '<%= t.commonImports.module.createRPC %>';
|
|
4
4
|
import { schema } from './schema<%= t.nodeNextResolutionExt.ts %>';
|
|
5
|
-
import { openapi } from './openapi<%= t.nodeNextResolutionExt.
|
|
5
|
+
import { openapi } from './openapi<%= t.nodeNextResolutionExt.ts %>';
|
|
6
6
|
<% Object.values(t.schema.segments).filter((segment) => segment.emitSchema).forEach((segment, i) => { if(segment.segmentType !== 'mixin') { %>
|
|
7
7
|
import type { Controllers as Controllers<%= i %> } from "<%= t.segmentMeta[segment.segmentName].segmentImportPath %>";
|
|
8
8
|
<% }
|
package/dist/bundle/index.mjs
CHANGED
|
@@ -30,6 +30,7 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
|
30
30
|
fullSchema,
|
|
31
31
|
locatedSegments,
|
|
32
32
|
cliGenerateOptions: {
|
|
33
|
+
schemaPath: cliBundleOptions?.schemaPath,
|
|
33
34
|
origin: cliBundleOptions?.origin,
|
|
34
35
|
openapiSpec: cliBundleOptions?.openapiSpec,
|
|
35
36
|
openapiGetModuleName: cliBundleOptions?.openapiGetModuleName,
|
|
@@ -63,6 +64,16 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
|
63
64
|
tsconfig,
|
|
64
65
|
});
|
|
65
66
|
log.debug(`Bundled schema.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
67
|
+
await build({
|
|
68
|
+
entry: path.join(tsFullClientOutAbsoluteDirInput, './openapi.ts'),
|
|
69
|
+
dts: true,
|
|
70
|
+
format: ['cjs'],
|
|
71
|
+
fixedExtension: true,
|
|
72
|
+
outDir: outDirAbsolute,
|
|
73
|
+
clean: false,
|
|
74
|
+
tsconfig,
|
|
75
|
+
});
|
|
76
|
+
log.debug(`Bundled openapi.ts to ${chalkHighlightThing(outDirAbsolute)}`);
|
|
66
77
|
const requiresGroup = groupBy(Object.entries(bundleConfig.requires), ([, relativePath]) => relativePath);
|
|
67
78
|
for (const [relativePath, group] of Object.entries(requiresGroup)) {
|
|
68
79
|
await generate({
|
|
@@ -72,6 +83,7 @@ export async function bundle({ projectInfo, fullSchema, cliBundleOptions, }) {
|
|
|
72
83
|
fullSchema,
|
|
73
84
|
locatedSegments,
|
|
74
85
|
cliGenerateOptions: {
|
|
86
|
+
schemaPath: cliBundleOptions?.schemaPath,
|
|
75
87
|
origin: cliBundleOptions?.origin,
|
|
76
88
|
composedFrom: group.map(([templateName]) => templateName),
|
|
77
89
|
composedOut: path.resolve(outDirAbsolute, relativePath),
|
|
@@ -94,7 +94,9 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
94
94
|
.map((segment) => ({ ...segment }))),
|
|
95
95
|
};
|
|
96
96
|
const { config, cwd, log, srcRoot, vovkCliPackage } = projectInfo;
|
|
97
|
-
Object.entries(config.generatorConfig.segments ?? {})
|
|
97
|
+
Object.entries(config.generatorConfig.segments ?? {})
|
|
98
|
+
.filter(([, segmentConfig]) => segmentConfig.openAPIMixin)
|
|
99
|
+
.forEach(([segmentName, segmentConfig]) => {
|
|
98
100
|
fullSchema.segments = {
|
|
99
101
|
...fullSchema.segments,
|
|
100
102
|
[segmentName]: openAPIToVovkSchema({ ...segmentConfig.openAPIMixin, segmentName }).segments[segmentName],
|
|
@@ -172,6 +174,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
172
174
|
isBundle,
|
|
173
175
|
origin: cliGenerateOptions?.origin ?? origin,
|
|
174
176
|
configKey: 'composedClient',
|
|
177
|
+
cliSchemaPath: cliGenerateOptions?.schemaPath ?? null,
|
|
175
178
|
});
|
|
176
179
|
const outAbsoluteDir = path.resolve(cwd, outCwdRelativeDir);
|
|
177
180
|
return {
|
|
@@ -253,6 +256,7 @@ export async function generate({ isEnsuringClient = false, isBundle = false, pro
|
|
|
253
256
|
isBundle,
|
|
254
257
|
origin: cliGenerateOptions?.origin ?? origin,
|
|
255
258
|
configKey: 'segmentedClient',
|
|
259
|
+
cliSchemaPath: cliGenerateOptions?.schemaPath ?? null,
|
|
256
260
|
});
|
|
257
261
|
return {
|
|
258
262
|
written,
|
|
@@ -2,7 +2,17 @@ import path from 'node:path';
|
|
|
2
2
|
import { getGeneratorConfig } from 'vovk';
|
|
3
3
|
import { ROOT_SEGMENT_FILE_NAME } from '../dev/writeOneSegmentSchemaFile.mjs';
|
|
4
4
|
export default function getTemplateClientImports({ fullSchema, outCwdRelativeDir, segmentName, isBundle, }) {
|
|
5
|
-
const { imports } = getGeneratorConfig({ schema: fullSchema, segmentName, isBundle });
|
|
5
|
+
const { imports: configImports } = getGeneratorConfig({ schema: fullSchema, segmentName, isBundle });
|
|
6
|
+
const validateOnClientImport = configImports?.validateOnClient ?? null;
|
|
7
|
+
const fetcherImport = configImports?.fetcher ?? 'vovk';
|
|
8
|
+
const createRPCImport = configImports?.createRPC ?? 'vovk';
|
|
9
|
+
const imports = {
|
|
10
|
+
fetcher: typeof fetcherImport === 'string' ? [fetcherImport] : fetcherImport,
|
|
11
|
+
validateOnClient: typeof validateOnClientImport === 'string'
|
|
12
|
+
? [validateOnClientImport]
|
|
13
|
+
: (validateOnClientImport ?? null),
|
|
14
|
+
createRPC: typeof createRPCImport === 'string' ? [createRPCImport] : createRPCImport,
|
|
15
|
+
};
|
|
6
16
|
const getImportPath = (p, s = '') => p.startsWith('.') ? path.relative(path.join(outCwdRelativeDir, s), p) : p;
|
|
7
17
|
const clientImports = {
|
|
8
18
|
composedClient: {
|
|
@@ -5,7 +5,7 @@ import type { ClientTemplateFile } from './getClientTemplateFiles.mjs';
|
|
|
5
5
|
import type { Segment } from '../locateSegments.mjs';
|
|
6
6
|
import { OpenAPIObject } from 'openapi3-ts/oas31';
|
|
7
7
|
export declare function normalizeOutTemplatePath(out: string, packageJson: PackageJson): string;
|
|
8
|
-
export default function writeOneClientFile({ cwd, projectInfo, clientTemplateFile, fullSchema, prettifyClient, segmentName, templateContent, matterResult: { data, content }, openapi, package: packageJson, readme, snippets, isEnsuringClient, outCwdRelativeDir, locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, }: {
|
|
8
|
+
export default function writeOneClientFile({ cwd, projectInfo, clientTemplateFile, fullSchema, prettifyClient, segmentName, templateContent, matterResult: { data, content }, openapi, package: packageJson, readme, snippets, isEnsuringClient, outCwdRelativeDir, locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, cliSchemaPath, }: {
|
|
9
9
|
cwd: string;
|
|
10
10
|
projectInfo: ProjectInfo;
|
|
11
11
|
clientTemplateFile: ClientTemplateFile;
|
|
@@ -34,6 +34,7 @@ export default function writeOneClientFile({ cwd, projectInfo, clientTemplateFil
|
|
|
34
34
|
isBundle: boolean;
|
|
35
35
|
origin: string | null;
|
|
36
36
|
configKey: 'composedClient' | 'segmentedClient';
|
|
37
|
+
cliSchemaPath: string | null;
|
|
37
38
|
}): Promise<{
|
|
38
39
|
written: boolean;
|
|
39
40
|
}>;
|
|
@@ -16,7 +16,7 @@ export default async function writeOneClientFile({ cwd, projectInfo, clientTempl
|
|
|
16
16
|
// imports,
|
|
17
17
|
templateContent, matterResult: { data, content }, openapi, package: packageJson, readme, snippets, isEnsuringClient, outCwdRelativeDir,
|
|
18
18
|
// templateDef,
|
|
19
|
-
locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, }) {
|
|
19
|
+
locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage, isBundle, origin, configKey, cliSchemaPath, }) {
|
|
20
20
|
const { config, apiRoot } = projectInfo;
|
|
21
21
|
const { templateFilePath, relativeDir } = clientTemplateFile;
|
|
22
22
|
const locatedSegmentsByName = _.keyBy(locatedSegments, 'segmentName');
|
|
@@ -64,8 +64,8 @@ locatedSegments, isNodeNextResolution, hasMixins, isVovkProject, vovkCliPackage,
|
|
|
64
64
|
mjs: isNodeNextResolution ? '.mjs' : '',
|
|
65
65
|
},
|
|
66
66
|
schemaOutDir: typeof segmentName === 'string'
|
|
67
|
-
? path.relative(path.join(outCwdRelativeDir, segmentName || ROOT_SEGMENT_FILE_NAME), config.schemaOutDir)
|
|
68
|
-
: path.relative(outCwdRelativeDir, config.schemaOutDir),
|
|
67
|
+
? path.relative(path.join(outCwdRelativeDir, segmentName || ROOT_SEGMENT_FILE_NAME), cliSchemaPath ?? config.schemaOutDir)
|
|
68
|
+
: path.relative(outCwdRelativeDir, cliSchemaPath ?? config.schemaOutDir),
|
|
69
69
|
commonImports: getTemplateClientImports({ fullSchema, isBundle, outCwdRelativeDir, segmentName })['composedClient'],
|
|
70
70
|
segmentImports: Object.fromEntries(Object.values(fullSchema.segments).map(({ segmentName: sName }) => {
|
|
71
71
|
const clientImports = getTemplateClientImports({ fullSchema, segmentName: sName, isBundle, outCwdRelativeDir });
|
|
@@ -17,16 +17,6 @@ export default async function getConfig({ configPath, cwd, logLevel, }) {
|
|
|
17
17
|
const env = process.env;
|
|
18
18
|
const clientTemplateDefs = getTemplateDefs(conf.clientTemplateDefs);
|
|
19
19
|
const srcRoot = await getRelativeSrcRoot({ cwd });
|
|
20
|
-
const validateOnClientImport = conf.generatorConfig?.imports?.validateOnClient ?? null;
|
|
21
|
-
const fetcherImport = conf.generatorConfig?.imports?.fetcher ?? 'vovk';
|
|
22
|
-
const createRPCImport = conf.generatorConfig?.imports?.createRPC ?? 'vovk';
|
|
23
|
-
const imports = {
|
|
24
|
-
fetcher: typeof fetcherImport === 'string' ? [fetcherImport] : fetcherImport,
|
|
25
|
-
validateOnClient: typeof validateOnClientImport === 'string'
|
|
26
|
-
? [validateOnClientImport]
|
|
27
|
-
: (validateOnClientImport ?? null),
|
|
28
|
-
createRPC: typeof createRPCImport === 'string' ? [createRPCImport] : createRPCImport,
|
|
29
|
-
};
|
|
30
20
|
const config = {
|
|
31
21
|
$schema: VovkSchemaIdEnum.CONFIG,
|
|
32
22
|
clientTemplateDefs,
|
|
@@ -51,7 +41,6 @@ export default async function getConfig({ configPath, cwd, logLevel, }) {
|
|
|
51
41
|
requires: {
|
|
52
42
|
[BuiltInTemplateName.readme]: '.',
|
|
53
43
|
[BuiltInTemplateName.packageJson]: '.',
|
|
54
|
-
[BuiltInTemplateName.openapiJson]: '.',
|
|
55
44
|
},
|
|
56
45
|
generatorConfig: {},
|
|
57
46
|
...conf.bundle,
|
|
@@ -74,7 +63,6 @@ export default async function getConfig({ configPath, cwd, logLevel, }) {
|
|
|
74
63
|
libs: conf.libs ?? {},
|
|
75
64
|
generatorConfig: {
|
|
76
65
|
...conf.generatorConfig,
|
|
77
|
-
imports,
|
|
78
66
|
origin: (env.VOVK_ORIGIN ?? conf?.generatorConfig?.origin ?? '').replace(/\/$/, ''), // Remove trailing slash
|
|
79
67
|
segments: Object.fromEntries(await Promise.all(Object.entries(conf.generatorConfig?.segments ?? {}).map(async ([key, value]) => [
|
|
80
68
|
key,
|
package/dist/index.mjs
CHANGED
|
@@ -123,8 +123,8 @@ program
|
|
|
123
123
|
.option('--exclude, --exclude-segments <segments...>', 'exclude segments')
|
|
124
124
|
.option('--prebundle-out-dir, --prebundle-out <path>', 'path to output directory for prebundle')
|
|
125
125
|
.option('--keep-prebundle-dir', 'do not delete prebundle directory after bundling')
|
|
126
|
-
.option('--
|
|
127
|
-
.option('--
|
|
126
|
+
.option('--schema, --schema-path <path>', 'path to schema folder (default: .vovk-schema)')
|
|
127
|
+
.option('--config, --config-path <config>', 'path to config file')
|
|
128
128
|
.option('--origin <url>', 'set the origin URL for the generated client')
|
|
129
129
|
.option('--tsconfig <path>', 'path to tsconfig.json for bundling by tsdown')
|
|
130
130
|
.option('--openapi, --openapi-spec <openapi_path_or_urls...>', 'use OpenAPI schema instead of Vovk schema')
|
|
@@ -134,7 +134,7 @@ program
|
|
|
134
134
|
.option('--log-level <level>', 'set the log level')
|
|
135
135
|
.action(async (cliBundleOptions) => {
|
|
136
136
|
const projectInfo = await getProjectInfo({
|
|
137
|
-
configPath: cliBundleOptions.
|
|
137
|
+
configPath: cliBundleOptions.configPath,
|
|
138
138
|
srcRootRequired: false,
|
|
139
139
|
logLevel: cliBundleOptions.logLevel,
|
|
140
140
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function createStandardSchemaValidatorFile({
|
|
2
|
-
|
|
1
|
+
export declare function createStandardSchemaValidatorFile({ root, validationLibrary, }: {
|
|
2
|
+
root: string;
|
|
3
3
|
validationLibrary: 'arktype' | 'valibot';
|
|
4
4
|
}): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
|
-
import getRelativeSrcRoot from '../getProjectInfo/getConfig/getRelativeSrcRoot.mjs';
|
|
3
2
|
import path from 'path';
|
|
3
|
+
import getRelativeSrcRoot from '../getProjectInfo/getConfig/getRelativeSrcRoot.mjs';
|
|
4
4
|
function getCode(validationLibrary) {
|
|
5
5
|
if (validationLibrary === 'valibot') {
|
|
6
6
|
return `
|
|
@@ -29,10 +29,11 @@ export default withArk;
|
|
|
29
29
|
}
|
|
30
30
|
throw new Error(`Unknown validation library: ${validationLibrary}`);
|
|
31
31
|
}
|
|
32
|
-
export async function createStandardSchemaValidatorFile({
|
|
32
|
+
export async function createStandardSchemaValidatorFile({ root, validationLibrary, }) {
|
|
33
33
|
const code = getCode(validationLibrary);
|
|
34
|
-
const srcRoot = (await getRelativeSrcRoot({ cwd })) ?? '.';
|
|
35
|
-
const libDir = path.
|
|
34
|
+
const srcRoot = (await getRelativeSrcRoot({ cwd: root })) ?? '.';
|
|
35
|
+
const libDir = path.resolve(root, srcRoot, 'lib');
|
|
36
|
+
const filePath = path.join(libDir, `${validationLibrary === 'arktype' ? 'withArk' : 'withValibot'}.ts`);
|
|
36
37
|
await fs.mkdir(libDir, { recursive: true });
|
|
37
|
-
await fs.writeFile(
|
|
38
|
+
await fs.writeFile(filePath, code);
|
|
38
39
|
}
|
package/dist/init/index.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import { createStandardSchemaValidatorFile } from './createStandardSchemaValidat
|
|
|
18
18
|
export class Init {
|
|
19
19
|
root;
|
|
20
20
|
log;
|
|
21
|
-
async #init({ configPaths, pkgJson,
|
|
21
|
+
async #init({ configPaths, pkgJson, }, { useNpm, useYarn, usePnpm, useBun, skipInstall, updateTsConfig, updateScripts, validationLibrary, lang, dryRun, channel, }) {
|
|
22
22
|
const { log, root } = this;
|
|
23
23
|
const dependencies = ['vovk', 'vovk-client', 'openapi3-ts', 'vovk-ajv', 'ajv'];
|
|
24
24
|
const devDependencies = ['vovk-cli'];
|
|
@@ -132,7 +132,7 @@ export class Init {
|
|
|
132
132
|
}
|
|
133
133
|
if (validationLibrary === 'valibot' || validationLibrary === 'arktype') {
|
|
134
134
|
createStandardSchemaValidatorFile({
|
|
135
|
-
|
|
135
|
+
root,
|
|
136
136
|
validationLibrary,
|
|
137
137
|
});
|
|
138
138
|
}
|
|
@@ -202,21 +202,21 @@ export class Init {
|
|
|
202
202
|
value: 'class-validator',
|
|
203
203
|
description: 'Use class-validator for data validation',
|
|
204
204
|
},
|
|
205
|
-
{
|
|
206
|
-
name: 'Valibot',
|
|
207
|
-
value: 'valibot',
|
|
208
|
-
description: 'Use valibot for data validation.',
|
|
209
|
-
},
|
|
210
205
|
{
|
|
211
206
|
name: 'ArkType',
|
|
212
207
|
value: 'arktype',
|
|
213
|
-
description: 'Use
|
|
208
|
+
description: 'Use ArkType for data validation.',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: 'Valibot',
|
|
212
|
+
value: 'valibot',
|
|
213
|
+
description: 'Use Valibot for data validation.',
|
|
214
214
|
},
|
|
215
215
|
{ name: 'None', value: null, description: 'Install validation library later' },
|
|
216
216
|
],
|
|
217
217
|
})));
|
|
218
218
|
updateScripts ??= await select({
|
|
219
|
-
message: 'Do you want to update "dev" and "
|
|
219
|
+
message: 'Do you want to update "dev" and add "prebuild" NPM scripts at package.json?',
|
|
220
220
|
default: 'implicit',
|
|
221
221
|
choices: [
|
|
222
222
|
{
|
package/dist/types.d.mts
CHANGED
|
@@ -40,7 +40,8 @@ export interface GenerateOptions {
|
|
|
40
40
|
logLevel?: LogLevelNames;
|
|
41
41
|
}
|
|
42
42
|
export interface BundleOptions extends Partial<Pick<VovkStrictConfig['bundle'], 'prebundleOutDir' | 'keepPrebundleDir' | 'includeSegments' | 'excludeSegments'>> {
|
|
43
|
-
|
|
43
|
+
configPath?: string;
|
|
44
|
+
schemaPath?: string;
|
|
44
45
|
schema?: string;
|
|
45
46
|
outDir?: string;
|
|
46
47
|
origin?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vovk-cli",
|
|
3
|
-
"version": "0.0.1-draft.
|
|
3
|
+
"version": "0.0.1-draft.341",
|
|
4
4
|
"bin": {
|
|
5
5
|
"vovk": "./dist/index.mjs"
|
|
6
6
|
},
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://vovk.dev",
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"vovk": "^3.0.0-draft.
|
|
38
|
+
"vovk": "^3.0.0-draft.406"
|
|
39
39
|
},
|
|
40
40
|
"optionalDependencies": {
|
|
41
41
|
"@rolldown/binding-linux-x64-gnu": "1.0.0-beta.31"
|