appydave-tools 0.72.0 → 0.73.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 584067a790d262ecf04ab52f20557fc879db4cf968928199ae279438afddc0e9
4
- data.tar.gz: c2d31308bd43b6e93e66bbdcff15bcde169fe6cde278de0d03a793c4dc605e1c
3
+ metadata.gz: 53447fe92cfd604234875affe143a083bc07b267ccf92ad11782e6640e440fa6
4
+ data.tar.gz: 74ed454547b2f4a3a5d859ca1bc41228b7efc340dc31c8f3a174b6ff4e1774dd
5
5
  SHA512:
6
- metadata.gz: 6f8d108fd12581e5e22d1d4125c85794f0df4e94ea8f626dddf1e26bdfcde423bccee1325e4548a5b55c0f33c9f87e7aaaa1d55ead202b8010caa766afdf90ef
7
- data.tar.gz: 95b5b25e5b1d6816f271a0a12cb6cfd57ce53652c23fc1fdb34e6eed31eefc5fc63bd5381ea812355184f410d7537f81329ff34fd312cc0b7345727c9dc561ca
6
+ metadata.gz: 61ab02e5529f5a95be3aeeb85674e2f92d9db9d13571aafefc6569cec9f30f967a5d79b48885ad2f636816b50380c39ecdaf67d05b3d403c25ce06517efb8761
7
+ data.tar.gz: db15735eb6b14e5060a9f533231067222402edff360e5034e997c03483b8755692751ce54e95628eea2893e2f649c75a7f9af6e625c7c1be661c8f392d2908e9
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [0.72.0](https://github.com/appydave/appydave-tools/compare/v0.71.1...v0.72.0) (2025-12-18)
2
+
3
+
4
+ ### Features
5
+
6
+ * add ah-help generate target for aliases-help.zsh format ([874fde9](https://github.com/appydave/appydave-tools/commit/874fde982a2b66ba7d9ec8f8078d79fcde7db4f6))
7
+
1
8
  ## [0.71.1](https://github.com/appydave/appydave-tools/compare/v0.71.0...v0.71.1) (2025-12-15)
2
9
 
3
10
 
@@ -7,6 +7,18 @@ module Appydave
7
7
  # Generate command creates shell aliases and help content
8
8
  class Generate < Base
9
9
  VALID_TARGETS = %w[aliases help ah-help all].freeze
10
+ MAX_BACKUPS = 10
11
+
12
+ TITLE_MAPPINGS = {
13
+ 'appydave' => 'Appy Dave',
14
+ 'supportsignal' => 'SupportSignal',
15
+ 'beauty-and-joy' => 'Beauty & Joy',
16
+ 'david-cruwys' => 'David Cruwys',
17
+ 'guy-monroe' => 'Guy Monroe',
18
+ 'voz' => 'VOZ',
19
+ 'kiros' => 'Kiros',
20
+ 'aitldr' => 'AITLDR'
21
+ }.freeze
10
22
 
11
23
  attr_reader :target, :output_path, :output_dir
12
24
 
@@ -82,20 +94,25 @@ module Appydave
82
94
  lines << "# Generated by: jump generate aliases (#{Time.now.strftime('%Y-%m-%d %H:%M')})"
83
95
  lines << '# Source: ~/.config/appydave/locations.json'
84
96
  lines << ''
85
- lines << '# Usage: source this file in your .zshrc'
86
- lines << '# source ~/.oh-my-zsh/custom/aliases-jump.zsh'
87
- lines << ''
88
97
 
89
- # Group by brand/client
90
- grouped = group_locations_for_aliases
98
+ # Build grouped sections using smart logic
99
+ sections = build_smart_alias_sections
100
+
101
+ sections.each do |section|
102
+ # Add major section separator if needed
103
+ if section[:major]
104
+ lines << '# ========================================'
105
+ lines << "# #{section[:title]}"
106
+ lines << '# ========================================'
107
+ else
108
+ lines << "# #{section[:title]}"
109
+ end
91
110
 
92
- grouped.each do |group_name, locations|
93
- lines << "# #{group_name}"
94
- locations.each do |loc|
95
- path = path_validator.expand(loc.path)
96
- desc = loc.description ? " # #{loc.description}" : ''
97
- lines << "alias #{loc.jump}=\"cd '#{path}'\"#{desc}"
111
+ section[:locations].each do |loc|
112
+ path = format_display_path(loc.path)
113
+ lines << "alias #{loc.jump}=\"cd #{path}\""
98
114
  end
115
+
99
116
  lines << ''
100
117
  end
101
118
 
@@ -230,15 +247,132 @@ module Appydave
230
247
  end
231
248
  end
232
249
 
250
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
251
+ def build_smart_alias_sections
252
+ sections = []
253
+ locations = config.locations.dup
254
+
255
+ # 1. JUMPS - Base directories (monorepo/config without brand/client)
256
+ jumps = locations.select { |l| %w[monorepo config].include?(l.type) && l.brand.nil? && l.client.nil? }
257
+ add_section(sections, 'JUMPS', jumps) unless jumps.empty?
258
+ locations -= jumps
259
+
260
+ # 2. Brain / Second Brain (only non-client brains)
261
+ brains = locations.select { |l| l.type == 'brain' && l.client.nil? }
262
+ add_section(sections, 'Brain / Second Brain', brains) unless brains.empty?
263
+ locations -= brains
264
+
265
+ # 3. Appy Dave (including david-cruwys ecosystem docs, excluding video, archive, and subprojects)
266
+ appydave_all = locations.select do |l|
267
+ %w[appydave david-cruwys].include?(l.brand) && !%w[video archive brain].include?(l.type)
268
+ end
269
+
270
+ # Extract subgroups
271
+ flivideo = appydave_all.select { |l| l.key.start_with?('flivideo') }
272
+ storyline = appydave_all.select { |l| l.key.start_with?('storyline') }
273
+ awb = appydave_all.select { |l| l.key.start_with?('agent-workflow', 'awb') }
274
+ klueless = appydave_all.select { |l| l.key == 'klueless' }
275
+
276
+ appydave_main = appydave_all - flivideo - storyline - awb - klueless
277
+
278
+ add_section(sections, 'Appy Dave', appydave_main) unless appydave_main.empty?
279
+ add_section(sections, 'KlueLess', klueless) unless klueless.empty?
280
+ add_section(sections, 'FliVideo', flivideo) unless flivideo.empty?
281
+ add_section(sections, 'Storyline App', storyline) unless storyline.empty?
282
+ add_section(sections, 'Agent Workflow Builder', awb) unless awb.empty?
283
+
284
+ locations -= appydave_all
285
+
286
+ # 4. CLIENT WORK (major section)
287
+ clients = locations.select { |l| l.client && l.type != 'video' }
288
+ unless clients.empty?
289
+ # Add major separator
290
+ sections << { title: 'CLIENT WORK', major: true, locations: [] }
291
+
292
+ # Group by client
293
+ clients.group_by(&:client).sort.each do |client_name, client_locs|
294
+ title = format_title(client_name, 'Client')
295
+ add_section(sections, title, client_locs)
296
+ end
297
+ end
298
+ locations -= clients
299
+
300
+ # 5. VIDEO PROJECTS (major section)
301
+ videos = locations.select { |l| l.type == 'video' }
302
+ unless videos.empty?
303
+ sections << { title: 'VIDEO PROJECTS', major: true, locations: [] }
304
+
305
+ # Split into brand and client videos
306
+ brand_videos = videos.select(&:brand)
307
+ client_videos = videos.select(&:client)
308
+ other_videos = videos - brand_videos - client_videos
309
+
310
+ add_section(sections, 'Brand Video Projects', brand_videos) unless brand_videos.empty?
311
+ add_section(sections, 'Client Video Projects', client_videos) unless client_videos.empty?
312
+ add_section(sections, 'Video Projects', other_videos) unless other_videos.empty?
313
+ end
314
+ locations -= videos
315
+
316
+ # 6. Beauty & Joy (non-video)
317
+ joy = locations.select { |l| l.brand == 'beauty-and-joy' }
318
+ add_section(sections, 'Beauty & Joy', joy, major: true) unless joy.empty?
319
+ locations -= joy
320
+
321
+ # 7. Archive
322
+ archives = locations.select { |l| l.type == 'archive' }
323
+ add_section(sections, 'Archive', archives) unless archives.empty?
324
+ locations -= archives
325
+
326
+ # 8. GEMs
327
+ gems = locations.select { |l| l.type == 'gem' }
328
+ add_section(sections, 'GEMs', gems) unless gems.empty?
329
+ locations -= gems
330
+
331
+ # 9. Reference / 3rd Party
332
+ refs = locations.select { |l| l.type == 'reference' }
333
+ add_section(sections, 'Reference / 3rd Party', refs) unless refs.empty?
334
+ locations -= refs
335
+
336
+ # 10. Experiments
337
+ experiments = locations.select { |l| l.type == 'experiments' }
338
+ add_section(sections, 'Experiments', experiments) unless experiments.empty?
339
+ locations -= experiments
340
+
341
+ # 11. Other (anything remaining)
342
+ add_section(sections, 'Other', locations) unless locations.empty?
343
+
344
+ sections.reject { |s| s[:locations].empty? && !s[:major] }
345
+ end
346
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
347
+
348
+ def add_section(sections, title, locations, major: false)
349
+ return if locations.empty?
350
+
351
+ sections << {
352
+ title: title,
353
+ major: major,
354
+ locations: locations.sort_by(&:jump)
355
+ }
356
+ end
357
+
358
+ def format_title(name, suffix = nil)
359
+ title = TITLE_MAPPINGS[name] || name.split('-').map(&:capitalize).join(' ')
360
+ suffix ? "#{title} #{suffix}" : title
361
+ end
362
+
233
363
  def write_or_return(content, path, default_filename)
234
364
  if path
365
+ backup_result = backup_existing_file(path)
235
366
  FileUtils.mkdir_p(File.dirname(path))
236
367
  File.write(path, content)
237
- success_result(
368
+
369
+ result = success_result(
238
370
  message: "Generated #{default_filename}",
239
371
  path: path,
240
372
  lines: content.lines.count
241
373
  )
374
+ result[:backup] = backup_result if backup_result
375
+ result
242
376
  else
243
377
  success_result(
244
378
  content: content,
@@ -246,6 +380,36 @@ module Appydave
246
380
  )
247
381
  end
248
382
  end
383
+
384
+ def backup_existing_file(path)
385
+ return nil unless File.exist?(path)
386
+
387
+ # Create backup directory
388
+ dir = File.dirname(path)
389
+ filename = File.basename(path, '.*')
390
+ backup_dir = File.join(dir, 'backups', filename)
391
+ FileUtils.mkdir_p(backup_dir)
392
+
393
+ # Generate timestamped backup filename
394
+ timestamp = Time.now.strftime('%Y-%m-%d-%H%M%S')
395
+ ext = File.extname(path)
396
+ backup_path = File.join(backup_dir, "#{timestamp}#{ext}")
397
+
398
+ # Copy existing file to backup
399
+ FileUtils.cp(path, backup_path)
400
+
401
+ # Clean up old backups (keep last N)
402
+ cleanup_old_backups(backup_dir, ext)
403
+
404
+ backup_path
405
+ end
406
+
407
+ def cleanup_old_backups(backup_dir, ext)
408
+ backups = Dir.glob(File.join(backup_dir, "*#{ext}")).sort.reverse
409
+ return if backups.length <= MAX_BACKUPS
410
+
411
+ backups[MAX_BACKUPS..].each { |f| File.delete(f) }
412
+ end
249
413
  end
250
414
  end
251
415
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Appydave
4
4
  module Tools
5
- VERSION = '0.72.0'
5
+ VERSION = '0.73.0'
6
6
  end
7
7
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appydave-tools",
3
- "version": "0.72.0",
3
+ "version": "0.73.0",
4
4
  "description": "AppyDave YouTube Automation Tools",
5
5
  "scripts": {
6
6
  "release": "semantic-release"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appydave-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.72.0
4
+ version: 0.73.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys