All files / context / codegen.ts

100.00% Branches 0/0
13.79% Lines 8/58
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
 
x2
x2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x2
x2
x2
 
 
 
 
 
 
 
 
 
 
 
x2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x2
x2






























































































import type { Returns, Async, Step, DirEntry } from '../index.ts';
import { Dir, Txt } from './fs.ts';
import { chunked, Name } from '../format.ts';
/** An application project. */
export type Project = Name & Rust & ECMAScript & {
  gitignore?: string[],
  dotenv?: boolean,
  direnv?: boolean
};
/** Define a project. */
export const Project = (name: string, ...ops: DirEntry[]) =>
  Name(name, Dir(name, Readme(name, `Generated by @hackbg/fadroma.`), ...ops));
/** Define the project's README. */
export const Readme = (title: string, ...sections: string[]) =>
  Markdown('README.md', chunked('\n\n')(`# ${title}`, ...sections));
/** Define a Markdown file. */
export const Markdown = (name: string, ...args: (string|unknown)[]): DirEntry =>
  Txt(name, chunked('\n\n')(...args));
/** Semantic version. */
export type Semver = string; // TODO
/** Versioned component. */
export type Versioned = { /* The version. */ version: Semver };
/** Define the project's Git ignorelist. */
export const gitignore = (...lines: string[]) => Txt('.gitignore', ...lines);
/** Define text file format. */
export const textFormat = <T = string|number|object|null> (format: Returns<string>) =>
  (path: string, value?: T|T[]|Step<T>, ...steps: Array<T|Step<T>>) =>
    Txt(path, value, ...steps, format as (_:T)=>Async<T>);
/** Define JSON file. */
export const Json = textFormat((x: unknown) => JSON.stringify(x));
/** Define YAML file. */
export const Yaml = textFormat((_: unknown) => { throw new Error('unimplemented') });
/** Define TOML file. */
export const Toml = textFormat((_: unknown) => { throw new Error('unimplemented') });
/** Define Rust file. */
export const Rust = textFormat((_: unknown) => { throw new Error('unimplemented') });
/** Rust tools config. */
export type Rust = { rust?: boolean, bacon?: boolean, mold?: boolean, workspace?: boolean };
/** Add Mold to a project. */
export const Mold = Dir('.cargo', Toml('config.toml'));
/** Add Bacon to a project. */
export const Bacon = ({ watch = [ "programs/*" ], jobs = [] }) => Toml('bacon.toml', {
  "default_job": jobs[0][0],
  "env.CARGO_TERM_COLOR": "always",
  "keybindings": Object.fromEntries(jobs.map(([name, key, _])=>[key, name])),
  jobs: {},
  ...Object.fromEntries(jobs.map(([name, _, command])=>[name, {
    need_stdout: false,
    command,
    watch,
  }]))
});
/** Cargo package manifest */
export type Crate = Versioned & {
  name: string, deps: CrateDep[], devDeps: CrateDep[], features: CrateFeature[] };
/** Cargo dependency */
export type CrateDep = Versioned & { name: string, features: CrateFeature[] };
/** Cargo feature */
export type CrateFeature = { name: string, features: string[] };
/** Define JavaScript file. */
export const Js = textFormat((_: unknown) => {
  throw new Error('unimplemented') });
/** Define TypeScript file. */
export const Ts = textFormat((_: unknown) => {
  throw new Error('unimplemented') });
/** JS/TS config. */
export type ECMAScript =
  { js?: boolean, esm?: boolean, ts?: boolean, node?: boolean, deno?: boolean
  , pnpm?: boolean, eslint?: boolean };
/** Define NPM package manifest. */
export const PackageJson = ({
  name,
  path             = 'package.json',
  version          = '0.0.0',
  isPrivate        = true,
  legacy           = false,
  scripts          = [],
  dependencies     = [],
  devDependencies  = [],
  peerDependencies = [],
  main             = undefined,
  exports          = undefined,
}) => Json(path, ()=>({
  name,
  type: legacy ? "script" : "module",
  main,
  version,
  "private": isPrivate,
  exports,
  scripts:          Object.fromEntries(scripts.filter(Boolean)),
  dependencies:     Object.fromEntries(dependencies.filter(Boolean)),
  devDependencies:  Object.fromEntries(devDependencies.filter(Boolean)),
  peerDependencies: Object.fromEntries(peerDependencies.filter(Boolean)),
}))
export const tsConfig     = Json('tsconfig.json');
export const eslintConfig = Js('eslint.config.js');