Skip to content
This repository was archived by the owner on Apr 13, 2025. It is now read-only.

Commit 6201338

Browse files
authored
feat(generate): use nodecg-types in generated bundles (#25)
Refer to codeoverflow-org/nodecg-io#239 for more information about `nodecg-types`. This PR updates the generation logic to generate bundles depending on `nodecg-types` instead of `nodecg` for typings when generating a TypeScript bundle.
1 parent 7458776 commit 6201338

File tree

4 files changed

+19
-32
lines changed

4 files changed

+19
-32
lines changed

src/generate/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export async function genExtension(opts: GenerationOptions, install: ProductionI
4242
genImport(writer, "requireService", opts.corePackage.name, opts.language);
4343

4444
if (opts.language === "typescript") {
45-
genImport(writer, "NodeCG", "nodecg/types/server", opts.language);
45+
genImport(writer, "NodeCG", "nodecg-types/types/server", opts.language);
4646
// Service import statements
4747
services.forEach((svc) => {
4848
genImport(writer, svc.clientName, svc.packageName, opts.language);

src/generate/index.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export const generateModule: CommandModule = {
2929

3030
const opts = await promptGenerationOpts(nodecgDir, install);
3131

32-
await generateBundle(nodecgDir, opts, install);
32+
await generateBundle(opts, install);
3333

3434
logger.success(`Successfully generated bundle ${opts.bundleName}.`);
3535
} catch (e) {
@@ -63,11 +63,7 @@ export function ensureValidInstallation(install: Installation | undefined): inst
6363
return true;
6464
}
6565

66-
export async function generateBundle(
67-
nodecgDir: string,
68-
opts: GenerationOptions,
69-
install: ProductionInstallation,
70-
): Promise<void> {
66+
export async function generateBundle(opts: GenerationOptions, install: ProductionInstallation): Promise<void> {
7167
// Create dir if necessary
7268
if (!(await directoryExists(opts.bundlePath))) {
7369
await fs.promises.mkdir(opts.bundlePath);
@@ -84,7 +80,7 @@ export async function generateBundle(
8480
}
8581

8682
// All of these calls only generate files if they are set accordingly in the GenerationOptions
87-
await genPackageJson(nodecgDir, opts);
83+
await genPackageJson(opts);
8884
await genTsConfig(opts);
8985
await genGitIgnore(opts);
9086
await genExtension(opts, install);

src/generate/packageJson.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { GenerationOptions } from "./prompt";
22
import { logger } from "../utils/log";
3-
import { getNodeCGVersion } from "../utils/nodecgInstallation";
43
import { getLatestPackageVersion } from "../utils/npm";
54
import { genNodeCGDashboardConfig, genNodeCGGraphicConfig } from "./panel";
65
import { SemVer } from "semver";
@@ -17,7 +16,7 @@ type Dependency = [string, string];
1716
* @param nodecgDir the directory in which nodecg is installed
1817
* @param opts the options that the user chose for the bundle.
1918
*/
20-
export async function genPackageJson(nodecgDir: string, opts: GenerationOptions): Promise<void> {
19+
export async function genPackageJson(opts: GenerationOptions): Promise<void> {
2120
const serviceDeps: Dependency[] = opts.servicePackages.map((pkg) => [pkg.name, addSemverCaret(pkg.version)]);
2221

2322
const content = {
@@ -32,7 +31,7 @@ export async function genPackageJson(nodecgDir: string, opts: GenerationOptions)
3231
},
3332
// These scripts are for compiling TS and thus are only needed when generating a TS bundle
3433
scripts: genScripts(opts),
35-
dependencies: Object.fromEntries(await genDependencies(opts, serviceDeps, nodecgDir)),
34+
dependencies: Object.fromEntries(await genDependencies(opts, serviceDeps)),
3635
};
3736

3837
await writeBundleFile(content, opts.bundlePath, "package.json");
@@ -46,12 +45,12 @@ export async function genPackageJson(nodecgDir: string, opts: GenerationOptions)
4645
* @param nodecgDir the directory in which nodecg is installed
4746
* @return the dependencies for a bundle with the given options.
4847
*/
49-
async function genDependencies(opts: GenerationOptions, serviceDeps: Dependency[], nodecgDir: string) {
48+
async function genDependencies(opts: GenerationOptions, serviceDeps: Dependency[]) {
5049
const core = [opts.corePackage.name, addSemverCaret(opts.corePackage.version)];
5150

5251
if (opts.language === "typescript") {
5352
// For typescript we need core, all services (for typings) and special packages like ts itself or node typings.
54-
const deps = [core, ...serviceDeps, ...(await genTypeScriptDependencies(nodecgDir))];
53+
const deps = [core, ...serviceDeps, ...(await genTypeScriptDependencies())];
5554
deps.sort();
5655
return deps;
5756
} else {
@@ -65,16 +64,16 @@ async function genDependencies(opts: GenerationOptions, serviceDeps: Dependency[
6564
* and types for node.
6665
* @param nodecgDir the directory in which nodecg is installed. Used to get nodecg version which will be used by nodecg dependency.
6766
*/
68-
async function genTypeScriptDependencies(nodecgDir: string): Promise<Dependency[]> {
69-
logger.debug("Fetching latest typescript and @types/node versions...");
67+
async function genTypeScriptDependencies(): Promise<Dependency[]> {
68+
logger.debug("Fetching latest nodecg-types, typescript and @types/node versions...");
7069
const [nodecgVersion, latestNodeTypes, latestTypeScript] = await Promise.all([
71-
getNodeCGVersion(nodecgDir),
70+
getLatestPackageVersion("nodecg-types"),
7271
getLatestPackageVersion("@types/node"),
7372
getLatestPackageVersion("typescript"),
7473
]);
7574

7675
return [
77-
["nodecg", addSemverCaret(nodecgVersion)],
76+
["nodecg-types", addSemverCaret(nodecgVersion)],
7877
["@types/node", addSemverCaret(latestNodeTypes)],
7978
["typescript", addSemverCaret(latestTypeScript)],
8079
];

test/generate/index.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
import { vol } from "memfs";
2-
import {
3-
corePkg,
4-
fsRoot,
5-
nodecgPackageJson,
6-
nodecgPackageJsonStr,
7-
twitchChatPkg,
8-
validDevInstall,
9-
validProdInstall,
10-
} from "../test.util";
2+
import { corePkg, fsRoot, nodecgPackageJsonStr, twitchChatPkg, validDevInstall, validProdInstall } from "../test.util";
113
import { SemVer } from "semver";
124
import * as path from "path";
135
import * as installation from "../../src/utils/installation";
@@ -56,29 +48,29 @@ describe("generateBundle", () => {
5648
test("should fail if bundle directory already contains files", async () => {
5749
// Create some file inside the directory in which the bundle would be generated.
5850
await vol.promises.writeFile(packageJsonPath, "");
59-
await expect(generateBundle(fsRoot, defaultOpts, validProdInstall)).rejects.toThrow(
51+
await expect(generateBundle(defaultOpts, validProdInstall)).rejects.toThrow(
6052
"already exists and contains files",
6153
);
6254
});
6355

6456
test("should install dependencies", async () => {
6557
const installMock = jest.spyOn(npm, "runNpmInstall").mockResolvedValue();
66-
await generateBundle(fsRoot, defaultOpts, validProdInstall);
58+
await generateBundle(defaultOpts, validProdInstall);
6759

6860
expect(installMock).toHaveBeenCalled();
6961
expect(installMock).toHaveBeenCalledWith(defaultOpts.bundlePath, false);
7062
});
7163

7264
test("should run build if typescript", async () => {
7365
const buildMock = jest.spyOn(npm, "runNpmBuild").mockClear().mockResolvedValue();
74-
await generateBundle(fsRoot, defaultOpts, validProdInstall);
66+
await generateBundle(defaultOpts, validProdInstall);
7567
expect(buildMock).toHaveBeenCalledTimes(1);
7668
expect(buildMock).toHaveBeenCalledWith(defaultOpts.bundlePath);
7769
});
7870

7971
test("should not run build if javascript", async () => {
8072
const buildMock = jest.spyOn(npm, "runNpmBuild").mockClear().mockResolvedValue();
81-
await generateBundle(fsRoot, jsOpts, validProdInstall);
73+
await generateBundle(jsOpts, validProdInstall);
8274
expect(buildMock).toHaveBeenCalledTimes(0);
8375
});
8476
});
@@ -87,7 +79,7 @@ describe("genPackageJson", () => {
8779
// We don't have a good type for a package.json and this is only testing code so this should be fine.
8880
// eslint-disable-next-line @typescript-eslint/no-explicit-any
8981
async function genPackageJSON(opts: GenerationOptions = defaultOpts): Promise<any> {
90-
await generateBundle(fsRoot, opts, validProdInstall);
82+
await generateBundle(opts, validProdInstall);
9183
const packageJsonStr = await vol.promises.readFile(packageJsonPath);
9284
if (!packageJsonStr) throw new Error("package.json does not exist");
9385
return JSON.parse(packageJsonStr.toString());
@@ -112,12 +104,12 @@ describe("genPackageJson", () => {
112104
test("should have all required typing packages as dependency if typescript", async () => {
113105
const deps = (await genPackageJSON(defaultOpts))["dependencies"];
114106
const e = Object.entries(deps);
115-
expect(e).toEqual(expect.arrayContaining([["nodecg", `^${nodecgPackageJson.version}`]]));
116107
expect(e).toEqual(expect.arrayContaining([[twitchChatPkg.name, `^${twitchChatPkg.version}`]]));
117108

118109
// These dependencies should always have the latest version which is fetched by the mocked getLatestPackageVersion
119110
expect(e).toEqual(expect.arrayContaining([["typescript", `^1.2.3`]]));
120111
expect(e).toEqual(expect.arrayContaining([["@types/node", `^1.2.3`]]));
112+
expect(e).toEqual(expect.arrayContaining([["nodecg-types", `^1.2.3`]]));
121113
});
122114

123115
test("should have build scripts if typescript", async () => {

0 commit comments

Comments
 (0)