Skip to content

Commit 171970a

Browse files
authored
Merge pull request #199 from yandex-cloud/service-endpoints-map
Endpoints
2 parents d8fe728 + 7ccc975 commit 171970a

File tree

6 files changed

+420
-666
lines changed

6 files changed

+420
-666
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
"webpack-cli": "^5.1.4"
7878
},
7979
"scripts": {
80-
"test": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" node --experimental-vm-modules node_modules/jest/bin/jest.js -c config/jest.ts --passWithNoTests '.*\\.test\\.ts$'",
80+
"test": "npm run cloudapi:generate-services && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" node --experimental-vm-modules node_modules/jest/bin/jest.js -c config/jest.ts --passWithNoTests '.*\\.test\\.ts$'",
8181
"lint": "eslint src config",
8282
"check-endpoints": "ts-node scripts/check-endpoints.ts",
8383
"prettier:fix:clients": "prettier src/clients/ --write",

scripts/check-endpoints.ts

Lines changed: 87 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,106 @@
11
import * as fg from 'fast-glob';
22
import * as path from 'path';
33
import { Namespace, NamespaceBase, Root, Service } from 'protobufjs';
4-
import { SERVICE_ENDPOINTS_LIST } from '../src/service-endpoints';
4+
import SERVICE_ENDPOINTS_MAP from '../src/service-endpoints-map.json';
55

6-
const PROTO_DIR = path.resolve('./cloudapi');
7-
8-
const protoFiles = fg.sync('**/*.proto', { cwd: PROTO_DIR });
9-
10-
const pbRoot = new Root();
11-
12-
pbRoot.resolvePath = (origin, target) => {
13-
const targets = target.split('/');
14-
15-
switch (targets[0]) {
16-
case 'google': {
17-
switch (targets[1]) {
18-
case 'protobuf': {
19-
return `./node_modules/protobufjs/${target}`;
20-
}
21-
default: {
22-
return `./cloudapi/third_party/googleapis/${target}`;
23-
}
24-
}
25-
}
26-
case 'third_party': {
27-
return `./cloudapi/${target}`;
28-
}
29-
case 'yandex': {
30-
return `./cloudapi/${target}`;
31-
}
32-
default: {
33-
return target;
34-
}
35-
}
36-
};
37-
38-
const SERVICES: Service[] = [];
39-
const findServices = <T extends NamespaceBase>(node: T) => {
6+
const detectServices = <T extends NamespaceBase>(
7+
node: T,
8+
onService: (service: Service) => void,
9+
) => {
4010
for (const child of Object.values(node.nested ?? {}).sort((a, b) =>
4111
a.name < b.name ? -1 : a.name === b.name ? 0 : 1,
4212
)) {
4313
if (child instanceof Service) {
44-
SERVICES.push(child);
14+
onService(child);
4515
} else if (child instanceof Namespace) {
46-
findServices(child);
16+
detectServices(child, onService);
4717
}
4818
}
4919
};
5020

51-
pbRoot.load(protoFiles, { alternateCommentMode: true }).then((loadedRoot) => {
52-
const SERVICE_IDS = new Set<string>();
53-
let hasMissing = false;
21+
const newProtobufjsRoot = () => {
22+
const pbRoot = new Root();
23+
24+
pbRoot.resolvePath = (_origin, target) => {
25+
const targets = target.split('/');
5426

55-
for (const serviceEndpoint of SERVICE_ENDPOINTS_LIST) {
56-
for (const service of serviceEndpoint.serviceIds) {
57-
SERVICE_IDS.add(service);
27+
switch (targets[0]) {
28+
case 'google': {
29+
switch (targets[1]) {
30+
case 'protobuf': {
31+
return `./node_modules/protobufjs/${target}`;
32+
}
33+
default: {
34+
return `./cloudapi/third_party/googleapis/${target}`;
35+
}
36+
}
37+
}
38+
case 'third_party': {
39+
return `./cloudapi/${target}`;
40+
}
41+
case 'yandex': {
42+
return `./cloudapi/${target}`;
43+
}
44+
default: {
45+
return target;
46+
}
5847
}
59-
}
48+
};
49+
50+
return pbRoot;
51+
};
52+
53+
const main = () => {
54+
const PROTO_DIR = path.resolve('./cloudapi');
55+
const protoFiles = fg.sync('**/*.proto', { cwd: PROTO_DIR });
56+
57+
const pbRoot = newProtobufjsRoot();
58+
59+
const SERVICES: Service[] = [];
60+
const findServices = <T extends NamespaceBase>(node: T) => {
61+
detectServices(node, (service) => SERVICES.push(service));
62+
};
63+
64+
pbRoot.load(protoFiles, { alternateCommentMode: true }).then((loadedRoot) => {
65+
const SERVICE_IDS = new Set<string>();
66+
let hasMissing = false;
67+
68+
const map = SERVICE_ENDPOINTS_MAP as Record<string, string>;
69+
70+
Object.keys(map).forEach((service) => SERVICE_IDS.add(service));
71+
72+
findServices(loadedRoot);
73+
console.log('Missing services:');
74+
for (const s of SERVICES) {
75+
// full name without leading dot
76+
const fullName = s.fullName.slice(1);
6077

61-
findServices(loadedRoot);
62-
console.log('Missing services:');
63-
for (const s of SERVICES) {
64-
// full name without leading dot
65-
const fullName = s.fullName.slice(1);
78+
if (!SERVICE_IDS.has(fullName)) {
79+
console.log(fullName);
80+
hasMissing = true;
81+
}
82+
}
6683

67-
if (!SERVICE_IDS.has(fullName)) {
68-
console.log(fullName);
69-
hasMissing = true;
84+
if (hasMissing) {
85+
process.exit(1);
7086
}
71-
}
87+
});
88+
};
7289

73-
if (hasMissing) {
74-
process.exit(1);
75-
}
76-
});
90+
if (require.main === module) {
91+
main();
92+
}
93+
94+
export const getServiceList = async () => {
95+
const PROTO_DIR = path.resolve('./cloudapi');
96+
const protoFiles = fg.sync('**/*.proto', { cwd: PROTO_DIR });
97+
98+
const pbRoot = newProtobufjsRoot();
99+
100+
const serviceList: Service[] = [];
101+
102+
return pbRoot.load(protoFiles, { alternateCommentMode: true }).then((loadedRoot) => {
103+
detectServices(loadedRoot, (service) => serviceList.push(service));
104+
return serviceList;
105+
});
106+
};

scripts/generate_services/index.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import * as fs from 'fs';
22
import * as PATH from 'path';
33
import * as fg from 'fast-glob';
44
import { detectRootServices, writeToFile } from '../detect_services';
5+
import * as cp from 'child_process';
56

67
import { promisify } from 'node:util';
78
import child_process from 'node:child_process';
89

910
import { generateServiceName } from '../common';
11+
import { getServiceList } from '../check-endpoints';
1012

1113
const exec = promisify(child_process.exec);
1214

@@ -79,12 +81,9 @@ const addReExports = async (
7981
fs.writeFileSync(indexModulePath, indexModuleContent, 'utf8');
8082
};
8183

82-
const generateCloudApi = () => {
83-
const YA_PROTO_DIR = PATH.join(PROTO_DIR, 'yandex');
84+
const generateCloudApi = (protoFiles: string[]) => {
8485
const GENERATED_CODE_DIR = PATH.resolve('./src/generated');
8586

86-
const protoFiles = fg.sync('**/*.proto', { cwd: YA_PROTO_DIR, absolute: true });
87-
8887
const commandArgs = [
8988
'npx --no-install grpc_tools_node_protoc',
9089
`--ts_proto_out=${GENERATED_CODE_DIR}`,
@@ -146,12 +145,39 @@ const modifyPackageJSON = async (serviceDirList: string[]) => {
146145
fs.writeFileSync(path, JSON.stringify(jsonData, replacer, 2) + '\n', 'utf8');
147146
};
148147

148+
const generateServiceEndpointsMap = async () => {
149+
const serviceList = await getServiceList();
150+
151+
const filePath = PATH.resolve('./src/service-endpoints-map.json');
152+
const data = fs.readFileSync(filePath, 'utf8');
153+
const jsonData = JSON.parse(data) as Record<string, string>;
154+
155+
serviceList.forEach((s) => {
156+
// full name without leading dot
157+
const serviceName = s.fullName.slice(1);
158+
jsonData[serviceName] = jsonData[serviceName] || '';
159+
});
160+
161+
fs.writeFile(filePath, JSON.stringify(jsonData, undefined, 2), 'utf8', (err) => {
162+
if (err !== null) {
163+
throw err;
164+
}
165+
166+
const configPath = PATH.resolve('./.prettierrc.js');
167+
const comand = `npx --no-install prettier ${filePath} --write --config ${configPath}`;
168+
cp.execSync(comand);
169+
});
170+
};
171+
149172
const main = async () => {
150173
const serviceMap = await detectRootServices(YANDEX_CLOUD_DIR);
151174

152175
writeToFile(serviceMap);
153176

154-
await generateCloudApi();
177+
const YA_PROTO_DIR = PATH.join(PROTO_DIR, 'yandex');
178+
const protoFiles = fg.sync('**/*.proto', { cwd: YA_PROTO_DIR, absolute: true });
179+
180+
await Promise.all([generateCloudApi(protoFiles), generateServiceEndpointsMap()]);
155181

156182
const clientPromiseList = Object.keys(serviceMap).map(generateClient);
157183
const serviceDirList = await Promise.all(clientPromiseList);

0 commit comments

Comments
 (0)