@codeandmoney/jargal 0.0.0-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/TODO.md +2 -0
- package/actions/ai.ts +7 -0
- package/actions/answer.ts +7 -0
- package/actions/blank.ts +55 -0
- package/actions/combine.ts +10 -0
- package/actions/config.ts +7 -0
- package/actions/context/context.ts +44 -0
- package/actions/context.ts +10 -0
- package/actions/echo.ts +19 -0
- package/actions/exports.ts +9 -0
- package/actions/jargal-context.ts +21 -0
- package/actions/jargal-templates.ts +71 -0
- package/actions/jargal-write.ts +46 -0
- package/actions/load-templates.ts +107 -0
- package/actions/modify.ts +7 -0
- package/actions/parallel.ts +8 -0
- package/actions/pipe/pipe.ts +993 -0
- package/actions/pipe.ts +7 -0
- package/actions/prompt.ts +134 -0
- package/actions/render-template.ts +29 -0
- package/actions/run/run.ts +20 -0
- package/actions/select-generator.ts +24 -0
- package/actions/use.ts +9 -0
- package/actions/validate-answers.ts +13 -0
- package/actions/write/write.ts +69 -0
- package/actions/write.ts +52 -0
- package/biome.json +35 -0
- package/bun.lock +68 -0
- package/exports.ts +8 -0
- package/jargal.ts +156 -0
- package/lib.ts +101 -0
- package/package.json +39 -0
- package/renderer.ts +100 -0
- package/runner.test.ts +24 -0
- package/runner.ts +99 -0
- package/tsconfig.json +29 -0
- package/types.ts +91 -0
package/lib.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {
|
|
2
|
+
camelCase,
|
|
3
|
+
capitalCase,
|
|
4
|
+
constantCase,
|
|
5
|
+
dotCase,
|
|
6
|
+
kebabCase,
|
|
7
|
+
noCase,
|
|
8
|
+
pascalCase,
|
|
9
|
+
pascalSnakeCase,
|
|
10
|
+
pathCase,
|
|
11
|
+
sentenceCase,
|
|
12
|
+
snakeCase,
|
|
13
|
+
trainCase,
|
|
14
|
+
} from "change-case";
|
|
15
|
+
import { titleCase } from "title-case";
|
|
16
|
+
import { deburr, lowerFirst, startCase, trim } from "es-toolkit";
|
|
17
|
+
|
|
18
|
+
import type { ActionHooks, ActionHooksChanges, ActionHooksFailures, TextHelpers } from "./types.ts";
|
|
19
|
+
|
|
20
|
+
export const textHelpers: TextHelpers = {
|
|
21
|
+
upperCase: (str) => str.toUpperCase(),
|
|
22
|
+
lowerCase: (str) => str.toLowerCase(),
|
|
23
|
+
camelCase: (str) => camelCase(str),
|
|
24
|
+
snakeCase: (str) => snakeCase(str),
|
|
25
|
+
dotCase: (str) => dotCase(str),
|
|
26
|
+
pathCase: (str) => pathCase(str),
|
|
27
|
+
sentenceCase: (str) => sentenceCase(str),
|
|
28
|
+
constantCase: (str) => constantCase(str),
|
|
29
|
+
titleCase: (str) => titleCase(str),
|
|
30
|
+
kebabCase: (str) => kebabCase(str),
|
|
31
|
+
dashCase: (str) => kebabCase(str),
|
|
32
|
+
kabobCase: (str) => kebabCase(str),
|
|
33
|
+
pascalCase: (str) => pascalCase(str),
|
|
34
|
+
properCase: (str) => pascalCase(str),
|
|
35
|
+
deburr: (str) => deburr(str),
|
|
36
|
+
lowerFirst: (str) => lowerFirst(str),
|
|
37
|
+
startCase: (str) => startCase(str),
|
|
38
|
+
noCase: (str) => noCase(str),
|
|
39
|
+
capitalCase: (str) => capitalCase(str),
|
|
40
|
+
pascalSnakeCase: (str) => pascalSnakeCase(str),
|
|
41
|
+
trainCase: (str) => trainCase(str),
|
|
42
|
+
trim: (str) => trim(str),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export class Hooks implements ActionHooks {
|
|
46
|
+
onComment(message: string) {
|
|
47
|
+
console.info(message);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onSuccess(change: ActionHooksChanges) {
|
|
51
|
+
console.info(change);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
onFailure(failure: ActionHooksFailures) {
|
|
55
|
+
console.error(failure);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const ReadOnlyProxyDescriptor = {
|
|
60
|
+
get<T extends object>(target: T, key: keyof T & (string & {})): any {
|
|
61
|
+
const value = target[key];
|
|
62
|
+
|
|
63
|
+
if (!isObject(value)) {
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return readonly(value);
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
set(_target: object, _key: string) {
|
|
71
|
+
throw new ReadOnlyProxyWriteError("Cannot write on read-only proxy");
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
deleteProperty(_target: object, _key: string) {
|
|
75
|
+
throw new ReadOnlyProxyWriteError("Cannot delete on read-only proxy");
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
function isObject(thing: unknown) {
|
|
80
|
+
return thing !== null && typeof thing === "object";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
class ReadOnlyProxyWriteError extends Error {
|
|
84
|
+
override name = "ReadOnlyProxyWriteError";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Create a read-only proxy over an object.
|
|
88
|
+
// Sub-properties that are objects also return read-only proxies.
|
|
89
|
+
export function readonly<T extends object>(target: T) {
|
|
90
|
+
return new Proxy<T>(target, ReadOnlyProxyDescriptor);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const utilHelpers = {
|
|
94
|
+
isdefined: function (value: unknown) {
|
|
95
|
+
return value !== undefined;
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
is: function (left: unknown, right: unknown) {
|
|
99
|
+
return left === right;
|
|
100
|
+
},
|
|
101
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codeandmoney/jargal",
|
|
3
|
+
"version": "0.0.0-dev.11",
|
|
4
|
+
"description": "Renderer",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Code & Money Team",
|
|
7
|
+
"contributors": [
|
|
8
|
+
{
|
|
9
|
+
"name": "Alexey Sokolov",
|
|
10
|
+
"email": "alexey@codeandmoney.com",
|
|
11
|
+
"url": "https://codeandmoney.com"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
"./old": "./exports.ts",
|
|
16
|
+
".": "./jargal.ts",
|
|
17
|
+
"./types": "./types.ts",
|
|
18
|
+
"./actions": "./actions/exports.ts",
|
|
19
|
+
"./renderer": "./renderer.ts"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"change-case": "^5.4.4",
|
|
23
|
+
"enquirer": "^2.4.1",
|
|
24
|
+
"es-toolkit": "^1.40.0",
|
|
25
|
+
"handlebars": "^4.7.8",
|
|
26
|
+
"title-case": "^4.3.2",
|
|
27
|
+
"valibot": "^1.1.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/bun": "^1.3.0",
|
|
31
|
+
"@types/node": "^24.7.2"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"typescript": "^5"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
}
|
|
39
|
+
}
|
package/renderer.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { get, set } from "es-toolkit/compat";
|
|
2
|
+
import handlebars from "handlebars";
|
|
3
|
+
|
|
4
|
+
import type { GetReturnType, HelperFn, Helpers, MappingScope, Partials, SetOptions, Setter, SetterScope } from "./types.ts";
|
|
5
|
+
import { readonly, textHelpers, utilHelpers } from "./lib.ts";
|
|
6
|
+
|
|
7
|
+
export class Renderer {
|
|
8
|
+
#partials: Partials = {};
|
|
9
|
+
#helpers: Helpers = { ...textHelpers, ...utilHelpers };
|
|
10
|
+
|
|
11
|
+
#mapping: { partial: Partials; helper: Helpers } = {
|
|
12
|
+
partial: this.#partials,
|
|
13
|
+
helper: this.#helpers,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
#set<T extends SetterScope>(scope: T, config: Setter<T>, options?: SetOptions): Renderer {
|
|
17
|
+
if (!config.name) {
|
|
18
|
+
throw new Error("Name must be non-empty string");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const target = get(this.#mapping, scope);
|
|
22
|
+
|
|
23
|
+
if (!target) throw new Error("No mapping");
|
|
24
|
+
|
|
25
|
+
if (config.name in target && !options?.override) {
|
|
26
|
+
throw new Error("Can't override");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
set(target, config.name, config.target);
|
|
30
|
+
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private readonly partials: Partials = readonly(this.#partials);
|
|
35
|
+
private readonly helpers: Helpers = readonly(this.#helpers);
|
|
36
|
+
|
|
37
|
+
private get<T extends SetterScope>(scope: T, name: string): GetReturnType<T> {
|
|
38
|
+
const target = get(this.#mapping, scope);
|
|
39
|
+
|
|
40
|
+
if (!target) {
|
|
41
|
+
throw new Error("!");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return get(target, name);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private list<T extends `${SetterScope}s`, O extends boolean = false>(
|
|
48
|
+
scope: T,
|
|
49
|
+
options?: { full?: O },
|
|
50
|
+
): O extends true ? MappingScope[T extends `${infer S}s` ? S : T][] : string[] {
|
|
51
|
+
const target = get(this.#mapping, scope.slice(0, scope.length - 1));
|
|
52
|
+
|
|
53
|
+
if (!target) {
|
|
54
|
+
throw new Error("No mapping");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!options?.full) {
|
|
58
|
+
return Object.keys(target) as any;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
switch (scope) {
|
|
62
|
+
case "helpers":
|
|
63
|
+
return Object.entries(target).map(([name, helper]) => ({
|
|
64
|
+
name,
|
|
65
|
+
helper,
|
|
66
|
+
})) as any;
|
|
67
|
+
|
|
68
|
+
case "partials":
|
|
69
|
+
return Object.entries(target).map(([name, partial]) => ({
|
|
70
|
+
name,
|
|
71
|
+
partial,
|
|
72
|
+
})) as any;
|
|
73
|
+
|
|
74
|
+
default:
|
|
75
|
+
throw new Error("can't find the scope");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public setPartial(name: string, partial: string, options?: SetOptions): Renderer {
|
|
80
|
+
return this.#set("partial", { target: partial, name }, options);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public setHelper(name: string, helper: HelperFn, options?: SetOptions): Renderer {
|
|
84
|
+
return this.#set("helper", { target: helper, name }, options);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public renderString(params: { template: string; data: Record<string, unknown> }): string {
|
|
88
|
+
for (const [name, helper] of Object.entries(this.#helpers)) {
|
|
89
|
+
handlebars.registerHelper(name, helper);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const [name, partial] of Object.entries(this.#partials)) {
|
|
93
|
+
handlebars.registerPartial(name, partial);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const compiled = handlebars.compile(params.template);
|
|
97
|
+
|
|
98
|
+
return compiled(params.data);
|
|
99
|
+
}
|
|
100
|
+
}
|
package/runner.test.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
import { run } from "./runner.ts";
|
|
6
|
+
import { blank1, blank2 } from "./actions/blank.ts";
|
|
7
|
+
|
|
8
|
+
import type { Config, GeneratorConfig } from "./types.ts";
|
|
9
|
+
|
|
10
|
+
import { context } from "./actions/context.ts";
|
|
11
|
+
import { loadTemplates } from "./actions/load-templates.ts";
|
|
12
|
+
|
|
13
|
+
test("simple", async () => {
|
|
14
|
+
const simple: GeneratorConfig = {
|
|
15
|
+
name: "simple",
|
|
16
|
+
description: "description",
|
|
17
|
+
actions: [blank1, blank2, context(() => ({ kek: Math.random() })), console.log, loadTemplates(join(process.cwd(), "actions"))],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const config: Config = { generators: [simple] };
|
|
21
|
+
const result = await run(config);
|
|
22
|
+
|
|
23
|
+
assert(typeof result === "undefined");
|
|
24
|
+
});
|
package/runner.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Renderer } from "./renderer.ts";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import type { Action, Config, ExecuteActionParams, GeneratorParams } from "./types.ts";
|
|
4
|
+
import { selectGenerator } from "./actions/select-generator.ts";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
export async function runGenerator({ context, generator, renderer }: GeneratorParams): Promise<void> {
|
|
8
|
+
assert(generator);
|
|
9
|
+
assert(Array.isArray(generator.actions) && generator.actions.length > 0);
|
|
10
|
+
|
|
11
|
+
for (const action of generator.actions) {
|
|
12
|
+
await executeAction({ action, context, renderer });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function executeAction({ action, context, renderer }: ExecuteActionParams): Promise<void | Action | Action[]> {
|
|
17
|
+
if (Array.isArray(action)) {
|
|
18
|
+
for (const action_ of action) {
|
|
19
|
+
const executed = await action_({ context, renderer });
|
|
20
|
+
if (!executed) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
await execRecursive(executed, { context, renderer });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (typeof action !== "function") {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const executed = await action({ context, renderer });
|
|
32
|
+
|
|
33
|
+
if (!executed) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return await execRecursive(executed, { context, renderer });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function execRecursive(executed: Action | Action[], { context, renderer }: Omit<ExecuteActionParams, "action">): Promise<Action | Action[] | void> {
|
|
41
|
+
if (Array.isArray(executed)) {
|
|
42
|
+
const executionResults: Action[] = [];
|
|
43
|
+
|
|
44
|
+
for (const action of executed) {
|
|
45
|
+
const result = await executeAction({ action, context, renderer });
|
|
46
|
+
|
|
47
|
+
if (result) {
|
|
48
|
+
if (Array.isArray(result)) {
|
|
49
|
+
executionResults.push(...result.flat());
|
|
50
|
+
} else {
|
|
51
|
+
executionResults.push(result);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return executionResults;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (typeof executed === "function") {
|
|
60
|
+
return await executeAction({ action: executed, context, renderer });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const ConfigSchema = v.object({
|
|
67
|
+
generators: v.pipe(
|
|
68
|
+
v.array(
|
|
69
|
+
v.object({
|
|
70
|
+
name: v.string(),
|
|
71
|
+
description: v.optional(v.string()),
|
|
72
|
+
actions: v.pipe(v.array(v.any()), v.minLength(1)),
|
|
73
|
+
}),
|
|
74
|
+
),
|
|
75
|
+
v.minLength(1),
|
|
76
|
+
),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export async function run(runConfig: Config): Promise<void> {
|
|
80
|
+
const config = v.run(ConfigSchema, runConfig);
|
|
81
|
+
|
|
82
|
+
if (config.generators.length === 1) {
|
|
83
|
+
const generator = config.generators[0];
|
|
84
|
+
|
|
85
|
+
assert(generator);
|
|
86
|
+
|
|
87
|
+
return await runGenerator({
|
|
88
|
+
context: { errors: [], answers: {} },
|
|
89
|
+
renderer: new Renderer(),
|
|
90
|
+
generator,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return await runGenerator({
|
|
95
|
+
context: { errors: [], answers: {} },
|
|
96
|
+
renderer: new Renderer(),
|
|
97
|
+
generator: { name: "select", actions: [selectGenerator(config)] },
|
|
98
|
+
});
|
|
99
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
"noImplicitOverride": true,
|
|
23
|
+
|
|
24
|
+
// Some stricter flags (disabled by default)
|
|
25
|
+
"noUnusedLocals": false,
|
|
26
|
+
"noUnusedParameters": false,
|
|
27
|
+
"noPropertyAccessFromIndexSignature": false
|
|
28
|
+
}
|
|
29
|
+
}
|
package/types.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Renderer } from "./renderer.ts";
|
|
2
|
+
|
|
3
|
+
export interface Config {
|
|
4
|
+
generators: GeneratorConfig[];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type Context<Ctx extends object = {}> = Ctx & {
|
|
8
|
+
answers: Record<string, string | boolean | (string | boolean)[]>;
|
|
9
|
+
errors: Error[];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type DeepReadonly<T> = {
|
|
13
|
+
readonly [Key in keyof T]: T[Key] extends any[] ? T[Key] : T[Key] extends object ? DeepReadonly<T[Key]> : T[Key];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export interface GeneratorParams {
|
|
17
|
+
context: Context;
|
|
18
|
+
renderer: Renderer;
|
|
19
|
+
generator: GeneratorConfig;
|
|
20
|
+
hooks?: ActionHooks;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ActionParams<Ctx extends object = {}> {
|
|
24
|
+
context: Context<Ctx>;
|
|
25
|
+
renderer: Renderer;
|
|
26
|
+
hooks?: ActionHooks;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ExecuteActionParams<Ctx extends object = {}> {
|
|
30
|
+
context: Context<Ctx>;
|
|
31
|
+
renderer: Renderer;
|
|
32
|
+
action: Action;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type ContextAction<Ctx extends object = {}> = (params: DeepReadonly<ExecuteActionParams<Ctx>>) => Partial<Context<Ctx>> | Promise<Partial<Context<Ctx>>>;
|
|
36
|
+
|
|
37
|
+
export interface GeneratorConfig {
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
actions: Action[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type HelperFn = (str: string) => string;
|
|
44
|
+
|
|
45
|
+
export interface TextHelpers extends Record<string, HelperFn> {}
|
|
46
|
+
|
|
47
|
+
export type Action<Ctx extends object = {}> = (params: ActionParams<Ctx>) => void | Action | Action[] | Promise<void | Action | Action[]>;
|
|
48
|
+
|
|
49
|
+
export interface ActionHooksFailures {
|
|
50
|
+
path: string;
|
|
51
|
+
error: string;
|
|
52
|
+
message?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ActionHooksChanges {
|
|
56
|
+
path: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ActionHooks {
|
|
60
|
+
onComment?: (msg: string) => void;
|
|
61
|
+
onSuccess?: (change: ActionHooksChanges) => void;
|
|
62
|
+
onFailure?: (failure: ActionHooksFailures) => void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type SetterScope = "helper" | "partial";
|
|
66
|
+
|
|
67
|
+
export interface SetOptions {
|
|
68
|
+
override?: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface MappingScope {
|
|
72
|
+
helper: { name: string; target: HelperFn };
|
|
73
|
+
partial: { name: string; target: string };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface Mapping {
|
|
77
|
+
helper: HelperFn;
|
|
78
|
+
partial: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
type GetSetterType<Key extends SetterScope> = Mapping[Key];
|
|
82
|
+
|
|
83
|
+
export interface Setter<T extends SetterScope> {
|
|
84
|
+
target: GetSetterType<T>;
|
|
85
|
+
name: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type GetReturnType<T extends SetterScope> = Mapping[T];
|
|
89
|
+
|
|
90
|
+
export interface Partials extends Record<string, string> {}
|
|
91
|
+
export interface Helpers extends Record<string, any> {}
|