@outfitter/presets 0.2.0
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/dist/index.d.ts +43 -0
- package/dist/index.js +118 -0
- package/package.json +63 -0
- package/presets/.gitkeep +0 -0
- package/presets/basic/.gitignore.template +30 -0
- package/presets/basic/.lefthook.yml.template +26 -0
- package/presets/basic/package.json.template +39 -0
- package/presets/basic/src/index.ts.template +26 -0
- package/presets/basic/tsconfig.json.template +34 -0
- package/presets/cli/.gitignore.template +4 -0
- package/presets/cli/.lefthook.yml.template +26 -0
- package/presets/cli/README.md.template +35 -0
- package/presets/cli/biome.json.template +4 -0
- package/presets/cli/package.json.template +46 -0
- package/presets/cli/src/cli.ts.template +8 -0
- package/presets/cli/src/index.ts.template +7 -0
- package/presets/cli/src/program.ts.template +31 -0
- package/presets/cli/tsconfig.json.template +34 -0
- package/presets/daemon/.gitignore.template +4 -0
- package/presets/daemon/.lefthook.yml.template +26 -0
- package/presets/daemon/README.md.template +67 -0
- package/presets/daemon/biome.json.template +4 -0
- package/presets/daemon/package.json.template +49 -0
- package/presets/daemon/src/cli.ts.template +96 -0
- package/presets/daemon/src/daemon-main.ts.template +79 -0
- package/presets/daemon/src/daemon.ts.template +11 -0
- package/presets/daemon/src/index.ts.template +7 -0
- package/presets/daemon/tsconfig.json.template +23 -0
- package/presets/full-stack/.gitignore.template +30 -0
- package/presets/full-stack/README.md.template +30 -0
- package/presets/full-stack/apps/cli/package.json.template +35 -0
- package/presets/full-stack/apps/cli/src/cli.ts.template +24 -0
- package/presets/full-stack/apps/cli/src/index.test.ts.template +18 -0
- package/presets/full-stack/apps/cli/src/index.ts.template +5 -0
- package/presets/full-stack/apps/cli/tsconfig.json.template +37 -0
- package/presets/full-stack/apps/mcp/package.json.template +36 -0
- package/presets/full-stack/apps/mcp/src/index.test.ts.template +18 -0
- package/presets/full-stack/apps/mcp/src/index.ts.template +6 -0
- package/presets/full-stack/apps/mcp/src/mcp.ts.template +22 -0
- package/presets/full-stack/apps/mcp/src/server.ts.template +10 -0
- package/presets/full-stack/apps/mcp/tsconfig.json.template +37 -0
- package/presets/full-stack/package.json.template +16 -0
- package/presets/full-stack/packages/core/package.json.template +32 -0
- package/presets/full-stack/packages/core/src/handlers.ts.template +31 -0
- package/presets/full-stack/packages/core/src/index.test.ts.template +30 -0
- package/presets/full-stack/packages/core/src/index.ts.template +8 -0
- package/presets/full-stack/packages/core/src/types.ts.template +13 -0
- package/presets/full-stack/packages/core/tsconfig.json.template +34 -0
- package/presets/library/.gitignore.template +30 -0
- package/presets/library/README.md.template +29 -0
- package/presets/library/bunup.config.ts.template +20 -0
- package/presets/library/package.json.template +52 -0
- package/presets/library/src/handlers.ts.template +31 -0
- package/presets/library/src/index.test.ts.template +35 -0
- package/presets/library/src/index.ts.template +8 -0
- package/presets/library/src/types.ts.template +13 -0
- package/presets/library/tsconfig.json.template +34 -0
- package/presets/mcp/.gitignore.template +4 -0
- package/presets/mcp/.lefthook.yml.template +26 -0
- package/presets/mcp/README.md.template +54 -0
- package/presets/mcp/biome.json.template +4 -0
- package/presets/mcp/package.json.template +46 -0
- package/presets/mcp/src/index.ts.template +7 -0
- package/presets/mcp/src/mcp.ts.template +33 -0
- package/presets/mcp/src/server.ts.template +8 -0
- package/presets/mcp/tsconfig.json.template +23 -0
- package/presets/minimal/.gitignore.template +30 -0
- package/presets/minimal/.lefthook.yml.template +26 -0
- package/presets/minimal/package.json.template +46 -0
- package/presets/minimal/src/index.ts.template +26 -0
- package/presets/minimal/tsconfig.json.template +34 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
interface ResolvedVersions {
|
|
2
|
+
/** All dependency versions from the presets package (catalog-resolved at publish time). */
|
|
3
|
+
readonly all: Readonly<Record<string, string>>;
|
|
4
|
+
}
|
|
5
|
+
interface PresetInfo {
|
|
6
|
+
/** The preset name (directory name). */
|
|
7
|
+
readonly name: string;
|
|
8
|
+
/** Absolute path to the preset directory. */
|
|
9
|
+
readonly path: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get the absolute path to the presets directory.
|
|
13
|
+
* Works both in the monorepo (source) and when published to npm (dist/).
|
|
14
|
+
*/
|
|
15
|
+
declare function getPresetsDir(): string;
|
|
16
|
+
/**
|
|
17
|
+
* List all available presets.
|
|
18
|
+
*/
|
|
19
|
+
declare function listPresets(): readonly PresetInfo[];
|
|
20
|
+
/**
|
|
21
|
+
* Get the absolute path to a specific preset directory.
|
|
22
|
+
* Returns undefined if the preset does not exist.
|
|
23
|
+
*/
|
|
24
|
+
declare function getPresetPath(presetName: string): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Read resolved dependency versions from the presets package's own package.json.
|
|
27
|
+
*
|
|
28
|
+
* When published to npm, `catalog:` is replaced with concrete semver ranges,
|
|
29
|
+
* so versions are read directly. In the monorepo, `catalog:` references are
|
|
30
|
+
* resolved by reading the workspace root's catalog field.
|
|
31
|
+
*
|
|
32
|
+
* @returns Resolved versions for all declared dependencies.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* import { getResolvedVersions } from "@outfitter/presets";
|
|
37
|
+
*
|
|
38
|
+
* const { all } = getResolvedVersions();
|
|
39
|
+
* console.log(all["zod"]); // "^4.3.5"
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
declare function getResolvedVersions(): ResolvedVersions;
|
|
43
|
+
export { listPresets, getResolvedVersions, getPresetsDir, getPresetPath, ResolvedVersions, PresetInfo };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/presets/src/index.ts
|
|
3
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
4
|
+
import { dirname, isAbsolute, join, relative, resolve } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
var DEPENDENCY_SECTIONS = [
|
|
7
|
+
"dependencies",
|
|
8
|
+
"devDependencies",
|
|
9
|
+
"peerDependencies",
|
|
10
|
+
"optionalDependencies"
|
|
11
|
+
];
|
|
12
|
+
function getPresetsDir() {
|
|
13
|
+
const thisFile = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const presetsDir = join(thisFile, "..", "presets");
|
|
15
|
+
if (existsSync(presetsDir)) {
|
|
16
|
+
return presetsDir;
|
|
17
|
+
}
|
|
18
|
+
throw new Error(`Presets directory not found at ${presetsDir}. Ensure @outfitter/presets is properly installed.`);
|
|
19
|
+
}
|
|
20
|
+
function listPresets() {
|
|
21
|
+
const presetsDir = getPresetsDir();
|
|
22
|
+
return readdirSync(presetsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => ({
|
|
23
|
+
name: entry.name,
|
|
24
|
+
path: join(presetsDir, entry.name)
|
|
25
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
26
|
+
}
|
|
27
|
+
function getPresetPath(presetName) {
|
|
28
|
+
const presetsDir = getPresetsDir();
|
|
29
|
+
const presetDir = resolve(presetsDir, presetName);
|
|
30
|
+
const relativePath = relative(presetsDir, presetDir);
|
|
31
|
+
if (relativePath.length === 0 || relativePath.startsWith("..") || isAbsolute(relativePath)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!existsSync(presetDir)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
return statSync(presetDir).isDirectory() ? presetDir : undefined;
|
|
38
|
+
}
|
|
39
|
+
function isRecord(value) {
|
|
40
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41
|
+
}
|
|
42
|
+
function loadWorkspaceCatalog(packageDir) {
|
|
43
|
+
let dir = packageDir;
|
|
44
|
+
for (let i = 0;i < 10; i++) {
|
|
45
|
+
const rootPkgPath = join(dir, "package.json");
|
|
46
|
+
if (existsSync(rootPkgPath)) {
|
|
47
|
+
try {
|
|
48
|
+
const raw = JSON.parse(readFileSync(rootPkgPath, "utf-8"));
|
|
49
|
+
if (isRecord(raw) && isRecord(raw["catalog"])) {
|
|
50
|
+
const catalog = {};
|
|
51
|
+
for (const [name, version] of Object.entries(raw["catalog"])) {
|
|
52
|
+
if (typeof version === "string") {
|
|
53
|
+
catalog[name] = version;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return catalog;
|
|
57
|
+
}
|
|
58
|
+
} catch {}
|
|
59
|
+
}
|
|
60
|
+
const parent = dirname(dir);
|
|
61
|
+
if (parent === dir)
|
|
62
|
+
break;
|
|
63
|
+
dir = parent;
|
|
64
|
+
}
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
function getResolvedVersions() {
|
|
68
|
+
const packageDir = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
69
|
+
const packageJsonPath = join(packageDir, "package.json");
|
|
70
|
+
const raw = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
71
|
+
if (!isRecord(raw)) {
|
|
72
|
+
throw new Error("@outfitter/presets package.json must be a JSON object");
|
|
73
|
+
}
|
|
74
|
+
const all = {};
|
|
75
|
+
let hasCatalogRefs = false;
|
|
76
|
+
for (const section of DEPENDENCY_SECTIONS) {
|
|
77
|
+
const deps = raw[section];
|
|
78
|
+
if (!isRecord(deps))
|
|
79
|
+
continue;
|
|
80
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
81
|
+
if (typeof version === "string") {
|
|
82
|
+
if (version === "catalog:") {
|
|
83
|
+
hasCatalogRefs = true;
|
|
84
|
+
} else {
|
|
85
|
+
all[name] = version;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (hasCatalogRefs) {
|
|
91
|
+
const catalog = loadWorkspaceCatalog(packageDir);
|
|
92
|
+
const unresolved = [];
|
|
93
|
+
for (const section of DEPENDENCY_SECTIONS) {
|
|
94
|
+
const deps = raw[section];
|
|
95
|
+
if (!isRecord(deps))
|
|
96
|
+
continue;
|
|
97
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
98
|
+
if (version === "catalog:") {
|
|
99
|
+
if (catalog[name]) {
|
|
100
|
+
all[name] = catalog[name];
|
|
101
|
+
} else {
|
|
102
|
+
unresolved.push(name);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (unresolved.length > 0) {
|
|
108
|
+
throw new Error(`Unresolvable catalog: references (no catalog entry found): ${unresolved.join(", ")}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return { all };
|
|
112
|
+
}
|
|
113
|
+
export {
|
|
114
|
+
listPresets,
|
|
115
|
+
getResolvedVersions,
|
|
116
|
+
getPresetsDir,
|
|
117
|
+
getPresetPath
|
|
118
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@outfitter/presets",
|
|
3
|
+
"description": "Scaffold presets and shared dependency versions for Outfitter projects",
|
|
4
|
+
"version": "0.2.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"presets"
|
|
9
|
+
],
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@biomejs/biome": "2.4.4",
|
|
23
|
+
"@clack/prompts": "^1.0.1",
|
|
24
|
+
"@logtape/logtape": "^2.0.0",
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
26
|
+
"@types/node": "^25.3.0",
|
|
27
|
+
"better-result": "^2.5.1",
|
|
28
|
+
"bunup": "^0.16.29",
|
|
29
|
+
"commander": "^14.0.2",
|
|
30
|
+
"lefthook": "^2.1.1",
|
|
31
|
+
"smol-toml": "^1.6.0",
|
|
32
|
+
"ultracite": "7.2.3",
|
|
33
|
+
"yaml": "^2.8.2",
|
|
34
|
+
"zod": "^4.3.5"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/bun": "^1.3.9",
|
|
38
|
+
"typescript": "^5.9.3"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"bun": ">=1.3.9"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"outfitter",
|
|
45
|
+
"presets",
|
|
46
|
+
"scaffolding",
|
|
47
|
+
"templates",
|
|
48
|
+
"versions"
|
|
49
|
+
],
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/outfitter-dev/stack.git",
|
|
54
|
+
"directory": "packages/presets"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "cd ../.. && bunup --filter @outfitter/presets",
|
|
58
|
+
"clean": "rm -rf dist .turbo",
|
|
59
|
+
"test": "bun test",
|
|
60
|
+
"typecheck": "tsc --noEmit",
|
|
61
|
+
"prepublishOnly": "bun ../../scripts/check-publish-manifest.ts"
|
|
62
|
+
}
|
|
63
|
+
}
|
package/presets/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# Build output
|
|
5
|
+
dist/
|
|
6
|
+
|
|
7
|
+
# IDE
|
|
8
|
+
.idea/
|
|
9
|
+
.vscode/
|
|
10
|
+
*.swp
|
|
11
|
+
*.swo
|
|
12
|
+
|
|
13
|
+
# OS
|
|
14
|
+
.DS_Store
|
|
15
|
+
Thumbs.db
|
|
16
|
+
|
|
17
|
+
# Logs
|
|
18
|
+
*.log
|
|
19
|
+
npm-debug.log*
|
|
20
|
+
|
|
21
|
+
# Environment
|
|
22
|
+
.env
|
|
23
|
+
.env.local
|
|
24
|
+
.env.*.local
|
|
25
|
+
|
|
26
|
+
# Test coverage
|
|
27
|
+
coverage/
|
|
28
|
+
|
|
29
|
+
# Bun
|
|
30
|
+
bun.lockb
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Lefthook configuration
|
|
2
|
+
# https://github.com/evilmartians/lefthook
|
|
3
|
+
|
|
4
|
+
pre-commit:
|
|
5
|
+
parallel: true
|
|
6
|
+
commands:
|
|
7
|
+
format:
|
|
8
|
+
glob: "*.{js,ts,tsx,json,md}"
|
|
9
|
+
run: bunx biome format --no-errors-on-unmatched {staged_files}
|
|
10
|
+
stage_fixed: true
|
|
11
|
+
|
|
12
|
+
lint:
|
|
13
|
+
glob: "*.{js,ts,tsx}"
|
|
14
|
+
run: bunx biome lint --no-errors-on-unmatched {staged_files}
|
|
15
|
+
|
|
16
|
+
typecheck:
|
|
17
|
+
glob: "*.{ts,tsx}"
|
|
18
|
+
run: bun run typecheck
|
|
19
|
+
|
|
20
|
+
pre-push:
|
|
21
|
+
parallel: false
|
|
22
|
+
commands:
|
|
23
|
+
verify:
|
|
24
|
+
# TDD-aware strict verification with RED-phase branch carveout
|
|
25
|
+
# (*-tests, */tests, *_tests).
|
|
26
|
+
run: bunx @outfitter/tooling pre-push
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "bun build ./src/index.ts --outdir=dist --format=esm",
|
|
21
|
+
"dev": "bun run --watch src/index.ts",
|
|
22
|
+
"test": "bun test",
|
|
23
|
+
"test:watch": "bun test --watch",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"check": "ultracite check",
|
|
26
|
+
"verify:ci": "bun run typecheck && bun run check && bun run build && bun run test",
|
|
27
|
+
"lint": "biome check .",
|
|
28
|
+
"lint:fix": "biome check . --write",
|
|
29
|
+
"format": "biome format --write .",
|
|
30
|
+
"clean:artifacts": "rm -rf dist .turbo",
|
|
31
|
+
"clean": "rm -rf dist"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {},
|
|
34
|
+
"engines": {
|
|
35
|
+
"bun": ">=1.3.9"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [],
|
|
38
|
+
"license": "MIT"
|
|
39
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{projectName}}
|
|
3
|
+
*
|
|
4
|
+
* {{description}}
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Main entry point for {{projectName}}.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { main } from "{{packageName}}";
|
|
15
|
+
*
|
|
16
|
+
* main();
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function main(): void {
|
|
20
|
+
console.log("Hello from {{projectName}}!");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Run if executed directly
|
|
24
|
+
if (import.meta.main) {
|
|
25
|
+
main();
|
|
26
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"lib": ["ESNext"],
|
|
8
|
+
"types": ["@types/bun"],
|
|
9
|
+
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noImplicitAny": true,
|
|
12
|
+
"strictNullChecks": true,
|
|
13
|
+
"noUncheckedIndexedAccess": true,
|
|
14
|
+
"exactOptionalPropertyTypes": true,
|
|
15
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
16
|
+
"noImplicitReturns": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
|
|
19
|
+
"declaration": true,
|
|
20
|
+
"declarationMap": true,
|
|
21
|
+
"sourceMap": true,
|
|
22
|
+
"outDir": "./dist",
|
|
23
|
+
"rootDir": "./src",
|
|
24
|
+
|
|
25
|
+
"esModuleInterop": true,
|
|
26
|
+
"forceConsistentCasingInFileNames": true,
|
|
27
|
+
"isolatedModules": true,
|
|
28
|
+
"verbatimModuleSyntax": true,
|
|
29
|
+
"skipLibCheck": true,
|
|
30
|
+
"resolveJsonModule": true
|
|
31
|
+
},
|
|
32
|
+
"include": ["src/**/*"],
|
|
33
|
+
"exclude": ["node_modules", "dist"]
|
|
34
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Lefthook configuration
|
|
2
|
+
# https://github.com/evilmartians/lefthook
|
|
3
|
+
|
|
4
|
+
pre-commit:
|
|
5
|
+
parallel: true
|
|
6
|
+
commands:
|
|
7
|
+
format:
|
|
8
|
+
glob: "*.{js,ts,tsx,json,md}"
|
|
9
|
+
run: bunx biome format --no-errors-on-unmatched {staged_files}
|
|
10
|
+
stage_fixed: true
|
|
11
|
+
|
|
12
|
+
lint:
|
|
13
|
+
glob: "*.{js,ts,tsx}"
|
|
14
|
+
run: bunx biome lint --no-errors-on-unmatched {staged_files}
|
|
15
|
+
|
|
16
|
+
typecheck:
|
|
17
|
+
glob: "*.{ts,tsx}"
|
|
18
|
+
run: bun run typecheck
|
|
19
|
+
|
|
20
|
+
pre-push:
|
|
21
|
+
parallel: false
|
|
22
|
+
commands:
|
|
23
|
+
verify:
|
|
24
|
+
# TDD-aware strict verification with RED-phase branch carveout
|
|
25
|
+
# (*-tests, */tests, *_tests).
|
|
26
|
+
run: bunx @outfitter/tooling pre-push
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
{{description}}
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add {{packageName}}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
{{binName}} hello [name]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Development
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Install dependencies
|
|
21
|
+
bun install
|
|
22
|
+
|
|
23
|
+
# Run in development
|
|
24
|
+
bun run dev
|
|
25
|
+
|
|
26
|
+
# Build
|
|
27
|
+
bun run build
|
|
28
|
+
|
|
29
|
+
# Run tests
|
|
30
|
+
bun run test
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## License
|
|
34
|
+
|
|
35
|
+
MIT
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"{{binName}}": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "bun build src/cli.ts --outdir dist --target bun && bun build src/index.ts --outdir dist --target bun --sourcemap",
|
|
19
|
+
"dev": "bun --watch src/cli.ts",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"check": "ultracite check",
|
|
22
|
+
"verify:ci": "bun run typecheck && bun run check && bun run build && bun run test",
|
|
23
|
+
"test": "bun test",
|
|
24
|
+
"test:watch": "bun test --watch",
|
|
25
|
+
"lint": "biome check .",
|
|
26
|
+
"lint:fix": "biome check . --write",
|
|
27
|
+
"format": "biome format --write .",
|
|
28
|
+
"clean:artifacts": "rm -rf dist .turbo"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@outfitter/contracts": "workspace:*",
|
|
32
|
+
"@outfitter/types": "workspace:*",
|
|
33
|
+
"@outfitter/cli": "workspace:*",
|
|
34
|
+
"@outfitter/logging": "workspace:*",
|
|
35
|
+
"commander": "^14.0.2"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {},
|
|
38
|
+
"outfitter": {
|
|
39
|
+
"template": {
|
|
40
|
+
"kind": "runnable",
|
|
41
|
+
"placement": "apps",
|
|
42
|
+
"surfaces": ["cli"]
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"license": "MIT"
|
|
46
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{projectName}} - CLI program definition
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { command, createCLI } from "@outfitter/cli/command";
|
|
6
|
+
import { verbosePreset } from "@outfitter/cli/flags";
|
|
7
|
+
import { createLogger } from "@outfitter/logging";
|
|
8
|
+
|
|
9
|
+
const logger = createLogger({ name: "{{binName}}" });
|
|
10
|
+
|
|
11
|
+
export const program = createCLI({
|
|
12
|
+
name: "{{binName}}",
|
|
13
|
+
version: "{{version}}",
|
|
14
|
+
description: "{{description}}",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const verbose = verbosePreset();
|
|
18
|
+
|
|
19
|
+
program.register(
|
|
20
|
+
command("hello [name]")
|
|
21
|
+
.description("Say hello")
|
|
22
|
+
.preset(verbose)
|
|
23
|
+
.action<{ verbose: boolean }>(async ({ args, flags }) => {
|
|
24
|
+
const { verbose: isVerbose } = verbose.resolve(flags);
|
|
25
|
+
const name = args[0] ?? "World";
|
|
26
|
+
logger.info(`Hello, ${name}!`);
|
|
27
|
+
if (isVerbose) {
|
|
28
|
+
logger.debug("Running in verbose mode");
|
|
29
|
+
}
|
|
30
|
+
}),
|
|
31
|
+
);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"lib": ["ESNext"],
|
|
8
|
+
"types": ["@types/bun"],
|
|
9
|
+
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noImplicitAny": true,
|
|
12
|
+
"strictNullChecks": true,
|
|
13
|
+
"noUncheckedIndexedAccess": true,
|
|
14
|
+
"exactOptionalPropertyTypes": true,
|
|
15
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
16
|
+
"noImplicitReturns": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
|
|
19
|
+
"declaration": true,
|
|
20
|
+
"declarationMap": true,
|
|
21
|
+
"sourceMap": true,
|
|
22
|
+
"outDir": "./dist",
|
|
23
|
+
"rootDir": "./src",
|
|
24
|
+
|
|
25
|
+
"esModuleInterop": true,
|
|
26
|
+
"forceConsistentCasingInFileNames": true,
|
|
27
|
+
"isolatedModules": true,
|
|
28
|
+
"verbatimModuleSyntax": true,
|
|
29
|
+
"skipLibCheck": true,
|
|
30
|
+
"resolveJsonModule": true
|
|
31
|
+
},
|
|
32
|
+
"include": ["src/**/*"],
|
|
33
|
+
"exclude": ["node_modules", "dist"]
|
|
34
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Lefthook configuration
|
|
2
|
+
# https://github.com/evilmartians/lefthook
|
|
3
|
+
|
|
4
|
+
pre-commit:
|
|
5
|
+
parallel: true
|
|
6
|
+
commands:
|
|
7
|
+
format:
|
|
8
|
+
glob: "*.{js,ts,tsx,json,md}"
|
|
9
|
+
run: bunx biome format --no-errors-on-unmatched {staged_files}
|
|
10
|
+
stage_fixed: true
|
|
11
|
+
|
|
12
|
+
lint:
|
|
13
|
+
glob: "*.{js,ts,tsx}"
|
|
14
|
+
run: bunx biome lint --no-errors-on-unmatched {staged_files}
|
|
15
|
+
|
|
16
|
+
typecheck:
|
|
17
|
+
glob: "*.{ts,tsx}"
|
|
18
|
+
run: bun run typecheck
|
|
19
|
+
|
|
20
|
+
pre-push:
|
|
21
|
+
parallel: false
|
|
22
|
+
commands:
|
|
23
|
+
verify:
|
|
24
|
+
# TDD-aware strict verification with RED-phase branch carveout
|
|
25
|
+
# (*-tests, */tests, *_tests).
|
|
26
|
+
run: bunx @outfitter/tooling pre-push
|