UNPKG

@decoupled/magic

Version:

1,208 lines (956 loc) 179 kB
// modules are defined as an array // [ module function, map of requires ] // // map of requires is short require name -> numeric require // // anything defined in a previous bundle is accessed via the // orig method which is the require for previous bundles parcelRequire = (function (modules, cache, entry, globalName) { // Save the require from previous bundle to this closure if any var previousRequire = typeof parcelRequire === 'function' && parcelRequire; var nodeRequire = typeof require === 'function' && require; function newRequire(name, jumped) { if (!cache[name]) { if (!modules[name]) { // if we cannot find the module within our internal map or // cache jump to the current global require ie. the last bundle // that was added to the page. var currentRequire = typeof parcelRequire === 'function' && parcelRequire; if (!jumped && currentRequire) { return currentRequire(name, true); } // If there are other bundles on this page the require from the // previous one is saved to 'previousRequire'. Repeat this as // many times as there are bundles until the module is found or // we exhaust the require chain. if (previousRequire) { return previousRequire(name, true); } // Try the node require function if it exists. if (nodeRequire && typeof name === 'string') { return nodeRequire(name); } var err = new Error('Cannot find module \'' + name + '\''); err.code = 'MODULE_NOT_FOUND'; throw err; } localRequire.resolve = resolve; localRequire.cache = {}; var module = cache[name] = new newRequire.Module(name); modules[name][0].call(module.exports, localRequire, module, module.exports, this); } return cache[name].exports; function localRequire(x){ return newRequire(localRequire.resolve(x)); } function resolve(x){ return modules[name][1][x] || x; } } function Module(moduleName) { this.id = moduleName; this.bundle = newRequire; this.exports = {}; } newRequire.isParcelRequire = true; newRequire.Module = Module; newRequire.modules = modules; newRequire.cache = cache; newRequire.parent = previousRequire; newRequire.register = function (id, exports) { modules[id] = [function (require, module) { module.exports = exports; }, {}]; }; var error; for (var i = 0; i < entry.length; i++) { try { newRequire(entry[i]); } catch (e) { // Save first error but execute all entries if (!error) { error = e; } } } if (entry.length) { // Expose entry point to Node, AMD or browser globals // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js var mainExports = newRequire(entry[entry.length - 1]); // CommonJS if (typeof exports === "object" && typeof module !== "undefined") { module.exports = mainExports; // RequireJS } else if (typeof define === "function" && define.amd) { define(function () { return mainExports; }); // <script> } else if (globalName) { this[globalName] = mainExports; } } // Override the current require with this new one parcelRequire = newRequire; if (error) { // throw error from earlier, _after updating parcelRequire_ throw error; } return newRequire; })({"../../x/typescript/ts_removeExt.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Removes ts,tsx,js,jsx if present (does not change string otherwise) * works with absolute and relative filepaths * @param filePath */ function ts_removeExt(filePath) { const exts = ["ts", "tsx", "js", "jsx"]; for (const ext of exts) if (filePath.endsWith(ext)) return filePath.substr(0, filePath.length - ext.length - 1); return filePath; } exports.ts_removeExt = ts_removeExt; },{}],"../../x/crypto/crypto_sha256.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const crypto_1 = require("crypto"); function crypto_sha256(str) { return crypto_1.createHash("sha256").update(str).digest("base64"); } exports.crypto_sha256 = crypto_sha256; },{}],"../../x/crypto/crypto_filenameFriendlyHash.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const crypto_sha256_1 = require("./crypto_sha256"); function crypto_filenameFriendlyHash(str) { return crypto_sha256_1.crypto_sha256(str).replace(/\W/g, "").toLowerCase(); } exports.crypto_filenameFriendlyHash = crypto_filenameFriendlyHash; },{"./crypto_sha256":"../../x/crypto/crypto_sha256.ts"}],"../../magic-marco/entrypoints/file_generator.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function lambdaEntrypoint(entry) { if (entry.kind === "lambda") { const source = `"use strict"; exports.__esModule = true; exports.handler = (async function(event){ const args = (JSON.parse(event.body || "{}").args || []); return { statusCode: 200, body: JSON.stringify({ result: await require("${entry.importPath}").default(...args) }) }; });`; return [{ filepath: entry.runnerFilepathNoExt + ".js", source }]; } return []; } function spaEntrypoint(entry) { if (entry.kind === "spa") { const js_source = `"use strict"; exports.__esModule = true; const react = require("react"); const react_dom_1 = require("react-dom"); const MagicSpa = require("${entry.importPath}").default; react_dom_1.render(react.createElement(MagicSpa, null), document.getElementById("root"));`; const html_source = `<html> <body> <div id="root"></div> <script src="./${entry.runnerFilenameNoExt}.js"></script> </body> </html>`; return [{ filepath: entry.runnerFilepathNoExt + ".js", source: js_source }, { filepath: entry.runnerFilepathNoExt + ".html", source: html_source }]; } return []; } function electronEntrypoint(entry) { if (entry.kind === "electron") { const renderer_source = `"use strict"; exports.__esModule = true; window.FUNCTIONS_URL = require("electron").remote.getGlobal("FUNCTIONS_URL") const react = require("react"); const react_dom_1 = require("react-dom"); const ElectronWindow = require("${entry.importPath}").default; react_dom_1.render(react.createElement(ElectronWindow, null), document.getElementById("root"));`; const html_source = `<html> <body> <div id="root"></div> <script src="./${entry.runnerFilenameNoExt}.renderer.js"></script> </body> </html>`; const main_source = `"use strict"; exports.__esModule = true; var electron = require("electron"); const windowOpts = require("./${entry.runnerFilenameNoExt}.opts.json") var mainWindow; global.FUNCTIONS_URL = process.env.FUNCTIONS_URL function createWindow() { mainWindow = new electron.BrowserWindow(Object.assign({ height: 600, width: 800, webPreferences: { nodeIntegration: true, }, }, windowOpts)); mainWindow.loadURL("http://localhost:" + (process.env.WINDOW_PORT || 5000)); mainWindow.on("closed", function() { mainWindow = null; }); } electron.app.on("ready", createWindow); electron.app.on("window-all-closed", function() { electron.app.quit(); }); electron.app.on("activate", function() { if (mainWindow === null) { createWindow(); } }); `; return [{ filepath: entry.runnerFilepathNoExt + ".renderer.js", source: renderer_source }, { filepath: entry.runnerFilepathNoExt + ".html", source: html_source }, { filepath: entry.runnerFilepathNoExt + ".main.js", source: main_source }]; } return []; } exports.generators = [lambdaEntrypoint, spaEntrypoint, electronEntrypoint]; },{}],"../../magic-marco/entrypoints/entrypoint.ts":[function(require,module,exports) { "use strict"; var __decorate = this && this.__decorate || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importStar = this && this.__importStar || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const path = __importStar(require("path")); const ts_removeExt_1 = require("../../x/typescript/ts_removeExt"); const fs_extra_1 = require("fs-extra"); const chokidar = __importStar(require("chokidar")); const lazy_get_decorator_1 = require("lazy-get-decorator"); const utils_1 = require("../utils"); const file_generator_1 = require("./file_generator"); class EntryPoint { constructor(relativeFilePath, opts) { this.relativeFilePath = relativeFilePath; this.opts = opts; this.createdFiles = []; } build() { return __awaiter(this, void 0, void 0, function* () { yield this.createEntry(); }); } watch() { const ww = chokidar.watch(this.filepath); const isSelf = p => p === this.filepath; ww.on("add", path => isSelf(path) && this.createEntry()); ww.on("change", path => isSelf(path) && this.clearFiles().then(() => this.createEntry())); ww.on("unlink", path => isSelf(path) && this.clearFiles() && this.stop()); this.ww = ww; } stop() { if (this.ww) { this.ww.close(); this.ww = undefined; } } clearFiles() { return __awaiter(this, void 0, void 0, function* () { // TODO: parcel raises errors when files are deleted // await Promise.all(this.createdFiles.map(filepath => remove(filepath))) this.createdFiles = []; }); } createEntry() { return __awaiter(this, void 0, void 0, function* () { yield Promise.all(file_generator_1.generators.flatMap(gen => gen(this).map(({ filepath, source }) => __awaiter(this, void 0, void 0, function* () { // repeated outputs mess up parcel-bundler sometimes // if (!existsSync(filepath)) { yield fs_extra_1.outputFile(filepath, source); this.createdFiles.push(filepath); // } })))); }); } get filepath() { return path.join(this.opts.rootDir, this.relativeFilePath); } get kind() { const { kind } = breakObjectFilepath(this.relativeFilePath) || { kind: "none" }; return kind; } get magicObjectName() { const { filename, objectName } = breakObjectFilepath(this.relativeFilePath) || {}; if (typeof filename === "undefined") return undefined; return filename + "#" + objectName; } get importPath() { return ts_removeExt_1.ts_removeExt(path.relative(this.runnerDirpath, this.filepath)); } get runnerFilenameNoExt() { return this.magicObjectName && utils_1.filenameForMagicObject(this.magicObjectName); } get runnerFilepathNoExt() { return this.runnerFilenameNoExt && path.join(this.runnerDirpath, this.runnerFilenameNoExt); } get runnerDirpath() { return path.join(this.opts.entrypointDir, utils_1.outputDirForKind(this.kind)); } } __decorate([lazy_get_decorator_1.LazyGetter()], EntryPoint.prototype, "filepath", null); __decorate([lazy_get_decorator_1.LazyGetter()], EntryPoint.prototype, "kind", null); __decorate([lazy_get_decorator_1.LazyGetter()], EntryPoint.prototype, "magicObjectName", null); __decorate([lazy_get_decorator_1.LazyGetter()], EntryPoint.prototype, "importPath", null); __decorate([lazy_get_decorator_1.LazyGetter()], EntryPoint.prototype, "runnerFilenameNoExt", null); __decorate([lazy_get_decorator_1.LazyGetter()], EntryPoint.prototype, "runnerFilepathNoExt", null); __decorate([lazy_get_decorator_1.LazyGetter()], EntryPoint.prototype, "runnerDirpath", null); exports.EntryPoint = EntryPoint; function breakObjectFilepath(objectFilePath) { const match = objectFilePath.match(/^(.*)\.(\w+)\.(lambda|spa|electron)\.(t|j)sx?$/); if (!match) return; const [_, filename, objectName, kind] = match; return { filename, kind, objectName }; } },{"../../x/typescript/ts_removeExt":"../../x/typescript/ts_removeExt.ts","../utils":"../../magic-marco/utils/index.ts","./file_generator":"../../magic-marco/entrypoints/file_generator.ts"}],"../../magic-marco/entrypoints/index.ts":[function(require,module,exports) { "use strict"; var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importStar = this && this.__importStar || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_extra_1 = require("fs-extra"); const glob = __importStar(require("glob")); const chokidar = __importStar(require("chokidar")); const entrypoint_1 = require("./entrypoint"); function buildEntrypoints(opts, loggerCallback) { return __awaiter(this, void 0, void 0, function* () { if (opts.clear || opts.clear === undefined) { fs_extra_1.emptyDirSync(opts.entrypointDir); } if (!opts.watch) { yield Promise.all(glob.sync("**", { cwd: opts.rootDir }).map(filepath => new entrypoint_1.EntryPoint(filepath, opts).build())); } else { const ww = chokidar.watch("", { cwd: opts.rootDir }); ww.on("add", filepath => new entrypoint_1.EntryPoint(filepath, opts).watch()); ww.on("unlinkDir", dirpath => fs_extra_1.remove(dirpath)); //ww.on("all", (ev, filepath) => console.log(`[${ev}] => ${filepath}`)) yield new Promise(res => ww.on("ready", res)); return () => ww.close(); } return Promise.resolve(); }); } exports.buildEntrypoints = buildEntrypoints; },{"./entrypoint":"../../magic-marco/entrypoints/entrypoint.ts"}],"../../x/typescript/ts_tsconfig_get_rootDir.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fs_extra_1 = require("fs-extra"); const path_1 = require("path"); /** * Looks for "rootDir" and returns absolute path * @param tsConfigFilePath */ function ts_tsconfig_get_rootDir(tsConfigFilePath) { const d = fs_extra_1.readJSONSync(tsConfigFilePath); if (!(typeof d.compilerOptions.rootDir === "string")) throw new Error("tsconfig.rootDir not found"); return path_1.resolve(path_1.dirname(tsConfigFilePath), d.compilerOptions.rootDir); } exports.ts_tsconfig_get_rootDir = ts_tsconfig_get_rootDir; },{}],"../../magic-marco/utils/path.ts":[function(require,module,exports) { "use strict"; var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importStar = this && this.__importStar || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; var __importDefault = this && this.__importDefault || function (mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path = __importStar(require("path")); const fs = __importStar(require("fs-extra")); const ts_tsconfig_get_rootDir_1 = require("../../x/typescript/ts_tsconfig_get_rootDir"); const index_1 = require("./index"); const chokidar_1 = __importDefault(require("chokidar")); function magicPathsForWorkspace(workspacePath, watch) { return __awaiter(this, void 0, void 0, function* () { const tsconfig_path = path.join(workspacePath, "tsconfig.json"); if (!fs.existsSync(tsconfig_path)) { if (watch) { const ww = chokidar_1.default.watch("", { cwd: workspacePath }); yield new Promise(resolve => ww.on("add", path => path === "tsconfig.json" && resolve())); ww.close(); } else { throw new Error("tsconfig.json file was not found on workspace"); } } const rootDir = ts_tsconfig_get_rootDir_1.ts_tsconfig_get_rootDir(tsconfig_path); const magicDir = path.join(workspacePath, ".magic"); return { rootDir, magicDir, explodedRootDir: path.join(magicDir, "out"), entrypointDir: path.join(magicDir, "entrypoints"), devDir: path.join(magicDir, "dev"), buildDir: path.join(magicDir, "build") }; }); } exports.magicPathsForWorkspace = magicPathsForWorkspace; function getEntrypointFilepathNoExtForMagicObject(magicObjectName, kind, entrypointDir) { return path.join(entrypointDir, index_1.outputDirForKind(kind), index_1.filenameForMagicObject(magicObjectName)); } exports.getEntrypointFilepathNoExtForMagicObject = getEntrypointFilepathNoExtForMagicObject; },{"../../x/typescript/ts_tsconfig_get_rootDir":"../../x/typescript/ts_tsconfig_get_rootDir.ts","./index":"../../magic-marco/utils/index.ts"}],"../../x/fs/fs_appendToFilenameKeepExtension.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = require("path"); function fs_appendToFilenameKeepExtension(filePath, toAppend) { const ext = path_1.extname(filePath); const filePathNoExt = filePath.substr(0, filePath.length - ext.length); return filePathNoExt + toAppend + ext; } exports.fs_appendToFilenameKeepExtension = fs_appendToFilenameKeepExtension; },{}],"../../x/ts-morph/tsm_Node_containsJSX.ts":[function(require,module,exports) { "use strict"; var __importStar = this && this.__importStar || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const tsm = __importStar(require("ts-morph")); /** * There are two kinds of JSX elements (normal + self closing) * This searches for both. * @param node */ function tsm_Node_containsJSX(node) { for (const d of node.getDescendants()) { if (d instanceof tsm.JsxElement) return true; if (d instanceof tsm.JsxSelfClosingElement) return true; } return false; } exports.tsm_Node_containsJSX = tsm_Node_containsJSX; },{}],"../../x/ts-morph/tsm_Node_getContainingImportDeclaration.ts":[function(require,module,exports) { "use strict"; var __importStar = this && this.__importStar || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const tsm = __importStar(require("ts-morph")); /** * There are two kinds of potential import declarations: * - ImportEqualsDeclaration * - ImportDeclaration * @param node */ function tsm_Node_getContainingImportDeclaration(node) { if (tsm.TypeGuards.isImportDeclaration(node)) return node; if (tsm.TypeGuards.isImportEqualsDeclaration(node)) return node; const i1 = node.getFirstAncestorByKind(tsm.SyntaxKind.ImportEqualsDeclaration); if (i1) return i1; const i2 = node.getFirstAncestorByKind(tsm.SyntaxKind.ImportDeclaration); if (i2) return i2; } exports.tsm_Node_getContainingImportDeclaration = tsm_Node_getContainingImportDeclaration; },{}],"../../x/crypto/crypto_varnameFriendlyHash.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const crypto_sha256_1 = require("./crypto_sha256"); function crypto_varnameFriendlyHash(str, len) { const varname = "_" + crypto_sha256_1.crypto_sha256(str).replace(/\W/g, ""); if (typeof len === "undefined") return varname; return varname.slice(0, len); } exports.crypto_varnameFriendlyHash = crypto_varnameFriendlyHash; },{"./crypto_sha256":"../../x/crypto/crypto_sha256.ts"}],"../../magic-marco/utils/assets.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const validAssetExtensions = { browser: ["css", "jpg", "jpeg", "png", "csv", "svg"], chromium: ["css", "jpg", "jpeg", "png", "csv", "svg"], node: [] }; const allExtensions = Array.from(new Set(Object.values(validAssetExtensions).flatMap(ext => ext))); function isAsset(moduleSpecifierValue) { return allExtensions.some(ext => moduleSpecifierValue.endsWith("." + ext)); } exports.isAsset = isAsset; function validAssetForRuntime(assetPath, runtime) { return validAssetExtensions[runtime].some(ext => assetPath.endsWith("." + ext)); } exports.validAssetForRuntime = validAssetForRuntime; },{}],"../../magic-marco/tsm-utils.ts":[function(require,module,exports) { "use strict"; var __importStar = this && this.__importStar || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const tsm = __importStar(require("ts-morph")); const crypto_varnameFriendlyHash_1 = require("../x/crypto/crypto_varnameFriendlyHash"); const assets_1 = require("./utils/assets"); function newNameForNamespaceAccessProperty(namespace, property) { // TODO: generate value of same length that is *unique* const inpt = `${namespace}.${property}`; return crypto_varnameFriendlyHash_1.crypto_varnameFriendlyHash(inpt, inpt.length); } function newNameForModule(moduleSpecifier, property) { // Check if this is a node module or a file within the project // TODO: better check // TODO: make sure name is unique if (assets_1.isAsset(moduleSpecifier)) { return moduleSpecifier; } if (moduleSpecifier.startsWith(".") || moduleSpecifier.startsWith("/")) { return `${moduleSpecifier}.${property}`; } else { return moduleSpecifier; } } exports.newNameForModule = newNameForModule; function refactorNameSpaceImports(sourcefile, opts = {}) { const nameSpaceImports = sourcefile.getImportDeclarations().map(idec => idec.getNamespaceImport()).filter(idec => idec); const newImportExpressions = []; // we need to iterate in reverse order, so that when imports get deleted, the // added whitespace does not form part of the following import nameSpaceImports.reverse().forEach(nsi => { const properties = new Set(); const namespaceName = nsi.getSymbolOrThrow().getName(); nsi.findReferencesAsNodes().forEach(n => { const nn = n.getParent(); if (typeof nn === "undefined") return; let propertyName; if (tsm.TypeGuards.isPropertyAccessExpression(nn)) { propertyName = nn.getName(); } else if (tsm.TypeGuards.isQualifiedName(nn)) { propertyName = nn.getRight().getText(); } else { return; // throw new Error( // `Unknown namespace usage: \`${nn.getKindName()}\` on ${sourcefile.getFilePath()}` // ) } properties.add(propertyName); nn.replaceWithText(newNameForNamespaceAccessProperty(namespaceName, propertyName)); }); const importNode = nsi.getFirstAncestorByKindOrThrow(tsm.SyntaxKind.ImportDeclaration); const propertyImports = Array.from(properties.values()).map(p => `${p} as ${newNameForNamespaceAccessProperty(namespaceName, p)}`); const importExpr = `import {${propertyImports.join(", ")}} from "${importNode.getModuleSpecifierValue()}"`; const leadingComments = importNode.getFullText().substring(0, importNode.getLeadingTriviaWidth()).replace(/^\n+/, ""); // remove leading new lines if (opts.keepAbsoluteIndex) { // replace all nonwhitespace characters with whitespace (this keeps newlines) importNode.replaceWithText(leadingComments + importNode.getText().replace(/\S/g, " ")); newImportExpressions.push(importExpr); } else { importNode.replaceWithText(leadingComments + importExpr); } if (namespaceName === "React") { newImportExpressions.push(`import * as React from "react"`); } // TODO: add flag to import at the end and replace original with spaces (maintain absolute character index) }); if (opts.keepAbsoluteIndex) { sourcefile.insertText(sourcefile.getEnd(), "\n" + newImportExpressions.join("\n")); } } exports.refactorNameSpaceImports = refactorNameSpaceImports; },{"../x/crypto/crypto_varnameFriendlyHash":"../../x/crypto/crypto_varnameFriendlyHash.ts","./utils/assets":"../../magic-marco/utils/assets.ts"}],"../../magic-marco/explosion/cache.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = require("fs"); const crypto_filenameFriendlyHash_1 = require("../../x/crypto/crypto_filenameFriendlyHash"); const path_1 = require("path"); const crypto_sha256_1 = require("../../x/crypto/crypto_sha256"); const fs_extra_1 = require("fs-extra"); const _1 = require("."); const CACHEDIR = "magic-explosion-cache"; function cache_get_file_is_exploded(filename, contents) { const cachedir = path_1.join(_1.Exploder.paths.magicDir, CACHEDIR); const cachefile = path_1.join(cachedir, crypto_filenameFriendlyHash_1.crypto_filenameFriendlyHash(filename)); if (!fs_1.existsSync(cachefile)) return false; const content = fs_1.readFileSync(cachefile).toString(); return crypto_sha256_1.crypto_sha256(contents) === content; } exports.cache_get_file_is_exploded = cache_get_file_is_exploded; function cache_set_file_as_exploded(filename, contents) { const cachedir = path_1.join(_1.Exploder.paths.magicDir, CACHEDIR); const cachefile = path_1.join(cachedir, crypto_filenameFriendlyHash_1.crypto_filenameFriendlyHash(filename)); fs_extra_1.outputFileSync(cachefile, crypto_sha256_1.crypto_sha256(contents)); } exports.cache_set_file_as_exploded = cache_set_file_as_exploded; },{"../../x/crypto/crypto_filenameFriendlyHash":"../../x/crypto/crypto_filenameFriendlyHash.ts","../../x/crypto/crypto_sha256":"../../x/crypto/crypto_sha256.ts",".":"../../magic-marco/explosion/index.ts"}],"../../magic-marco/explosion/phase_one.ts":[function(require,module,exports) { "use strict"; var __decorate = this && this.__decorate || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = this && this.__importStar || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const lazy_get_decorator_1 = require("lazy-get-decorator"); const lodash_decorators_1 = require("lodash-decorators"); const path = __importStar(require("path")); const tsm = __importStar(require("ts-morph")); const fs_appendToFilenameKeepExtension_1 = require("../../x/fs/fs_appendToFilenameKeepExtension"); const tsm_Node_containsJSX_1 = require("../../x/ts-morph/tsm_Node_containsJSX"); const tsm_Node_getContainingImportDeclaration_1 = require("../../x/ts-morph/tsm_Node_getContainingImportDeclaration"); const ts_removeExt_1 = require("../../x/typescript/ts_removeExt"); const tsm_utils_1 = require("../tsm-utils"); const cache_1 = require("./cache"); /** * - utility to isolate top-level declarations. * - creates one file per declaration * - removes unused imports (only copies used imports) * - maintains position * TODO: handle assignments like this: * const Foo = () => {} * Foo.meta = 'hello' * * TODO: * handle general expressions with no name (or throw diagnostics) */ class ExplodableFileP1 { constructor(opts) { this.opts = opts; } get tsmp() { return new tsm.Project({ useVirtualFileSystem: true }); } get filename() { return this.opts.filename; } get sourceFile() { const sf = this.tsmp.createSourceFile(this.opts.filename, this.opts.sourceCode); tsm_utils_1.refactorNameSpaceImports(sf, { keepAbsoluteIndex: true }); return sf; } get localObjects() { return this.sourceFile.getLocals().map(s => new LocalObject(this, s)); } get globalImports() { return this.sourceFile.getImportDeclarations().filter(idcl => typeof idcl.getImportClause() === "undefined"); } get explodableObjects() { if (!this.opts.noCache) if (cache_1.cache_get_file_is_exploded(this.opts.filename, this.opts.sourceCode)) return []; const objects = this.localObjects.filter(s => s.isExplodable); if (!this.opts.noCache) cache_1.cache_set_file_as_exploded(this.opts.filename, this.opts.sourceCode); return objects; } symbolDeclaration(symbol) { return symbol.getDeclarations().find(decl => decl.getSourceFile().getFilePath() == path.join("/", this.filename)); } } __decorate([lazy_get_decorator_1.LazyGetter()], ExplodableFileP1.prototype, "tsmp", null); __decorate([lazy_get_decorator_1.LazyGetter()], ExplodableFileP1.prototype, "sourceFile", null); __decorate([lazy_get_decorator_1.LazyGetter()], ExplodableFileP1.prototype, "localObjects", null); __decorate([lazy_get_decorator_1.LazyGetter()], ExplodableFileP1.prototype, "globalImports", null); __decorate([lazy_get_decorator_1.LazyGetter()], ExplodableFileP1.prototype, "explodableObjects", null); __decorate([lodash_decorators_1.memoize], ExplodableFileP1.prototype, "symbolDeclaration", null); exports.ExplodableFileP1 = ExplodableFileP1; class LocalObject { constructor(file, symbol) { this.file = file; this.symbol = symbol; } get name() { return this.symbol.getName(); //? } get filepath() { return path.join("/", this.file.filename); } get declaration() { const decl = this.file.symbolDeclaration(this.symbol); if (typeof decl === "undefined") throw new Error("local declaration for symbol not found"); return decl; } get containingImportDeclaration() { return tsm_Node_getContainingImportDeclaration_1.tsm_Node_getContainingImportDeclaration(this.declaration); } get isImport() { return typeof this.containingImportDeclaration !== "undefined"; } get globalImports() { this.file.sourceFile.getImportDeclarations(); return []; } get importExpr() { const d = this.declaration; const srcbase = ts_removeExt_1.ts_removeExt(this.filepath); if (this.isImport) { const idcl = d.getFirstAncestorByKindOrThrow(tsm.SyntaxKind.ImportDeclaration); const m = idcl.getModuleSpecifierValue(); if (tsm.TypeGuards.isImportSpecifier(d)) { // special case // we don't want to copy the whole import because we might carry over // imports that aren't needed (if multiple specifiers are present) // ex: import {a,b} from "c" const name = d.getName(); const aliasNode = d.getAliasNode(); const aliasText = aliasNode ? " as " + aliasNode.getText() : ""; return `import {${name}${aliasText}} from "${tsm_utils_1.newNameForModule(m, name)}"`; } // otherwise let's just copy the original export statement over if (tsm.TypeGuards.isImportClause(d)) { const ii = `import ${this.name} from "${tsm_utils_1.newNameForModule(m, this.name)}"`; return ii; } return this.containingImportDeclaration.getText(); } // the way to import a local is to pull in its (generated) file return `import ${this.name} from "./${srcbase}.${this.name}"`; } get is_React_import() { if (!this.isImport) return false; if (this.name !== "React") return false; return true; // TODO: make sure the "react" module is being imported } get isExplodable() { return !this.isImport; } get explodedFilename() { if (!this.isExplodable) throw new Error("Object may not be exploded into a valid file"); return fs_appendToFilenameKeepExtension_1.fs_appendToFilenameKeepExtension(this.file.filename, "." + this.name); } get originalCodeContainsJSX() { return tsm_Node_containsJSX_1.tsm_Node_containsJSX(this.declaration); } get directlyUsedLocalObjects() { if (this.isImport) return []; // imports don't use any other symbols const d = this.declaration; const otherLocals = this.file.localObjects.filter(l => l !== this); const usedSymbolDecls = new Set(d.getDescendantsOfKind(tsm.SyntaxKind.Identifier).map(n => n.getSymbol()).filter(n => typeof n !== "undefined").map(s => this.file.symbolDeclaration(s))); const usedLocalsSet = new Set(otherLocals.filter(l => usedSymbolDecls.has(l.declaration))); if (this.originalCodeContainsJSX) { // calls to React.createElement are not explicit in JSX // so we need to force the presence "import React from 'react'" const ri = otherLocals.find(x => x.is_React_import); if (ri) usedLocalsSet.add(ri); } return Array.from(usedLocalsSet); } get objectSourceCode() { const empty = this.file.sourceFile.getFullText().replace(/\S/g, " "); let node = this.declaration; if (tsm.TypeGuards.isVariableDeclaration(node)) { const decl_list = node.getFirstAncestorByKindOrThrow(tsm.SyntaxKind.VariableDeclarationList); const statement = decl_list.getParentIfKindOrThrow(tsm.SyntaxKind.VariableStatement); const keyword = decl_list.getDeclarationKindKeyword(); return empty.substring(0, statement.getStart()) + statement.getText().substring(0, keyword.getEnd() - statement.getStart()) + empty.substring(keyword.getEnd(), this.declaration.getStart()) + this.declaration.getText() + empty.substring(this.declaration.getEnd()); } return empty.substring(0, this.declaration.getStart()) + this.declaration.getText() + empty.substring(this.declaration.getEnd()); } get explodedSourceCode() { if (!this.isExplodable) throw new Error("Object may not be exploded into a valid file"); const localObjectImports = this.directlyUsedLocalObjects.map(s => s.importExpr); const globalImports = this.file.globalImports.map(idcl => idcl.getText()); const imports = [...localObjectImports, ...globalImports]; return `${this.objectSourceCode} //-------- export default ${this.name} ${imports.join("\n")} `; } } __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "name", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "filepath", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "declaration", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "containingImportDeclaration", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "isImport", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "globalImports", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "importExpr", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "is_React_import", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "isExplodable", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "explodedFilename", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "originalCodeContainsJSX", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "directlyUsedLocalObjects", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "objectSourceCode", null); __decorate([lazy_get_decorator_1.LazyGetter()], LocalObject.prototype, "explodedSourceCode", null); exports.LocalObject = LocalObject; },{"../../x/fs/fs_appendToFilenameKeepExtension":"../../x/fs/fs_appendToFilenameKeepExtension.ts","../../x/ts-morph/tsm_Node_containsJSX":"../../x/ts-morph/tsm_Node_containsJSX.ts","../../x/ts-morph/tsm_Node_getContainingImportDeclaration":"../../x/ts-morph/tsm_Node_getContainingImportDeclaration.ts","../../x/typescript/ts_removeExt":"../../x/typescript/ts_removeExt.ts","../tsm-utils":"../../magic-marco/tsm-utils.ts","./cache":"../../magic-marco/explosion/cache.ts"}],"../types/decoupled_magic.d.rollup.source.ts":[function(require,module,exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = "import React from 'react';\r\n\r\ndeclare type CacheInvalidationKeysForFunction<T extends Function> = {\r\n [K in keyof Function_ArgumentTypes<T>[0]]: true\r\n}\r\n\r\nexport declare function cli(...args: any[]): { magicKind: \"cli\" }\r\n\r\n/**\r\n * Mark a value as editable via the Magic CMS.\r\n * Some restrictions:\r\n *\r\n * - no references to outside objects (this is just a tree)\r\n * - only a few types are supported (JSON)\r\n *\r\n * @param name\r\n * @param data\r\n * @see https://dev.decoupled.com/docs-magic-cms\r\n */\r\nexport declare function cms<T>(name: string, data: T): T\r\n\r\ndeclare interface DefaultFontFamily {\r\n /**\r\n * Defaults to `Times New Roman`.\r\n */\r\n standard?: string\r\n /**\r\n * Defaults to `Times New Roman`.\r\n */\r\n serif?: string\r\n /**\r\n * Defaults to `Arial`.\r\n */\r\n sansSerif?: string\r\n /**\r\n * Defaults to `Courier New`.\r\n */\r\n monospace?: string\r\n /**\r\n * Defaults to `Script`.\r\n */\r\n cursive?: string\r\n /**\r\n * Defaults to `Impact`.\r\n */\r\n fantasy?: string\r\n}\r\n\r\n/**\r\n * Start a development server from code.\r\n * This only works if you are editing in Decoupled Studio (VSCode)\r\n * or if you have the magic dev server running for this project.\r\n *\r\n * @param args\r\n * @see https://dev.decoupled.com/docs-magic-dev\r\n */\r\nexport declare function dev(\r\n spa: { magicKind: \"spa\" },\r\n opts: { target?: \"browser\" | \"vscode\" }\r\n): void\r\n\r\nexport declare function dev(\r\n electron: { magicKind: \"electron\" },\r\n opts: { stayOnTop?: boolean }\r\n): void\r\n\r\nexport declare function dev(\r\n cli: { magicKind: \"cli\" },\r\n opts: { openInVSCodeTerminal?: boolean }\r\n): void\r\n\r\nexport declare function dev(...args: any[]): void\r\n\r\n/**\r\n * Declares an Electron App (Desktop)\r\n *\r\n * @param app\r\n * @param opts\r\n * @see https://dev.decoupled.com/docs-magic-electron\r\n */\r\nexport declare function electron(\r\n app: () => any,\r\n opts?: MagicElectronSingleWindowConstructorOptions\r\n): { magicKind: \"electron\" }\r\n\r\ndeclare type Function_ArgumentTypes<T> = T extends (...args: infer A) => infer R\r\n ? A\r\n : never\r\n\r\ndeclare type Function_ReturnType<T> = T extends (...args: infer A) => infer R\r\n ? R\r\n : never\r\n\r\ndeclare type FunctionArgumentsType<T> = T extends (...args: infer A) => any\r\n ? A\r\n : never\r\n\r\ndeclare type FunctionReturnType<T> = T extends (...args: any[]) => infer R\r\n ? R\r\n : never\r\n\r\nexport declare const funk: T_funk;\r\n\r\n/**\r\n * Declares a server-side Node.js lambda.\r\n * Lambdas are stateless and scale as needed.\r\n *\r\n * @param func\r\n * @param opts\r\n * @see https://dev.decoupled.com/docs-magic-lambda\r\n */\r\nexport declare function lambda<T extends Function>(\r\n func: T,\r\n opts?: LambdaOpts\r\n): {\r\n magicKind: \"lambda\"\r\n} & PromisifyFunction<T>\r\n\r\nexport declare interface LambdaOpts {}\r\n\r\nexport declare const Link: React.FC<{\r\n to: React.ReactElement | string\r\n children: React.ReactNode\r\n}>;\r\n\r\nexport declare const LinkTarget: React.FC<{\r\n /**\r\n * Initial component to display inside this LinkTarget\r\n */\r\n children?: React.ReactNode\r\n}>;\r\n\r\nexport declare type Locale = string\r\n\r\nexport declare function log(...args: any[]): void\r\n\r\ndeclare interface MagicElectronSingleWindowConstructorOptions {\r\n /**\r\n * Window's width in pixels. Default is `800`.\r\n */\r\n width?: number\r\n /**\r\n * Window's height in pixels. Default is `600`.\r\n */\r\n height?: number\r\n /**\r\n * (**required** if y is used) Window's left offset from screen. Default is to\r\n * center the window.\r\n */\r\n x?: number\r\n /**\r\n * (**required** if x is used) Window's top offset from screen. Default is to\r\n * center the window.\r\n */\r\n y?: number\r\n /**\r\n * The `width` and `height` would be used as web page's size, which means the\r\n * actual window's size will include window frame's size and be slightly larger.\r\n * Default is `false`.\r\n */\r\n useContentSize?: boolean\r\n /**\r\n * Show window in the center of the screen.\r\n */\r\n center?: boolean\r\n /**\r\n * Window's minimum width. Default is `0`.\r\n */\r\n minWidth?: number\r\n /**\r\n * Window's minimum height. Default is `0`.\r\n */\r\n minHeight?: number\r\n /**\r\n * Window's maximum width. Default is no limit.\r\n */\r\n maxWidth?: number\r\n /**\r\n * Window's maximum height. Default is no limit.\r\n */\r\n maxHeight?: number\r\n /**\r\n * Whether window is resizable. Default is `true`.\r\n */\r\n resizable?: boolean\r\n /**\r\n * Whether window is movable. This is not implemented on Linux. Default is `true`.\r\n */\r\n movable?: boolean\r\n /**\r\n * Whether window is minimizable. This is not implemented on Linux. Default is\r\n * `true`.\r\n */\r\n minimizable?: boolean\r\n /**\r\n * Whether window is maximizable. This is not implemented on Linux. Default is\r\n * `true`.\r\n */\r\n maximizable?: boolean\r\n /**\r\n * Whether window is closable. This is not implemented on Linux. Default is `true`.\r\n */\r\n closable?: boolean\r\n /**\r\n * Whether the window can be focused. Default is `true`. On Windows setting\r\n * `focusable: false` also implies setting `skipTaskbar: true`. On Linux setting\r\n * `focusable: false` makes the window stop interacting with wm, so the window will\r\n * always stay on top in all workspaces.\r\n */\r\n focusable?: boolean\r\n /**\r\n * Whether the window should always stay on top of other windows. Default is\r\n * `false`.\r\n */\r\n alwaysOnTop?: boolean\r\n /**\r\n * Whether the window should show in fullscreen. When explicitly set to `false` the\r\n * fullscreen button will be hidden or disabled on macOS. Default is `false`.\r\n */\r\n fullscreen?: boolean\r\n /**\r\n * Whether the window can be put into fullscreen mode. On macOS, also whether the\r\n * maximize/zoom button should toggle full screen mode or maximize window. Default\r\n * is `true`.\r\n */\r\n fullscreenable?: boolean\r\n /**\r\n * Use pre-Lion fullscreen on macOS. Default is `false`.\r\n */\r\n simpleFullscreen?: boolean\r\n /**\r\n * Whether to show the window in taskbar. Default is `false`.\r\n */\r\n skipTaskbar?: boolean\r\n /**\r\n * The kiosk mode. Default is `false`.\r\n */\r\n kiosk?: boolean\r\n /**\r\n * Default window title. Default is `\"Electron\"`. If the HTML tag `<title>` is\r\n * defined in the HTML file loaded by `loadURL()`, this property will be ignored.\r\n */\r\n title?: string\r\n /**\r\n * The window icon. On Windows it is recommended to use `ICO` icons to get best\r\n * visual effects, you can also leave it undefined so the executable's icon will be\r\n * used.\r\n */\r\n //icon?: NativeImage | string\r\n icon?: string // TODO: magicKind: asset\r\n /**\r\n * Whether window should be shown when created. Default is `true`.\r\n */\r\n show?: boolean\r\n /**\r\n * Whether the renderer should be active when `show` is `false` and it has just\r\n * been created. In order for `document.visibilityState` to work correctly on\r\n * first load with `show: false` you should set this to `false`. Setting this to\r\n * `false` will cause the `ready-to-show` event to not fire. Default is `true`.\r\n */\r\n paintWhenInitiallyHidden?: boolean\r\n /**\r\n * Specify `false` to create a Frameless Window. Default is `true`.\r\n */\r\n frame?: boolean\r\n /**\r\n * Specify parent window. Default is `null`.\r\n */\r\n //parent?: BrowserWindow;\r\n /**\r\n * Whether this is a modal window. This only works when the window is a child\r\n * window. Default is `false`.\r\n */\r\n modal?: boolean\r\n /**\r\n * Whether the web view accepts a single mouse-down event that simultaneously\r\n * activates the window. Default is `false`.\r\n */\r\n acceptFirstMouse?: boolean\r\n /**\r\n * Whether to hide cursor when typing. Default is `false`.\r\n */\r\n disableAutoHideCursor?: boolean\r\n /**\r\n * Auto hide the menu bar unless the `Alt` key is pressed. Default is `false`.\r\n */\r\n autoHideMenuBar?: boolean\r\n /**\r\n * Enable the window to be resized larger than screen. Only relevant for macOS, as\r\n * other OSes allow larger-than-screen windows by default. Default is `false`.\r\n */\r\n enableLargerThanScreen?: boolean\r\n /**\r\n * Window's background color as a hexadecimal value, like `#66CD00` or `#FFF` or\r\n * `#80FFFFFF` (alpha in #AARRGGBB format is supported if `transparent` is set to\r\n * `true`). Default is `#FFF` (white).\r\n */\r\n backgroundColor?: string\r\n /**\r\n * Whether window should have a shadow. This is only implemented on macOS. Default\r\n * is `true`.\r\n */\r\n hasShadow?: boolean\r\n /**\r\n * Set the initial opacity of the window, between 0.0 (fully transparent) and 1.0\r\n * (fully opaque). This is only implemented on Windows and macOS.\r\n */\r\n opacity?: number\r\n /**\r\n * Forces using dark theme for the window, only works on some GTK+3 desktop\r\n * environments. Default is `false`.\r\n */\r\n darkTheme?: boolean\r\n /**\r\n * Makes the window transparent. Default is `false`. On Windows, does not work\r\n * unless the window is frameless.\r\n */\r\n transparent?: boolean\r\n /**\r\n * The type of window, default is normal window. See more about this below.\r\n */\r\n type?: string\r\n /**\r\n * The style of window title bar. Default is `default`. Possible values are:\r\n */\r\n titleBarStyle?: \"default\" | \"hidden\" | \"hiddenInset\" | \"customButtonsOnHover\"\r\n /**\r\n * Shows the title in the title bar in full screen mode on macOS for all\r\n * `titleBarStyle` options. Default is `false`.\r\n */\r\n fullscreenWindowTitle?: boolean\r\n /**\r\n * Use `WS_THICKFRAME` style for frameless windows on Windows, which adds standard\r\n * window frame. Setting it to `false` will remove window shadow and window\r\n * animations. Default is `true`.\r\n */\r\n thickFrame?: boolean\r\n /**\r\n * Add a type of vibrancy effect to the window, only on macOS. Can be\r\n * `appearance-based`, `light`, `dark`, `titlebar`, `selection`, `menu`, `popove