@f-o-t/cli 0.1.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/README.md ADDED
@@ -0,0 +1,410 @@
1
+ # @f-o-t/cli
2
+
3
+ CLI tool for managing FOT (Factories of Tomorrow) libraries in monorepo workspaces.
4
+
5
+ ## Features
6
+
7
+ - **Build** - Compile TypeScript libraries with optimized bundling
8
+ - **Dev Mode** - Watch mode for rapid development with automatic rebuilds
9
+ - **Test** - Run tests with optional coverage and watch mode
10
+ - **Check** - Run all checks (typecheck + test) in one command
11
+ - **Typecheck** - TypeScript type checking without builds
12
+ - **Generate** - Generate configuration files from `fot.config.ts`
13
+ - **Create** - Scaffold new libraries with complete boilerplate
14
+
15
+ ## Installation
16
+
17
+ Install as a dev dependency in your monorepo:
18
+
19
+ ```bash
20
+ bun add -D @f-o-t/cli
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```bash
26
+ # Create a new library
27
+ fot create my-library "A new library for FOT"
28
+
29
+ # Build the library
30
+ cd libraries/my-library
31
+ fot build
32
+
33
+ # Run tests
34
+ fot test
35
+
36
+ # Start development mode with watch
37
+ fot dev
38
+ ```
39
+
40
+ ## Commands
41
+
42
+ ### `fot build`
43
+
44
+ Build the current library using bunup bundler.
45
+
46
+ ```bash
47
+ fot build
48
+ ```
49
+
50
+ Builds TypeScript source files into the `dist/` directory with proper type declarations and source maps.
51
+
52
+ **What it does:**
53
+ - Compiles TypeScript to JavaScript
54
+ - Generates type declaration files (.d.ts)
55
+ - Creates source maps for debugging
56
+ - Optimizes output for production
57
+
58
+ ---
59
+
60
+ ### `fot dev`
61
+
62
+ Start development mode with file watching and automatic rebuilds.
63
+
64
+ ```bash
65
+ fot dev
66
+ ```
67
+
68
+ **What it does:**
69
+ - Watches source files for changes
70
+ - Automatically rebuilds on file changes
71
+ - Provides fast feedback during development
72
+ - Keeps TypeScript types in sync
73
+
74
+ ---
75
+
76
+ ### `fot test [options]`
77
+
78
+ Run tests for the current library.
79
+
80
+ ```bash
81
+ # Run tests once
82
+ fot test
83
+
84
+ # Run tests in watch mode
85
+ fot test --watch
86
+
87
+ # Run tests with coverage report
88
+ fot test --coverage
89
+ ```
90
+
91
+ **Options:**
92
+ - `--watch` - Run tests in watch mode, re-running on file changes
93
+ - `--coverage` - Generate test coverage report
94
+
95
+ **What it does:**
96
+ - Executes test files matching `*.test.ts` pattern
97
+ - Provides detailed test output
98
+ - Optionally generates coverage metrics
99
+ - Integrates with Bun's native test runner
100
+
101
+ ---
102
+
103
+ ### `fot check`
104
+
105
+ Run all checks (typecheck + test) in sequence.
106
+
107
+ ```bash
108
+ fot check
109
+ ```
110
+
111
+ **What it does:**
112
+ - First runs TypeScript type checking
113
+ - Then runs the full test suite
114
+ - Exits with error if either check fails
115
+ - Perfect for CI/CD pipelines
116
+
117
+ ---
118
+
119
+ ### `fot typecheck`
120
+
121
+ Run TypeScript type checking without building.
122
+
123
+ ```bash
124
+ fot typecheck
125
+ ```
126
+
127
+ **What it does:**
128
+ - Validates TypeScript types across your codebase
129
+ - Checks for type errors without generating output files
130
+ - Faster than a full build when you only need type validation
131
+ - Uses your tsconfig.json configuration
132
+
133
+ ---
134
+
135
+ ### `fot generate`
136
+
137
+ Generate configuration files from `fot.config.ts`.
138
+
139
+ ```bash
140
+ fot generate
141
+ ```
142
+
143
+ **What it does:**
144
+ - Reads your `fot.config.ts` configuration
145
+ - Generates `package.json` with proper dependencies and scripts
146
+ - Creates `tsconfig.json` with TypeScript settings
147
+ - Generates `biome.json` for code formatting and linting
148
+ - Ensures configuration stays in sync
149
+
150
+ **Use cases:**
151
+ - After updating `fot.config.ts`
152
+ - Setting up a new library
153
+ - Syncing configuration across team members
154
+
155
+ ---
156
+
157
+ ### `fot create <name> [description]`
158
+
159
+ Create a new library with complete scaffolding.
160
+
161
+ ```bash
162
+ # Create with description
163
+ fot create my-library "A new library for FOT"
164
+
165
+ # Create with minimal setup (uses default description)
166
+ fot create my-library
167
+ ```
168
+
169
+ **Arguments:**
170
+ - `<name>` - Library name (required, e.g., "my-library")
171
+ - `[description]` - Optional description for the library
172
+
173
+ **What it creates:**
174
+ - `libraries/<name>/` directory structure
175
+ - `fot.config.ts` with library configuration
176
+ - `src/index.ts` with example code
177
+ - `src/index.test.ts` with sample tests
178
+ - `README.md` with documentation template
179
+ - Generated configuration files (package.json, tsconfig.json, biome.json)
180
+ - Installed dependencies
181
+
182
+ **Example output:**
183
+ ```
184
+ Creating library: @f-o-t/my-library
185
+ Description: A new library for FOT
186
+
187
+ Creating directory structure...
188
+ ✓ Created libraries/my-library/src
189
+
190
+ Generating template files...
191
+ ✓ Created libraries/my-library/fot.config.ts
192
+ ✓ Created libraries/my-library/src/index.ts
193
+ ✓ Created libraries/my-library/src/index.test.ts
194
+ ✓ Created libraries/my-library/README.md
195
+
196
+ Generating configuration files...
197
+ ✓ Generated libraries/my-library/package.json
198
+ ✓ Generated libraries/my-library/tsconfig.json
199
+ ✓ Generated libraries/my-library/biome.json
200
+
201
+ Installing dependencies...
202
+ ✓ Dependencies installed
203
+
204
+ ✓ Library created successfully!
205
+ ```
206
+
207
+ ---
208
+
209
+ ### `fot help`
210
+
211
+ Show help information with all available commands.
212
+
213
+ ```bash
214
+ fot help
215
+ # or
216
+ fot --help
217
+ # or
218
+ fot -h
219
+ ```
220
+
221
+ ---
222
+
223
+ ### `fot version`
224
+
225
+ Display the CLI version number.
226
+
227
+ ```bash
228
+ fot version
229
+ # or
230
+ fot --version
231
+ # or
232
+ fot -v
233
+ ```
234
+
235
+ ## Configuration
236
+
237
+ The CLI reads configuration from `fot.config.ts` in your library's root directory. This file defines:
238
+
239
+ - Library name and description
240
+ - Dependencies and peer dependencies
241
+ - TypeScript compiler options
242
+ - Build and output settings
243
+ - Linting and formatting rules
244
+
245
+ See [@f-o-t/config](../config/README.md) for detailed configuration options.
246
+
247
+ **Example `fot.config.ts`:**
248
+
249
+ ```typescript
250
+ import { defineFotConfig } from "@f-o-t/config";
251
+
252
+ export default defineFotConfig({
253
+ name: "my-library",
254
+ description: "A new library for FOT",
255
+ dependencies: {
256
+ "zod": "^3.22.4",
257
+ },
258
+ tsconfig: {
259
+ compilerOptions: {
260
+ strict: true,
261
+ target: "ES2022",
262
+ },
263
+ },
264
+ });
265
+ ```
266
+
267
+ ## CI/CD Integration
268
+
269
+ The CLI is designed to work seamlessly in CI/CD pipelines. Here's an example GitHub Actions workflow:
270
+
271
+ ```yaml
272
+ name: Test and Build
273
+
274
+ on:
275
+ push:
276
+ branches: [main, develop]
277
+ pull_request:
278
+ branches: [main, develop]
279
+
280
+ jobs:
281
+ test:
282
+ runs-on: ubuntu-latest
283
+ steps:
284
+ - uses: actions/checkout@v4
285
+
286
+ - name: Setup Bun
287
+ uses: oven-sh/setup-bun@v1
288
+ with:
289
+ bun-version: latest
290
+
291
+ - name: Install dependencies
292
+ run: bun install
293
+
294
+ - name: Run checks
295
+ run: |
296
+ cd libraries/my-library
297
+ fot check
298
+
299
+ - name: Build
300
+ run: |
301
+ cd libraries/my-library
302
+ fot build
303
+
304
+ - name: Test with coverage
305
+ run: |
306
+ cd libraries/my-library
307
+ fot test --coverage
308
+ ```
309
+
310
+ **Pipeline best practices:**
311
+ - Use `fot check` to run both typechecking and tests
312
+ - Run `fot test --coverage` to track code coverage
313
+ - Build after tests pass with `fot build`
314
+ - Cache `node_modules` for faster CI runs
315
+
316
+ ## Development
317
+
318
+ ### Prerequisites
319
+
320
+ - Bun runtime (latest version)
321
+ - Node.js 18+ (for compatibility)
322
+ - TypeScript 5.0+
323
+
324
+ ### Setup
325
+
326
+ ```bash
327
+ # Clone the monorepo
328
+ git clone <repository-url>
329
+
330
+ # Install dependencies
331
+ bun install
332
+
333
+ # Navigate to CLI package
334
+ cd libraries/cli
335
+
336
+ # Build the CLI
337
+ bun run build
338
+
339
+ # Run in development mode
340
+ bun run dev
341
+ ```
342
+
343
+ ### Testing the CLI
344
+
345
+ ```bash
346
+ # Run tests
347
+ bun test
348
+
349
+ # Run tests with coverage
350
+ bun test --coverage
351
+
352
+ # Test the CLI locally
353
+ ./dist/index.js --help
354
+ ```
355
+
356
+ ### Project Structure
357
+
358
+ ```
359
+ libraries/cli/
360
+ ├── src/
361
+ │ ├── commands/ # Command implementations
362
+ │ │ ├── build.ts # Build command
363
+ │ │ ├── dev.ts # Dev command
364
+ │ │ ├── test.ts # Test command
365
+ │ │ ├── check.ts # Check command
366
+ │ │ ├── typecheck.ts # Typecheck command
367
+ │ │ ├── generate.ts # Generate command
368
+ │ │ ├── create.ts # Create command
369
+ │ │ └── index.ts # Command exports
370
+ │ ├── templates/ # Library scaffolding templates
371
+ │ ├── builder.ts # Build utilities
372
+ │ ├── config-loader.ts # Configuration loader
373
+ │ └── index.ts # CLI entry point
374
+ ├── dist/ # Built output
375
+ ├── fot.config.ts # CLI library config
376
+ ├── package.json
377
+ ├── tsconfig.json
378
+ └── README.md
379
+ ```
380
+
381
+ ## Troubleshooting
382
+
383
+ ### Build fails with module errors
384
+
385
+ Ensure all dependencies are installed:
386
+ ```bash
387
+ bun install
388
+ ```
389
+
390
+ ### TypeScript errors in development
391
+
392
+ Run typecheck to see detailed errors:
393
+ ```bash
394
+ fot typecheck
395
+ ```
396
+
397
+ ### Tests not running
398
+
399
+ Verify test files match the pattern `*.test.ts` and are in the `src/` directory.
400
+
401
+ ### Configuration out of sync
402
+
403
+ Regenerate configuration files:
404
+ ```bash
405
+ fot generate
406
+ ```
407
+
408
+ ## License
409
+
410
+ MIT
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Generate configuration files (package.json, tsconfig.json, biome.json) from fot.config.ts
3
+ *
4
+ * @param cwd - The directory containing the fot.config.ts file
5
+ */
6
+ declare function generateConfigFiles(cwd: string): Promise<void>;
7
+ /**
8
+ * Options for building a library
9
+ */
10
+ interface BuildOptions {
11
+ /**
12
+ * The working directory containing the fot.config.ts file
13
+ * @default process.cwd()
14
+ */
15
+ cwd?: string;
16
+ /**
17
+ * Whether to watch for changes and rebuild
18
+ * @default false
19
+ */
20
+ watch?: boolean;
21
+ }
22
+ /**
23
+ * Build a library using Bun's bundler
24
+ *
25
+ * @param options - Build options
26
+ * @throws {Error} If the build fails
27
+ */
28
+ declare function buildLibrary(options?: BuildOptions): Promise<void>;
29
+ /**
30
+ * Execute the build command
31
+ *
32
+ * @param options - Build options
33
+ */
34
+ declare function buildCommand(options?: BuildOptions): Promise<void>;
35
+ import { ResolvedFotConfig } from "@f-o-t/config";
36
+ /**
37
+ * Checks if a fot.config.ts file exists in the given directory
38
+ *
39
+ * @param cwd - The directory to check
40
+ * @returns True if fot.config.ts exists, false otherwise
41
+ */
42
+ declare function hasFotConfig(cwd: string): boolean;
43
+ /**
44
+ * Loads and validates a fot.config.ts file from the given directory
45
+ *
46
+ * @param cwd - The directory containing the fot.config.ts file
47
+ * @returns The resolved FOT configuration
48
+ * @throws {Error} If the config file is not found or has no default */
49
+ declare function loadFotConfig(cwd: string): Promise<ResolvedFotConfig>;
50
+ export { loadFotConfig, hasFotConfig, generateConfigFiles, buildLibrary, buildCommand, BuildOptions };
package/dist/index.js ADDED
@@ -0,0 +1,453 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // src/builder.ts
5
+ import { join as join2 } from "path";
6
+ var {build: bunBuild } = globalThis.Bun;
7
+ var {$ } = globalThis.Bun;
8
+
9
+ // src/config-loader.ts
10
+ import { existsSync } from "fs";
11
+ import { join } from "path";
12
+ function hasFotConfig(cwd) {
13
+ const configPath = join(cwd, "fot.config.ts");
14
+ return existsSync(configPath);
15
+ }
16
+ async function loadFotConfig(cwd) {
17
+ const configPath = join(cwd, "fot.config.ts");
18
+ if (!existsSync(configPath)) {
19
+ throw new Error(`fot.config.ts not found in ${cwd}. Please create a fot.config.ts file.`);
20
+ }
21
+ try {
22
+ const configModule = await import(configPath);
23
+ if (!configModule.default) {
24
+ throw new Error(`fot.config.ts in ${cwd} must have a default export. Use 'export default defineFotConfig({ ... })'.`);
25
+ }
26
+ return configModule.default;
27
+ } catch (error) {
28
+ if (error instanceof Error && error.message.includes("fot.config.ts")) {
29
+ throw error;
30
+ }
31
+ throw new Error(`Failed to load fot.config.ts from ${cwd}: ${error instanceof Error ? error.message : String(error)}`);
32
+ }
33
+ }
34
+
35
+ // src/builder.ts
36
+ async function buildLibrary(options = {}) {
37
+ const cwd = options.cwd || process.cwd();
38
+ const watch = options.watch || false;
39
+ console.log("Loading fot.config.ts...");
40
+ const config = await loadFotConfig(cwd);
41
+ const entryPoints = [];
42
+ const mainEntry = join2(cwd, "src", "index.ts");
43
+ entryPoints.push(mainEntry);
44
+ for (const plugin of config.plugins) {
45
+ if (plugin.enabled !== false) {
46
+ const pluginEntry = join2(cwd, "src", "plugins", plugin.name, "index.ts");
47
+ entryPoints.push(pluginEntry);
48
+ }
49
+ }
50
+ console.log(`Building ${entryPoints.length} entry point(s)...`);
51
+ for (const format of config.formats) {
52
+ console.log(`Building ${format} format...`);
53
+ try {
54
+ const result = await bunBuild({
55
+ entrypoints: entryPoints,
56
+ outdir: join2(cwd, "dist"),
57
+ target: "bun",
58
+ format: format === "esm" ? "esm" : "cjs",
59
+ splitting: format === "esm",
60
+ minify: false,
61
+ sourcemap: "external",
62
+ external: config.external,
63
+ naming: {
64
+ entry: "[dir]/[name].js",
65
+ chunk: "[name]-[hash].js"
66
+ }
67
+ });
68
+ if (!result.success) {
69
+ const errors = result.logs.map((log) => log.message).join(`
70
+ `);
71
+ throw new Error(`Build failed for ${format} format:
72
+ ${errors}`);
73
+ }
74
+ console.log(`\u2713 ${format} format built successfully`);
75
+ } catch (error) {
76
+ throw new Error(`Build failed for ${format} format: ${error instanceof Error ? error.message : String(error)}`);
77
+ }
78
+ }
79
+ console.log("Build completed successfully!");
80
+ if (config.typescript.declaration) {
81
+ console.log("Generating TypeScript declarations...");
82
+ try {
83
+ await $`cd ${cwd} && bun tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist --noEmit false`.quiet();
84
+ console.log("\u2713 TypeScript declarations generated");
85
+ } catch (error) {
86
+ throw new Error(`Declaration generation failed: ${error instanceof Error ? error.message : String(error)}`);
87
+ }
88
+ }
89
+ if (watch) {
90
+ console.log("Watching for changes...");
91
+ }
92
+ }
93
+
94
+ // src/commands/build.ts
95
+ async function buildCommand(options = {}) {
96
+ try {
97
+ await buildLibrary(options);
98
+ } catch (error) {
99
+ console.error("Build failed:", error instanceof Error ? error.message : String(error));
100
+ process.exit(1);
101
+ }
102
+ }
103
+ // src/commands/dev.ts
104
+ async function devCommand() {
105
+ try {
106
+ console.log("Starting development mode...");
107
+ await buildLibrary({ watch: true });
108
+ } catch (error) {
109
+ console.error("Development mode failed:", error instanceof Error ? error.message : String(error));
110
+ process.exit(1);
111
+ }
112
+ }
113
+ // src/commands/test.ts
114
+ var {spawn } = globalThis.Bun;
115
+ async function testCommand(options = {}) {
116
+ const args = ["test"];
117
+ if (options.coverage) {
118
+ args.push("--coverage");
119
+ }
120
+ if (options.watch) {
121
+ args.push("--watch");
122
+ }
123
+ console.log(`Running: bun ${args.join(" ")}`);
124
+ const proc = spawn({
125
+ cmd: ["bun", ...args],
126
+ stdio: ["inherit", "inherit", "inherit"]
127
+ });
128
+ const exitCode = await proc.exited;
129
+ process.exit(exitCode);
130
+ }
131
+ // src/commands/check.ts
132
+ var {spawn: spawn2 } = globalThis.Bun;
133
+ async function checkCommand() {
134
+ console.log("Running Biome check with auto-fix...");
135
+ const proc = spawn2({
136
+ cmd: ["bunx", "biome", "check", "--write", "."],
137
+ stdio: ["inherit", "inherit", "inherit"]
138
+ });
139
+ const exitCode = await proc.exited;
140
+ if (exitCode === 0) {
141
+ console.log("\u2713 Check completed successfully");
142
+ } else {
143
+ console.error("Check failed");
144
+ }
145
+ process.exit(exitCode);
146
+ }
147
+ // src/commands/typecheck.ts
148
+ var {spawn: spawn3 } = globalThis.Bun;
149
+ async function typecheckCommand() {
150
+ console.log("Running TypeScript type checking...");
151
+ const proc = spawn3({
152
+ cmd: ["bunx", "tsc"],
153
+ stdio: ["inherit", "inherit", "inherit"]
154
+ });
155
+ const exitCode = await proc.exited;
156
+ if (exitCode === 0) {
157
+ console.log("\u2713 Type checking completed successfully");
158
+ } else {
159
+ console.error("Type checking failed");
160
+ }
161
+ process.exit(exitCode);
162
+ }
163
+ // src/commands/generate.ts
164
+ import { writeFileSync } from "fs";
165
+ import { join as join3 } from "path";
166
+ import {
167
+ generatePackageJson,
168
+ generateTSConfig,
169
+ generateBiomeConfig
170
+ } from "@f-o-t/config";
171
+ async function generateConfigFiles(cwd) {
172
+ console.log("Loading fot.config.ts...");
173
+ const config = await loadFotConfig(cwd);
174
+ console.log("Generating package.json...");
175
+ const libraryName = cwd.split("/").pop() || "library";
176
+ const packageJson = generatePackageJson(libraryName, "0.1.0", config);
177
+ const packageJsonPath = join3(cwd, "package.json");
178
+ writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + `
179
+ `);
180
+ console.log(`\u2713 Generated ${packageJsonPath}`);
181
+ console.log("Generating tsconfig.json...");
182
+ const tsconfig = generateTSConfig(config);
183
+ const tsconfigPath = join3(cwd, "tsconfig.json");
184
+ writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2) + `
185
+ `);
186
+ console.log(`\u2713 Generated ${tsconfigPath}`);
187
+ console.log("Generating biome.json...");
188
+ const biomeConfig = generateBiomeConfig(config);
189
+ const biomeConfigPath = join3(cwd, "biome.json");
190
+ writeFileSync(biomeConfigPath, JSON.stringify(biomeConfig, null, 2) + `
191
+ `);
192
+ console.log(`\u2713 Generated ${biomeConfigPath}`);
193
+ console.log("All configuration files generated successfully!");
194
+ }
195
+ // src/commands/create.ts
196
+ import { existsSync as existsSync2, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
197
+ import { join as join4 } from "path";
198
+ var {spawn: spawn4 } = globalThis.Bun;
199
+
200
+ // src/templates/library.ts
201
+ function getLibraryTemplate(name, description) {
202
+ const packageName = `@f-o-t/${name}`;
203
+ const fotConfig = `import { defineFotConfig } from "@f-o-t/config";
204
+
205
+ export default defineFotConfig({
206
+ formats: ["esm", "cjs"],
207
+ external: [],
208
+ typescript: {
209
+ declaration: true,
210
+ },
211
+ });
212
+ `;
213
+ const indexTs = `/**
214
+ * ${packageName}
215
+ * ${description}
216
+ */
217
+
218
+ export function hello(): string {
219
+ return "Hello from ${packageName}!";
220
+ }
221
+ `;
222
+ const indexTestTs = `import { describe, expect, test as it } from "bun:test";
223
+ import { hello } from "./index";
224
+
225
+ describe("${packageName}", () => {
226
+ it("should export hello function", () => {
227
+ expect(hello()).toBe("Hello from ${packageName}!");
228
+ });
229
+ });
230
+ `;
231
+ const readme = `# ${packageName}
232
+
233
+ ${description}
234
+
235
+ ## Installation
236
+
237
+ \`\`\`bash
238
+ # bun
239
+ bun add ${packageName}
240
+
241
+ # npm
242
+ npm install ${packageName}
243
+
244
+ # yarn
245
+ yarn add ${packageName}
246
+
247
+ # pnpm
248
+ pnpm add ${packageName}
249
+ \`\`\`
250
+
251
+ ## Quick Start
252
+
253
+ \`\`\`typescript
254
+ import { hello } from "${packageName}";
255
+
256
+ console.log(hello());
257
+ \`\`\`
258
+
259
+ ## API Reference
260
+
261
+ ### \`hello()\`
262
+
263
+ Returns a greeting string.
264
+
265
+ \`\`\`typescript
266
+ const greeting = hello();
267
+ console.log(greeting); // "Hello from ${packageName}!"
268
+ \`\`\`
269
+
270
+ ## Contributing
271
+
272
+ Contributions are welcome! Please check the repository for guidelines.
273
+
274
+ ## License
275
+
276
+ MIT License - see [LICENSE](./LICENSE) file for details.
277
+
278
+ ## Links
279
+
280
+ - [GitHub Repository](https://github.com/F-O-T/libraries)
281
+ - [Issue Tracker](https://github.com/F-O-T/libraries/issues)
282
+ `;
283
+ return {
284
+ fotConfig,
285
+ indexTs,
286
+ indexTestTs,
287
+ readme
288
+ };
289
+ }
290
+
291
+ // src/commands/create.ts
292
+ async function createCommand(options) {
293
+ const { name, description, cwd = process.cwd() } = options;
294
+ console.log(`Creating library: @f-o-t/${name}`);
295
+ console.log(`Description: ${description}`);
296
+ const libraryPath = join4(cwd, "libraries", name);
297
+ if (existsSync2(libraryPath)) {
298
+ console.error(`Error: Library already exists at ${libraryPath}`);
299
+ process.exit(1);
300
+ }
301
+ console.log(`
302
+ Creating directory structure...`);
303
+ const srcPath = join4(libraryPath, "src");
304
+ mkdirSync(srcPath, { recursive: true });
305
+ console.log(`\u2713 Created ${srcPath}`);
306
+ console.log(`
307
+ Generating template files...`);
308
+ const templates = getLibraryTemplate(name, description);
309
+ const fotConfigPath = join4(libraryPath, "fot.config.ts");
310
+ writeFileSync2(fotConfigPath, templates.fotConfig);
311
+ console.log(`\u2713 Created ${fotConfigPath}`);
312
+ const indexTsPath = join4(srcPath, "index.ts");
313
+ writeFileSync2(indexTsPath, templates.indexTs);
314
+ console.log(`\u2713 Created ${indexTsPath}`);
315
+ const indexTestTsPath = join4(srcPath, "index.test.ts");
316
+ writeFileSync2(indexTestTsPath, templates.indexTestTs);
317
+ console.log(`\u2713 Created ${indexTestTsPath}`);
318
+ const readmePath = join4(libraryPath, "README.md");
319
+ writeFileSync2(readmePath, templates.readme);
320
+ console.log(`\u2713 Created ${readmePath}`);
321
+ console.log(`
322
+ Generating configuration files...`);
323
+ await generateConfigFiles(libraryPath);
324
+ console.log(`
325
+ Installing dependencies...`);
326
+ const installProc = spawn4({
327
+ cmd: ["bun", "install"],
328
+ cwd: libraryPath,
329
+ stdio: ["inherit", "inherit", "inherit"]
330
+ });
331
+ const exitCode = await installProc.exited;
332
+ if (exitCode !== 0) {
333
+ console.error("Failed to install dependencies");
334
+ process.exit(exitCode);
335
+ }
336
+ console.log("\u2713 Dependencies installed");
337
+ console.log(`
338
+ ` + "=".repeat(60));
339
+ console.log("\u2713 Library created successfully!");
340
+ console.log("=".repeat(60));
341
+ console.log(`
342
+ Next steps:`);
343
+ console.log(` 1. cd libraries/${name}`);
344
+ console.log(" 2. Edit src/index.ts to implement your library");
345
+ console.log(" 3. Add tests in src/index.test.ts");
346
+ console.log(" 4. Run 'bun test' to verify tests pass");
347
+ console.log(" 5. Run 'bun run build' to build the library");
348
+ console.log(`
349
+ Happy coding! \uD83D\uDE80`);
350
+ }
351
+ // src/index.ts
352
+ function printHelp() {
353
+ console.log(`
354
+ FOT CLI - Build tools for monorepo libraries
355
+
356
+ Usage: fot <command> [options]
357
+
358
+ Commands:
359
+ build Build the current library
360
+ dev Start development mode with watch
361
+ test Run tests
362
+ --watch Run tests in watch mode
363
+ --coverage Run tests with coverage
364
+ check Run all checks (typecheck + test)
365
+ typecheck Run TypeScript type checking
366
+ generate Generate configuration files
367
+ create <name> Create a new library
368
+ [description] Optional description for the library
369
+ help, --help, -h Show this help message
370
+ version, --version, -v Show version number
371
+
372
+ Examples:
373
+ fot build
374
+ fot dev
375
+ fot test --coverage
376
+ fot test --watch
377
+ fot create my-lib "A new library"
378
+ fot generate
379
+ fot check
380
+ `);
381
+ }
382
+ async function main() {
383
+ const args = process.argv.slice(2);
384
+ const command = args[0];
385
+ try {
386
+ switch (command) {
387
+ case "build":
388
+ await buildCommand();
389
+ break;
390
+ case "dev":
391
+ await devCommand();
392
+ break;
393
+ case "test": {
394
+ const options = {
395
+ coverage: args.includes("--coverage"),
396
+ watch: args.includes("--watch")
397
+ };
398
+ await testCommand(options);
399
+ break;
400
+ }
401
+ case "check":
402
+ await checkCommand();
403
+ break;
404
+ case "typecheck":
405
+ await typecheckCommand();
406
+ break;
407
+ case "generate":
408
+ await generateConfigFiles(process.cwd());
409
+ break;
410
+ case "create": {
411
+ const name = args[1];
412
+ const description = args[2] || `A new FOT library: ${name}`;
413
+ const options = {
414
+ name,
415
+ description
416
+ };
417
+ await createCommand(options);
418
+ break;
419
+ }
420
+ case "help":
421
+ case "--help":
422
+ case "-h":
423
+ printHelp();
424
+ break;
425
+ case "version":
426
+ case "--version":
427
+ case "-v":
428
+ console.log("fot v0.1.0");
429
+ break;
430
+ case undefined:
431
+ printHelp();
432
+ break;
433
+ default:
434
+ console.error(`Unknown command: ${command}`);
435
+ console.log('Run "fot --help" for usage information');
436
+ process.exit(1);
437
+ }
438
+ } catch (error) {
439
+ console.error("Error:", error instanceof Error ? error.message : error);
440
+ process.exit(1);
441
+ }
442
+ }
443
+ main();
444
+ export {
445
+ loadFotConfig,
446
+ hasFotConfig,
447
+ generateConfigFiles,
448
+ buildLibrary,
449
+ buildCommand
450
+ };
451
+
452
+ //# debugId=3D1BC492518C26A964756E2164756E21
453
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL2J1aWxkZXIudHMiLCAic3JjL2NvbmZpZy1sb2FkZXIudHMiLCAic3JjL2NvbW1hbmRzL2J1aWxkLnRzIiwgInNyYy9jb21tYW5kcy9kZXYudHMiLCAic3JjL2NvbW1hbmRzL3Rlc3QudHMiLCAic3JjL2NvbW1hbmRzL2NoZWNrLnRzIiwgInNyYy9jb21tYW5kcy90eXBlY2hlY2sudHMiLCAic3JjL2NvbW1hbmRzL2dlbmVyYXRlLnRzIiwgInNyYy9jb21tYW5kcy9jcmVhdGUudHMiLCAic3JjL3RlbXBsYXRlcy9saWJyYXJ5LnRzIiwgInNyYy9pbmRleC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICJpbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgYnVpbGQgYXMgYnVuQnVpbGQgfSBmcm9tIFwiYnVuXCI7XG5pbXBvcnQgeyAkIH0gZnJvbSBcImJ1blwiO1xuaW1wb3J0IHR5cGUgeyBCdWlsZEZvcm1hdCB9IGZyb20gXCJAZi1vLXQvY29uZmlnXCI7XG5pbXBvcnQgeyBsb2FkRm90Q29uZmlnIH0gZnJvbSBcIi4vY29uZmlnLWxvYWRlclwiO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGJ1aWxkaW5nIGEgbGlicmFyeVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgd29ya2luZyBkaXJlY3RvcnkgY29udGFpbmluZyB0aGUgZm90LmNvbmZpZy50cyBmaWxlXG4gICAqIEBkZWZhdWx0IHByb2Nlc3MuY3dkKClcbiAgICovXG4gIGN3ZD86IHN0cmluZztcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gd2F0Y2ggZm9yIGNoYW5nZXMgYW5kIHJlYnVpbGRcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHdhdGNoPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIGxpYnJhcnkgdXNpbmcgQnVuJ3MgYnVuZGxlclxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gQnVpbGQgb3B0aW9uc1xuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBidWlsZCBmYWlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYnVpbGRMaWJyYXJ5KG9wdGlvbnM6IEJ1aWxkT3B0aW9ucyA9IHt9KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGN3ZCA9IG9wdGlvbnMuY3dkIHx8IHByb2Nlc3MuY3dkKCk7XG4gIGNvbnN0IHdhdGNoID0gb3B0aW9ucy53YXRjaCB8fCBmYWxzZTtcblxuICBjb25zb2xlLmxvZyhcIkxvYWRpbmcgZm90LmNvbmZpZy50cy4uLlwiKTtcbiAgY29uc3QgY29uZmlnID0gYXdhaXQgbG9hZEZvdENvbmZpZyhjd2QpO1xuXG4gIC8vIENvbGxlY3QgYWxsIGVudHJ5IHBvaW50cyAobWFpbiArIHBsdWdpbnMpXG4gIGNvbnN0IGVudHJ5UG9pbnRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8vIE1haW4gZW50cnkgcG9pbnRcbiAgY29uc3QgbWFpbkVudHJ5ID0gam9pbihjd2QsIFwic3JjXCIsIFwiaW5kZXgudHNcIik7XG4gIGVudHJ5UG9pbnRzLnB1c2gobWFpbkVudHJ5KTtcblxuICAvLyBQbHVnaW4gZW50cnkgcG9pbnRzXG4gIGZvciAoY29uc3QgcGx1Z2luIG9mIGNvbmZpZy5wbHVnaW5zKSB7XG4gICAgaWYgKHBsdWdpbi5lbmFibGVkICE9PSBmYWxzZSkge1xuICAgICAgY29uc3QgcGx1Z2luRW50cnkgPSBqb2luKGN3ZCwgXCJzcmNcIiwgXCJwbHVnaW5zXCIsIHBsdWdpbi5uYW1lLCBcImluZGV4LnRzXCIpO1xuICAgICAgZW50cnlQb2ludHMucHVzaChwbHVnaW5FbnRyeSk7XG4gICAgfVxuICB9XG5cbiAgY29uc29sZS5sb2coYEJ1aWxkaW5nICR7ZW50cnlQb2ludHMubGVuZ3RofSBlbnRyeSBwb2ludChzKS4uLmApO1xuXG4gIC8vIEl0ZXJhdGUgb3ZlciBmb3JtYXRzIGFuZCBidWlsZCBlYWNoXG4gIGZvciAoY29uc3QgZm9ybWF0IG9mIGNvbmZpZy5mb3JtYXRzKSB7XG4gICAgY29uc29sZS5sb2coYEJ1aWxkaW5nICR7Zm9ybWF0fSBmb3JtYXQuLi5gKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBidW5CdWlsZCh7XG4gICAgICAgIGVudHJ5cG9pbnRzOiBlbnRyeVBvaW50cyxcbiAgICAgICAgb3V0ZGlyOiBqb2luKGN3ZCwgXCJkaXN0XCIpLFxuICAgICAgICB0YXJnZXQ6IFwiYnVuXCIsXG4gICAgICAgIGZvcm1hdDogZm9ybWF0ID09PSBcImVzbVwiID8gXCJlc21cIiA6IFwiY2pzXCIsXG4gICAgICAgIHNwbGl0dGluZzogZm9ybWF0ID09PSBcImVzbVwiLFxuICAgICAgICBtaW5pZnk6IGZhbHNlLFxuICAgICAgICBzb3VyY2VtYXA6IFwiZXh0ZXJuYWxcIixcbiAgICAgICAgZXh0ZXJuYWw6IGNvbmZpZy5leHRlcm5hbCxcbiAgICAgICAgbmFtaW5nOiB7XG4gICAgICAgICAgZW50cnk6IFwiW2Rpcl0vW25hbWVdLmpzXCIsXG4gICAgICAgICAgY2h1bms6IFwiW25hbWVdLVtoYXNoXS5qc1wiLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGlmICghcmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgY29uc3QgZXJyb3JzID0gcmVzdWx0LmxvZ3MubWFwKChsb2cpID0+IGxvZy5tZXNzYWdlKS5qb2luKFwiXFxuXCIpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJ1aWxkIGZhaWxlZCBmb3IgJHtmb3JtYXR9IGZvcm1hdDpcXG4ke2Vycm9yc31gKTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coYOKckyAke2Zvcm1hdH0gZm9ybWF0IGJ1aWx0IHN1Y2Nlc3NmdWxseWApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBCdWlsZCBmYWlsZWQgZm9yICR7Zm9ybWF0fSBmb3JtYXQ6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgY29uc29sZS5sb2coXCJCdWlsZCBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5IVwiKTtcblxuICAvLyBHZW5lcmF0ZSBUeXBlU2NyaXB0IGRlY2xhcmF0aW9ucyBpZiBlbmFibGVkXG4gIGlmIChjb25maWcudHlwZXNjcmlwdC5kZWNsYXJhdGlvbikge1xuICAgIGNvbnNvbGUubG9nKFwiR2VuZXJhdGluZyBUeXBlU2NyaXB0IGRlY2xhcmF0aW9ucy4uLlwiKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgJGBjZCAke2N3ZH0gJiYgYnVuIHRzYyAtLWVtaXREZWNsYXJhdGlvbk9ubHkgLS1kZWNsYXJhdGlvbiAtLWRlY2xhcmF0aW9uTWFwIC0tb3V0RGlyIGRpc3QgLS1ub0VtaXQgZmFsc2VgLnF1aWV0KCk7XG4gICAgICBjb25zb2xlLmxvZyhcIuKckyBUeXBlU2NyaXB0IGRlY2xhcmF0aW9ucyBnZW5lcmF0ZWRcIik7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYERlY2xhcmF0aW9uIGdlbmVyYXRpb24gZmFpbGVkOiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGlmICh3YXRjaCkge1xuICAgIGNvbnNvbGUubG9nKFwiV2F0Y2hpbmcgZm9yIGNoYW5nZXMuLi5cIik7XG4gICAgLy8gVE9ETzogSW1wbGVtZW50IHdhdGNoIG1vZGUgaW4gZnV0dXJlXG4gIH1cbn1cbiIsCiAgICAiaW1wb3J0IHsgZXhpc3RzU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBSZXNvbHZlZEZvdENvbmZpZyB9IGZyb20gXCJAZi1vLXQvY29uZmlnXCI7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgZm90LmNvbmZpZy50cyBmaWxlIGV4aXN0cyBpbiB0aGUgZ2l2ZW4gZGlyZWN0b3J5XG4gKlxuICogQHBhcmFtIGN3ZCAtIFRoZSBkaXJlY3RvcnkgdG8gY2hlY2tcbiAqIEByZXR1cm5zIFRydWUgaWYgZm90LmNvbmZpZy50cyBleGlzdHMsIGZhbHNlIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzRm90Q29uZmlnKGN3ZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGNvbmZpZ1BhdGggPSBqb2luKGN3ZCwgXCJmb3QuY29uZmlnLnRzXCIpO1xuICByZXR1cm4gZXhpc3RzU3luYyhjb25maWdQYXRoKTtcbn1cblxuLyoqXG4gKiBMb2FkcyBhbmQgdmFsaWRhdGVzIGEgZm90LmNvbmZpZy50cyBmaWxlIGZyb20gdGhlIGdpdmVuIGRpcmVjdG9yeVxuICpcbiAqIEBwYXJhbSBjd2QgLSBUaGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGZvdC5jb25maWcudHMgZmlsZVxuICogQHJldHVybnMgVGhlIHJlc29sdmVkIEZPVCBjb25maWd1cmF0aW9uXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIGNvbmZpZyBmaWxlIGlzIG5vdCBmb3VuZCBvciBoYXMgbm8gZGVmYXVsdCBleHBvcnRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxvYWRGb3RDb25maWcoY3dkOiBzdHJpbmcpOiBQcm9taXNlPFJlc29sdmVkRm90Q29uZmlnPiB7XG4gIGNvbnN0IGNvbmZpZ1BhdGggPSBqb2luKGN3ZCwgXCJmb3QuY29uZmlnLnRzXCIpO1xuXG4gIGlmICghZXhpc3RzU3luYyhjb25maWdQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBmb3QuY29uZmlnLnRzIG5vdCBmb3VuZCBpbiAke2N3ZH0uIFBsZWFzZSBjcmVhdGUgYSBmb3QuY29uZmlnLnRzIGZpbGUuYFxuICAgICk7XG4gIH1cblxuICB0cnkge1xuICAgIC8vIER5bmFtaWMgaW1wb3J0IHRvIGxvYWQgdGhlIGNvbmZpZyBmaWxlXG4gICAgY29uc3QgY29uZmlnTW9kdWxlID0gYXdhaXQgaW1wb3J0KGNvbmZpZ1BhdGgpO1xuXG4gICAgaWYgKCFjb25maWdNb2R1bGUuZGVmYXVsdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgZm90LmNvbmZpZy50cyBpbiAke2N3ZH0gbXVzdCBoYXZlIGEgZGVmYXVsdCBleHBvcnQuIFVzZSAnZXhwb3J0IGRlZmF1bHQgZGVmaW5lRm90Q29uZmlnKHsgLi4uIH0pJy5gXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBjb25maWdNb2R1bGUuZGVmYXVsdCBhcyBSZXNvbHZlZEZvdENvbmZpZztcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAvLyBJZiBpdCdzIGFscmVhZHkgb3VyIGN1c3RvbSBlcnJvciwgcmUtdGhyb3cgaXRcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKFwiZm90LmNvbmZpZy50c1wiKSkge1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuXG4gICAgLy8gT3RoZXJ3aXNlLCB3cmFwIHRoZSBlcnJvciB3aXRoIG1vcmUgY29udGV4dFxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBGYWlsZWQgdG8gbG9hZCBmb3QuY29uZmlnLnRzIGZyb20gJHtjd2R9OiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1gXG4gICAgKTtcbiAgfVxufVxuIiwKICAgICJpbXBvcnQgeyBidWlsZExpYnJhcnksIHR5cGUgQnVpbGRPcHRpb25zIH0gZnJvbSBcIi4uL2J1aWxkZXJcIjtcblxuLyoqXG4gKiBFeGVjdXRlIHRoZSBidWlsZCBjb21tYW5kXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBCdWlsZCBvcHRpb25zXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWlsZENvbW1hbmQob3B0aW9uczogQnVpbGRPcHRpb25zID0ge30pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBhd2FpdCBidWlsZExpYnJhcnkob3B0aW9ucyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgIFwiQnVpbGQgZmFpbGVkOlwiLFxuICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgKTtcbiAgICBwcm9jZXNzLmV4aXQoMSk7XG4gIH1cbn1cbiIsCiAgICAiaW1wb3J0IHsgYnVpbGRMaWJyYXJ5IH0gZnJvbSBcIi4uL2J1aWxkZXJcIjtcblxuLyoqXG4gKiBFeGVjdXRlIHRoZSBkZXYgY29tbWFuZFxuICogUnVucyB0aGUgYnVpbGQgaW4gd2F0Y2ggbW9kZSBmb3IgZGV2ZWxvcG1lbnRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRldkNvbW1hbmQoKTogUHJvbWlzZTx2b2lkPiB7XG4gIHRyeSB7XG4gICAgY29uc29sZS5sb2coXCJTdGFydGluZyBkZXZlbG9wbWVudCBtb2RlLi4uXCIpO1xuICAgIGF3YWl0IGJ1aWxkTGlicmFyeSh7IHdhdGNoOiB0cnVlIH0pO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBcIkRldmVsb3BtZW50IG1vZGUgZmFpbGVkOlwiLFxuICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgKTtcbiAgICBwcm9jZXNzLmV4aXQoMSk7XG4gIH1cbn1cbiIsCiAgICAiaW1wb3J0IHsgc3Bhd24gfSBmcm9tIFwiYnVuXCI7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgdGhlIHRlc3QgY29tbWFuZFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlc3RPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZ2VuZXJhdGUgY292ZXJhZ2UgcmVwb3J0c1xuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgY292ZXJhZ2U/OiBib29sZWFuO1xuICAvKipcbiAgICogV2hldGhlciB0byB3YXRjaCBmb3IgY2hhbmdlcyBhbmQgcmUtcnVuIHRlc3RzXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICB3YXRjaD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogRXhlY3V0ZSB0aGUgdGVzdCBjb21tYW5kXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBUZXN0IG9wdGlvbnNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3RDb21tYW5kKG9wdGlvbnM6IFRlc3RPcHRpb25zID0ge30pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYXJncyA9IFtcInRlc3RcIl07XG5cbiAgaWYgKG9wdGlvbnMuY292ZXJhZ2UpIHtcbiAgICBhcmdzLnB1c2goXCItLWNvdmVyYWdlXCIpO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMud2F0Y2gpIHtcbiAgICBhcmdzLnB1c2goXCItLXdhdGNoXCIpO1xuICB9XG5cbiAgY29uc29sZS5sb2coYFJ1bm5pbmc6IGJ1biAke2FyZ3Muam9pbihcIiBcIil9YCk7XG5cbiAgY29uc3QgcHJvYyA9IHNwYXduKHtcbiAgICBjbWQ6IFtcImJ1blwiLCAuLi5hcmdzXSxcbiAgICBzdGRpbzogW1wiaW5oZXJpdFwiLCBcImluaGVyaXRcIiwgXCJpbmhlcml0XCJdLFxuICB9KTtcblxuICBjb25zdCBleGl0Q29kZSA9IGF3YWl0IHByb2MuZXhpdGVkO1xuICBwcm9jZXNzLmV4aXQoZXhpdENvZGUpO1xufVxuIiwKICAgICJpbXBvcnQgeyBzcGF3biB9IGZyb20gXCJidW5cIjtcblxuLyoqXG4gKiBFeGVjdXRlIHRoZSBjaGVjayBjb21tYW5kXG4gKiBSdW5zIEJpb21lIHRvIGNoZWNrIGFuZCBmaXggY29kZSBzdHlsZSBpc3N1ZXNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNoZWNrQ29tbWFuZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc29sZS5sb2coXCJSdW5uaW5nIEJpb21lIGNoZWNrIHdpdGggYXV0by1maXguLi5cIik7XG5cbiAgY29uc3QgcHJvYyA9IHNwYXduKHtcbiAgICBjbWQ6IFtcImJ1bnhcIiwgXCJiaW9tZVwiLCBcImNoZWNrXCIsIFwiLS13cml0ZVwiLCBcIi5cIl0sXG4gICAgc3RkaW86IFtcImluaGVyaXRcIiwgXCJpbmhlcml0XCIsIFwiaW5oZXJpdFwiXSxcbiAgfSk7XG5cbiAgY29uc3QgZXhpdENvZGUgPSBhd2FpdCBwcm9jLmV4aXRlZDtcblxuICBpZiAoZXhpdENvZGUgPT09IDApIHtcbiAgICBjb25zb2xlLmxvZyhcIuKckyBDaGVjayBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5XCIpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJDaGVjayBmYWlsZWRcIik7XG4gIH1cblxuICBwcm9jZXNzLmV4aXQoZXhpdENvZGUpO1xufVxuIiwKICAgICJpbXBvcnQgeyBzcGF3biB9IGZyb20gXCJidW5cIjtcblxuLyoqXG4gKiBFeGVjdXRlIHRoZSB0eXBlY2hlY2sgY29tbWFuZFxuICogUnVucyBUeXBlU2NyaXB0IGNvbXBpbGVyIHRvIGNoZWNrIGZvciB0eXBlIGVycm9yc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdHlwZWNoZWNrQ29tbWFuZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc29sZS5sb2coXCJSdW5uaW5nIFR5cGVTY3JpcHQgdHlwZSBjaGVja2luZy4uLlwiKTtcblxuICBjb25zdCBwcm9jID0gc3Bhd24oe1xuICAgIGNtZDogW1wiYnVueFwiLCBcInRzY1wiXSxcbiAgICBzdGRpbzogW1wiaW5oZXJpdFwiLCBcImluaGVyaXRcIiwgXCJpbmhlcml0XCJdLFxuICB9KTtcblxuICBjb25zdCBleGl0Q29kZSA9IGF3YWl0IHByb2MuZXhpdGVkO1xuXG4gIGlmIChleGl0Q29kZSA9PT0gMCkge1xuICAgIGNvbnNvbGUubG9nKFwi4pyTIFR5cGUgY2hlY2tpbmcgY29tcGxldGVkIHN1Y2Nlc3NmdWxseVwiKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmVycm9yKFwiVHlwZSBjaGVja2luZyBmYWlsZWRcIik7XG4gIH1cblxuICBwcm9jZXNzLmV4aXQoZXhpdENvZGUpO1xufVxuIiwKICAgICJpbXBvcnQgeyB3cml0ZUZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQge1xuICBnZW5lcmF0ZVBhY2thZ2VKc29uLFxuICBnZW5lcmF0ZVRTQ29uZmlnLFxuICBnZW5lcmF0ZUJpb21lQ29uZmlnLFxufSBmcm9tIFwiQGYtby10L2NvbmZpZ1wiO1xuaW1wb3J0IHsgbG9hZEZvdENvbmZpZyB9IGZyb20gXCIuLi9jb25maWctbG9hZGVyXCI7XG5cbi8qKlxuICogR2VuZXJhdGUgY29uZmlndXJhdGlvbiBmaWxlcyAocGFja2FnZS5qc29uLCB0c2NvbmZpZy5qc29uLCBiaW9tZS5qc29uKSBmcm9tIGZvdC5jb25maWcudHNcbiAqXG4gKiBAcGFyYW0gY3dkIC0gVGhlIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBmb3QuY29uZmlnLnRzIGZpbGVcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlQ29uZmlnRmlsZXMoY3dkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc29sZS5sb2coXCJMb2FkaW5nIGZvdC5jb25maWcudHMuLi5cIik7XG4gIGNvbnN0IGNvbmZpZyA9IGF3YWl0IGxvYWRGb3RDb25maWcoY3dkKTtcblxuICBjb25zb2xlLmxvZyhcIkdlbmVyYXRpbmcgcGFja2FnZS5qc29uLi4uXCIpO1xuICAvLyBFeHRyYWN0IGxpYnJhcnkgbmFtZSBmcm9tIGRpcmVjdG9yeSBuYW1lIG9yIHVzZSBhIGRlZmF1bHRcbiAgY29uc3QgbGlicmFyeU5hbWUgPSBjd2Quc3BsaXQoXCIvXCIpLnBvcCgpIHx8IFwibGlicmFyeVwiO1xuICBjb25zdCBwYWNrYWdlSnNvbiA9IGdlbmVyYXRlUGFja2FnZUpzb24obGlicmFyeU5hbWUsIFwiMC4xLjBcIiwgY29uZmlnKTtcbiAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gam9pbihjd2QsIFwicGFja2FnZS5qc29uXCIpO1xuICB3cml0ZUZpbGVTeW5jKHBhY2thZ2VKc29uUGF0aCwgSlNPTi5zdHJpbmdpZnkocGFja2FnZUpzb24sIG51bGwsIDIpICsgXCJcXG5cIik7XG4gIGNvbnNvbGUubG9nKGDinJMgR2VuZXJhdGVkICR7cGFja2FnZUpzb25QYXRofWApO1xuXG4gIGNvbnNvbGUubG9nKFwiR2VuZXJhdGluZyB0c2NvbmZpZy5qc29uLi4uXCIpO1xuICBjb25zdCB0c2NvbmZpZyA9IGdlbmVyYXRlVFNDb25maWcoY29uZmlnKTtcbiAgY29uc3QgdHNjb25maWdQYXRoID0gam9pbihjd2QsIFwidHNjb25maWcuanNvblwiKTtcbiAgd3JpdGVGaWxlU3luYyh0c2NvbmZpZ1BhdGgsIEpTT04uc3RyaW5naWZ5KHRzY29uZmlnLCBudWxsLCAyKSArIFwiXFxuXCIpO1xuICBjb25zb2xlLmxvZyhg4pyTIEdlbmVyYXRlZCAke3RzY29uZmlnUGF0aH1gKTtcblxuICBjb25zb2xlLmxvZyhcIkdlbmVyYXRpbmcgYmlvbWUuanNvbi4uLlwiKTtcbiAgY29uc3QgYmlvbWVDb25maWcgPSBnZW5lcmF0ZUJpb21lQ29uZmlnKGNvbmZpZyk7XG4gIGNvbnN0IGJpb21lQ29uZmlnUGF0aCA9IGpvaW4oY3dkLCBcImJpb21lLmpzb25cIik7XG4gIHdyaXRlRmlsZVN5bmMoYmlvbWVDb25maWdQYXRoLCBKU09OLnN0cmluZ2lmeShiaW9tZUNvbmZpZywgbnVsbCwgMikgKyBcIlxcblwiKTtcbiAgY29uc29sZS5sb2coYOKckyBHZW5lcmF0ZWQgJHtiaW9tZUNvbmZpZ1BhdGh9YCk7XG5cbiAgY29uc29sZS5sb2coXCJBbGwgY29uZmlndXJhdGlvbiBmaWxlcyBnZW5lcmF0ZWQgc3VjY2Vzc2Z1bGx5IVwiKTtcbn1cbiIsCiAgICAiaW1wb3J0IHsgZXhpc3RzU3luYywgbWtkaXJTeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBzcGF3biB9IGZyb20gXCJidW5cIjtcbmltcG9ydCB7IGdldExpYnJhcnlUZW1wbGF0ZSB9IGZyb20gXCIuLi90ZW1wbGF0ZXMvbGlicmFyeVwiO1xuaW1wb3J0IHsgZ2VuZXJhdGVDb25maWdGaWxlcyB9IGZyb20gXCIuL2dlbmVyYXRlXCI7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY3JlYXRpbmcgYSBuZXcgbGlicmFyeVxuICovXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZU9wdGlvbnMge1xuICAvKipcbiAgICogTmFtZSBvZiB0aGUgbGlicmFyeSAoZS5nLiwgXCJteS1saWJyYXJ5XCIpXG4gICAqL1xuICBuYW1lOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBCcmllZiBkZXNjcmlwdGlvbiBvZiB0aGUgbGlicmFyeVxuICAgKi9cbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgLyoqXG4gICAqIFdvcmtpbmcgZGlyZWN0b3J5IChkZWZhdWx0cyB0byBwcm9jZXNzLmN3ZCgpKVxuICAgKi9cbiAgY3dkPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIG5ldyBsaWJyYXJ5IHdpdGggc2NhZmZvbGRlZCBmaWxlc1xuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gQ3JlYXRlIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUNvbW1hbmQob3B0aW9uczogQ3JlYXRlT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IG5hbWUsIGRlc2NyaXB0aW9uLCBjd2QgPSBwcm9jZXNzLmN3ZCgpIH0gPSBvcHRpb25zO1xuXG4gIGNvbnNvbGUubG9nKGBDcmVhdGluZyBsaWJyYXJ5OiBAZi1vLXQvJHtuYW1lfWApO1xuICBjb25zb2xlLmxvZyhgRGVzY3JpcHRpb246ICR7ZGVzY3JpcHRpb259YCk7XG5cbiAgLy8gRGV0ZXJtaW5lIGxpYnJhcnkgcGF0aFxuICBjb25zdCBsaWJyYXJ5UGF0aCA9IGpvaW4oY3dkLCBcImxpYnJhcmllc1wiLCBuYW1lKTtcblxuICAvLyBDaGVjayBpZiBsaWJyYXJ5IGFscmVhZHkgZXhpc3RzXG4gIGlmIChleGlzdHNTeW5jKGxpYnJhcnlQYXRoKSkge1xuICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yOiBMaWJyYXJ5IGFscmVhZHkgZXhpc3RzIGF0ICR7bGlicmFyeVBhdGh9YCk7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG5cbiAgLy8gQ3JlYXRlIGRpcmVjdG9yeSBzdHJ1Y3R1cmVcbiAgY29uc29sZS5sb2coXCJcXG5DcmVhdGluZyBkaXJlY3Rvcnkgc3RydWN0dXJlLi4uXCIpO1xuICBjb25zdCBzcmNQYXRoID0gam9pbihsaWJyYXJ5UGF0aCwgXCJzcmNcIik7XG4gIG1rZGlyU3luYyhzcmNQYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgY29uc29sZS5sb2coYOKckyBDcmVhdGVkICR7c3JjUGF0aH1gKTtcblxuICAvLyBHZXQgdGVtcGxhdGVzXG4gIGNvbnNvbGUubG9nKFwiXFxuR2VuZXJhdGluZyB0ZW1wbGF0ZSBmaWxlcy4uLlwiKTtcbiAgY29uc3QgdGVtcGxhdGVzID0gZ2V0TGlicmFyeVRlbXBsYXRlKG5hbWUsIGRlc2NyaXB0aW9uKTtcblxuICAvLyBXcml0ZSBmb3QuY29uZmlnLnRzXG4gIGNvbnN0IGZvdENvbmZpZ1BhdGggPSBqb2luKGxpYnJhcnlQYXRoLCBcImZvdC5jb25maWcudHNcIik7XG4gIHdyaXRlRmlsZVN5bmMoZm90Q29uZmlnUGF0aCwgdGVtcGxhdGVzLmZvdENvbmZpZyk7XG4gIGNvbnNvbGUubG9nKGDinJMgQ3JlYXRlZCAke2ZvdENvbmZpZ1BhdGh9YCk7XG5cbiAgLy8gV3JpdGUgc3JjL2luZGV4LnRzXG4gIGNvbnN0IGluZGV4VHNQYXRoID0gam9pbihzcmNQYXRoLCBcImluZGV4LnRzXCIpO1xuICB3cml0ZUZpbGVTeW5jKGluZGV4VHNQYXRoLCB0ZW1wbGF0ZXMuaW5kZXhUcyk7XG4gIGNvbnNvbGUubG9nKGDinJMgQ3JlYXRlZCAke2luZGV4VHNQYXRofWApO1xuXG4gIC8vIFdyaXRlIHNyYy9pbmRleC50ZXN0LnRzXG4gIGNvbnN0IGluZGV4VGVzdFRzUGF0aCA9IGpvaW4oc3JjUGF0aCwgXCJpbmRleC50ZXN0LnRzXCIpO1xuICB3cml0ZUZpbGVTeW5jKGluZGV4VGVzdFRzUGF0aCwgdGVtcGxhdGVzLmluZGV4VGVzdFRzKTtcbiAgY29uc29sZS5sb2coYOKckyBDcmVhdGVkICR7aW5kZXhUZXN0VHNQYXRofWApO1xuXG4gIC8vIFdyaXRlIFJFQURNRS5tZFxuICBjb25zdCByZWFkbWVQYXRoID0gam9pbihsaWJyYXJ5UGF0aCwgXCJSRUFETUUubWRcIik7XG4gIHdyaXRlRmlsZVN5bmMocmVhZG1lUGF0aCwgdGVtcGxhdGVzLnJlYWRtZSk7XG4gIGNvbnNvbGUubG9nKGDinJMgQ3JlYXRlZCAke3JlYWRtZVBhdGh9YCk7XG5cbiAgLy8gR2VuZXJhdGUgY29uZmlndXJhdGlvbiBmaWxlc1xuICBjb25zb2xlLmxvZyhcIlxcbkdlbmVyYXRpbmcgY29uZmlndXJhdGlvbiBmaWxlcy4uLlwiKTtcbiAgYXdhaXQgZ2VuZXJhdGVDb25maWdGaWxlcyhsaWJyYXJ5UGF0aCk7XG5cbiAgLy8gUnVuIGJ1biBpbnN0YWxsXG4gIGNvbnNvbGUubG9nKFwiXFxuSW5zdGFsbGluZyBkZXBlbmRlbmNpZXMuLi5cIik7XG4gIGNvbnN0IGluc3RhbGxQcm9jID0gc3Bhd24oe1xuICAgIGNtZDogW1wiYnVuXCIsIFwiaW5zdGFsbFwiXSxcbiAgICBjd2Q6IGxpYnJhcnlQYXRoLFxuICAgIHN0ZGlvOiBbXCJpbmhlcml0XCIsIFwiaW5oZXJpdFwiLCBcImluaGVyaXRcIl0sXG4gIH0pO1xuXG4gIGNvbnN0IGV4aXRDb2RlID0gYXdhaXQgaW5zdGFsbFByb2MuZXhpdGVkO1xuXG4gIGlmIChleGl0Q29kZSAhPT0gMCkge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJGYWlsZWQgdG8gaW5zdGFsbCBkZXBlbmRlbmNpZXNcIik7XG4gICAgcHJvY2Vzcy5leGl0KGV4aXRDb2RlKTtcbiAgfVxuXG4gIGNvbnNvbGUubG9nKFwi4pyTIERlcGVuZGVuY2llcyBpbnN0YWxsZWRcIik7XG5cbiAgLy8gU2hvdyBuZXh0IHN0ZXBzXG4gIGNvbnNvbGUubG9nKFwiXFxuXCIgKyBcIj1cIi5yZXBlYXQoNjApKTtcbiAgY29uc29sZS5sb2coXCLinJMgTGlicmFyeSBjcmVhdGVkIHN1Y2Nlc3NmdWxseSFcIik7XG4gIGNvbnNvbGUubG9nKFwiPVwiLnJlcGVhdCg2MCkpO1xuICBjb25zb2xlLmxvZyhcIlxcbk5leHQgc3RlcHM6XCIpO1xuICBjb25zb2xlLmxvZyhgICAxLiBjZCBsaWJyYXJpZXMvJHtuYW1lfWApO1xuICBjb25zb2xlLmxvZyhcIiAgMi4gRWRpdCBzcmMvaW5kZXgudHMgdG8gaW1wbGVtZW50IHlvdXIgbGlicmFyeVwiKTtcbiAgY29uc29sZS5sb2coXCIgIDMuIEFkZCB0ZXN0cyBpbiBzcmMvaW5kZXgudGVzdC50c1wiKTtcbiAgY29uc29sZS5sb2coXCIgIDQuIFJ1biAnYnVuIHRlc3QnIHRvIHZlcmlmeSB0ZXN0cyBwYXNzXCIpO1xuICBjb25zb2xlLmxvZyhcIiAgNS4gUnVuICdidW4gcnVuIGJ1aWxkJyB0byBidWlsZCB0aGUgbGlicmFyeVwiKTtcbiAgY29uc29sZS5sb2coXCJcXG5IYXBweSBjb2RpbmchIPCfmoBcIik7XG59XG4iLAogICAgIi8qKlxuICogVGVtcGxhdGVzIGZvciBzY2FmZm9sZGluZyBuZXcgbGlicmFyaWVzXG4gKi9cblxuZXhwb3J0IGludGVyZmFjZSBMaWJyYXJ5VGVtcGxhdGVzIHtcbiAgZm90Q29uZmlnOiBzdHJpbmc7XG4gIGluZGV4VHM6IHN0cmluZztcbiAgaW5kZXhUZXN0VHM6IHN0cmluZztcbiAgcmVhZG1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogR2V0IHRlbXBsYXRlcyBmb3IgYSBuZXcgbGlicmFyeVxuICpcbiAqIEBwYXJhbSBuYW1lIC0gTGlicmFyeSBuYW1lIChlLmcuLCBcIm15LWxpYnJhcnlcIilcbiAqIEBwYXJhbSBkZXNjcmlwdGlvbiAtIEJyaWVmIGRlc2NyaXB0aW9uIG9mIHRoZSBsaWJyYXJ5XG4gKiBAcmV0dXJucyBPYmplY3QgY29udGFpbmluZyBhbGwgdGVtcGxhdGUgZmlsZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldExpYnJhcnlUZW1wbGF0ZShcbiAgbmFtZTogc3RyaW5nLFxuICBkZXNjcmlwdGlvbjogc3RyaW5nXG4pOiBMaWJyYXJ5VGVtcGxhdGVzIHtcbiAgY29uc3QgcGFja2FnZU5hbWUgPSBgQGYtby10LyR7bmFtZX1gO1xuXG4gIGNvbnN0IGZvdENvbmZpZyA9IGBpbXBvcnQgeyBkZWZpbmVGb3RDb25maWcgfSBmcm9tIFwiQGYtby10L2NvbmZpZ1wiO1xuXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVGb3RDb25maWcoe1xuICBmb3JtYXRzOiBbXCJlc21cIiwgXCJjanNcIl0sXG4gIGV4dGVybmFsOiBbXSxcbiAgdHlwZXNjcmlwdDoge1xuICAgIGRlY2xhcmF0aW9uOiB0cnVlLFxuICB9LFxufSk7XG5gO1xuXG4gIGNvbnN0IGluZGV4VHMgPSBgLyoqXG4gKiAke3BhY2thZ2VOYW1lfVxuICogJHtkZXNjcmlwdGlvbn1cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaGVsbG8oKTogc3RyaW5nIHtcbiAgcmV0dXJuIFwiSGVsbG8gZnJvbSAke3BhY2thZ2VOYW1lfSFcIjtcbn1cbmA7XG5cbiAgY29uc3QgaW5kZXhUZXN0VHMgPSBgaW1wb3J0IHsgZGVzY3JpYmUsIGV4cGVjdCwgdGVzdCBhcyBpdCB9IGZyb20gXCJidW46dGVzdFwiO1xuaW1wb3J0IHsgaGVsbG8gfSBmcm9tIFwiLi9pbmRleFwiO1xuXG5kZXNjcmliZShcIiR7cGFja2FnZU5hbWV9XCIsICgpID0+IHtcbiAgaXQoXCJzaG91bGQgZXhwb3J0IGhlbGxvIGZ1bmN0aW9uXCIsICgpID0+IHtcbiAgICBleHBlY3QoaGVsbG8oKSkudG9CZShcIkhlbGxvIGZyb20gJHtwYWNrYWdlTmFtZX0hXCIpO1xuICB9KTtcbn0pO1xuYDtcblxuICBjb25zdCByZWFkbWUgPSBgIyAke3BhY2thZ2VOYW1lfVxuXG4ke2Rlc2NyaXB0aW9ufVxuXG4jIyBJbnN0YWxsYXRpb25cblxuXFxgXFxgXFxgYmFzaFxuIyBidW5cbmJ1biBhZGQgJHtwYWNrYWdlTmFtZX1cblxuIyBucG1cbm5wbSBpbnN0YWxsICR7cGFja2FnZU5hbWV9XG5cbiMgeWFyblxueWFybiBhZGQgJHtwYWNrYWdlTmFtZX1cblxuIyBwbnBtXG5wbnBtIGFkZCAke3BhY2thZ2VOYW1lfVxuXFxgXFxgXFxgXG5cbiMjIFF1aWNrIFN0YXJ0XG5cblxcYFxcYFxcYHR5cGVzY3JpcHRcbmltcG9ydCB7IGhlbGxvIH0gZnJvbSBcIiR7cGFja2FnZU5hbWV9XCI7XG5cbmNvbnNvbGUubG9nKGhlbGxvKCkpO1xuXFxgXFxgXFxgXG5cbiMjIEFQSSBSZWZlcmVuY2VcblxuIyMjIFxcYGhlbGxvKClcXGBcblxuUmV0dXJucyBhIGdyZWV0aW5nIHN0cmluZy5cblxuXFxgXFxgXFxgdHlwZXNjcmlwdFxuY29uc3QgZ3JlZXRpbmcgPSBoZWxsbygpO1xuY29uc29sZS5sb2coZ3JlZXRpbmcpOyAvLyBcIkhlbGxvIGZyb20gJHtwYWNrYWdlTmFtZX0hXCJcblxcYFxcYFxcYFxuXG4jIyBDb250cmlidXRpbmdcblxuQ29udHJpYnV0aW9ucyBhcmUgd2VsY29tZSEgUGxlYXNlIGNoZWNrIHRoZSByZXBvc2l0b3J5IGZvciBndWlkZWxpbmVzLlxuXG4jIyBMaWNlbnNlXG5cbk1JVCBMaWNlbnNlIC0gc2VlIFtMSUNFTlNFXSguL0xJQ0VOU0UpIGZpbGUgZm9yIGRldGFpbHMuXG5cbiMjIExpbmtzXG5cbi0gW0dpdEh1YiBSZXBvc2l0b3J5XShodHRwczovL2dpdGh1Yi5jb20vRi1PLVQvbGlicmFyaWVzKVxuLSBbSXNzdWUgVHJhY2tlcl0oaHR0cHM6Ly9naXRodWIuY29tL0YtTy1UL2xpYnJhcmllcy9pc3N1ZXMpXG5gO1xuXG4gIHJldHVybiB7XG4gICAgZm90Q29uZmlnLFxuICAgIGluZGV4VHMsXG4gICAgaW5kZXhUZXN0VHMsXG4gICAgcmVhZG1lLFxuICB9O1xufVxuIiwKICAgICIjIS91c3IvYmluL2VudiBidW5cblxuaW1wb3J0IHtcbiAgYnVpbGRDb21tYW5kLFxuICBkZXZDb21tYW5kLFxuICB0ZXN0Q29tbWFuZCxcbiAgY2hlY2tDb21tYW5kLFxuICB0eXBlY2hlY2tDb21tYW5kLFxuICBnZW5lcmF0ZUNvbmZpZ0ZpbGVzLFxuICBjcmVhdGVDb21tYW5kLFxuICB0eXBlIFRlc3RPcHRpb25zLFxuICB0eXBlIENyZWF0ZU9wdGlvbnMsXG59IGZyb20gXCIuL2NvbW1hbmRzL2luZGV4XCI7XG5cbi8vIEV4cG9ydCBhbGwgY29tbWFuZHMgYW5kIHV0aWxpdGllc1xuZXhwb3J0IHsgZ2VuZXJhdGVDb25maWdGaWxlcyB9IGZyb20gXCIuL2NvbW1hbmRzL2dlbmVyYXRlXCI7XG5leHBvcnQgeyBidWlsZENvbW1hbmQgfSBmcm9tIFwiLi9jb21tYW5kcy9idWlsZFwiO1xuZXhwb3J0IHsgYnVpbGRMaWJyYXJ5LCB0eXBlIEJ1aWxkT3B0aW9ucyB9IGZyb20gXCIuL2J1aWxkZXJcIjtcbmV4cG9ydCB7IGxvYWRGb3RDb25maWcsIGhhc0ZvdENvbmZpZyB9IGZyb20gXCIuL2NvbmZpZy1sb2FkZXJcIjtcblxuZnVuY3Rpb24gcHJpbnRIZWxwKCkge1xuICBjb25zb2xlLmxvZyhgXG5GT1QgQ0xJIC0gQnVpbGQgdG9vbHMgZm9yIG1vbm9yZXBvIGxpYnJhcmllc1xuXG5Vc2FnZTogZm90IDxjb21tYW5kPiBbb3B0aW9uc11cblxuQ29tbWFuZHM6XG4gIGJ1aWxkICAgICAgICAgICAgICBCdWlsZCB0aGUgY3VycmVudCBsaWJyYXJ5XG4gIGRldiAgICAgICAgICAgICAgICBTdGFydCBkZXZlbG9wbWVudCBtb2RlIHdpdGggd2F0Y2hcbiAgdGVzdCAgICAgICAgICAgICAgIFJ1biB0ZXN0c1xuICAgIC0td2F0Y2ggICAgICAgICAgUnVuIHRlc3RzIGluIHdhdGNoIG1vZGVcbiAgICAtLWNvdmVyYWdlICAgICAgIFJ1biB0ZXN0cyB3aXRoIGNvdmVyYWdlXG4gIGNoZWNrICAgICAgICAgICAgICBSdW4gYWxsIGNoZWNrcyAodHlwZWNoZWNrICsgdGVzdClcbiAgdHlwZWNoZWNrICAgICAgICAgIFJ1biBUeXBlU2NyaXB0IHR5cGUgY2hlY2tpbmdcbiAgZ2VuZXJhdGUgICAgICAgICAgIEdlbmVyYXRlIGNvbmZpZ3VyYXRpb24gZmlsZXNcbiAgY3JlYXRlIDxuYW1lPiAgICAgIENyZWF0ZSBhIG5ldyBsaWJyYXJ5XG4gICAgW2Rlc2NyaXB0aW9uXSAgICBPcHRpb25hbCBkZXNjcmlwdGlvbiBmb3IgdGhlIGxpYnJhcnlcbiAgaGVscCwgLS1oZWxwLCAtaCAgIFNob3cgdGhpcyBoZWxwIG1lc3NhZ2VcbiAgdmVyc2lvbiwgLS12ZXJzaW9uLCAtdiAgU2hvdyB2ZXJzaW9uIG51bWJlclxuXG5FeGFtcGxlczpcbiAgZm90IGJ1aWxkXG4gIGZvdCBkZXZcbiAgZm90IHRlc3QgLS1jb3ZlcmFnZVxuICBmb3QgdGVzdCAtLXdhdGNoXG4gIGZvdCBjcmVhdGUgbXktbGliIFwiQSBuZXcgbGlicmFyeVwiXG4gIGZvdCBnZW5lcmF0ZVxuICBmb3QgY2hlY2tcbmApO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtYWluKCkge1xuICBjb25zdCBhcmdzID0gcHJvY2Vzcy5hcmd2LnNsaWNlKDIpO1xuICBjb25zdCBjb21tYW5kID0gYXJnc1swXTtcblxuICB0cnkge1xuICAgIHN3aXRjaCAoY29tbWFuZCkge1xuICAgICAgY2FzZSBcImJ1aWxkXCI6XG4gICAgICAgIGF3YWl0IGJ1aWxkQ29tbWFuZCgpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImRldlwiOlxuICAgICAgICBhd2FpdCBkZXZDb21tYW5kKCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwidGVzdFwiOiB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnM6IFRlc3RPcHRpb25zID0ge1xuICAgICAgICAgIGNvdmVyYWdlOiBhcmdzLmluY2x1ZGVzKFwiLS1jb3ZlcmFnZVwiKSxcbiAgICAgICAgICB3YXRjaDogYXJncy5pbmNsdWRlcyhcIi0td2F0Y2hcIiksXG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IHRlc3RDb21tYW5kKG9wdGlvbnMpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgY2FzZSBcImNoZWNrXCI6XG4gICAgICAgIGF3YWl0IGNoZWNrQ29tbWFuZCgpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcInR5cGVjaGVja1wiOlxuICAgICAgICBhd2FpdCB0eXBlY2hlY2tDb21tYW5kKCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiZ2VuZXJhdGVcIjpcbiAgICAgICAgYXdhaXQgZ2VuZXJhdGVDb25maWdGaWxlcyhwcm9jZXNzLmN3ZCgpKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJjcmVhdGVcIjoge1xuICAgICAgICBjb25zdCBuYW1lID0gYXJnc1sxXTtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBhcmdzWzJdIHx8IGBBIG5ldyBGT1QgbGlicmFyeTogJHtuYW1lfWA7XG4gICAgICAgIGNvbnN0IG9wdGlvbnM6IENyZWF0ZU9wdGlvbnMgPSB7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICBkZXNjcmlwdGlvbixcbiAgICAgICAgfTtcbiAgICAgICAgYXdhaXQgY3JlYXRlQ29tbWFuZChvcHRpb25zKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGNhc2UgXCJoZWxwXCI6XG4gICAgICBjYXNlIFwiLS1oZWxwXCI6XG4gICAgICBjYXNlIFwiLWhcIjpcbiAgICAgICAgcHJpbnRIZWxwKCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwidmVyc2lvblwiOlxuICAgICAgY2FzZSBcIi0tdmVyc2lvblwiOlxuICAgICAgY2FzZSBcIi12XCI6XG4gICAgICAgIGNvbnNvbGUubG9nKFwiZm90IHYwLjEuMFwiKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgICBwcmludEhlbHAoKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYFVua25vd24gY29tbWFuZDogJHtjb21tYW5kfWApO1xuICAgICAgICBjb25zb2xlLmxvZygnUnVuIFwiZm90IC0taGVscFwiIGZvciB1c2FnZSBpbmZvcm1hdGlvbicpO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvcjpcIiwgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBlcnJvcik7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG59XG5cbm1haW4oKTtcbiIKICBdLAogICJtYXBwaW5ncyI6ICI7Ozs7QUFBQSxpQkFBUztBQUNUO0FBQ0E7OztBQ0ZBO0FBQ0E7QUFTTyxTQUFTLFlBQVksQ0FBQyxLQUFzQjtBQUFBLEVBQ2pELE1BQU0sYUFBYSxLQUFLLEtBQUssZUFBZTtBQUFBLEVBQzVDLE9BQU8sV0FBVyxVQUFVO0FBQUE7QUFVOUIsZUFBc0IsYUFBYSxDQUFDLEtBQXlDO0FBQUEsRUFDM0UsTUFBTSxhQUFhLEtBQUssS0FBSyxlQUFlO0FBQUEsRUFFNUMsSUFBSSxDQUFDLFdBQVcsVUFBVSxHQUFHO0FBQUEsSUFDM0IsTUFBTSxJQUFJLE1BQ1IsOEJBQThCLDBDQUNoQztBQUFBLEVBQ0Y7QUFBQSxFQUVBLElBQUk7QUFBQSxJQUVGLE1BQU0sZUFBZSxNQUFhO0FBQUEsSUFFbEMsSUFBSSxDQUFDLGFBQWEsU0FBUztBQUFBLE1BQ3pCLE1BQU0sSUFBSSxN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QUErQztBQUFBLEVBQzNELFFBQVEsSUFBSTtBQUFBLDJCQUFtQjtBQUFBOztBRXJGakMsU0FBUyxTQUFTLEdBQUc7QUFBQSxFQUNuQixRQUFRLElBQUk7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsQ0EyQmI7QUFBQTtBQUdELGVBQWUsSUFBSSxHQUFHO0FBQUEsRUFDcEIsTUFBTSxPQUFPLFFBQVEsS0FBSyxNQUFNLENBQUM7QUFBQSxFQUNqQyxNQUFNLFVBQVUsS0FBSztBQUFBLEVBRXJCLElBQUk7QUFBQSxJQUNGLFFBQVE7QUFBQSxXQUNEO0FBQUEsUUFDSCxNQUFNLGFBQWE7QUFBQSxRQUNuQjtBQUFBLFdBRUc7QUFBQSxRQUNILE1BQU0sV0FBVztBQUFBLFFBQ2pCO0FBQUEsV0FFRyxRQUFRO0FBQUEsUUFDWCxNQUFNLFVBQXVCO0FBQUEsVUFDM0IsVUFBVSxLQUFLLFNBQVMsWUFBWTtBQUFBLFVBQ3BDLE9BQU8sS0FBSyxTQUFTLFNBQVM7QUFBQSxRQUNoQztBQUFBLFFBQ0EsTUFBTSxZQUFZLE9BQU87QUFBQSxRQUN6QjtBQUFBLE1BQ0Y7QUFBQSxXQUVLO0FBQUEsUUFDSCxNQUFNLGFBQWE7QUFBQSxRQUNuQjtBQUFBLFdBRUc7QUFBQSxRQUNILE1BQU0saUJBQWlCO0FBQUEsUUFDdkI7QUFBQSxXQUVHO0FBQUEsUUFDSCxNQUFNLG9CQUFvQixRQUFRLElBQUksQ0FBQztBQUFBLFFBQ3ZDO0FBQUEsV0FFRyxVQUFVO0FBQUEsUUFDYixNQUFNLE9BQU8sS0FBSztBQUFBLFFBQ2xCLE1BQU0sY0FBYyxLQUFLLE1BQU0sc0JBQXNCO0FBQUEsUUFDckQsTUFBTSxVQUF5QjtBQUFBLFVBQzdCO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxRQUNBLE1BQU0sY0FBYyxPQUFPO0FBQUEsUUFDM0I7QUFBQSxNQUNGO0FBQUEsV0FFSztBQUFBLFdBQ0E7QUFBQSxXQUNBO0FBQUEsUUFDSCxVQUFVO0FBQUEsUUFDVjtBQUFBLFdBRUc7QUFBQSxXQUNBO0FBQUEsV0FDQTtBQUFBLFFBQ0gsUUFBUSxJQUFJLFlBQVk7QUFBQSxRQUN4QjtBQUFBLFdBRUc7QUFBQSxRQUNILFVBQVU7QUFBQSxRQUNWO0FBQUE7QUFBQSxRQUdBLFFBQVEsTUFBTSxvQkFBb0IsU0FBUztBQUFBLFFBQzNDLFFBQVEsSUFBSSx3Q0FBd0M7QUFBQSxRQUNwRCxRQUFRLEtBQUssQ0FBQztBQUFBO0FBQUEsSUFFbEIsT0FBTyxPQUFPO0FBQUEsSUFDZCxRQUFRLE1BQU0sVUFBVSxpQkFBaUIsUUFBUSxNQUFNLFVBQVUsS0FBSztBQUFBLElBQ3RFLFFBQVEsS0FBSyxDQUFDO0FBQUE7QUFBQTtBQUlsQixLQUFLOyIsCiAgImRlYnVnSWQiOiAiM0QxQkM0OTI1MThDMjZBOTY0NzU2RTIxNjQ3NTZFMjEiLAogICJuYW1lcyI6IFtdCn0=
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@f-o-t/cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI tool for managing FOT libraries",
5
+ "type": "module",
6
+ "bin": {
7
+ "fot": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "build": "bunup",
16
+ "dev": "bunup --watch",
17
+ "test": "bun test"
18
+ },
19
+ "dependencies": {
20
+ "@f-o-t/config": "workspace:*",
21
+ "commander": "^12.1.0"
22
+ },
23
+ "devDependencies": {
24
+ "@types/bun": "latest",
25
+ "bunup": "^0.16.20",
26
+ "typescript": "^5.7.3"
27
+ },
28
+ "peerDependencies": {
29
+ "typescript": ">=5.0.0"
30
+ }
31
+ }