Skip to content

Commit

Permalink
feat(workspace-tools): Added the config-schema generator to create js…
Browse files Browse the repository at this point in the history
…on schemas for Storm Config
  • Loading branch information
sullivanpj committed Dec 2, 2023
1 parent 72d9e51 commit 4b66f3c
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 4 deletions.
5 changes: 5 additions & 0 deletions packages/workspace-tools/generators.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
"aliases": ["node-lib"],
"x-type": "library",
"description": "Generate a new node library project in the Storm workspace"
},
"config-schema": {
"factory": "./src/generators/config-schema/generator",
"schema": "./src/generators/config-schema/schema.json",
"description": "Create a Storm JSON schema based on the workspaces project configurations"
}
}
}
9 changes: 8 additions & 1 deletion packages/workspace-tools/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
export * from "./src/base";
export * from "./src/executors/tsup-neutral/executor";
export * from "./src/executors/tsup-neutral/schema.d";
export * from "./src/executors/tsup-node/executor";
export * from "./src/executors/tsup-node/schema.d";
export * from "./src/executors/tsup/executor";
export * from "./src/executors/tsup/schema.d";
export * from "./src/generators/config-schema/generator";
export * from "./src/generators/config-schema/schema.d";
export * from "./src/generators/init/init";
export * from "./src/generators/init/schema.d";
export * from "./src/generators/node-library/generator";
export * from "./src/generators/node-library/schema.d";
export * from "./src/generators/preset/generator";
export * from "./src/generators/preset/schema.d";
export * from "./src/utils/versions";
export * from "./src/utils";
4 changes: 3 additions & 1 deletion packages/workspace-tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
"rollup-plugin-dts": "^6.1.0",
"terser": "^5.24.0",
"tslib": "2.6.2",
"tsup": "8.0.0"
"tsup": "8.0.0",
"zod": "^3.22.4",
"zod-to-json-schema": "^3.22.1"
},
"publishConfig": {
"access": "public"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createTreeWithEmptyWorkspace } from "@nx/devkit/testing";
import { Tree, readProjectConfiguration } from "@nx/devkit";

import { configSchemaGenerator } from "./generator";
import { ConfigSchemaGeneratorSchema } from "./schema";

describe("config-schema generator", () => {
let tree: Tree;
const options: ConfigSchemaGeneratorSchema = { name: "test" };

beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
});

it("should run successfully", async () => {
await configSchemaGenerator(tree, options);
const config = readProjectConfiguration(tree, "test");
expect(config).toBeDefined();
});
});
89 changes: 89 additions & 0 deletions packages/workspace-tools/src/generators/config-schema/generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { formatFiles, ProjectConfiguration, Tree, writeJson } from "@nx/devkit";
import { StormConfigSchema } from "@storm-software/config-tools/schema";
import { existsSync } from "fs";
import { join } from "path";
import * as z from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import { withRunGenerator } from "../../base/base-generator";
import { getProjectConfigurations } from "../../utils/get-project-configurations";
import { getWorkspaceRoot } from "../../utils/get-workspace-root";
import { ConfigSchemaGeneratorSchema } from "./schema";

export type ModuleSchema = {
name: string;
schema: z.ZodObject<any>;
};

export async function configSchemaGeneratorFn(
tree: Tree,
options: ConfigSchemaGeneratorSchema
) {
const schema = {};
const projectConfigurations = getProjectConfigurations<
ProjectConfiguration & { config: any }
>();
const workspaceRoot = getWorkspaceRoot();

const modules = await Promise.all(
Object.keys(projectConfigurations).map(async key => {
if (projectConfigurations[key]?.config) {
const configPath = join(
workspaceRoot,
projectConfigurations[key].config
);
if (existsSync(configPath)) {
const mod = await import(configPath);
if (mod.default) {
return { name: key, schema: mod.default } as ModuleSchema;
}
}
}

return null;
})
);

const workspaceSchema = z.object({
modules: z
.object(
modules
.filter(module => !!module)
.reduce(
(
ret: Record<string, z.ZodObject<any>>,
module: ModuleSchema | null
) => {
if (module?.schema && !ret[module.name]) {
ret[module.name] = module.schema;
}

return ret;
},
{}
)
)
.describe("Configuration of each used extension")
});

const ModulesSchema = z
.union([workspaceSchema, StormConfigSchema])
.describe(
"The values set in the Storm config file. This file is expected to be named `storm.config.js` and be located in the root of the workspace"
);

writeJson(
tree,
options.outputFile
? join(workspaceRoot, options.outputFile)
: join(workspaceRoot, "storm.schema.json"),
zodToJsonSchema(ModulesSchema, "StormConfig")
);
await formatFiles(tree);

return null;
}

export default withRunGenerator<ConfigSchemaGeneratorSchema>(
"Configuration Schema Creator",
configSchemaGeneratorFn
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface ConfigSchemaGeneratorSchema {
outputFile?: string;
}
20 changes: 20 additions & 0 deletions packages/workspace-tools/src/generators/config-schema/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "http://json-schema.org/schema",
"$id": "config-schema",
"title": "Configuration Schema Creator",
"description": "Create a StormConfig JSON schema based on the workspace's project configurations",
"type": "object",
"properties": {
"outputFile": {
"type": "string",
"description": "The file path where the schema json will be written (relative to the workspace root)",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Where should the schema json be written (relative to the workspace root)?",
"default": "{workspaceRoot}/storm.schema.json"
}
},
"required": ["outputFile"]
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"$schema": "http://json-schema.org/schema",
"$id": "NodeLibrary",
"$id": "node-library",
"title": "Add Node Library",
"description": "Create a Storm JSON schema based on the workspace's project configurations",
"type": "object",
"properties": {
"name": {
Expand Down
2 changes: 1 addition & 1 deletion packages/workspace-tools/src/generators/preset/schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/schema",
"$id": "Preset",
"$id": "preset",
"title": "Workspace Preset",
"description": "Create a Storm workspace with all of the required files and recommended packages installed.",
"type": "object",
Expand Down
17 changes: 17 additions & 0 deletions pnpm-lock.yaml

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

0 comments on commit 4b66f3c

Please sign in to comment.