@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 +410 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +453 -0
- package/package.json +31 -0
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
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|