Skip to content

Commit

Permalink
feat: Create definitions for pseudo modules
Browse files Browse the repository at this point in the history
  • Loading branch information
d3xter666 committed Apr 4, 2024
1 parent cd36baf commit b4d8048
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 4 deletions.
78 changes: 77 additions & 1 deletion npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"unit-debug": "ava debug",
"unit-update-snapshots": "ava --update-snapshots",
"unit-watch": "ava --watch",
"update-semantic-model-info": "tsx scripts/metadataProvider/createMetadataInfo.ts"
"update-semantic-model-info": "tsx scripts/metadataProvider/createMetadataInfo.ts",
"update-pseudo-modules-info": "tsx scripts/metadataProvider/createPseudoModulesInfo.ts"
},
"files": [
"CHANGELOG.md",
Expand Down Expand Up @@ -83,6 +84,7 @@
"@types/he": "^1.2.3",
"@types/node": "^20.12.2",
"@types/sinon": "^17.0.3",
"@types/unzip-stream": "^0.3.4",
"@types/yargs": "^17.0.32",
"@ui5-language-assistant/semantic-model": "^3.3.1",
"@ui5-language-assistant/semantic-model-types": "^3.3.1",
Expand All @@ -97,6 +99,7 @@
"semver": "^7.6.0",
"sinon": "^17.0.1",
"tsx": "^4.7.1",
"typescript-eslint": "^7.4.0"
"typescript-eslint": "^7.4.0",
"unzip-stream": "^0.3.1"
}
}
139 changes: 139 additions & 0 deletions scripts/metadataProvider/createPseudoModulesInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {pipeline} from "node:stream/promises";
import {Extract} from "unzip-stream";
import MetadataProvider from "./MetadataProvider.js";
import {writeFile} from "node:fs/promises";

import type {UI5Enum} from "@ui5-language-assistant/semantic-model-types";

const API_JSON_LOCATION = "https://int.repositories.cloud.sap/artifactory/build-releases/com/sap/ui5/dist/sapui5-sdk-dist/{versionPlaceholder}/sapui5-sdk-dist-{versionPlaceholder}-api-jsons.zip";
const RAW_API_JSON_FILES_FOLDER = "tmp/apiJson";

async function downloadAPIJsons(sapui5Version: string) {
const url = API_JSON_LOCATION.replaceAll("{versionPlaceholder}", sapui5Version);

const response = await fetch(url);
if (!response.ok) {
throw new Error(`unexpected response ${response.statusText}`);
}

if (response.body && response.body instanceof ReadableStream) {
await pipeline(response.body, Extract({path: RAW_API_JSON_FILES_FOLDER}));
} else {
throw new Error("Malformed response");
}
}

async function transformFiles() {
const metadataProvider = new MetadataProvider();
await metadataProvider.init(RAW_API_JSON_FILES_FOLDER);

const {enums} = metadataProvider.getModel();

const groupedEnums = Object.keys(enums).reduce((acc: Record<string, UI5Enum[]>, enumKey: string) => {
const curEnum = enums[enumKey];

acc[curEnum.library] = acc[curEnum.library] ?? [];
acc[curEnum.library].push(curEnum);

return acc;
}, Object.create(null));

await addOverrides(groupedEnums);
}

async function addOverrides(enums: Record<string, UI5Enum[]>) {
const indexFilesImports: string[] = [];
const buildJSDoc = (enumEntry: UI5Enum, indent: string = "") => {
const jsDocBuilder: string[] = [`${indent}/**`];

if (enumEntry.description) {
jsDocBuilder.push(`${indent} * ${enumEntry.description.replaceAll("\n", "\n" + indent + " * ")}`);
jsDocBuilder.push(`${indent} *`);
}

if (enumEntry.experimentalInfo) {
let experimental: string = `${indent} * @experimental`;
if (enumEntry.experimentalInfo.since) {
experimental += ` (since ${enumEntry.experimentalInfo.since})`;
}
if (enumEntry.experimentalInfo.text) {
experimental += ` - ${enumEntry.experimentalInfo.text}`;
}
jsDocBuilder.push(experimental);
}

if (enumEntry.deprecatedInfo) {
let deprecated: string = `${indent} * @deprecated`;
if (enumEntry.deprecatedInfo.since) {
deprecated += ` (since ${enumEntry.deprecatedInfo.since})`;
}
if (enumEntry.deprecatedInfo.text) {
deprecated += ` - ${enumEntry.deprecatedInfo.text}`;
}
jsDocBuilder.push(deprecated);
}

if (enumEntry.visibility) {
jsDocBuilder.push(`${indent} * @${enumEntry.visibility}`);
}

if (enumEntry.since) {
jsDocBuilder.push(`${indent} * @since ${enumEntry.since}`);
}
jsDocBuilder.push(`${indent}*/`);

return jsDocBuilder.join("\n");
}

Object.keys(enums).forEach(async (libName) => {
const enumEntries = enums[libName];

let stringBuilder: string[] = [
`declare module "${libName.replaceAll(".", "/")}/library" {`
];
enumEntries.forEach((enumEntry) => {
if (enumEntry.kind !== "UI5Enum") {
return;
}

stringBuilder.push(buildJSDoc(enumEntry, "\t"));
stringBuilder.push(`\texport enum ${enumEntry.name} {`);
enumEntry.fields.forEach((value) => {
stringBuilder.push(buildJSDoc(value, "\t\t"));
stringBuilder.push(`\t\t${value.name} = "${value.name}",`);
});
stringBuilder.push(`\t}`);

return stringBuilder.join("\n");
});
stringBuilder.push(`}`)

indexFilesImports.push(`import "./${libName}";`);
await writeFile(
new URL(`../../resources/overrides/library/${libName}.d.ts`, import.meta.url),
stringBuilder.join("\n")
);
});

await writeFile(
new URL(`../../resources/overrides/library/index.d.ts`, import.meta.url),
indexFilesImports.join("\n")
);
}

async function main(sapui5Version: string) {
await downloadAPIJsons(sapui5Version);

await transformFiles();
}

try {
const sapui5Version = process.argv[2];
if (!sapui5Version) {
throw new Error("second argument \"sapui5Version\" is missing");
}
await main(sapui5Version);
} catch (err) {
process.stderr.write(String(err));
process.exit(1);
}
2 changes: 1 addition & 1 deletion scripts/metadataProvider/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export async function createSemanticModel(apiJsonsRoot: string): Promise<UI5Sema
console.error = () => {};
}
model = generate({
version: "1.120.9",
version: "1.120.11",
libraries: indexJson,
typeNameFix: getTypeNameFix(),
strict: false, // Throw instead of log errors
Expand Down

0 comments on commit b4d8048

Please sign in to comment.