Commit 7af7dd12 authored by Bradley Hilton's avatar Bradley Hilton

First incomplete commit

parents
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# 4 space indentation
[**.*]
indent_style = space
indent_size = 4
{
"extends": "eslint:recommended",
"env": {
"browser": false,
"commonjs": true,
"es6": true,
"node": true
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"sourceType": "module"
},
"rules": {
"semi": ["error", "always"],
"no-console": "off"
}
}
# Created by https://www.gitignore.io/api/node
### Node ###
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
### Typings ###
## Ignore downloaded typings
/typings
## Ignore distribution folder
dist/
# Rocketlets Server
The core server piece which manages and controls everything.
const gulp = require('gulp');
const del = require('del');
const sourcemaps = require('gulp-sourcemaps');
const tsc = require('gulp-typescript');
const shell = require('gulp-shell');
const spawn = require('child_process').spawn;
const tsp = tsc.createProject('tsconfig.json');
gulp.task('clean-generated', function _cleanTypescript() {
const distFiles = ['./dist/**/*.*'];
return del(distFiles);
});
gulp.task('compile-ts', ['clean-generated'], function _compileTypescript() {
return tsp.src().pipe(sourcemaps.init())
.pipe(tsp())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist'));
});
let server;
gulp.task('run-server', ['compile-ts'], function _runTheServer() {
if (server) server.kill();
server = spawn('node', ['server.js'], { stdio: 'inherit' });
server.on('close', (code) => {
if (code === 8) {
gulp.log('Error detected, waiting for changes....');
}
});
});
process.on('exit', () => {
if (server) server.kill();
});
gulp.task('defult', ['compile-ts', 'run-server'], function _watchCodeAndRun() {
gulp.watch('src/**/*.ts', ['compile-ts', 'run-server']);
});
//Tasks for getting it ready and publishing
gulp.task('npm-files', function _npmFileGathering() {
return gulp.src(['README.md', 'LICENSE', 'package.json']).pipe(gulp.dest('dist'));
});
gulp.task('pack', ['clean-generated', 'compile-ts', 'npm-files'], shell.task([
'cd dist && npm pack'
]));
gulp.task('publish', ['clean-generated', 'compile-ts', 'npm-files'], shell.task([
'cd dist && npm publish && npm pack'
]));
This diff is collapsed.
{
"name": "temporary-rocketlets-server",
"version": "0.0.1",
"description": "Temporary location for the server's piece for the Rocketlets, it manages, runs, translates, and coordinates and all of that.",
"main": "index.js",
"typings": "index",
"keywords": [
"rocketlets",
"rocket.chat"
],
"author": "Bradley Hilton <bradley.hilton@rocket.chat>",
"license": "MIT",
"devDependencies": {
"@types/node": "^8.0.7",
"del": "^3.0.0",
"eslint": "^4.1.1",
"gulp": "^3.9.1",
"gulp-shell": "^0.6.3",
"gulp-sourcemaps": "^2.6.0",
"gulp-tslint": "^8.1.1",
"gulp-typescript": "^3.1.7"
},
"dependencies": {
"temporary-rocketlets-ts-definition": "^0.5.3",
"typescript": "^2.4.1"
}
}
import { ICompilerFile } from './interfaces';
import * as fs from 'fs';
import * as path from 'path';
import { Rocketlet } from 'temporary-rocketlets-ts-definition/Rocketlet';
import * as ts from 'typescript';
import * as vm from 'vm';
export class RocketletCompiler {
private readonly compilerOptions: ts.CompilerOptions;
private libraryFiles: { [s: string]: ICompilerFile };
constructor() {
this.compilerOptions = {
target: ts.ScriptTarget.ES2016,
module: ts.ModuleKind.CommonJS,
moduleResolution: ts.ModuleResolutionKind.NodeJs,
declaration: false,
noImplicitAny: false,
removeComments: true,
noImplicitReturns: true,
experimentalDecorators: true,
emitDecoratorMetadata: true,
};
this.libraryFiles = {};
}
public getLibraryFile(fileName: string): ICompilerFile {
if (!fileName.endsWith('.d.ts')) {
return undefined;
}
const norm = path.normalize(fileName);
if (this.libraryFiles[norm]) {
return this.libraryFiles[norm];
}
if (!fs.existsSync(fileName)) {
return undefined;
}
this.libraryFiles[norm] = {
content: fs.readFileSync(fileName).toString(),
version: 0,
};
return this.libraryFiles[norm];
}
public linttTs(source: string): void {
throw new Error('Not implemented yet.');
}
public toJs(source: string): any {
const files: { [s: string]: ICompilerFile } = {
'rocketlet.ts': {
version: 0,
content: source,
},
};
const host: ts.LanguageServiceHost = {
getScriptFileNames: () => Object.keys(files),
getScriptVersion: (fileName) => {
fileName = path.normalize(fileName);
return files[fileName] && files[fileName].version.toString();
},
getScriptSnapshot: (fileName) => {
fileName = path.normalize(fileName);
const file = files[fileName] || this.getLibraryFile(fileName);
if (!file || !file.content) {
return;
}
return ts.ScriptSnapshot.fromString(file.content);
},
getCompilationSettings: () => this.compilerOptions,
getCurrentDirectory: () => process.cwd(),
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(this.compilerOptions),
};
const languageService = ts.createLanguageService(host, ts.createDocumentRegistry());
// const dia = languageService.getProgram().getGlobalDiagnostics();
const dia = languageService.getCompilerOptionsDiagnostics();
if (dia.length !== 0) {
return {
success: false,
others: dia,
};
}
function logErrors(fileName: string) {
const allDiagnostics = languageService.getCompilerOptionsDiagnostics()
.concat(languageService.getSyntacticDiagnostics(fileName))
.concat(languageService.getSemanticDiagnostics(fileName));
allDiagnostics.forEach((diagnostic) => {
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
if (diagnostic.file) {
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
} else {
console.log(` Error: ${message}`);
}
});
}
const checker = languageService.getProgram().getTypeChecker();
const src = languageService.getProgram().getSourceFile('rocketlet.ts');
ts.forEachChild(src, (n) => {
if (n.kind === ts.SyntaxKind.ClassDeclaration) {
ts.forEachChild(n, (node) => {
if (node.kind === ts.SyntaxKind.HeritageClause) {
const e = node as ts.HeritageClause;
if (e.token === ts.SyntaxKind.ImplementsKeyword) {
console.log('Implements the following:');
} else if (e.token === ts.SyntaxKind.ExtendsKeyword) {
console.log('Extends the following:');
}
ts.forEachChild(node, (nn) => {
// console.log(ts.SyntaxKind[nn.kind]);
console.log(nn.getText());
});
}
});
// console.log(n);
// const sym = checker.getSymbolAtLocation((n as ts.ClassDeclaration).name);
// console.log(sym);
}
});
const output = languageService.getEmitOutput('rocketlet.ts');
if (output.emitSkipped) {
console.log('Emitting failed...');
logErrors('rocketlet.ts');
}
output.outputFiles.forEach((o) => console.log(o.name, 'output is:', o.text));
// const result = ts.transpileModule(source, { compilerOptions: this.compilerOptions });
// TODO: implement the `ts.createProject` so that we get `result.diagnostics`
// return result.outputText;
return {
success: true,
};
}
public toSandBox(js: string): Rocketlet {
const script = new vm.Script(js);
const context = vm.createContext({ require, exports });
const result = script.runInContext(context);
if (typeof result !== 'function') {
throw new Error('The provided script is not valid.');
}
const rl = new result();
if (!(rl instanceof Rocketlet)) {
throw new Error('The script must extend BaseRocketlet.');
}
if (typeof rl.getName !== 'function') {
throw new Error ('The Rocketlet doesn\'t have a `getName` function, this is required.');
}
if (typeof rl.getVersion !== 'function') {
throw new Error ('The Rocketlet doesn\'t have a `getVersion` function, this is required.');
}
if (typeof rl.getID !== 'function') {
throw new Error ('The Rocketlet doesn\'t have a `getID` function, this is required.');
}
if (typeof rl.getDescription !== 'function') {
throw new Error ('The Rocketlet doesn\'t have a `getDescription` function, this is required.');
}
if (typeof rl.getRequiredApiVersion !== 'function') {
throw new Error ('The Rocketlet doesn\'t have a `getRequiredApiVersion` function, this is required.');
}
return rl as Rocketlet;
}
}
import { RocketletCompiler } from './compiler';
import { RocketletManager} from './manager';
export { RocketletCompiler, RocketletManager };
export interface ICompilerFile {
content: string;
version: number;
}
export interface IGetRocketletsFilter {
ids?: Array<number>;
name?: string | RegExp;
count?: number;
enabled?: boolean;
disabled?: boolean;
}
import { ICompilerFile } from './ICompilerFile';
import { IGetRocketletsFilter } from './IGetRocketletsFilter';
export { ICompilerFile, IGetRocketletsFilter};
import { RocketletCompiler } from './compiler';
import { IGetRocketletsFilter } from './interfaces';
import * as fs from 'fs';
import * as path from 'path';
import { Rocketlet } from 'temporary-rocketlets-ts-definition/Rocketlet';
import * as ts from 'typescript';
import * as vm from 'vm';
export class RocketletManager {
private readonly activeRocketlets: Map<number, Rocketlet>;
private readonly inactiveRocketlets: Map<number, Rocketlet>;
private readonly compiler: RocketletCompiler;
constructor(public folder: string) {
this.activeRocketlets = new Map<number, Rocketlet>();
this.inactiveRocketlets = new Map<number, Rocketlet>();
this.compiler = new RocketletCompiler();
console.log('Constructed the RocketletLoader and the src folder is:', this.folder);
}
public getCompiler(): RocketletCompiler {
return this.compiler;
}
public load(): Promise<Array<Rocketlet>> {
return new Promise((resolve, reject) => {
if (this.folder === '') {
return reject(new Error('Invalid source folder for loading Rocketlets from.'));
}
try {
fs.readdirSync(this.folder).forEach((file) => {
const filePath = path.join(this.folder, file);
// Verify it's a typescript file
if (!file.endsWith('.ts')) {
return;
}
// Verify it is actually a file
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
return;
}
const src = this.getCompiler().toJs(fs.readFileSync(filePath, 'utf8'));
console.log('toJs result:', src);
// const rocketlet = this.getCompiler().toSandBox(src);
// console.log(`Successfully loaded ${rocketlet.getName()}!`);
});
} catch (e) {
return reject(e);
}
// TODO: Combine the two maps values
return new Array<Rocketlet>();
});
}
public get(filter: IGetRocketletsFilter): Array<Rocketlet> {
throw new Error('Not implemented yet.');
}
public enable(id: number): boolean {
throw new Error('Not implemented yet.');
}
public disable(id: number): boolean {
throw new Error('Not implemented yet.');
}
// TODO: Determine what to do with this - add or addRocketlet?
public addRocketlet(source: string): Rocketlet {
throw new Error('Not implemented nor architected.');
}
// TODO: Determine what to do with this - add or addRocketlet?
public removeRocketlet(id: number): Rocketlet {
throw new Error('Not implemented nor architected.');
}
}
{
"compileOnSave": false,
"compilerOptions": {
"sourceMap": true,
"target": "es5",
"module": "commonjs",
"declaration": true,
"noImplicitAny": false,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"lib": ["es2017", "dom"],
"outDir": "dist"
},
"exclude": [
"node_modules",
"dist",
"examples"
],
"atom": {
"rewriteTsconfig": false
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment