express-tsx
Advanced tools
Comparing version 2.1.4 to 2.2.0
"use strict"; | ||
const ts = require("typescript"); | ||
const path = require("path"); | ||
const express = require("express"); | ||
const fs = require("fs"); | ||
const configExtend = require("config-extend"); | ||
const chokidar = require("chokidar"); | ||
const mkdirp = require("mkdirp"); | ||
exports.defaultOutDir = '.tsx_compile'; | ||
exports.defaultCompilerOptions = { | ||
module: ts.ModuleKind.AMD, | ||
target: ts.ScriptTarget.ES5, | ||
jsx: ts.JsxEmit.React, | ||
sourceMap: true, | ||
outDir: exports.defaultOutDir, | ||
}; | ||
class Shot { | ||
constructor() { | ||
this.version = 0; | ||
this.expired = false; | ||
this.includeFiles = new Set(); | ||
this.version = '1'; | ||
this.expired = true; | ||
} | ||
@@ -15,81 +25,58 @@ } | ||
class Compile { | ||
constructor(compileOptions, rootDir = process.cwd()) { | ||
this.compilerOptions = Compile.defaultCompilerOptions; | ||
this.filesVersion = new Map(); | ||
constructor(options, rootDir = process.cwd()) { | ||
this.compilerOptions = {}; | ||
this.files = new Proxy({}, { | ||
get(target, file) { | ||
file = require.resolve(file); | ||
if (!target[file]) { | ||
target[file] = new Shot(); | ||
} | ||
return target[file]; | ||
}, | ||
}); | ||
this.compile = (file) => { | ||
let shot = this.filesVersion.get(file); | ||
let code; | ||
let expired = true; | ||
if (!shot) { | ||
expired = true; | ||
file = require.resolve(file); | ||
let deps = require.cache[file].children; | ||
let expiredFiles = [file].concat(deps.map(o => o.filename)).filter(Compile.filterFiles).filter(f => this.files[f].expired); | ||
if (expiredFiles.length) { | ||
expiredFiles.forEach(file => { | ||
let outputFiles = this.service.getEmitOutput(file).outputFiles; | ||
outputFiles.forEach(o => { | ||
mkdirp.sync(path.dirname(o.name)); | ||
fs.writeFileSync(o.name, o.text); | ||
}); | ||
let shot = this.files[file]; | ||
shot.expired = false; | ||
shot.outputFile = path.relative(this.compilerOptions.outDir, outputFiles.slice(-1)[0].name); | ||
}); | ||
} | ||
else if (!!Array.from(new Set(shot.includeFiles)).filter(({ expired }) => expired).length) { | ||
expired = true; | ||
} | ||
else { | ||
expired = false; | ||
code = shot.compiledCode; | ||
} | ||
if (expired) { | ||
code = this.service.getEmitOutput(this.file = file).outputFiles[0].text; | ||
if (!shot) { | ||
shot = this.filesVersion.get(file); | ||
} | ||
shot.expired = false; | ||
shot.compiledCode = code; | ||
} | ||
return code; | ||
return this.files[file].outputFile; | ||
}; | ||
let compilerOptions = this.compilerOptions = configExtend(this.compilerOptions, compileOptions); | ||
let { filesVersion } = this; | ||
let defaultLibFileName = ts.getDefaultLibFilePath(this.compilerOptions); | ||
configExtend(this.compilerOptions, Compile.defaultCompilerOptions, options); | ||
let { outDir } = this.compilerOptions; | ||
this.compilerOptions.outDir = path.join(rootDir, outDir); | ||
this.service = ts.createLanguageService({ | ||
getCompilationSettings: () => this.compilerOptions, | ||
getScriptFileNames: () => [this.file], | ||
getScriptVersion: (file) => { | ||
let shot; | ||
if (!filesVersion.has(file)) { | ||
filesVersion.set(file, new Shot()); | ||
shot = filesVersion.get(file); | ||
//add watch | ||
chokidar.watch(file) | ||
.on('change', function () { | ||
shot.version++; | ||
shot.expired = true; | ||
}) | ||
.on('unlink', function () { | ||
this.close(); | ||
filesVersion.delete(file); | ||
}); | ||
} | ||
else { | ||
shot = filesVersion.get(file); | ||
} | ||
let mainShot = filesVersion.get(this.file); | ||
if (mainShot.includeFiles.has(shot)) { | ||
shot.expired = false; | ||
} | ||
else { | ||
mainShot.includeFiles.add(shot); | ||
} | ||
return shot.version.toString(); | ||
}, | ||
getScriptSnapshot: (file) => { | ||
if (!fs.existsSync(file)) { | ||
return undefined; | ||
} | ||
return ts.ScriptSnapshot.fromString(fs.readFileSync(file).toString()); | ||
}, | ||
getScriptFileNames: () => Object.keys(this.files), | ||
getScriptVersion: (file) => this.files[file].version, | ||
getScriptSnapshot: (file) => !fs.existsSync(file) ? undefined : ts.ScriptSnapshot.fromString(fs.readFileSync(file).toString()), | ||
getCurrentDirectory: () => rootDir, | ||
getDefaultLibFileName: (options) => defaultLibFileName | ||
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options) | ||
}); | ||
this.FSWatch = chokidar.watch(rootDir) | ||
.on('change', (file) => { | ||
if (!Reflect.has(this.files, file)) { | ||
return; | ||
} | ||
let shot = this.files[file]; | ||
shot.version = (Number(shot.version) + 1).toString(); | ||
shot.expired = true; | ||
}); | ||
this.middleware = express.static(this.compilerOptions.outDir); | ||
} | ||
} | ||
Compile.defaultCompilerOptions = { | ||
module: ts.ModuleKind.AMD, | ||
target: ts.ScriptTarget.ES5, | ||
jsx: ts.JsxEmit.React, | ||
outFile: 'bundle.js', | ||
}; | ||
Compile.defaultCompilerOptions = exports.defaultCompilerOptions; | ||
Compile.filterFiles = (file) => !(/node_modules/.test(file)); | ||
exports.Compile = Compile; | ||
exports.compile = new Compile(); | ||
//# sourceMappingURL=Compile.js.map |
@@ -10,61 +10,50 @@ "use strict"; | ||
}; | ||
function __export(m) { | ||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; | ||
} | ||
const configExtend = require("config-extend"); | ||
const React = require("react"); | ||
global.React = React; | ||
const path = require("path"); | ||
const ReactDOM = require("react-dom/server"); | ||
const chokidar = require("chokidar"); | ||
const express_1 = require("express"); | ||
const Compile_1 = require("./Compile"); | ||
var Compile_2 = require("./Compile"); | ||
exports.Compile = Compile_2.Compile; | ||
__export(require("./Compile")); | ||
const ssrWrap_1 = require("./ssrWrap"); | ||
class Options { | ||
constructor() { | ||
/**模板热更新 */ | ||
this.hotload = false; | ||
/**文档类型 */ | ||
this.doctype = '<!DOCTYPE html>'; | ||
/**服务器同构渲染 */ | ||
constructor(options) { | ||
this.compile = Compile_1.compile.compile; | ||
this.renderToJSX = React.createElement; | ||
this.ssr = false; | ||
/**编译函数 */ | ||
this.compile = new Compile_1.Compile().compile; | ||
this.ssrRender = (Render, data, filepath, compile) => __awaiter(this, void 0, void 0, function* () { | ||
let app = React.createElement(Render, data); | ||
let appModuleName = path.basename(filepath, path.extname(filepath)); | ||
let appDefineScript = `<script>${yield compile(filepath)}</script>`; | ||
return App_1.WrapApp(ReactDOM.renderToString(app), data, [ | ||
appDefineScript, | ||
App_1.BowserRender(appModuleName, data), | ||
]); | ||
}); | ||
this.path = '/' + Compile_1.defaultOutDir; | ||
this.requirejs = { | ||
paths: { | ||
'react': '//cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react', | ||
'react-dom': '//cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom', | ||
} | ||
}; | ||
this.ssrWrap = ssrWrap_1.ssrWrap; | ||
configExtend(this, options); | ||
this.renderToString = this.ssr ? ReactDOM.renderToString : ReactDOM.renderToStaticMarkup; | ||
} | ||
} | ||
exports.Options = Options; | ||
/**默认配置 */ | ||
exports.defaultOptions = new Options(); | ||
const configExtend = require("config-extend"); | ||
const App_1 = require("./App"); | ||
function render(options = exports.defaultOptions) { | ||
const { hotload, doctype, ssr, compile, ssrRender } = configExtend({}, exports.defaultOptions, options); | ||
return function (filepath, data, cb) { | ||
exports.middleware = express_1.Router(); | ||
function render(options) { | ||
let { renderToJSX, renderToString, ssrWrap, compile, path, requirejs, ssr } = new Options(options); | ||
if (path) { | ||
exports.middleware.use(path, Compile_1.compile.middleware); | ||
} | ||
return (file, data, send) => new Promise(function __express(resolve) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
filepath = require.resolve(filepath); | ||
if (hotload) { | ||
chokidar.watch(filepath).on('change', () => delete require.cache[filepath]); | ||
} | ||
let exports = require(filepath); | ||
let exports = ((file) => require(file))(file); | ||
let Render = exports && exports.default || exports; | ||
let html = doctype; | ||
let body = renderToString(renderToJSX(Render, data)); | ||
if (ssr) { | ||
html += yield ssrRender(Render, data, filepath, compile); | ||
body = ssrWrap(body, path + '/' + compile(file), data, requirejs); | ||
} | ||
else { | ||
html += ReactDOM.renderToStaticMarkup(React.createElement(Render, data)); | ||
} | ||
cb(null, html); | ||
send(null, body); | ||
}); | ||
}; | ||
}) | ||
.catch(send); | ||
} | ||
exports.render = render; | ||
exports.__express = render; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.default = render; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "express-tsx", | ||
"version": "2.1.4", | ||
"version": "2.2.0", | ||
"description": "express view tsx render", | ||
@@ -8,3 +8,4 @@ "main": "lib/index.js", | ||
"chokidar": "^1.6.1", | ||
"config-extend": "^0.1.1" | ||
"config-extend": "^0.1.1", | ||
"mkdirp": "^0.5.1" | ||
}, | ||
@@ -14,3 +15,3 @@ "peerDependencies": { | ||
"express": "^4.15.2", | ||
"typescript": "^2.2.2", | ||
"typescript": "^2.3.2", | ||
"react-dom": "^15.4.2" | ||
@@ -17,0 +18,0 @@ }, |
import ts = require('typescript') | ||
import path = require('path') | ||
import express = require('express') | ||
import fs = require('fs') | ||
import configExtend = require('config-extend') | ||
import chokidar = require('chokidar') | ||
import mkdirp = require('mkdirp') | ||
export let defaultOutDir = '.tsx_compile' | ||
export let defaultCompilerOptions:ts.CompilerOptions = { | ||
module:ts.ModuleKind.AMD, | ||
target:ts.ScriptTarget.ES5, | ||
jsx:ts.JsxEmit.React, | ||
sourceMap:true, | ||
outDir:defaultOutDir, | ||
} | ||
export class Shot { | ||
version:number = 0 | ||
compiledCode?:string | ||
expired?:boolean = false | ||
includeFiles? = new Set<Shot>() | ||
version:string = '1' | ||
outputFile:string | ||
expired:boolean = true | ||
} | ||
export class Compile { | ||
static defaultCompilerOptions:ts.CompilerOptions = { | ||
module:ts.ModuleKind.AMD, | ||
target:ts.ScriptTarget.ES5, | ||
jsx:ts.JsxEmit.React, | ||
outFile:'bundle.js', | ||
} | ||
compilerOptions:ts.CompilerOptions = Compile.defaultCompilerOptions | ||
file:string | ||
filesVersion = new Map<string,Shot>() | ||
service:ts.LanguageService | ||
constructor(compileOptions?:ts.CompilerOptions,rootDir=process.cwd()){ | ||
let compilerOptions = this.compilerOptions = configExtend(this.compilerOptions,compileOptions) | ||
let { filesVersion } = this | ||
let defaultLibFileName = ts.getDefaultLibFilePath(this.compilerOptions) | ||
static defaultCompilerOptions = defaultCompilerOptions | ||
compilerOptions:ts.CompilerOptions = {} | ||
outDir:string | ||
constructor(options?:ts.CompilerOptions,rootDir=process.cwd()){ | ||
configExtend(this.compilerOptions,Compile.defaultCompilerOptions,options) | ||
let { outDir } = this.compilerOptions | ||
this.compilerOptions.outDir = path.join(rootDir,outDir) | ||
this.service = ts.createLanguageService({ | ||
getCompilationSettings:()=>this.compilerOptions, | ||
getScriptFileNames:()=>[this.file], | ||
getScriptVersion:(file)=>{ | ||
let shot:Shot | ||
if(!filesVersion.has(file)){ | ||
filesVersion.set(file,new Shot()) | ||
shot = filesVersion.get(file) | ||
//add watch | ||
chokidar.watch(file) | ||
.on('change',function(){ | ||
shot.version ++ | ||
shot.expired = true | ||
}) | ||
.on('unlink',function(this:chokidar.FSWatcher){ | ||
this.close() | ||
filesVersion.delete(file) | ||
}) | ||
}else{ | ||
shot = filesVersion.get(file) | ||
} | ||
let mainShot = filesVersion.get(this.file) | ||
if(mainShot.includeFiles.has(shot)){ | ||
shot.expired = false | ||
}else{ | ||
mainShot.includeFiles.add(shot) | ||
} | ||
return shot.version.toString() | ||
}, | ||
getScriptSnapshot:(file)=>{ | ||
if(!fs.existsSync(file)){ | ||
return undefined | ||
} | ||
return ts.ScriptSnapshot.fromString(fs.readFileSync(file).toString()) | ||
}, | ||
getScriptFileNames:()=>Object.keys(this.files), | ||
getScriptVersion:(file)=>this.files[file].version, | ||
getScriptSnapshot:(file)=>!fs.existsSync(file)?undefined:ts.ScriptSnapshot.fromString(fs.readFileSync(file).toString()), | ||
getCurrentDirectory:()=>rootDir, | ||
getDefaultLibFileName:(options)=>defaultLibFileName | ||
getDefaultLibFileName:(options)=>ts.getDefaultLibFilePath(options) | ||
}) | ||
this.FSWatch = chokidar.watch(rootDir) | ||
.on('change',(file)=>{ | ||
if(!Reflect.has(this.files,file)){ | ||
return | ||
} | ||
let shot = this.files[file] | ||
shot.version = (Number(shot.version) + 1).toString() | ||
shot.expired = true | ||
}) | ||
this.middleware = express.static(this.compilerOptions.outDir) | ||
} | ||
compile = (file:string):string=>{ | ||
let shot = this.filesVersion.get(file) | ||
let code:string | ||
let expired:boolean = true | ||
if(!shot){ | ||
expired = true | ||
}else if(!!Array.from(new Set(shot.includeFiles)).filter(({expired})=>expired).length){ | ||
expired = true | ||
}else{ | ||
expired = false | ||
code = shot.compiledCode | ||
} | ||
if(expired){ | ||
code = this.service.getEmitOutput(this.file = file).outputFiles[0].text | ||
if(!shot){ | ||
shot = this.filesVersion.get(file) | ||
FSWatch:chokidar.FSWatcher | ||
middleware:express.Handler | ||
service:ts.LanguageService | ||
files = new Proxy({} as {[key:string]:Shot},{ | ||
get(target,file:string){ | ||
file = require.resolve(file) | ||
if(!target[file]){ | ||
target[file] = new Shot() | ||
} | ||
shot.expired = false | ||
shot.compiledCode = code | ||
return target[file] | ||
}, | ||
}) | ||
static filterFiles = (file:string)=>!(/node_modules/.test(file)) | ||
compile:(file:string)=>string = (file)=>{ | ||
file = require.resolve(file) | ||
let deps:NodeModule[] = require.cache[file].children | ||
let expiredFiles = [file].concat(deps.map(o=>o.filename)).filter(Compile.filterFiles).filter(f=>this.files[f].expired) | ||
if(expiredFiles.length){ | ||
expiredFiles.forEach(file=>{ | ||
let outputFiles = this.service.getEmitOutput(file).outputFiles | ||
outputFiles.forEach(o=>{ | ||
mkdirp.sync(path.dirname(o.name)) | ||
fs.writeFileSync(o.name,o.text) | ||
}) | ||
let shot = this.files[file] | ||
shot.expired = false | ||
shot.outputFile = path.relative(this.compilerOptions.outDir,outputFiles.slice(-1)[0].name) | ||
}) | ||
} | ||
return code | ||
return this.files[file].outputFile | ||
} | ||
} | ||
} | ||
export let compile = new Compile() |
@@ -1,59 +0,49 @@ | ||
import React = require('react'); | ||
(global as any).React = React | ||
declare global { | ||
namespace React {} | ||
} | ||
import path = require('path') | ||
import ReactDOM = require('react-dom/server'); | ||
import ts = require('typescript') | ||
import chokidar = require('chokidar') | ||
import { Compile } from "./Compile"; | ||
export { Compile } from "./Compile"; | ||
import configExtend = require('config-extend') | ||
import React = require('react') | ||
import ReactDOM = require('react-dom/server') | ||
import { Router } from "express"; | ||
import { compile as c,defaultOutDir } from "./Compile"; | ||
export * from './Compile' | ||
import { ssrWrap } from "./ssrWrap"; | ||
export class Options { | ||
/**模板热更新 */ | ||
hotload?:boolean = false | ||
/**文档类型 */ | ||
doctype?:string = '<!DOCTYPE html>' | ||
/**服务器同构渲染 */ | ||
constructor(options?:Options){ | ||
configExtend(this,options) | ||
this.renderToString = this.ssr?ReactDOM.renderToString:ReactDOM.renderToStaticMarkup | ||
} | ||
compile:(file:string)=>any = c.compile | ||
renderToJSX?:(Render,data:Object)=>JSX.Element = React.createElement | ||
renderToString?:(jsx)=>string | ||
ssr?:boolean = false | ||
/**编译函数 */ | ||
compile? = new Compile().compile | ||
ssrRender ?= async(Render,data,filepath:string,compile:(filepath:string)=>(Promise<string>|string))=>{ | ||
let app = React.createElement(Render,data) | ||
let appModuleName = path.basename(filepath,path.extname(filepath)) | ||
let appDefineScript = `<script>${await compile(filepath)}</script>` | ||
return WrapApp(ReactDOM.renderToString(app),data,[ | ||
appDefineScript, | ||
BowserRender(appModuleName,data), | ||
]) | ||
path?:string = '/'+defaultOutDir | ||
requirejs?:RequireConfig = { | ||
paths:{ | ||
'react' :'//cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react', | ||
'react-dom' :'//cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom', | ||
} | ||
} | ||
ssrWrap?:(body:string,Render:string,data:Object,requirejs:RequireConfig)=>string = ssrWrap | ||
} | ||
/**默认配置 */ | ||
export let defaultOptions:Options = new Options() | ||
import configExtend = require("config-extend") | ||
import { BowserRender, WrapApp } from './App' | ||
export let middleware = Router() | ||
export function render(options:Options=defaultOptions){ | ||
const { hotload, doctype, ssr, compile, ssrRender }:Options = configExtend({},defaultOptions,options) | ||
return async function(filepath:string, data:any, cb){ | ||
filepath = require.resolve(filepath) | ||
if( hotload ){ | ||
chokidar.watch(filepath).on('change',()=>delete require.cache[filepath]) | ||
} | ||
let exports = require(filepath) | ||
import { join } from 'path' | ||
export function render(options?:Options){ | ||
let { renderToJSX,renderToString,ssrWrap,compile,path,requirejs,ssr } = new Options(options) | ||
if(path){ | ||
middleware.use(path,c.middleware) | ||
} | ||
return (file:string,data:Object,send)=> | ||
new Promise(async function __express(resolve){ | ||
let exports = ((file)=>require(file))(file) | ||
let Render = exports && exports.default || exports | ||
let html:string = doctype | ||
let body = renderToString( renderToJSX(Render,data) ) | ||
if(ssr){ | ||
html += await ssrRender(Render,data,filepath,compile) | ||
}else{ | ||
html += ReactDOM.renderToStaticMarkup( | ||
React.createElement(Render,data) | ||
) | ||
body = ssrWrap(body,path+'/'+compile(file),data,requirejs) | ||
} | ||
cb(null,html) | ||
} | ||
send(null,body) | ||
}) | ||
.catch(send) | ||
} | ||
export let __express = render | ||
export default render |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
29876
20
441
7
6
1
+ Addedmkdirp@^0.5.1
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)