Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion labs/playground1/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
result.json
spec-oas3.yaml
.vulcan-debug
.vulcan-debug
dist
6 changes: 1 addition & 5 deletions labs/playground1/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@
.PHONY: install build start pkg-core pkg-build pkg-serve pkg-cli clean pkg-extension-driver-duckdb

# start vulcan server (default goal)
start: install build test-data/moma.db ../../node_modules
start: build test-data/moma.db ../../node_modules
@vulcan start

# install node modules and like playground extensions
install:
@yarn;

# build the required packages
build: pkg-core pkg-build pkg-serve pkg-cli pkg-extension-driver-duckdb

Expand Down
8 changes: 6 additions & 2 deletions labs/playground1/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{
"name": "my-first-vulcan-project",
"dependencies": {
"lodash": "^4.17.21",
"redoc": "^2.0.0-rc.76"
"@vulcan-sql/core": "0.2.0-dev.20220922.0",
"@vulcan-sql/extension-driver-duckdb": "0.2.0-dev.20220919.0",
"@vulcan-sql/serve": "0.2.0-dev.20220922.0"
},
"devDependencies": {
"@vulcan-sql/build": "0.2.0-dev.20220922.0"
}
}
8 changes: 7 additions & 1 deletion labs/playground1/vulcan.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ schema-parser:
document-generator:
specs:
- oas3
folderPath: .
types:
- RESTFUL
extensions:
Expand All @@ -34,3 +33,10 @@ enforce-https:
enabled: false
auth:
enabled: false
response-format:
enabled: true
options:
default: json
formats:
- json
- csv
607 changes: 0 additions & 607 deletions labs/playground1/yarn.lock

This file was deleted.

6 changes: 5 additions & 1 deletion packages/build/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
"outputPath": "dist/packages/build",
"main": "packages/build/src/index.ts",
"tsConfig": "packages/build/tsconfig.lib.json",
"assets": ["packages/build/*.md"],
"assets": [
"packages/build/*.md",
"packages/build/src/models/extensions/packager/assets/**/*",
"packages/build/src/lib/packager/dockerPackager/assets/**/*"
],
"buildableProjectDepsInPackageJsonType": "dependencies"
},
"dependsOn": [
Expand Down
2 changes: 2 additions & 0 deletions packages/build/src/containers/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IBuildOptions } from '@vulcan-sql/build/models';
import {
documentGeneratorModule,
extensionModule,
packagerModule,
schemaParserModule,
} from './modules';

Expand Down Expand Up @@ -32,6 +33,7 @@ export class Container {
);
await this.inversifyContainer.loadAsync(extensionModule(options));
await this.inversifyContainer.loadAsync(documentGeneratorModule());
await this.inversifyContainer.loadAsync(packagerModule());
}

public async unload() {
Expand Down
4 changes: 4 additions & 0 deletions packages/build/src/containers/modules/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { builtInSchemaReader } from '@vulcan-sql/build/schema-parser';
import { ExtensionLoader } from '@vulcan-sql/core';
import { AsyncContainerModule } from 'inversify';
import { builtInSpecGenerator } from '../../lib/document-generator';
import { builtInPackager } from '../../lib/packager';
import { IBuildOptions } from '../../models/buildOptions';

export const extensionModule = (options: IBuildOptions) =>
Expand All @@ -15,5 +16,8 @@ export const extensionModule = (options: IBuildOptions) =>
// Spec generator
loader.loadInternalExtensionModule(builtInSpecGenerator);

// Packager
loader.loadInternalExtensionModule(builtInPackager);

loader.bindExtensions(bind);
});
1 change: 1 addition & 0 deletions packages/build/src/containers/modules/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './schemaParser';
export * from './extension';
export * from './documentGenerator';
export * from './packager';
11 changes: 11 additions & 0 deletions packages/build/src/containers/modules/packager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { AsyncContainerModule, interfaces } from 'inversify';
import { Packager } from '../../models/extensions';
import { TYPES } from '../types';

export const packagerModule = () =>
new AsyncContainerModule(async (bind) => {
// Document generator
bind<interfaces.AutoNamedFactory<Packager>>(
TYPES.Factory_Packager
).toAutoNamedFactory(TYPES.Extension_Packager);
});
3 changes: 3 additions & 0 deletions packages/build/src/containers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ export const TYPES = {
// Document
DocumentGenerator: Symbol.for('DocumentGenerator'),
Factory_SpecGenerator: Symbol.for('Factory_SpecGenerator'),
// Packager
Factory_Packager: Symbol.for('Factory_Packager'),
// Extension
Extension_SchemaReader: Symbol.for('Extension_SchemaReader'),
Extension_SpecGenerator: Symbol.for('Extension_SpecGenerator'),
Extension_Packager: Symbol.for('Extension_Packager'),
};
21 changes: 9 additions & 12 deletions packages/build/src/lib/document-generator/documentGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
import {
APISchema,
ArtifactBuilder,
BuiltInArtifactKeys,
DocumentOptions,
TYPES as CORE_TYPES,
} from '@vulcan-sql/core';
import { inject, injectable, interfaces } from 'inversify';
import { TYPES } from '../../containers/types';
import { SpecGenerator } from '../../models/extensions';
import * as jsYAML from 'js-yaml';
import * as path from 'path';
import { promises as fs } from 'fs';

@injectable()
export class DocumentGenerator {
private specGenerators: SpecGenerator[];
private folderPath: string;
private artifactBuilder: ArtifactBuilder;

constructor(
@inject(TYPES.Factory_SpecGenerator)
specGeneratorFactory: interfaces.AutoNamedFactory<SpecGenerator>,
@inject(CORE_TYPES.DocumentOptions) options: DocumentOptions
@inject(CORE_TYPES.DocumentOptions) options: DocumentOptions,
@inject(CORE_TYPES.ArtifactBuilder) artifactBuilder: ArtifactBuilder
) {
this.specGenerators = [];
for (const spec of options.specs) {
this.specGenerators.push(specGeneratorFactory(spec));
}
this.folderPath = options.folderPath;
this.artifactBuilder = artifactBuilder;
}

public async generateDocuments(schemas: APISchema[]) {
const specs: Record<string, any> = {};
for (const generator of this.specGenerators) {
const spec = generator.getSpec(schemas);
const filePath = path.resolve(
this.folderPath,
`spec-${generator.getExtensionId()}.yaml`
);
await fs.writeFile(filePath, jsYAML.dump(spec), 'utf-8');
specs[generator.getExtensionId()!] = generator.getSpec(schemas);
}
this.artifactBuilder.addArtifact(BuiltInArtifactKeys.Specs, specs);
}
}
19 changes: 19 additions & 0 deletions packages/build/src/lib/packager/dockerPackager/assets/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Use bullseye for glibc > 2.29
FROM node:16-bullseye AS build

# create app directory
WORKDIR /usr/app

# install dependencies
COPY package.json .
RUN npm install --omit=dev

FROM node:16-bullseye-slim
WORKDIR /usr/app
COPY --from=build /usr/app /usr/app
COPY config.json .
COPY index.js .
COPY result.json .
ENV NODE_ENV production

CMD [ "node", "index.js" ]
62 changes: 62 additions & 0 deletions packages/build/src/lib/packager/dockerPackager/dockerPackager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
ArtifactBuilderProviderType,
VulcanExtensionId,
VulcanInternalExtension,
} from '@vulcan-sql/core';
import { IBuildOptions } from '../../../models/buildOptions';
import { Packager, PackagerType } from '../../../models/extensions';
import * as path from 'path';
import { promises as fs } from 'fs';

export interface DockerPackagerConfig {
folderPath?: string;
}

@VulcanExtensionId(PackagerType.Docker)
@VulcanInternalExtension('docker-packager')
export class DockerPackager extends Packager<DockerPackagerConfig> {
private logger = this.getLogger();

public async package(option: IBuildOptions): Promise<void> {
const { folderPath = 'dist' } = this.getConfig() || {};
const distFolder = path.resolve(process.cwd(), folderPath);
await fs.rm(distFolder, { recursive: true, force: true });
await fs.mkdir(distFolder, { recursive: true });
// package.json
await fs.writeFile(
path.resolve(distFolder, 'package.json'),
JSON.stringify(await this.getPackageJson(), null, 4),
'utf-8'
);
// config.json (vulcan config)
await fs.writeFile(
path.resolve(distFolder, 'config.json'),
JSON.stringify(option),
'utf-8'
);
// entrypoint
await fs.writeFile(
path.resolve(distFolder, 'index.js'),
await this.getEntryJS(),
'utf-8'
);
// result.json
if (
option.artifact.provider === ArtifactBuilderProviderType.LocalFile &&
option.artifact.filePath
) {
await fs.copyFile(
path.resolve(process.cwd(), option.artifact.filePath),
path.resolve(distFolder, option.artifact.filePath)
);
}
// Dockerfile
await fs.copyFile(
path.resolve(__dirname, 'assets', 'Dockerfile'),
path.resolve(distFolder, 'Dockerfile')
);
this.logger.info(
`Package successfully, you can go to "${folderPath}" folder and run "docker build ." to build the image.`
);
}
}
1 change: 1 addition & 0 deletions packages/build/src/lib/packager/dockerPackager/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './dockerPackager';
7 changes: 7 additions & 0 deletions packages/build/src/lib/packager/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { DockerPackager } from './dockerPackager';
import { NodePackager } from './nodePackager';

export * from './nodePackager';
export * from './dockerPackager';

export const builtInPackager = [NodePackager, DockerPackager];
57 changes: 57 additions & 0 deletions packages/build/src/lib/packager/nodePackager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {
ArtifactBuilderProviderType,
VulcanExtensionId,
VulcanInternalExtension,
} from '@vulcan-sql/core';
import { IBuildOptions } from '../../models/buildOptions';
import { Packager, PackagerType } from '../../models/extensions';
import * as path from 'path';
import { promises as fs } from 'fs';

export interface NodePackagerConfig {
folderPath?: string;
}

@VulcanExtensionId(PackagerType.Node)
@VulcanInternalExtension('node-packager')
export class NodePackager extends Packager<NodePackagerConfig> {
private logger = this.getLogger();

public async package(option: IBuildOptions): Promise<void> {
const { folderPath = 'dist' } = this.getConfig() || {};
const distFolder = path.resolve(process.cwd(), folderPath);
await fs.rm(distFolder, { recursive: true, force: true });
await fs.mkdir(distFolder, { recursive: true });
// package.json
await fs.writeFile(
path.resolve(distFolder, 'package.json'),
JSON.stringify(await this.getPackageJson(), null, 4),
'utf-8'
);
// config.json (vulcan config)
await fs.writeFile(
path.resolve(distFolder, 'config.json'),
JSON.stringify(option),
'utf-8'
);
// entrypoint
await fs.writeFile(
path.resolve(distFolder, 'index.js'),
await this.getEntryJS(),
'utf-8'
);
// result.json
if (
option.artifact.provider === ArtifactBuilderProviderType.LocalFile &&
option.artifact.filePath
) {
await fs.copyFile(
path.resolve(process.cwd(), option.artifact.filePath),
path.resolve(distFolder, option.artifact.filePath)
);
}
this.logger.info(
`Package successfully, you can go to "${folderPath}" folder and run "npm install && node index.js" to start the server`
);
}
}
24 changes: 21 additions & 3 deletions packages/build/src/lib/vulcanBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { IBuildOptions } from '@vulcan-sql/build/models';
import {
IBuildOptions,
Packager,
PackagerType,
} from '@vulcan-sql/build/models';
import { Container, TYPES } from '@vulcan-sql/build/containers';
import { SchemaParser } from '@vulcan-sql/build/schema-parser';
import {
DataSource,
BuiltInArtifactKeys,
TemplateEngine,
TYPES as CORE_TYPES,
VulcanArtifactBuilder,
getLogger,
} from '@vulcan-sql/core';
import { DocumentGenerator } from './document-generator';
import { interfaces } from 'inversify';

const logger = getLogger({ scopeName: 'BUILD' });

Expand All @@ -18,7 +24,7 @@ export class VulcanBuilder {
this.options = options;
}

public async build() {
public async build(packagerName?: PackagerType | string) {
const container = new Container();
await container.load(this.options);
const schemaParser = container.get<SchemaParser>(TYPES.SchemaParser);
Expand All @@ -44,9 +50,21 @@ export class VulcanBuilder {
const { metadata, templates } = await templateEngine.compile();
const { schemas } = await schemaParser.parse({ metadata });

await artifactBuilder.build({ schemas, templates });
artifactBuilder.addArtifact(BuiltInArtifactKeys.Templates, templates);
artifactBuilder.addArtifact(BuiltInArtifactKeys.Schemas, schemas);

await documentGenerator.generateDocuments(schemas);
await artifactBuilder.build();

// Package
if (packagerName) {
const packagerFactory = container.get<
interfaces.AutoNamedFactory<Packager>
>(TYPES.Factory_Packager);
const packager = packagerFactory(packagerName);
await packager.activate();
await packager.package(this.options);
}

await container.unload();
}
Expand Down
1 change: 1 addition & 0 deletions packages/build/src/models/extensions/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './schemaReader';
export * from './specGenerator';
export * from './packager';
7 changes: 7 additions & 0 deletions packages/build/src/models/extensions/packager/assets/entry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { VulcanServer } = require('@vulcan-sql/serve');
const { getLogger } = require('@vulcan-sql/core');
const logger = getLogger({ scopeName: 'CORE' });
const fs = require('fs');
const config = JSON.parse(fs.readFileSync('config.json', 'utf-8'));
const server = new VulcanServer(config);
server.start().then(() => logger.info('server started'));
Loading