Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 18x 4x 4x 4x 4x 4x 22x 19x 3x 6x 22x 22x 22x 18x 18x 18x 18x 1x 1x 1x | /**
* Where the framework sits, and where the repo mounting it sits.
*
* A face or a family mounts the framework one folder down, at paf/ when paf fills it, so its faces, build
* sandboxes, and node_modules/ live one level above the framework. The folder can have any name. Checked
* out on its own, the framework is its own workspace and holds no faces.
*/
import fs from 'node:fs';
import path from 'node:path';
import { createRequire } from 'node:module';
/** The appinfo that makes a folder a face, which sits at the face's own root. */
export const APPINFO_REL = 'pebble.appinfo.json';
/**
* Whether a folder's package.json lists a workspace by name, as `name`, `./name`, or `name/`, in the plain
* list form or under packages.
*/
function listsWorkspace(dir: string, name: string): boolean {
try {
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'));
const workspaces = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces && pkg.workspaces.packages;
return Array.isArray(workspaces)
&& workspaces.some((entry: unknown) => typeof entry === 'string' && entry.replace(/^\.\//, '').replace(/\/+$/, '') === name);
} catch (error) {
return false;
}
}
/**
* Whether a folder is a family: a core/ beside at least one face.
*
* @param dir The folder to look in.
* @return True when the folder holds a core/ and a face beside it.
*/
export function isFamilyRoot(dir: string): boolean {
if (!fs.existsSync(path.join(dir, 'core'))) {
return false;
}
return fs.readdirSync(dir, { withFileTypes: true })
.some((entry) => entry.isDirectory() && fs.existsSync(path.join(dir, entry.name, APPINFO_REL)));
}
/**
* The workspace a framework folder belongs to: the repo of faces above it, or the framework itself.
*
* The folder above counts when its package.json lists the framework's folder in workspaces and it is
* a face, or a family with its faces beside a core/. The name the framework's folder was given plays no
* part. The workspaces listing is what stops a framework cloned on its own from mistaking whatever
* folder it sits in for a repo of faces.
*
* @param engine The framework's folder.
* @return The repo of faces mounting it, or the framework's own folder when nothing mounts it.
*/
export function workspaceFor(engine: string): string {
const parent = path.dirname(engine);
const holdsFaces = fs.existsSync(path.join(parent, APPINFO_REL)) || isFamilyRoot(parent);
return holdsFaces && listsWorkspace(parent, path.basename(engine)) ? parent : engine;
}
/** The framework root. */
export const ENGINE = path.resolve(import.meta.dirname, '..', '..');
/** The repo mounting the framework, or the framework itself when it is checked out on its own. */
export const WORKSPACE = workspaceFor(ENGINE);
/** Whether a repo of faces mounts the framework. */
export const MOUNTED = WORKSPACE !== ENGINE;
/**
* The framework's folder relative to the workspace, with forward slashes: paf in a unit paf fills,
* or . when the framework is checked out on its own. Anything that writes the framework's path into
* a build uses this rather than assuming a name.
*/
export const ENGINE_REL = path.relative(WORKSPACE, ENGINE).split(path.sep).join('/') || '.';
/**
* Where ical.js's prebuilt ES5 CommonJS file sits, found the way node finds the package from the
* framework: its own node_modules first, then the mounting repo's once npm workspaces hoist it.
*
* The package's `exports` map blocks asking for the file by its subpath, so this resolves the
* package's `require` entry, which sits in the same dist/ folder.
*
* @return The file's absolute path, or null when ical.js is not installed.
*/
export function icaljsBundle(): string | null {
try {
const entry = createRequire(path.join(ENGINE, 'package.json')).resolve('ical.js');
return path.join(path.dirname(entry), 'ical.es5.min.cjs');
} catch {
return null;
}
}
|