diff --git a/.ghjk/lock.json b/.ghjk/lock.json index 5f546e72..6e0b86c9 100644 --- a/.ghjk/lock.json +++ b/.ghjk/lock.json @@ -17,7 +17,7 @@ "version": "3.12.1", "depConfigs": { "tar_aa": { - "version": "1.34", + "version": "1.35", "depConfigs": {}, "portRef": "tar_aa@0.1.0" }, @@ -37,7 +37,7 @@ "version": "3.12.1", "depConfigs": { "tar_aa": { - "version": "1.34", + "version": "1.35", "depConfigs": {}, "portRef": "tar_aa@0.1.0" }, @@ -50,7 +50,7 @@ "portRef": "cpy_bs_ghrel@0.1.0" }, "9e3fa7742c431c34ae7ba8d1e907e50c937ccfb631fb4dcfb7a1773742abe267": { - "version": "1.34", + "version": "1.35", "depConfigs": {}, "portRef": "tar_aa@0.1.0" }, @@ -63,7 +63,7 @@ "version": "3.12.0", "depConfigs": { "tar_aa": { - "version": "1.34", + "version": "1.35", "depConfigs": {}, "portRef": "tar_aa@0.1.0" }, @@ -103,6 +103,15 @@ "7d7b0f4b9ec5375688fceab016687f3ac3fbc94c" ], "allowedDeps": "48a429761f3837562b097b47afe07601ba4ffca5" + }, + "ghjkEnvProvInstSet___test": { + "installs": [ + "aa103d26454710ca5d7f43358123341380389864", + "c4cf06e095dadfbdd5e26070bc2b7baffc5ff45f", + "9283b97b5499e8da4dcfb7f14c1306c25e8e8a44", + "7d7b0f4b9ec5375688fceab016687f3ac3fbc94c" + ], + "allowedDeps": "48a429761f3837562b097b47afe07601ba4ffca5" } } } @@ -117,7 +126,25 @@ { "id": "envs", "config": { - "envs": {} + "envs": { + "main": { + "provides": [ + { + "ty": "ghjk.ports.InstallSetRef", + "setId": "ghjkEnvProvInstSet___main" + } + ] + }, + "test": { + "provides": [ + { + "ty": "ghjk.ports.InstallSetRef", + "setId": "ghjkEnvProvInstSet___test" + } + ] + } + }, + "defaultEnv": "main" } } ], @@ -523,6 +550,20 @@ "asdf_plugin_git": "a36b37f4eda81bf51a50d00362637690c7fea473", "node_org": "5843605c861f0b7307c0192a1628c3823fe28ed9", "cpy_bs_ghrel": "7a33163826283c47b52964a23b87a4762662c746" + }, + "aa103d26454710ca5d7f43358123341380389864": { + "port": { + "ty": "denoWorker@v1", + "name": "protoc_ghrel", + "platforms": [ + "aarch64-linux", + "x86_64-linux", + "aarch64-darwin", + "x86_64-darwin" + ], + "version": "0.1.0", + "moduleSpecifier": "file:///ports/protoc.ts" + } } } } diff --git a/ghjk.ts b/ghjk.ts index 64d4c2d2..c841dd78 100644 --- a/ghjk.ts +++ b/ghjk.ts @@ -1,5 +1,5 @@ export { ghjk } from "./mod.ts"; -import { install, stdSecureConfig } from "./mod.ts"; +import { env, install, stdSecureConfig } from "./mod.ts"; import * as ports from "./ports/mod.ts"; // these are just for quick testing @@ -12,4 +12,10 @@ install( ports.cpy_bs({ releaseTag: "20231002" }), ); -export const secureConfig = stdSecureConfig({ enableRuntimes: true }); +env("test") + .install(ports.protoc()); + +export const secureConfig = stdSecureConfig({ + enableRuntimes: true, + defaultBaseEnv: "test", +}); diff --git a/mod.ts b/mod.ts index 811e6ca7..fd2c986d 100644 --- a/mod.ts +++ b/mod.ts @@ -44,7 +44,7 @@ import { WellKnownProvision, } from "./modules/envs/types.ts"; -const DEFAULT_ENV_NAME = "main"; +const DEFAULT_BASE_ENV_NAME = "main"; export type EnvDefArgs = { name: string; @@ -135,7 +135,7 @@ class GhjkfileBuilder { env = new EnvBuilder(this, (fin) => finalizer = fin, args.name); this.#seenEnvs[args.name] = [env, finalizer!]; } - if (args.envBase) { + if (args.envBase !== undefined) { env.base(args.envBase); } if (args.installs) { @@ -162,8 +162,14 @@ class GhjkfileBuilder { toConfig(secureConfig: PortsModuleSecureConfig | undefined) { try { - const envsConfig = this.#processEnvs(); - const tasksConfig = this.#processTasks(envsConfig); + const defaultEnv = secureConfig?.defaultEnv ?? DEFAULT_BASE_ENV_NAME; + const defaultBaseEnv = secureConfig?.defaultBaseEnv ?? + DEFAULT_BASE_ENV_NAME; + const envsConfig = this.#processEnvs( + defaultEnv, + defaultBaseEnv, + ); + const tasksConfig = this.#processTasks(envsConfig, defaultBaseEnv); const portsConfig = this.#processInstalls( secureConfig?.masterPortDepAllowList ?? stdDeps(), ); @@ -208,7 +214,10 @@ class GhjkfileBuilder { // this processes the defined envs, normalizing dependency (i.e. "envBase") // relationships to produce the standard EnvsModuleConfig - #processEnvs() { + #processEnvs( + defaultEnv: string, + defaultBaseEnv: string, + ) { const all = {} as Record< string, ReturnType & { envBaseResolved: null | string } @@ -223,7 +232,7 @@ class GhjkfileBuilder { const envBaseResolved = typeof envBase === "string" ? envBase : envBase - ? DEFAULT_ENV_NAME + ? defaultBaseEnv : null; all[name] = { ...final, envBaseResolved }; if (envBaseResolved) { @@ -238,14 +247,16 @@ class GhjkfileBuilder { } } const processed = {} as Record; - const out: EnvsModuleConfig = { envs: {} }; - const workingSet = indie; + const out: EnvsModuleConfig = { envs: {}, defaultEnv }; + const workingSet = [...indie]; while (workingSet.length > 0) { const item = workingSet.pop()!; const final = all[item]; + const base = final.envBaseResolved ? processed[final.envBaseResolved] : null; + let processedInstallSetId: string | undefined; { const installSet = this.#installSets.get(final.installSetId); @@ -286,23 +297,29 @@ class GhjkfileBuilder { ...Object.entries(final.vars).map(( [key, val], ) => { - const prov: WellKnownProvision = { ty: "envVar", key, val }; + const prov: WellKnownProvision = { ty: "posix.envVar", key, val }; return prov; }), ], }; if (processedInstallSetId) { const prov: InstallSetRefProvision = { - ty: "ghjkPortsInstallSetRef", + ty: "ghjk.ports.InstallSetRef", setId: processedInstallSetId, }; out.envs[final.name].provides.push(prov); } + + const curRevDeps = revDeps.get(final.name); + if (curRevDeps) { + workingSet.push(...curRevDeps); + revDeps.delete(final.name); + } } return out; } - #processTasks(envsConfig: EnvsModuleConfig) { + #processTasks(envsConfig: EnvsModuleConfig, defaultBaseEnv: string) { const out: TasksModuleConfig = { envs: {}, tasks: {}, @@ -317,7 +334,7 @@ class GhjkfileBuilder { const envBaseResolved = typeof envBase === "string" ? envBase : envBase - ? DEFAULT_ENV_NAME + ? defaultBaseEnv : null; const envBaseRecipe = envBaseResolved @@ -344,11 +361,11 @@ class GhjkfileBuilder { | InstallSetRefProvision )[] ) { - if (prov.ty == "envVar") { + if (prov.ty == "posix.envVar") { if (!mergedEnvVars[prov.key]) { mergedEnvVars[prov.key] = prov.val; } - } else if (prov.ty == "ghjkPortsInstallSetRef") { + } else if (prov.ty == "ghjk.ports.InstallSetRef") { const baseSet = this.#installSets.get(prov.setId)!; const mergedInstallsSet = new Set([ ...taskInstallSet.installs, @@ -373,7 +390,7 @@ class GhjkfileBuilder { const setId = `ghjkTaskInstSet___${name}`; this.#installSets.set(setId, taskInstallSet); const prov: InstallSetRefProvision = { - ty: "ghjkPortsInstallSetRef", + ty: "ghjk.ports.InstallSetRef", setId, }; taskEnvRecipe.provides.push(prov); @@ -383,7 +400,7 @@ class GhjkfileBuilder { ...Object.entries(mergedEnvVars).map(( [key, val], ) => { - const prov: WellKnownProvision = { ty: "envVar", key, val }; + const prov: WellKnownProvision = { ty: "posix.envVar", key, val }; return prov; }), ); @@ -514,7 +531,7 @@ class EnvBuilder { const file = new GhjkfileBuilder(); const mainEnv = file.addEnv({ - name: DEFAULT_ENV_NAME, + name: DEFAULT_BASE_ENV_NAME, envBase: false, allowedPortDeps: stdDeps(), }); @@ -579,7 +596,7 @@ export function stdSecureConfig( args: { additionalAllowedPorts?: PortsModuleSecureConfig["masterPortDepAllowList"]; enableRuntimes?: boolean; - }, + } & Pick, ): PortsModuleSecureConfig { const { additionalAllowedPorts, enableRuntimes = false } = args; const out: PortsModuleSecureConfig = { diff --git a/modules/envs/mod.ts b/modules/envs/mod.ts index 8304b15a..5b785217 100644 --- a/modules/envs/mod.ts +++ b/modules/envs/mod.ts @@ -9,7 +9,7 @@ export * from "./types.ts"; import { cliffy_cmd, zod } from "../../deps/cli.ts"; -import { Json } from "../../utils/mod.ts"; +import { $, Json, unwrapParseRes } from "../../utils/mod.ts"; import validators from "./types.ts"; import type { EnvsModuleConfigX } from "./types.ts"; @@ -17,48 +17,72 @@ import type { GhjkCtx, ModuleManifest } from "../types.ts"; import { ModuleBase } from "../mod.ts"; import { Blackboard } from "../../host/types.ts"; +import { reduceStrangeProvisions } from "./reducer.ts"; +import { cookPosixEnv } from "./posix.ts"; + +export type EnvsCtx = { + activeEnv: string; + config: EnvsModuleConfigX; +}; -export type EnvsCtx = {}; const lockValidator = zod.object({ version: zod.string(), }); + type EnvsLockEnt = zod.infer; export class EnvsModule extends ModuleBase { processManifest( _ctx: GhjkCtx, manifest: ModuleManifest, - _bb: Blackboard, + bb: Blackboard, _lockEnt: EnvsLockEnt | undefined, ) { - const res = validators.envsModuleConfig.safeParse(manifest.config); - if (!res.success) { - throw new Error("error parsing module config", { - cause: { - config: manifest.config, - zodErr: res.error, - }, - }); + function unwrapParseCurry(res: zod.SafeParseReturnType) { + return unwrapParseRes(res, { + id: manifest.id, + config: manifest.config, + bb, + }, "error parsing module config"); } - const config: EnvsModuleConfigX = { - ...res.data, - }; + const config = unwrapParseCurry( + validators.envsModuleConfig.safeParse(manifest.config), + ); + + const activeEnv = config.defaultEnv; return Promise.resolve({ + activeEnv, config, }); } command( - _gcx: GhjkCtx, - _ecx: EnvsCtx, + gcx: GhjkCtx, + ecx: EnvsCtx, ) { const root: cliffy_cmd.Command = new cliffy_cmd .Command() + .description("Envs module, the cornerstone") .alias("e") + .alias("env") .action(function () { this.showHelp(); }) + .command( + "sync", + new cliffy_cmd.Command().description("Syncs the environment.") + .action(async () => { + const envName = ecx.activeEnv; + + const env = ecx.config.envs[envName]; + // TODO: diff env and ask confirmation from user + const reducedEnv = await reduceStrangeProvisions(gcx, env); + const envDir = $.path(gcx.ghjkDir).join("envs", envName).toString(); + + await cookPosixEnv(reducedEnv, envDir, true); + }), + ) .description("Envs module."); return root; } diff --git a/modules/envs/posix.ts b/modules/envs/posix.ts index fd7c2484..8a2b2f5a 100644 --- a/modules/envs/posix.ts +++ b/modules/envs/posix.ts @@ -1,61 +1,14 @@ import { std_fs, std_path } from "../../deps/cli.ts"; -import type { - EnvRecipeX, - Provision, - WellKnownEnvRecipeX, - WellKnownProvision, -} from "./types.ts"; -import validators from "./types.ts"; -import { wellKnownProvisionTypes } from "./types.ts"; +import type { WellKnownEnvRecipeX } from "./types.ts"; import getLogger from "../../utils/logger.ts"; import { $, PathRef } from "../../utils/mod.ts"; -import type { GhjkCtx } from "../types.ts"; -import { getProvisionReducerStore } from "./reducer.ts"; const logger = getLogger(import.meta); -export async function reduceStrangeProvisions( - gcx: GhjkCtx, - env: EnvRecipeX, -) { - const reducerStore = getProvisionReducerStore(gcx); - const bins = {} as Record; - for (const item of env.provides) { - let bin = bins[item.ty]; - if (!bin) { - bin = []; - bins[item.ty] = bin; - } - bin.push(item); - } - const reducedSet = [] as WellKnownProvision[]; - for (const [ty, items] of Object.entries(bins)) { - if (wellKnownProvisionTypes.includes(ty as any)) { - reducedSet.push( - ...items.map((item) => validators.wellKnownProvision.parse(item)), - ); - continue; - } - const reducer = reducerStore.get(ty); - if (!reducer) { - throw new Error(`no provider reducer found for ty: ${ty}`, { - cause: items, - }); - } - const reduced = await reducer(items); - reducedSet.push(validators.wellKnownProvision.parse(reduced)); - } - const out: WellKnownEnvRecipeX = { - ...env, - provides: reducedSet, - }; - return out; -} - -export async function cookUnixEnv( +export async function cookPosixEnv( env: WellKnownEnvRecipeX, envDir: string, - createShellLoaders = true, + createShellLoaders = false, ) { // create the shims for the user's environment const shimDir = $.path(envDir).join("shims"); @@ -78,16 +31,16 @@ export async function cookUnixEnv( await Promise.all(env.provides.map((item) => { switch (item.ty) { - case "posixExec": + case "posix.exec": binPaths.push(item.absolutePath); break; - case "posixSharedLib": + case "posix.sharedLib": libPaths.push(item.absolutePath); break; - case "headerFile": + case "posix.headerFile": includePaths.push(item.absolutePath); break; - case "envVar": + case "posix.envVar": if (vars[item.key]) { throw new Error( `env var conflict cooking unix env: key "${item.key}" has entries "${ @@ -101,21 +54,23 @@ export async function cookUnixEnv( throw Error(`unsupported provision type: ${(item as any).provision}`); } })); - // bin shims - void await shimLinkPaths( - binPaths, - binShimDir, - ); - // lib shims - void await shimLinkPaths( - libPaths, - libShimDir, - ); - // include shims - void await shimLinkPaths( - includePaths, - includeShimDir, - ); + void await Promise.all([ + // bin shims + await shimLinkPaths( + binPaths, + binShimDir, + ), + // lib shims + await shimLinkPaths( + libPaths, + libShimDir, + ), + // include shims + await shimLinkPaths( + includePaths, + includeShimDir, + ), + ]); // write loader for the env vars mandated by the installs logger.debug("adding vars to loader", vars); // FIXME: prevent malicious env manipulations diff --git a/modules/envs/reducer.ts b/modules/envs/reducer.ts index 3860de33..28357be8 100644 --- a/modules/envs/reducer.ts +++ b/modules/envs/reducer.ts @@ -1,5 +1,14 @@ +import { unwrapParseRes } from "../../port.ts"; import type { GhjkCtx } from "../types.ts"; -import type { Provision, ProvisionReducer } from "./types.ts"; +import type { + EnvRecipeX, + Provision, + ProvisionReducer, + WellKnownEnvRecipeX, + WellKnownProvision, +} from "./types.ts"; +import { wellKnownProvisionTypes } from "./types.ts"; +import validators from "./types.ts"; export type ProvisionReducerStore = Map>; export function getProvisionReducerStore( @@ -15,3 +24,50 @@ export function getProvisionReducerStore( } return store; } + +export async function reduceStrangeProvisions( + gcx: GhjkCtx, + env: EnvRecipeX, +) { + const reducerStore = getProvisionReducerStore(gcx); + // Replace by `Object.groupBy` once the types for it are fixed + const bins = {} as Record; + for (const item of env.provides) { + let bin = bins[item.ty]; + if (!bin) { + bin = []; + bins[item.ty] = bin; + } + bin.push(item); + } + const reducedSet = [] as WellKnownProvision[]; + for (const [ty, items] of Object.entries(bins)) { + if (wellKnownProvisionTypes.includes(ty as any)) { + reducedSet.push( + ...items.map((item) => validators.wellKnownProvision.parse(item)), + ); + continue; + } + const reducer = reducerStore.get(ty); + if (!reducer) { + throw new Error(`no provider reducer found for ty: ${ty}`, { + cause: items, + }); + } + const reduced = await reducer(items); + reducedSet.push( + ...reduced.map((prov) => + unwrapParseRes( + validators.wellKnownProvision.safeParse(prov), + { prov }, + `error parsing reduced provision`, + ) + ), + ); + } + const out: WellKnownEnvRecipeX = { + ...env, + provides: reducedSet, + }; + return out; +} diff --git a/modules/envs/types.ts b/modules/envs/types.ts index f0b347a3..00554972 100644 --- a/modules/envs/types.ts +++ b/modules/envs/types.ts @@ -5,15 +5,15 @@ const absolutePath = zod.string().refine((path) => std_path.isAbsolute(path)); const provision = zod.object({ ty: zod.string() }).passthrough(); const posixFileProvisionTypes = [ - "posixExec", - "posixSharedLib", - "headerFile", + "posix.exec", + "posix.sharedLib", + "posix.headerFile", ] as const; // we separate the posix file types in a separate // array in the interest of type inference export const wellKnownProvisionTypes = [ - "envVar", + "posix.envVar", ...posixFileProvisionTypes, ] as const; @@ -40,7 +40,10 @@ const wellKnownEnvRecipe = envRecipe.merge(zod.object({ })); const envsModuleConfig = zod.object({ + defaultEnv: zod.string(), envs: zod.record(zod.string(), envRecipe), +}).refine((conf) => conf.envs[conf.defaultEnv], { + message: `no env found under the provided "defaultEnv"`, }); const validators = { diff --git a/modules/ports/mod.ts b/modules/ports/mod.ts index 506556c8..49e60da9 100644 --- a/modules/ports/mod.ts +++ b/modules/ports/mod.ts @@ -1,7 +1,7 @@ export * from "./types.ts"; import { cliffy_cmd, zod } from "../../deps/cli.ts"; -import { $, Json, unwrapParseRes } from "../../utils/mod.ts"; +import { Json, unwrapParseRes } from "../../utils/mod.ts"; import logger from "../../utils/logger.ts"; import validators, { installSetProvisionTy, @@ -13,7 +13,6 @@ import { ModuleBase } from "../mod.ts"; import { buildInstallGraph, getResolutionMemo, - installFromGraphAndShimEnv, type InstallGraph, syncCtxFromGhjk, } from "./sync.ts"; // TODO: rename to install.ts @@ -113,8 +112,8 @@ export class PortsModule extends ModuleBase { } command( - gcx: GhjkCtx, - pcx: PortsCtx, + _gcx: GhjkCtx, + _pcx: PortsCtx, ) { return new cliffy_cmd.Command() .alias("p") @@ -122,20 +121,6 @@ export class PortsModule extends ModuleBase { this.showHelp(); }) .description("Ports module, install programs into your env.") - .command( - "sync", - new cliffy_cmd.Command().description("Syncs the environment.") - .action(async () => { - logger().debug("syncing ports"); - await using syncCx = await syncCtxFromGhjk(gcx); - void await installFromGraphAndShimEnv( - syncCx, - $.path(gcx.ghjkDir).join("envs", "default").toString(), - // FIXME: - pcx.installGraphs.values().next().value, - ); - }), - ) .command( "outdated", new cliffy_cmd.Command() diff --git a/modules/ports/reducers.ts b/modules/ports/reducers.ts index e275c639..9c843bbf 100644 --- a/modules/ports/reducers.ts +++ b/modules/ports/reducers.ts @@ -98,7 +98,7 @@ async function reduceInstArts( } foundEnvVars[key] = [val, instId]; out.push({ - ty: "envVar", + ty: "posix.envVar", key, val, }); @@ -117,19 +117,19 @@ async function reduceInstArts( out.push( ...binPathsNorm.flatMap((paths) => paths.map((absolutePath) => ({ - ty: "posixExec" as const, + ty: "posix.exec" as const, absolutePath, })) ), ...libPathsNorm.flatMap((paths) => paths.map((absolutePath) => ({ - ty: "posixSharedLib" as const, + ty: "posix.sharedLib" as const, absolutePath, })) ), ...includePathsNorm.flatMap((paths) => paths.map((absolutePath) => ({ - ty: "headerFile" as const, + ty: "posix.headerFile" as const, absolutePath, })) ), diff --git a/modules/ports/types.ts b/modules/ports/types.ts index 94942858..199ac4f1 100644 --- a/modules/ports/types.ts +++ b/modules/ports/types.ts @@ -146,6 +146,8 @@ const allowedPortDep = zod.object({ const portsModuleSecureConfig = zod.object({ masterPortDepAllowList: zod.array(allowedPortDep).nullish(), + defaultEnv: zod.string().nullish(), + defaultBaseEnv: zod.string().nullish(), }); const allowDepSet = zod.record(zod.string(), allowedPortDep); @@ -170,13 +172,13 @@ const portsModuleConfig = zod.object({ sets: zod.record(zod.string(), installSet), }); -export const installSetProvisionTy = "ghjkPortsInstallSet"; +export const installSetProvisionTy = "ghjk.ports.InstallSet"; const installSetProvision = zod.object({ ty: zod.literal(installSetProvisionTy), set: installSet, }); -export const installSetRefProvisionTy = "ghjkPortsInstallSetRef"; +export const installSetRefProvisionTy = "ghjk.ports.InstallSetRef"; const installSetRefProvision = zod.object({ ty: zod.literal(installSetRefProvisionTy), setId: zod.string(), diff --git a/modules/tasks/exec.ts b/modules/tasks/exec.ts index ed503348..4caa3a82 100644 --- a/modules/tasks/exec.ts +++ b/modules/tasks/exec.ts @@ -8,7 +8,8 @@ import { execTaskDeno } from "./deno.ts"; const logger = getLogger(import.meta); -import { cookUnixEnv, reduceStrangeProvisions } from "../envs/posix.ts"; +import { cookPosixEnv } from "../envs/posix.ts"; +import { reduceStrangeProvisions } from "../envs/reducer.ts"; export type TaskGraph = DePromisify>; @@ -117,7 +118,7 @@ export async function execTask( gcx, tasksConfig.envs[taskDef.envHash], ); - const { env: installEnvs } = await cookUnixEnv(reducedEnv, taskEnvDir); + const { env: installEnvs } = await cookPosixEnv(reducedEnv, taskEnvDir); logger.info("executing", taskName, args); await execTaskDeno( std_path.toFileUrl(gcx.ghjkfilePath).href, diff --git a/tests/ports.ts b/tests/ports.ts index d893483b..e52e9b8e 100644 --- a/tests/ports.ts +++ b/tests/ports.ts @@ -1,6 +1,6 @@ import "../setup_logger.ts"; import { std_async } from "../deps/dev.ts"; -import { secureConfig, stdDeps } from "../mod.ts"; +import { stdSecureConfig } from "../mod.ts"; import { dockerE2eTest, E2eTestCase, @@ -99,8 +99,8 @@ const cases: CustomE2eTestCase[] = [ name: "npmi-node-gyp", installConf: ports.npmi({ packageName: "node-gyp" }), ePoint: `node-gyp --version`, - secureConf: secureConfig({ - masterPortDepAllowList: stdDeps({ enableRuntimes: true }), + secureConf: stdSecureConfig({ + enableRuntimes: true, }), }, // node + more megs @@ -108,8 +108,8 @@ const cases: CustomE2eTestCase[] = [ name: "npmi-jco", installConf: ports.npmi({ packageName: "@bytecodealliance/jco" }), ePoint: `jco --version`, - secureConf: secureConfig({ - masterPortDepAllowList: stdDeps({ enableRuntimes: true }), + secureConf: stdSecureConfig({ + enableRuntimes: true, }), }, // 42 megs @@ -160,8 +160,8 @@ const cases: CustomE2eTestCase[] = [ name: "pipi-poetry", installConf: ports.pipi({ packageName: "poetry" }), ePoint: `poetry --version`, - secureConf: secureConfig({ - masterPortDepAllowList: stdDeps({ enableRuntimes: true }), + secureConf: stdSecureConfig({ + enableRuntimes: true, }), }, // rustup + 600 megs @@ -228,7 +228,7 @@ function testMany( // FIXME: better tests for the `InstallDb` // installs db means this shouldn't take too long // as it's the second sync - { cmd: "env bash -c 'timeout 1 ghjk ports sync'" }, + { cmd: "env bash -c 'timeout 1 ghjk env sync'" }, ], envs: { ...defaultEnvs, diff --git a/tests/test.Dockerfile b/tests/test.Dockerfile index b6b22279..9b526f2d 100644 --- a/tests/test.Dockerfile +++ b/tests/test.Dockerfile @@ -61,7 +61,7 @@ RUN < = T extends () => infer Inner ? Inner : T; + +export function switchMap< + K extends string | number | symbol, + All extends { + [Key in K]: All[K]; + }, >( val: K, branches: All, -): All[K] extends () => infer Inner ? Inner : All[K] { + // def?: D, +): K extends keyof All ? OrRetOf + : /* All[keyof All] | */ undefined { // return branches[val]; const branch = branches[val]; return typeof branch == "function" ? branch() : branch; } -const _b = match("hey", { - hey: () => 1, - hello: () => 2, - hi: 3 as const, - holla: 4, -}); +switchMap( + "holla" as string, + { + hey: () => 1, + hello: () => 2, + hi: 3, + holla: 4, + } as const, + // () =>5 +); export async function expandGlobsAndAbsolutize(path: string, wd: string) { if (std_path.isGlob(path)) {