Dependency audit / audit (push) Canceled after 0s
CI / plan (push) Canceled after 0s
Gitoxide helper admission / macos-latest (push) Canceled after 0s
Gitoxide helper admission / ubuntu-latest (push) Canceled after 0s
Gitoxide helper admission / windows-latest (push) Canceled after 0s
Runtime Host peer admission / quality (push) Canceled after 0s
Windows recovery / windows_recovery (push) Canceled after 0s
CI / heavy (push) Canceled after 0s
CI / test (push) Canceled after 0s
137 lines
5.2 KiB
JavaScript
137 lines
5.2 KiB
JavaScript
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
import { existsSync, readFileSync } from 'node:fs';
|
|
import { extname, join, relative, resolve, sep } from 'node:path';
|
|
import { build } from 'esbuild';
|
|
import { parse as parseYaml } from 'yaml';
|
|
|
|
const defaultRepoRoot = resolve(import.meta.dirname, '..');
|
|
const sourceExtensions = ['.ts', '.tsx', '.mts', '.cts', '.js', '.mjs', '.cjs', '.json'];
|
|
|
|
export const windowsPackageSourceEntrypoints = [
|
|
'packages/runtime/src/filesystem-worker/index.ts',
|
|
'packages/runtime/src/filesystem-worker/worker-entry.ts',
|
|
'packages/runtime/src/sandbox/index.ts',
|
|
];
|
|
|
|
export async function collectWindowsPackageSourceClosure(repoRoot = defaultRepoRoot) {
|
|
const workspaces = loadWorkspacePackages(repoRoot);
|
|
const result = await build({
|
|
absWorkingDir: repoRoot,
|
|
bundle: true,
|
|
entryPoints: windowsPackageSourceEntrypoints,
|
|
format: 'esm',
|
|
logLevel: 'silent',
|
|
metafile: true,
|
|
outdir: 'windows-package-source-closure',
|
|
packages: 'external',
|
|
platform: 'node',
|
|
plugins: [workspaceSourcePlugin(repoRoot, workspaces)],
|
|
treeShaking: false,
|
|
write: false,
|
|
});
|
|
return Object.keys(result.metafile.inputs)
|
|
.map(normalize)
|
|
.filter((path) => path.startsWith('packages/'))
|
|
.sort();
|
|
}
|
|
|
|
export function readWindowsReleasePathPatterns(repoRoot = defaultRepoRoot) {
|
|
const workflowPath = join(repoRoot, '.github', 'workflows', 'release-windows-check.yml');
|
|
const workflow = parseYaml(readFileSync(workflowPath, 'utf8'));
|
|
const paths = workflow?.on?.pull_request?.paths;
|
|
if (!Array.isArray(paths) || !paths.every((path) => typeof path === 'string')) {
|
|
throw new Error('Release Windows check must declare pull_request.paths as strings.');
|
|
}
|
|
return paths;
|
|
}
|
|
|
|
export function windowsReleasePatternCoversSource(path, pattern) {
|
|
if (path === pattern) return true;
|
|
return pattern.endsWith('/**') && path.startsWith(pattern.slice(0, -2));
|
|
}
|
|
|
|
function workspaceSourcePlugin(repoRoot, workspaces) {
|
|
return {
|
|
name: 'maka-workspace-source',
|
|
setup(esbuild) {
|
|
esbuild.onResolve({ filter: /^@maka\// }, ({ path: specifier }) => {
|
|
const workspace = [...workspaces.values()].find(
|
|
({ name }) => specifier === name || specifier.startsWith(`${name}/`),
|
|
);
|
|
if (!workspace) return undefined;
|
|
const subpath =
|
|
specifier === workspace.name ? '.' : `.${specifier.slice(workspace.name.length)}`;
|
|
const exported = exportTarget(workspace.manifest.exports?.[subpath]);
|
|
const candidate = exported
|
|
? resolve(workspace.directory, exported.replace(/^\.\/dist\//u, './src/'))
|
|
: resolve(workspace.directory, 'src', specifier.slice(workspace.name.length + 1));
|
|
return { path: resolveSourceCandidate(candidate, repoRoot, specifier) };
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
function resolveSourceCandidate(candidate, repoRoot, specifier) {
|
|
const extension = extname(candidate);
|
|
const candidates = [candidate];
|
|
if (['.js', '.mjs', '.cjs'].includes(extension)) {
|
|
const stem = candidate.slice(0, -extension.length);
|
|
candidates.push(...sourceExtensions.map((sourceExtension) => `${stem}${sourceExtension}`));
|
|
} else if (!extension) {
|
|
candidates.push(...sourceExtensions.map((sourceExtension) => `${candidate}${sourceExtension}`));
|
|
candidates.push(
|
|
...sourceExtensions.map((sourceExtension) => join(candidate, `index${sourceExtension}`)),
|
|
);
|
|
}
|
|
const resolved = candidates.find((path) => existsSync(path));
|
|
if (!resolved || !normalize(relative(repoRoot, resolved)).startsWith('packages/')) {
|
|
throw new Error(
|
|
`Unable to resolve local Windows package import ${specifier} from ${candidate}`,
|
|
);
|
|
}
|
|
return resolved;
|
|
}
|
|
|
|
function exportTarget(value) {
|
|
if (typeof value === 'string') return value;
|
|
if (!value || typeof value !== 'object') return undefined;
|
|
for (const condition of ['types', 'import', 'default']) {
|
|
const target = exportTarget(value[condition]);
|
|
if (target) return target;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function loadWorkspacePackages(repoRoot) {
|
|
const rootManifest = JSON.parse(readFileSync(join(repoRoot, 'package.json'), 'utf8'));
|
|
const result = new Map();
|
|
for (const workspacePath of rootManifest.workspaces ?? []) {
|
|
const directory = resolve(repoRoot, workspacePath);
|
|
const manifest = JSON.parse(readFileSync(join(directory, 'package.json'), 'utf8'));
|
|
result.set(manifest.name, { directory, manifest, name: manifest.name });
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function normalize(path) {
|
|
return path.split(sep).join('/');
|
|
}
|