Skip to content

Commit

Permalink
mapDict now accept all objects
Browse files Browse the repository at this point in the history
impoved computePropertyOnce & extendsObjectWithOnceComputedProperties
handle diffrent package managers to link
  • Loading branch information
kebkaldanil committed Aug 17, 2023
1 parent 27a751e commit 0302262
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 31 deletions.
58 changes: 45 additions & 13 deletions build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import { build, emptyDir, PackageJson } from "https://deno.land/x/dnt@0.38.0/mod
import * as flagsModule from "https://deno.land/std@0.194.0/flags/mod.ts";

const args = flagsModule.parse(Deno.args, {
string: ["d"],
string: ["d", "package-manager"],
alias: {
"package-manager": ["m"],
},
default: {
d: "./dist",
},
});
const distDir = args.d;
const packageManager = args["package-manager"] || Deno.env.get("PACKAGE_MANAGER") ||
"npm";

await emptyDir(distDir);

Expand All @@ -25,25 +30,52 @@ await build({
deno: true,
},
package: packageJson,
packageManager: "pnpm",
postBuild() {
(async () => {
const process = new Deno.Command("pnpm", {
args: ["link", "-g"],
cwd: distDir,
stderr: "piped",
stdout: "piped",
stdin: "null",
}).spawn();
packageManager: packageManager,
async postBuild() {
try {
let args: string[];
switch (packageManager) {
case "npm":
case "yarn":
args = ["link"];
break;
case "pnpm":
args = ["link", "--global"];
break;
default:
console.warn(`Unknown package manager ${packageManager}, can not link`);
return;
}
console.log(`${packageManager} ${args.join(" ")}`);
let process: Deno.ChildProcess;
try {
process = new Deno.Command(packageManager, {
args,
cwd: distDir,
stderr: "piped",
stdout: "piped",
stdin: "null",
}).spawn();
} catch (e) {
process = new Deno.Command(packageManager + ".cmd", {
args,
cwd: distDir,
stderr: "piped",
stdout: "piped",
stdin: "null",
}).spawn();
}
process.stderr.pipeTo(Deno.stderr.writable, { preventClose: true });
process.stdout.pipeTo(Deno.stdout.writable, { preventClose: true });
const { code, signal, success } = await process.status;
if (!success) {
throw new Error(
`pnpm link failed with code ${code} and signal ${signal}`,
`${packageManager} link failed with code ${code} and signal ${signal}`,
);
}
})().catch(console.error);
} catch (e) {
console.error(e);
}
//Deno.copyFileSync("CHANGELOG.md", "npm/CHANGELOG.md");
//Deno.copyFileSync("LICENSE", "npm/LICENSE");
//Deno.copyFileSync("README.md", "npm/README.md");
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kamikoto00lib",
"version": "0.2.1",
"version": "0.2.2",
"description": "",
"scripts": {
"build": "deno task build"
Expand Down
68 changes: 51 additions & 17 deletions src/types/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ export function pojoDeepCopy(src: Dict | primitive<null>): unknown {
return undefined;
}

export type ComputePropertyOnceOptions = {
enumerableAfterCompute?: boolean;
enumerableBeforeCompute?: boolean;
} | boolean;

export function computePropertyOnce<
const T extends object,
const K extends PropertyKey,
Expand All @@ -95,14 +100,26 @@ export function computePropertyOnce<
obj: T,
key: K,
compute: () => N,
options: ComputePropertyOnceOptions = true,
): asserts obj is T & Record<K, N> {
const { enumerableAfterCompute = true, enumerableBeforeCompute = true } =
typeof options === "boolean"
? { enumerableAfterCompute: options, enumerableBeforeCompute: options }
: options;
Object.defineProperty(obj, key, {
get: () => {
delete (obj as Record<K, N>)[key];
return (obj as Record<K, N>)[key] = compute.call(obj);
const value = compute.call(obj);
Object.defineProperty(obj, key, {
value,
configurable: true,
enumerable: enumerableAfterCompute,
writable: false,
});
return value;
},
configurable: true,
enumerable: true,
enumerable: enumerableBeforeCompute,
writable: false,
});
}

Expand All @@ -111,9 +128,17 @@ export type Getters<T> = {
};

export function extendsObjectWithOnceComputedProperties<
const T,
const A,
>(obj: T, compute: Getters<A>): asserts obj is T & A {
const T extends object,
const A extends object,
>(
obj: T,
compute: Getters<A>,
options: ComputePropertyOnceOptions = true,
): asserts obj is T & A {
const { enumerableAfterCompute = true, enumerableBeforeCompute = true } =
typeof options === "boolean"
? { enumerableAfterCompute: options, enumerableBeforeCompute: options }
: options;
const keys: (string | symbol)[] = [];
const symbols = Object.getOwnPropertySymbols(compute);
for (const key in compute) {
Expand All @@ -126,13 +151,20 @@ export function extendsObjectWithOnceComputedProperties<
keys.map((key) => {
const descriptor: PropertyDescriptor = {
get() {
delete obj[key as keyof T];
return obj[key as keyof T] = compute[key as keyof A].call(
const value = compute[key as keyof A].call(
obj as T & A,
) as never;
);
Object.defineProperty(obj, key, {
value,
configurable: true,
enumerable: enumerableAfterCompute,
writable: false,
});
return value;
},
configurable: true,
enumerable: true,
enumerable: enumerableBeforeCompute,
writable: false,
};
return [
key,
Expand All @@ -143,15 +175,17 @@ export function extendsObjectWithOnceComputedProperties<
Object.defineProperties(obj, descriptors);
}

export const mapDict = <const K extends PropertyKey, const TS, const TD>(
src: Record<K, TS>,
cb: (key: Extract<string, K>, value: TS) => TD,
export const mapDict = <const S extends object | Dict, const DT>(
src: S,
cb: <const K extends keyof S & primitive>(entry: [K, S[K]]) => DT,
) =>
Object.fromEntries(
Object.entries<TS>(src).map((
[key, value],
) => [key, cb(key as Extract<string, K>, value)]),
) as Record<Extract<string, K>, TD>;
Object.entries(src).map((
entry,
) => [entry[0], cb(entry as [keyof S & primitive, S[keyof S & primitive]])]),
) as {
-readonly [K in keyof S & primitive]: DT;
};

export const enum SwapKeyAndValuePriority {
First = 0,
Expand Down

0 comments on commit 0302262

Please sign in to comment.