UNPKG

8.68 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const fs = require("fs-extra");
4const path = require("path");
5const ts = require("typescript");
6const bearer_state_injector_1 = require("./transformers/bearer-state-injector");
7const component_tag_name_scoping_1 = require("./transformers/component-tag-name-scoping");
8const gather_metadata_1 = require("./transformers/gather-metadata");
9const imports_transformer_1 = require("./transformers/imports-transformer");
10const navigator_screen_transformer_1 = require("./transformers/navigator-screen-transformer");
11const prop_bearer_context_injector_1 = require("./transformers/prop-bearer-context-injector");
12const prop_importer_1 = require("./transformers/prop-importer");
13const prop_injector_1 = require("./transformers/prop-injector");
14const reference_id_injector_1 = require("./transformers/reference-id-injector");
15const replace_intent_decorator_1 = require("./transformers/replace-intent-decorator");
16const root_component_transformer_1 = require("./transformers/root-component-transformer");
17const scenario_id_accessor_injector_1 = require("./transformers/scenario-id-accessor-injector");
18const utils_1 = require("./utils");
19class Transpiler {
20 constructor(options) {
21 this.rootFileNames = [];
22 this.subscribers = {};
23 this.watchFiles = true;
24 this.buildFolder = '.bearer/views';
25 this.srcFolder = 'views';
26 this.verbose = true;
27 this.files = {};
28 this.metadata = {
29 components: []
30 };
31 this.compilerOptions = {
32 module: ts.ModuleKind.CommonJS
33 };
34 this.emitFiles = () => {
35 // Now let's watch the files
36 this.rootFileNames.forEach(fileName => {
37 this.files[fileName] = { version: 0 };
38 // First time around, emit all files
39 this.emitFile(fileName);
40 if (this.watchFiles) {
41 // Add a watch on the file to handle next change
42 fs.watchFile(fileName, { persistent: true, interval: 250 }, (curr, prev) => {
43 // Check timestamp
44 if (+curr.mtime <= +prev.mtime) {
45 return;
46 }
47 // Update the version to signal a change in the file
48 this.files[fileName].version++;
49 // write the changes to disk
50 this.emitFile(fileName);
51 });
52 }
53 });
54 };
55 this.emitFile = (fileName) => {
56 const output = this.service.getEmitOutput(fileName);
57 if (!output.emitSkipped) {
58 if (this.verbose) {
59 console.log(`Emitting ${fileName}`);
60 }
61 }
62 else {
63 console.log(`Emitting ${fileName} failed`);
64 this.logErrors(fileName);
65 }
66 };
67 this.trigger = (eventName) => {
68 const subscribers = this.subscribers[eventName] || [];
69 subscribers.forEach(callback => {
70 callback();
71 });
72 };
73 Object.assign(this, options);
74 this.ROOT_DIRECTORY = this.ROOT_DIRECTORY || process.cwd();
75 if (options.tagNamePrefix) {
76 this.metadata.prefix = options.tagNamePrefix;
77 }
78 if (options.tagNameSuffix) {
79 this.metadata.suffix = options.tagNameSuffix;
80 }
81 }
82 get transformers() {
83 const verbose = true;
84 return {
85 before: [
86 gather_metadata_1.default({
87 verbose,
88 metadata: this.metadata,
89 outDir: this.BUILD_SRC_DIRECTORY,
90 srcDir: this.ROOT_DIRECTORY
91 }),
92 root_component_transformer_1.default({ verbose, metadata: this.metadata }),
93 reference_id_injector_1.default({ verbose, metadata: this.metadata }),
94 replace_intent_decorator_1.default({ verbose, metadata: this.metadata }),
95 scenario_id_accessor_injector_1.default({ verbose, metadata: this.metadata }),
96 prop_importer_1.default({ verbose, metadata: this.metadata }),
97 prop_injector_1.default({ verbose, metadata: this.metadata }),
98 prop_bearer_context_injector_1.default({ verbose, metadata: this.metadata }),
99 bearer_state_injector_1.default({ verbose, metadata: this.metadata }),
100 navigator_screen_transformer_1.default({ verbose, metadata: this.metadata }),
101 imports_transformer_1.default({ verbose, metadata: this.metadata }),
102 component_tag_name_scoping_1.default({ verbose, metadata: this.metadata }),
103 dumpSourceCode({
104 verbose,
105 srcDirectory: this.VIEWS_DIRECTORY,
106 buildDirectory: this.BUILD_SRC_DIRECTORY
107 })
108 ],
109 after: []
110 };
111 }
112 get BUILD_DIRECTORY() {
113 return path.join(this.ROOT_DIRECTORY, this.buildFolder);
114 }
115 get BUILD_SRC_DIRECTORY() {
116 return path.join(this.BUILD_DIRECTORY, 'src');
117 }
118 get VIEWS_DIRECTORY() {
119 return path.join(this.ROOT_DIRECTORY, this.srcFolder);
120 }
121 run() {
122 this.refresh();
123 if (!this.watchFiles) {
124 this.stop();
125 }
126 }
127 refresh() {
128 this.clearWatchers();
129 const config = ts.readConfigFile(path.join(this.BUILD_DIRECTORY, 'tsconfig.json'), ts.sys.readFile);
130 if (config.error) {
131 throw new Error(config.error.messageText);
132 }
133 const parsed = ts.parseJsonConfigFileContent(config, ts.sys, this.VIEWS_DIRECTORY);
134 this.rootFileNames = parsed.fileNames;
135 if (!this.rootFileNames.length) {
136 console.warn('[BEARER]', 'No file to transpile');
137 }
138 const servicesHost = {
139 getScriptFileNames: () => this.rootFileNames,
140 getScriptVersion: fileName => this.files[fileName] && this.files[fileName].version.toString(),
141 getScriptSnapshot: fileName => {
142 if (!fs.existsSync(fileName)) {
143 return null;
144 }
145 return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString());
146 },
147 getCurrentDirectory: () => process.cwd(),
148 getCompilationSettings: () => this.compilerOptions,
149 getDefaultLibFileName: options => ts.getDefaultLibFilePath(options),
150 getCustomTransformers: () => this.transformers,
151 fileExists: ts.sys.fileExists,
152 readFile: ts.sys.readFile,
153 readDirectory: ts.sys.readDirectory
154 };
155 // Create the language service files
156 this.service = ts.createLanguageService(servicesHost, ts.createDocumentRegistry());
157 this.emitFiles();
158 }
159 stop() {
160 this.clearWatchers();
161 this.trigger('STOP');
162 }
163 clearWatchers() {
164 this.rootFileNames.forEach(fileName => {
165 fs.unwatchFile(fileName);
166 });
167 }
168 on(event, callback) {
169 this.subscribers[event] = this.subscribers[event] || [];
170 this.subscribers[event].push(callback);
171 }
172 logErrors(fileName) {
173 let allDiagnostics = this.service
174 .getCompilerOptionsDiagnostics()
175 .concat(this.service.getSyntacticDiagnostics(fileName))
176 .concat(this.service.getSemanticDiagnostics(fileName));
177 allDiagnostics.forEach(diagnostic => {
178 let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
179 if (diagnostic.file) {
180 let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
181 console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character +
182 1}): ${message}`);
183 }
184 else {
185 console.log(` Error: ${message}`);
186 }
187 });
188 }
189}
190exports.default = Transpiler;
191function dumpSourceCode({ srcDirectory, buildDirectory } = {
192 srcDirectory,
193 buildDirectory
194}) {
195 return _transformContext => {
196 return tsSourceFile => {
197 let outPath = tsSourceFile.fileName
198 .replace(srcDirectory, buildDirectory)
199 .replace(/js$/, 'ts')
200 .replace(/jsx$/, 'tsx');
201 fs.ensureFileSync(outPath);
202 fs.writeFileSync(outPath, utils_1.getSourceCode(tsSourceFile));
203 return tsSourceFile;
204 };
205 };
206}