makecode-core
Version:
MakeCode (PXT) - web-cached build tool
283 lines • 11.1 kB
JavaScript
"use strict";
/// <reference path="../external/pxtpackage.d.ts" />
Object.defineProperty(exports, "__esModule", { value: true });
exports.stringifyConfig = exports.setLogging = exports.debug = exports.error = exports.log = exports.Project = exports.cloudRoot = void 0;
exports.downloader = require("./downloader");
exports.files = require("./files");
exports.service = require("./service");
exports.loader = require("./loader");
const files_1 = require("./files");
exports.cloudRoot = "https://makecode.com/api/";
function jsonCopyFrom(trg, src) {
let v = JSON.parse(JSON.stringify(src));
for (let k of Object.keys(src)) {
;
trg[k] = v[k];
}
}
class Project {
constructor(directory, cache = null) {
this.directory = directory;
this.cache = cache;
this.writePxtModules = true;
this.linkPxtModules = false;
this.symlinkPxtModules = false;
this.outputPrefix = "built";
}
get hwVariant() {
return this._hwVariant;
}
set hwVariant(value) {
this._hwVariant = value;
if (this.mainPkg)
this.mainPkg.mkcConfig.hwVariant = value;
}
async guessHwVariantAsync() {
var _a;
if (this.mainPkg.mkcConfig.hwVariant)
return;
const variants = await this.service.getHardwareVariantsAsync();
const cfg = this.mainPkg.config;
for (const v of variants) {
if (cfg.dependencies[v.name] || ((_a = cfg.testDependencies) === null || _a === void 0 ? void 0 : _a[v.name])) {
(0, exports.log)("guessing hw-variant: " + hwid(v));
this.hwVariant = hwid(v);
return;
}
}
(0, exports.log)("selecting first hw-variant: " + hwid(variants[0]));
this.hwVariant = hwid(variants[0]);
function hwid(cfg) {
return cfg.name.replace(/hw---/, "");
}
}
readFileAsync(filename) {
return exports.files.readPrjFileAsync(this.directory, filename);
}
saveBuiltFilesAsync(res) {
return exports.files.saveBuiltFilesAsync(this.directory, res, this.outputPrefix);
}
async savePxtModulesAsync(filesmap0) {
var _a;
let filesmap = filesmap0;
if (this.linkPxtModules || this.symlinkPxtModules) {
let libsPath = await exports.files.findParentDirWithAsync("..", "pxtarget.json");
if (libsPath)
libsPath =
exports.files.relativePath(".", libsPath).replace(/\\/g, "/") +
"/libs";
filesmap = JSON.parse(JSON.stringify(filesmap0));
const pxtmod = "pxt_modules/";
const filesByPkg = {};
const filenames = Object.keys(filesmap);
for (const s of filenames) {
if (s.startsWith(pxtmod)) {
const id = s.slice(pxtmod.length).replace(/\/.*/, "");
if (!filesByPkg[id])
filesByPkg[id] = [];
filesByPkg[id].push(s);
}
}
for (const id of Object.keys(filesByPkg)) {
let lnk = (_a = this.mkcConfig.links) === null || _a === void 0 ? void 0 : _a[id];
let rel = "";
if (lnk)
rel = exports.files.relativePath(this.directory + "/pxt_modules/foobar", lnk);
else if (await exports.files.fileExistsAsync(`${libsPath}/${id}/pxt.json`)) {
lnk = `${libsPath}/${id}`;
rel = `../../${lnk}`;
}
if (lnk && this.linkPxtModules) {
for (const fn of filesByPkg[id])
delete filesmap[fn];
(0, exports.log)(`link ${id} -> ${lnk}`);
const pxtJson = JSON.stringify({
additionalFilePath: rel,
}, null, 4);
filesmap["pxt_modules/" + id + "/pxt.json"] = pxtJson;
if (/---/.test(id)) {
filesmap["pxt_modules/" +
id.replace(/---.*/, "") +
"/pxt.json"] = pxtJson;
}
}
else if (lnk && this.symlinkPxtModules) {
for (const fn of filesByPkg[id]) {
const bn = fn.replace(/.*\//, "");
if (await exports.files.fileExistsAsync(`${lnk}/${bn}`)) {
filesmap[fn] = { symlink: `${rel}/${bn}` };
// log(`symlink ${fn} -> ${rel}/${bn}`)
}
else {
(0, exports.log)(`not link ${fn}`);
}
}
}
}
}
return exports.files.savePxtModulesAsync(this.directory, filesmap);
}
async readPxtConfig() {
const pxtJson = await this.readFileAsync("pxt.json");
return JSON.parse(pxtJson);
}
async readPackageAsync() {
if (!this.mkcConfig)
this.mkcConfig = JSON.parse(await this.readFileAsync("mkc.json").then(s => s, _err => "{}"));
const res = {
config: await this.readPxtConfig(),
mkcConfig: this.mkcConfig,
files: {},
};
if (res.mkcConfig.overrides)
jsonCopyFrom(res.config, res.mkcConfig.overrides);
res.files["pxt.json"] = stringifyConfig(res.config);
for (let f of res.config.files.concat(res.config.testFiles || [])) {
res.files[f] = await this.readFileAsync(f);
}
if (res.files["main.ts"] === undefined)
res.files["main.ts"] = ""; // avoid bogus warning from PXT
return res;
}
async loadPkgAsync() {
if (this.mainPkg)
return;
const prj = await this.readPackageAsync();
exports.loader.guessMkcJson(prj);
if (this.hwVariant)
prj.mkcConfig.hwVariant = this.hwVariant;
// TODO handle require("lzma") in worker
prj.config.binaryonly = true;
const pxtJson = (prj.files["pxt.json"] = stringifyConfig(prj.config));
this.mainPkg = prj;
if (pxtJson != this.lastPxtJson) {
this.lastPxtJson = pxtJson;
if (this.service)
await this.service.setUserAsync(null);
}
}
updateEditorAsync() {
return this.loadEditorAsync(true);
}
async loadEditorAsync(forceUpdate = false) {
if (this.editor && !forceUpdate)
return false;
await this.loadPkgAsync();
const newEditor = await exports.downloader.downloadAsync(await this.getCacheAsync(), this.mainPkg.mkcConfig.targetWebsite, !forceUpdate);
if (!this.editor ||
newEditor.versionNumber != this.editor.versionNumber) {
this.editor = newEditor;
if (this.service) {
this.service.dispose();
}
this.service = new exports.service.Ctx(this.editor);
return true;
}
else {
return false;
}
}
async getCacheAsync() {
if (!this.cache)
this.cache = await exports.files.mkHomeCacheAsync();
return this.cache;
}
async maybeWritePxtModulesAsync() {
await this.loadEditorAsync();
await this.loadPkgAsync();
const wasThis = this.service.lastUser == this;
this.service.setUserAsync(this);
if (this.service.supportsGhPkgs) {
await this.service.installGhPackagesAsync(this.mainPkg);
}
else {
await exports.loader.loadDeps(this.editor, this.mainPkg);
}
if (this.writePxtModules && !wasThis) {
(0, exports.log)("writing pxt_modules/*");
await this.savePxtModulesAsync(this.mainPkg.files);
}
}
async linkedPackage(id) {
var _a, _b, _c;
const folder = (_c = (_b = (_a = this.mainPkg) === null || _a === void 0 ? void 0 : _a.mkcConfig) === null || _b === void 0 ? void 0 : _b.links) === null || _c === void 0 ? void 0 : _c[id];
if (folder)
return exports.files.readProjectAsync(folder);
return null;
}
async buildAsync(simpleOpts = {}) {
var _a;
this.mainPkg = null; // force reload
await this.maybeWritePxtModulesAsync();
await this.service.setUserAsync(this);
const res = await this.service.simpleCompileAsync(this.mainPkg, simpleOpts);
const err = res.errorMessage;
if (err)
throw new Error(err);
const binjs = "binary.js";
if (res.outfiles[binjs]) {
const appTarget = await this.service.languageService.getAppTargetAsync();
const boardDef = (_a = appTarget.simulator) === null || _a === void 0 ? void 0 : _a.boardDefinition;
if (boardDef) {
res.outfiles[binjs] =
`// boardDefinition=${JSON.stringify(boardDef)}\n` +
res.outfiles[binjs];
}
const webConfig = this.editor.webConfig || (await this.service.languageService.getWebConfigAsync());
const configs = await (0, files_1.monoRepoConfigsAsync)(this.directory, true);
const version = `v${await (0, files_1.collectCurrentVersionAsync)(configs) || "0"}`;
const meta = {
simUrl: webConfig.simUrl,
cdnUrl: webConfig.cdnUrl,
version,
target: appTarget.id,
targetVersion: appTarget.versions.target,
};
res.outfiles[binjs] =
`// meta=${JSON.stringify(meta)}\n` + res.outfiles[binjs];
}
await this.saveBuiltFilesAsync(res);
//delete res.outfiles
//delete (res as any).procDebugInfo
//console.log(res)
return res;
}
async buildSimJsInfoAsync(result) {
return await this.service.buildSimJsInfoAsync(result);
}
async mkChildProjectAsync(folder) {
const prj = new Project(folder, await this.getCacheAsync());
prj.service = this.service;
prj.mkcConfig = this.mkcConfig;
if (this._hwVariant)
prj.hwVariant = this._hwVariant;
prj.outputPrefix = this.outputPrefix;
prj.writePxtModules = this.writePxtModules;
prj.editor = this.editor;
return prj;
}
}
exports.Project = Project;
let log = (msg) => {
console.log(msg);
};
exports.log = log;
let error = (msg) => {
console.error(msg);
};
exports.error = error;
let debug = (msg) => {
console.debug(msg);
};
exports.debug = debug;
function setLogging(fns) {
exports.log = fns.log;
exports.error = fns.error;
exports.debug = fns.debug;
}
exports.setLogging = setLogging;
function stringifyConfig(cfg) {
return JSON.stringify(cfg, null, 4) + "\n";
}
exports.stringifyConfig = stringifyConfig;
//# sourceMappingURL=mkc.js.map