@asagiri-design/labels-config 0.2.2
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/LICENSE +21 -0
- package/README.ja.md +387 -0
- package/README.md +387 -0
- package/dist/chunk-4ZUJQMV7.mjs +285 -0
- package/dist/chunk-DGUMSQAI.mjs +496 -0
- package/dist/chunk-DSI7SDAM.mjs +161 -0
- package/dist/chunk-QJLMZSVA.mjs +496 -0
- package/dist/chunk-QZ7TP4HQ.mjs +7 -0
- package/dist/chunk-VU2JB66N.mjs +103 -0
- package/dist/chunk-ZYHIDOG2.mjs +247 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1417 -0
- package/dist/cli.mjs +436 -0
- package/dist/config/index.d.mts +49 -0
- package/dist/config/index.d.ts +49 -0
- package/dist/config/index.js +554 -0
- package/dist/config/index.mjs +10 -0
- package/dist/github/index.d.mts +113 -0
- package/dist/github/index.d.ts +113 -0
- package/dist/github/index.js +310 -0
- package/dist/github/index.mjs +9 -0
- package/dist/index.d.mts +309 -0
- package/dist/index.d.ts +309 -0
- package/dist/index.js +306 -0
- package/dist/index.mjs +44 -0
- package/dist/types-CkwsO1Iu.d.mts +50 -0
- package/dist/types-CkwsO1Iu.d.ts +50 -0
- package/docs/API.md +309 -0
- package/docs/GETTING_STARTED.md +305 -0
- package/package.json +87 -0
- package/templates/prod-labels.json +106 -0
package/docs/API.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## Types
|
|
4
|
+
|
|
5
|
+
### `LabelConfig`
|
|
6
|
+
|
|
7
|
+
Main label configuration interface.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
interface LabelConfig {
|
|
11
|
+
name: string // Label name (unique, 1-50 chars)
|
|
12
|
+
color: HexColor // Hex color code (6 digits)
|
|
13
|
+
description: string // Description (1-200 chars)
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### `LabelRegistry`
|
|
18
|
+
|
|
19
|
+
Container for label collections with metadata.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
interface LabelRegistry {
|
|
23
|
+
version: string
|
|
24
|
+
timestamp?: string
|
|
25
|
+
labels: LabelConfig[] | LabelCategory[]
|
|
26
|
+
metadata?: Record<string, unknown>
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### `LabelCategory`
|
|
31
|
+
|
|
32
|
+
Grouping mechanism for related labels.
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
interface LabelCategory {
|
|
36
|
+
category: string
|
|
37
|
+
labels: LabelConfig[]
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Classes
|
|
42
|
+
|
|
43
|
+
### `LabelManager`
|
|
44
|
+
|
|
45
|
+
Main class for managing label configurations in memory.
|
|
46
|
+
|
|
47
|
+
#### Constructor
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
new LabelManager(options?: LabelManagerOptions)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
- `labels?: LabelConfig[]` - Initial labels to load
|
|
55
|
+
- `strict?: boolean` - Strict validation mode (default: false)
|
|
56
|
+
|
|
57
|
+
#### Methods
|
|
58
|
+
|
|
59
|
+
##### `loadLabels(labels: LabelConfig[]): void`
|
|
60
|
+
|
|
61
|
+
Load labels from array. Clears previous labels.
|
|
62
|
+
|
|
63
|
+
##### `loadRegistry(registry: LabelRegistry): void`
|
|
64
|
+
|
|
65
|
+
Load labels from registry object. Handles both flat and categorized formats.
|
|
66
|
+
|
|
67
|
+
##### `addLabel(label: LabelConfig): void`
|
|
68
|
+
|
|
69
|
+
Add a new label. Throws if name already exists.
|
|
70
|
+
|
|
71
|
+
##### `updateLabel(name: string, updates: Partial<LabelConfig>): void`
|
|
72
|
+
|
|
73
|
+
Update an existing label. Throws if label not found.
|
|
74
|
+
|
|
75
|
+
##### `removeLabel(name: string): void`
|
|
76
|
+
|
|
77
|
+
Remove a label by name.
|
|
78
|
+
|
|
79
|
+
##### `getLabel(name: string): LabelConfig | undefined`
|
|
80
|
+
|
|
81
|
+
Get a label by name. Case-insensitive.
|
|
82
|
+
|
|
83
|
+
##### `hasLabel(name: string): boolean`
|
|
84
|
+
|
|
85
|
+
Check if label exists. Case-insensitive.
|
|
86
|
+
|
|
87
|
+
##### `getAllLabels(): LabelConfig[]`
|
|
88
|
+
|
|
89
|
+
Get all labels as array.
|
|
90
|
+
|
|
91
|
+
##### `count(): number`
|
|
92
|
+
|
|
93
|
+
Get total number of labels.
|
|
94
|
+
|
|
95
|
+
##### `export(): LabelConfig[]`
|
|
96
|
+
|
|
97
|
+
Export all labels as array.
|
|
98
|
+
|
|
99
|
+
##### `exportRegistry(version?: string, metadata?: Record<string, unknown>): LabelRegistry`
|
|
100
|
+
|
|
101
|
+
Export as registry object with metadata.
|
|
102
|
+
|
|
103
|
+
##### `search(query: string): LabelConfig[]`
|
|
104
|
+
|
|
105
|
+
Search labels by name or description. Case-insensitive.
|
|
106
|
+
|
|
107
|
+
##### `findByColor(color: string): LabelConfig[]`
|
|
108
|
+
|
|
109
|
+
Find labels by color code. Case-insensitive.
|
|
110
|
+
|
|
111
|
+
##### `clear(): void`
|
|
112
|
+
|
|
113
|
+
Clear all labels.
|
|
114
|
+
|
|
115
|
+
##### `validate(): { valid: boolean; duplicates: string[] }`
|
|
116
|
+
|
|
117
|
+
Validate current state. Returns duplicate label names.
|
|
118
|
+
|
|
119
|
+
### `GitHubLabelSync`
|
|
120
|
+
|
|
121
|
+
Synchronize labels with GitHub repositories.
|
|
122
|
+
|
|
123
|
+
#### Constructor
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
new GitHubLabelSync(options: GitHubSyncOptions)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Options:
|
|
130
|
+
- `token: string` - GitHub personal access token (required)
|
|
131
|
+
- `owner: string` - Repository owner (required)
|
|
132
|
+
- `repo: string` - Repository name (required)
|
|
133
|
+
- `dryRun?: boolean` - Dry run mode (default: false)
|
|
134
|
+
- `deleteExtra?: boolean` - Delete extra labels (default: false)
|
|
135
|
+
- `verbose?: boolean` - Verbose logging (default: false)
|
|
136
|
+
|
|
137
|
+
#### Methods
|
|
138
|
+
|
|
139
|
+
##### `async syncLabels(labels: LabelConfig[]): Promise<SyncResult>`
|
|
140
|
+
|
|
141
|
+
Sync local labels to GitHub repository.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
```typescript
|
|
145
|
+
interface SyncResult {
|
|
146
|
+
created: LabelConfig[]
|
|
147
|
+
updated: LabelConfig[]
|
|
148
|
+
deleted: string[]
|
|
149
|
+
unchanged: LabelConfig[]
|
|
150
|
+
errors: Array<{ name: string; error: string }>
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
##### `async fetchLabels(): Promise<LabelConfig[]>`
|
|
155
|
+
|
|
156
|
+
Fetch all labels from GitHub repository.
|
|
157
|
+
|
|
158
|
+
##### `async deleteLabel(name: string): Promise<void>`
|
|
159
|
+
|
|
160
|
+
Delete a single label from repository.
|
|
161
|
+
|
|
162
|
+
##### `async updateLabel(name: string, updates: Partial<LabelConfig>): Promise<void>`
|
|
163
|
+
|
|
164
|
+
Update a single label in repository.
|
|
165
|
+
|
|
166
|
+
### `ConfigLoader`
|
|
167
|
+
|
|
168
|
+
Load configurations from various sources.
|
|
169
|
+
|
|
170
|
+
#### Constructor
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
new ConfigLoader(options?: LoaderOptions)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Options:
|
|
177
|
+
- `strict?: boolean` - Strict validation mode (default: true)
|
|
178
|
+
|
|
179
|
+
#### Methods
|
|
180
|
+
|
|
181
|
+
##### `loadFromJSON(data: unknown): LabelConfig[]`
|
|
182
|
+
|
|
183
|
+
Load labels from JSON object or array.
|
|
184
|
+
|
|
185
|
+
##### `loadFromString(jsonString: string): LabelConfig[]`
|
|
186
|
+
|
|
187
|
+
Load labels from JSON string.
|
|
188
|
+
|
|
189
|
+
##### `loadRegistry(registry: LabelRegistry): LabelConfig[]`
|
|
190
|
+
|
|
191
|
+
Load labels from registry object.
|
|
192
|
+
|
|
193
|
+
## Functions
|
|
194
|
+
|
|
195
|
+
### Validation
|
|
196
|
+
|
|
197
|
+
#### `validateLabel(label: unknown): LabelConfig`
|
|
198
|
+
|
|
199
|
+
Validate and normalize a single label.
|
|
200
|
+
|
|
201
|
+
Throws: `ZodError` if validation fails.
|
|
202
|
+
|
|
203
|
+
#### `validateLabels(labels: unknown): LabelConfig[]`
|
|
204
|
+
|
|
205
|
+
Validate and normalize multiple labels.
|
|
206
|
+
|
|
207
|
+
Throws: `ZodError` if validation fails.
|
|
208
|
+
|
|
209
|
+
#### `validateRegistry(registry: unknown): LabelRegistry`
|
|
210
|
+
|
|
211
|
+
Validate complete registry object.
|
|
212
|
+
|
|
213
|
+
Throws: `ZodError` if validation fails.
|
|
214
|
+
|
|
215
|
+
#### `validateWithDetails(labels: unknown): ValidationResult`
|
|
216
|
+
|
|
217
|
+
Comprehensive validation with detailed error reporting.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
interface ValidationResult {
|
|
221
|
+
valid: boolean
|
|
222
|
+
labels: LabelConfig[]
|
|
223
|
+
errors: {
|
|
224
|
+
duplicateNames?: string[]
|
|
225
|
+
duplicateColors?: string[]
|
|
226
|
+
validationErrors?: ZodError[]
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### `checkDuplicateNames(labels: LabelConfig[]): string[]`
|
|
232
|
+
|
|
233
|
+
Find duplicate label names.
|
|
234
|
+
|
|
235
|
+
#### `checkDuplicateColors(labels: LabelConfig[]): string[]`
|
|
236
|
+
|
|
237
|
+
Find duplicate colors.
|
|
238
|
+
|
|
239
|
+
### Type Guards
|
|
240
|
+
|
|
241
|
+
#### `isCategorized(labels: LabelConfig[] | LabelCategory[]): labels is LabelCategory[]`
|
|
242
|
+
|
|
243
|
+
Check if labels are categorized.
|
|
244
|
+
|
|
245
|
+
#### `flattenLabels(labels: LabelConfig[] | LabelCategory[]): LabelConfig[]`
|
|
246
|
+
|
|
247
|
+
Flatten categorized labels to flat array.
|
|
248
|
+
|
|
249
|
+
### Templates
|
|
250
|
+
|
|
251
|
+
#### `getTemplate(name: TemplateName): LabelConfig[]`
|
|
252
|
+
|
|
253
|
+
Get predefined template by name.
|
|
254
|
+
|
|
255
|
+
Templates:
|
|
256
|
+
- `minimal` - Minimal set for getting started
|
|
257
|
+
- `github` - GitHub standard labels
|
|
258
|
+
- `prod` - Production project labels (Japanese)
|
|
259
|
+
- `prod-en` - Production project labels (English)
|
|
260
|
+
- `prod-ja` - Production project labels (Japanese, alias)
|
|
261
|
+
- `react` - React ecosystem labels
|
|
262
|
+
- `vue` - Vue.js ecosystem labels
|
|
263
|
+
- `frontend` - General frontend development labels
|
|
264
|
+
- `agile` - Agile/Scrum labels
|
|
265
|
+
|
|
266
|
+
#### `listTemplates(): TemplateName[]`
|
|
267
|
+
|
|
268
|
+
List all available template names.
|
|
269
|
+
|
|
270
|
+
## Error Handling
|
|
271
|
+
|
|
272
|
+
All validation functions throw `ZodError` on invalid input:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
import { validateLabel } from '@boxpistols/labels-config'
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
validateLabel({ name: 'test', color: 'invalid' })
|
|
279
|
+
} catch (error) {
|
|
280
|
+
if (error instanceof ZodError) {
|
|
281
|
+
error.errors.forEach(err => {
|
|
282
|
+
console.log(err.path, err.message)
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Strict Mode
|
|
289
|
+
|
|
290
|
+
When `strict: true` is passed to managers/loaders:
|
|
291
|
+
- All errors throw immediately
|
|
292
|
+
- No partial results are returned
|
|
293
|
+
- Validation is mandatory
|
|
294
|
+
|
|
295
|
+
When `strict: false`:
|
|
296
|
+
- Some errors are warnings
|
|
297
|
+
- Partial results may be returned
|
|
298
|
+
- Validation is optional
|
|
299
|
+
|
|
300
|
+
## Type Safety
|
|
301
|
+
|
|
302
|
+
All APIs are fully typed with TypeScript. No `any` types are used.
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
// Full type inference
|
|
306
|
+
const manager = new LabelManager({ labels: [] })
|
|
307
|
+
const label = manager.getLabel('test') // Type: LabelConfig | undefined
|
|
308
|
+
const all = manager.getAllLabels() // Type: LabelConfig[]
|
|
309
|
+
```
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# Getting Started with @boxpistols/labels-config
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
### npm
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @boxpistols/labels-config
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### yarn
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
yarn add @boxpistols/labels-config
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### pnpm
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @boxpistols/labels-config
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### CDN
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<script src="https://cdn.jsdelivr.net/npm/@boxpistols/labels-config/dist/index.umd.js"></script>
|
|
27
|
+
<script>
|
|
28
|
+
const { validateLabels } = window.LabelsConfig
|
|
29
|
+
</script>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Basic Usage
|
|
33
|
+
|
|
34
|
+
### Validate Labels
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { validateLabels } from '@boxpistols/labels-config'
|
|
38
|
+
|
|
39
|
+
const labels = [
|
|
40
|
+
{
|
|
41
|
+
name: 'bug',
|
|
42
|
+
color: 'ff0000',
|
|
43
|
+
description: 'Something is broken'
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'feature',
|
|
47
|
+
color: '00ff00',
|
|
48
|
+
description: 'New feature or request'
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
// Validate labels
|
|
53
|
+
const validated = validateLabels(labels)
|
|
54
|
+
console.log(validated) // Returns validated and normalized labels
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Using Label Manager
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { LabelManager } from '@boxpistols/labels-config'
|
|
61
|
+
|
|
62
|
+
const manager = new LabelManager({
|
|
63
|
+
labels: [
|
|
64
|
+
{ name: 'bug', color: 'ff0000', description: 'Bug' },
|
|
65
|
+
{ name: 'feature', color: '00ff00', description: 'Feature' }
|
|
66
|
+
]
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// Add a label
|
|
70
|
+
manager.addLabel({ name: 'docs', color: '0000ff', description: 'Documentation' })
|
|
71
|
+
|
|
72
|
+
// Get all labels
|
|
73
|
+
const allLabels = manager.getAllLabels()
|
|
74
|
+
|
|
75
|
+
// Search labels
|
|
76
|
+
const results = manager.search('feature')
|
|
77
|
+
|
|
78
|
+
// Export
|
|
79
|
+
const exported = manager.export()
|
|
80
|
+
const registry = manager.exportRegistry('1.0.0')
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### GitHub Synchronization
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { GitHubLabelSync } from '@boxpistols/labels-config/github'
|
|
87
|
+
|
|
88
|
+
const sync = new GitHubLabelSync({
|
|
89
|
+
token: process.env.GITHUB_TOKEN,
|
|
90
|
+
owner: 'your-org',
|
|
91
|
+
repo: 'your-repo',
|
|
92
|
+
verbose: true
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// Sync local labels to GitHub
|
|
96
|
+
const result = await sync.syncLabels([
|
|
97
|
+
{ name: 'bug', color: 'ff0000', description: 'Bug' },
|
|
98
|
+
{ name: 'feature', color: '00ff00', description: 'Feature' }
|
|
99
|
+
])
|
|
100
|
+
|
|
101
|
+
console.log(`Created: ${result.created.length}`)
|
|
102
|
+
console.log(`Updated: ${result.updated.length}`)
|
|
103
|
+
console.log(`Deleted: ${result.deleted.length}`)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Load Configuration from File
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import { ConfigLoader } from '@boxpistols/labels-config/config'
|
|
110
|
+
import { promises as fs } from 'fs'
|
|
111
|
+
|
|
112
|
+
const loader = new ConfigLoader()
|
|
113
|
+
const fileContent = await fs.readFile('labels.json', 'utf-8')
|
|
114
|
+
const labels = loader.loadFromString(fileContent)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Using Templates
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { CONFIG_TEMPLATES, listTemplates } from '@boxpistols/labels-config/config'
|
|
121
|
+
|
|
122
|
+
// Get production template (Japanese)
|
|
123
|
+
const prodLabels = CONFIG_TEMPLATES.prod
|
|
124
|
+
|
|
125
|
+
// List all available templates
|
|
126
|
+
const templates = listTemplates() // ['minimal', 'github', 'prod', 'prod-en', 'prod-ja', 'react', 'vue', 'frontend', 'agile']
|
|
127
|
+
|
|
128
|
+
// Use GitHub standard template
|
|
129
|
+
const githubLabels = CONFIG_TEMPLATES.github
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## CLI Usage
|
|
133
|
+
|
|
134
|
+
### Initialize Configuration
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Create from template
|
|
138
|
+
labels-config init prod-ja --file labels.json
|
|
139
|
+
|
|
140
|
+
# Available templates: minimal, github, prod, prod-en, prod-ja, react, vue, frontend, agile
|
|
141
|
+
labels-config init github --file labels.json
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Validate Configuration
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
labels-config validate ./labels.json
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Sync to GitHub
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
labels-config sync \
|
|
154
|
+
--token $GITHUB_TOKEN \
|
|
155
|
+
--owner your-org \
|
|
156
|
+
--repo your-repo \
|
|
157
|
+
--file labels.json \
|
|
158
|
+
--verbose
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Dry Run
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# See what would be changed without actually changing
|
|
165
|
+
labels-config sync \
|
|
166
|
+
--token $GITHUB_TOKEN \
|
|
167
|
+
--owner your-org \
|
|
168
|
+
--repo your-repo \
|
|
169
|
+
--file labels.json \
|
|
170
|
+
--dry-run \
|
|
171
|
+
--verbose
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Export from Repository
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Export existing labels from GitHub
|
|
178
|
+
labels-config export \
|
|
179
|
+
--token $GITHUB_TOKEN \
|
|
180
|
+
--owner your-org \
|
|
181
|
+
--repo your-repo \
|
|
182
|
+
--file exported-labels.json
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Configuration File Format
|
|
186
|
+
|
|
187
|
+
### Flat List
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
[
|
|
191
|
+
{
|
|
192
|
+
"name": "bug",
|
|
193
|
+
"color": "ff0000",
|
|
194
|
+
"description": "Something is broken"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"name": "feature",
|
|
198
|
+
"color": "00ff00",
|
|
199
|
+
"description": "New feature"
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Registry Format
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"version": "1.0.0",
|
|
209
|
+
"timestamp": "2024-11-12T00:00:00Z",
|
|
210
|
+
"labels": [
|
|
211
|
+
{
|
|
212
|
+
"name": "bug",
|
|
213
|
+
"color": "ff0000",
|
|
214
|
+
"description": "Something is broken"
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
"metadata": {
|
|
218
|
+
"project": "my-project"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Categorized Labels
|
|
224
|
+
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"version": "1.0.0",
|
|
228
|
+
"labels": [
|
|
229
|
+
{
|
|
230
|
+
"category": "Type",
|
|
231
|
+
"labels": [
|
|
232
|
+
{
|
|
233
|
+
"name": "bug",
|
|
234
|
+
"color": "ff0000",
|
|
235
|
+
"description": "Bug fix"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"name": "feature",
|
|
239
|
+
"color": "00ff00",
|
|
240
|
+
"description": "New feature"
|
|
241
|
+
}
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"category": "Priority",
|
|
246
|
+
"labels": [
|
|
247
|
+
{
|
|
248
|
+
"name": "priority:high",
|
|
249
|
+
"color": "ff0000",
|
|
250
|
+
"description": "High priority"
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
]
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Advanced Usage
|
|
259
|
+
|
|
260
|
+
### Error Handling
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { validateWithDetails } from '@boxpistols/labels-config'
|
|
264
|
+
|
|
265
|
+
const result = validateWithDetails(data)
|
|
266
|
+
|
|
267
|
+
if (!result.valid) {
|
|
268
|
+
console.log('Duplicate names:', result.errors.duplicateNames)
|
|
269
|
+
console.log('Duplicate colors:', result.errors.duplicateColors)
|
|
270
|
+
console.log('Validation errors:', result.errors.validationErrors)
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Custom Validation
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import { checkDuplicateNames, checkDuplicateColors } from '@boxpistols/labels-config'
|
|
278
|
+
|
|
279
|
+
const duplicateNames = checkDuplicateNames(labels)
|
|
280
|
+
const duplicateColors = checkDuplicateColors(labels)
|
|
281
|
+
|
|
282
|
+
if (duplicateNames.length > 0) {
|
|
283
|
+
console.warn('Found duplicate label names:', duplicateNames)
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Search and Filter
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
// Search by name or description
|
|
291
|
+
const results = manager.search('bug')
|
|
292
|
+
|
|
293
|
+
// Find by color
|
|
294
|
+
const redLabels = manager.findByColor('ff0000')
|
|
295
|
+
|
|
296
|
+
// Case-insensitive retrieval
|
|
297
|
+
const label = manager.getLabel('BUG') // Returns label named 'bug'
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Next Steps
|
|
301
|
+
|
|
302
|
+
- Read the [API documentation](./API.md)
|
|
303
|
+
- Check [examples](../examples)
|
|
304
|
+
- View [CLI documentation](./CLI.md)
|
|
305
|
+
- See [templates documentation](./TEMPLATES.md)
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@asagiri-design/labels-config",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Terminal-first label management system for GitHub repositories using gh CLI - No token required",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"browser": "dist/index.umd.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.esm.js",
|
|
13
|
+
"require": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./config": {
|
|
16
|
+
"types": "./dist/config/index.d.ts",
|
|
17
|
+
"import": "./dist/config/index.esm.js",
|
|
18
|
+
"require": "./dist/config/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./github": {
|
|
21
|
+
"types": "./dist/github/index.d.ts",
|
|
22
|
+
"import": "./dist/github/index.esm.js",
|
|
23
|
+
"require": "./dist/github/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"labels-config": "./dist/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"templates",
|
|
32
|
+
"docs"
|
|
33
|
+
],
|
|
34
|
+
"sideEffects": false,
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsup src/index.ts src/config/index.ts src/github/index.ts src/cli.ts --format cjs,esm --dts --shims",
|
|
37
|
+
"build:umd": "tsup src/index.ts --format iife --dts --globalName LabelsConfig --outDir dist",
|
|
38
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
39
|
+
"type-check": "tsc --noEmit",
|
|
40
|
+
"test": "vitest",
|
|
41
|
+
"test:ui": "vitest --ui",
|
|
42
|
+
"test:coverage": "vitest --coverage",
|
|
43
|
+
"lint": "eslint src --fix",
|
|
44
|
+
"cli": "tsx src/cli.ts",
|
|
45
|
+
"prepublishOnly": "npm run build",
|
|
46
|
+
"version": "node -e \"const fs=require('fs');const v=require('./package.json').version;fs.writeFileSync('src/version.ts','export const version = \\''+v+'\\'\\n')\" && git add src/version.ts",
|
|
47
|
+
"release:patch": "npm version patch -m 'Release v%s [skip ci]' && npm publish --access public && git push --follow-tags",
|
|
48
|
+
"release:minor": "npm version minor -m 'Release v%s [skip ci]' && npm publish --access public && git push --follow-tags",
|
|
49
|
+
"release:major": "npm version major -m 'Release v%s [skip ci]' && npm publish --access public && git push --follow-tags",
|
|
50
|
+
"release:beta": "npm version prerelease --preid=beta -m 'Release v%s [skip ci]' && npm publish --access public --tag beta && git push --follow-tags"
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"labels",
|
|
54
|
+
"github",
|
|
55
|
+
"issue-tracking",
|
|
56
|
+
"config",
|
|
57
|
+
"management",
|
|
58
|
+
"schema",
|
|
59
|
+
"validation"
|
|
60
|
+
],
|
|
61
|
+
"author": "BoxPistols",
|
|
62
|
+
"license": "MIT",
|
|
63
|
+
"repository": {
|
|
64
|
+
"type": "git",
|
|
65
|
+
"url": "https://github.com/BoxPistols/labels-config.git"
|
|
66
|
+
},
|
|
67
|
+
"bugs": {
|
|
68
|
+
"url": "https://github.com/BoxPistols/labels-config/issues"
|
|
69
|
+
},
|
|
70
|
+
"homepage": "https://github.com/BoxPistols/labels-config#readme",
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@types/node": "^20.10.0",
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
|
74
|
+
"@typescript-eslint/parser": "^6.13.0",
|
|
75
|
+
"eslint": "^8.54.0",
|
|
76
|
+
"tsup": "^8.0.2",
|
|
77
|
+
"tsx": "^4.7.0",
|
|
78
|
+
"typescript": "^5.3.3",
|
|
79
|
+
"vitest": "^1.0.4"
|
|
80
|
+
},
|
|
81
|
+
"dependencies": {
|
|
82
|
+
"zod": "^3.22.4"
|
|
83
|
+
},
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">=18.0.0"
|
|
86
|
+
}
|
|
87
|
+
}
|