mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) move home server into core
Summary: This moves enough server material into core to run a home server. The data engine is not yet incorporated (though in manual testing it works when ported). Test Plan: existing tests pass Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2552
This commit is contained in:
79
app/server/lib/manifest.ts
Normal file
79
app/server/lib/manifest.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import {BarePlugin} from 'app/plugin/PluginManifest';
|
||||
import PluginManifestTI from 'app/plugin/PluginManifest-ti';
|
||||
import * as fse from 'fs-extra';
|
||||
import * as yaml from 'js-yaml';
|
||||
import * as path from 'path';
|
||||
import {createCheckers} from "ts-interface-checker";
|
||||
|
||||
const manifestChecker = createCheckers(PluginManifestTI).BarePlugin;
|
||||
/**
|
||||
* Validate the manifest and generate appropriate errors.
|
||||
*/
|
||||
// TODO: should validate that the resources referenced within the manifest are located within the
|
||||
// plugin folder
|
||||
// TODO: Need a comprehensive test that triggers every notices;
|
||||
function isValidManifest(manifest: any, notices: string[]): boolean {
|
||||
if (!manifest) {
|
||||
notices.push("missing manifest");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
manifestChecker.check(manifest);
|
||||
} catch (e) {
|
||||
notices.push(`Invalid manifest: ${e.message}`);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
manifestChecker.strictCheck(manifest);
|
||||
} catch (e) {
|
||||
notices.push(`WARNING: ${e.message}` );
|
||||
/* but don't fail */
|
||||
}
|
||||
if (Object.keys(manifest.contributions).length === 0) {
|
||||
notices.push("WARNING: no valid contributions");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A ManifestError is an error caused by a wrongly formatted manifest or missing manifest. The
|
||||
* `notices` property holds a user-friendly description of the error(s).
|
||||
*/
|
||||
export class ManifestError extends Error {
|
||||
constructor(public notices: string[], message: string = "") {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the manifest. Look first for a Yaml manifest and then if missing for a Json manifest.
|
||||
*/
|
||||
export async function readManifest(pluginPath: string): Promise<BarePlugin> {
|
||||
const notices: string[] = [];
|
||||
const manifest = await _readManifest(pluginPath);
|
||||
if (isValidManifest(manifest, notices)) {
|
||||
return manifest as BarePlugin;
|
||||
}
|
||||
throw new ManifestError(notices);
|
||||
}
|
||||
|
||||
async function _readManifest(pluginPath: string): Promise<object> {
|
||||
try {
|
||||
return yaml.safeLoad(await readManifestFile("yml"));
|
||||
} catch (e) {
|
||||
if (e instanceof yaml.YAMLException) {
|
||||
throw new Error('error parsing yaml manifest: ' + e.message);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return JSON.parse(await readManifestFile("json"));
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
throw new Error('error parsing json manifest' + e.message);
|
||||
}
|
||||
throw new Error('cannot read manifest file: ' + e.message);
|
||||
}
|
||||
async function readManifestFile(fileExtension: string): Promise<string> {
|
||||
return await fse.readFile(path.join(pluginPath, "manifest." + fileExtension), "utf8");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user