@thegetty/quire-cli 1.0.0-rc.35 → 1.0.0-rc.37

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.
Files changed (159) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +9 -0
  3. package/bin/cli.js +19 -1
  4. package/package.json +21 -8
  5. package/patches/README.md +19 -0
  6. package/patches/install-npm-version+1.0.9.patch +12119 -0
  7. package/schemas/objects.schema.json +12 -38
  8. package/schemas/publication.schema.json +0 -22
  9. package/schemas/references.schema.json +0 -1
  10. package/src/Command.js +26 -6
  11. package/src/Command.spec.js +99 -0
  12. package/src/commands/README.md +213 -122
  13. package/src/commands/build.js +37 -36
  14. package/src/commands/build.spec.js +113 -0
  15. package/src/commands/build.test.js +397 -0
  16. package/src/commands/clean.js +25 -19
  17. package/src/commands/clean.spec.js +108 -0
  18. package/src/commands/clean.test.js +260 -0
  19. package/src/commands/config.js +251 -0
  20. package/src/commands/config.spec.js +107 -0
  21. package/src/commands/config.test.js +715 -0
  22. package/src/commands/create.js +42 -14
  23. package/src/commands/create.spec.js +112 -0
  24. package/src/commands/create.test.js +415 -0
  25. package/src/commands/epub.js +59 -30
  26. package/src/commands/epub.spec.js +114 -0
  27. package/src/commands/epub.test.js +503 -0
  28. package/src/commands/index.js +9 -2
  29. package/src/commands/info.js +18 -24
  30. package/src/commands/info.spec.js +64 -0
  31. package/src/commands/info.test.js +415 -0
  32. package/src/commands/pdf.js +58 -84
  33. package/src/commands/pdf.spec.js +114 -0
  34. package/src/commands/pdf.test.js +464 -0
  35. package/src/commands/preview.js +32 -31
  36. package/src/commands/preview.spec.js +97 -0
  37. package/src/commands/preview.test.js +250 -0
  38. package/src/commands/use.js +56 -0
  39. package/src/commands/use.spec.js +61 -0
  40. package/src/commands/use.test.js +280 -0
  41. package/src/commands/validate.js +31 -19
  42. package/src/commands/validate.spec.js +82 -0
  43. package/src/commands/validate.test.js +234 -0
  44. package/src/commands/workflows.js +70 -0
  45. package/src/errors/build/build-failed-error.js +19 -0
  46. package/src/errors/build/config-field-missing-error.js +20 -0
  47. package/src/errors/build/config-file-not-found-error.js +20 -0
  48. package/src/errors/build/index.js +11 -0
  49. package/src/errors/index.js +48 -0
  50. package/src/errors/install/dependency-install-error.js +19 -0
  51. package/src/errors/install/directory-not-empty-error.js +25 -0
  52. package/src/errors/install/index.js +12 -0
  53. package/src/errors/install/invalid-path-error.js +31 -0
  54. package/src/errors/install/invalid-starter-error.js +27 -0
  55. package/src/errors/install/version-not-found-error.js +35 -0
  56. package/src/errors/output/epub-generation-error.js +19 -0
  57. package/src/errors/output/index.js +14 -0
  58. package/src/errors/output/invalid-epub-library-error.js +20 -0
  59. package/src/errors/output/invalid-pdf-library-error.js +20 -0
  60. package/src/errors/output/missing-build-output-error.js +21 -0
  61. package/src/errors/output/pdf-generation-error.js +24 -0
  62. package/src/errors/output/tool-not-found-error.js +37 -0
  63. package/src/errors/project/index.js +10 -0
  64. package/src/errors/project/not-in-project-error.js +20 -0
  65. package/src/errors/project/project-create-error.js +21 -0
  66. package/src/errors/quire-error.js +27 -0
  67. package/src/errors/validation/validation-error.js +20 -11
  68. package/src/helpers/clean.js +1 -1
  69. package/src/helpers/docs-url.js +32 -0
  70. package/src/helpers/test-cwd.js +5 -6
  71. package/src/helpers/test-cwd.test.js +192 -0
  72. package/src/helpers/which.js +10 -4
  73. package/src/lib/11ty/README.md +135 -19
  74. package/src/lib/11ty/api.js +196 -94
  75. package/src/lib/11ty/cli.js +91 -37
  76. package/src/lib/11ty/index.js +64 -5
  77. package/src/lib/11ty/index.test.js +655 -0
  78. package/src/lib/README.md +275 -0
  79. package/src/lib/commander/index.js +100 -0
  80. package/src/lib/commander/index.test.js +86 -0
  81. package/src/lib/commander/options.js +195 -0
  82. package/src/lib/commander/options.test.js +109 -0
  83. package/src/lib/conf/README.md +84 -73
  84. package/src/lib/conf/config.js +5 -3
  85. package/src/lib/conf/config.test.js +281 -0
  86. package/src/lib/conf/defaults.js +44 -0
  87. package/src/lib/conf/format.js +60 -0
  88. package/src/lib/conf/format.test.js +106 -0
  89. package/src/lib/conf/helpers.js +91 -0
  90. package/src/lib/conf/helpers.test.js +136 -0
  91. package/src/lib/conf/index.js +22 -0
  92. package/src/lib/conf/schema.js +53 -8
  93. package/src/lib/epub/README.md +133 -2
  94. package/src/lib/epub/engines.js +46 -0
  95. package/src/lib/epub/epub.js +36 -11
  96. package/src/lib/epub/index.js +111 -21
  97. package/src/lib/epub/index.test.js +518 -0
  98. package/src/lib/epub/pandoc.js +33 -4
  99. package/src/lib/epub/pandoc.test.js +122 -0
  100. package/src/lib/epub/schema.js +21 -0
  101. package/src/lib/error/README.md +170 -0
  102. package/src/lib/error/handler.js +107 -0
  103. package/src/lib/git/README.md +151 -2
  104. package/src/lib/git/index.js +217 -13
  105. package/src/lib/git/index.spec.js +80 -0
  106. package/src/lib/git/index.test.js +453 -0
  107. package/src/lib/installer/index.js +309 -0
  108. package/src/lib/installer/index.spec.js +83 -0
  109. package/src/lib/installer/index.test.js +545 -0
  110. package/src/lib/logger/README.md +424 -0
  111. package/src/lib/logger/debug.js +132 -0
  112. package/src/lib/logger/debug.spec.js +130 -0
  113. package/src/lib/logger/debug.test.js +128 -0
  114. package/src/lib/logger/index.js +228 -0
  115. package/src/lib/logger/index.spec.js +131 -0
  116. package/src/lib/logger/index.test.js +477 -0
  117. package/src/lib/npm/README.md +127 -0
  118. package/src/lib/npm/index.js +198 -0
  119. package/src/lib/npm/index.spec.js +60 -0
  120. package/src/lib/npm/index.test.js +355 -0
  121. package/src/lib/pdf/README.md +131 -0
  122. package/src/lib/pdf/engines.js +46 -0
  123. package/src/lib/pdf/index.js +124 -21
  124. package/src/lib/pdf/index.test.js +708 -0
  125. package/src/lib/pdf/paged.js +100 -52
  126. package/src/lib/pdf/paged.test.js +366 -0
  127. package/src/lib/pdf/prince.js +115 -37
  128. package/src/lib/pdf/prince.test.js +202 -0
  129. package/src/lib/pdf/schema.js +21 -0
  130. package/src/lib/pdf/split.js +61 -33
  131. package/src/lib/pdf/split.test.js +445 -0
  132. package/src/lib/process/manager.js +110 -0
  133. package/src/lib/process/manager.test.js +55 -0
  134. package/src/lib/project/build.js +143 -0
  135. package/src/lib/project/build.test.js +253 -0
  136. package/src/lib/project/config.js +48 -0
  137. package/src/lib/project/config.test.js +134 -0
  138. package/src/{helpers/is-quire.js → lib/project/detect.js} +5 -3
  139. package/src/lib/project/detect.test.js +157 -0
  140. package/src/lib/project/index.js +40 -0
  141. package/src/lib/project/paths.js +224 -0
  142. package/src/lib/project/version.js +110 -0
  143. package/src/lib/project/version.test.js +350 -0
  144. package/src/lib/reporter/README.md +211 -2
  145. package/src/lib/reporter/index.js +512 -0
  146. package/src/lib/reporter/index.test.js +593 -0
  147. package/src/main.js +134 -47
  148. package/src/main.spec.js +61 -0
  149. package/src/main.test.js +347 -0
  150. package/src/validators/utils.js +2 -1
  151. package/src/commands/conf.js +0 -43
  152. package/src/commands/version.js +0 -43
  153. package/src/lib/11ty/paths.js +0 -103
  154. package/src/lib/i18n/README.md +0 -3
  155. package/src/lib/i18n/config.js +0 -53
  156. package/src/lib/i18n/index.js +0 -43
  157. package/src/lib/i18n/localeService.js +0 -58
  158. package/src/lib/quire/README.md +0 -19
  159. package/src/lib/quire/index.js +0 -350
@@ -2,7 +2,6 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "title": "Objects Schema",
4
4
  "type": "object",
5
-
6
5
  "required": [
7
6
  "object_card",
8
7
  "object_display_order",
@@ -12,23 +11,17 @@
12
11
  "properties": {
13
12
  "object_filters": {
14
13
  "type": "array",
15
- "items": {
16
- "type": "string"
17
- },
14
+ "items": { "type": "string" },
18
15
  "minItems": 0
19
16
  },
20
17
  "object_card": {
21
18
  "type": "array",
22
- "items": {
23
- "type": "string"
24
- },
19
+ "items": { "type": "string" },
25
20
  "minItems": 0
26
21
  },
27
22
  "object_display_order": {
28
23
  "type": "array",
29
- "items": {
30
- "type": "string"
31
- },
24
+ "items": { "type": "string" },
32
25
  "minItems": 0
33
26
  },
34
27
  "object_list": {
@@ -36,39 +29,20 @@
36
29
  "items": {
37
30
  "type": "object",
38
31
  "properties": {
39
- "id": {
40
- "type": "string"
41
- },
42
- "title": {
43
- "type": "string"
44
- },
45
- "artist": {
46
- "type": "string"
47
- },
48
- "year": {
49
- "type": "integer"
50
- },
51
- "medium": {
52
- "type": "string"
53
- },
54
- "dimensions": {
55
- "type": "string"
56
- },
57
- "location": {
58
- "type": "string"
59
- },
60
- "link": {
61
- "type": "string",
62
- "format": "uri"
63
- },
32
+ "id": { "type": "string" },
33
+ "title": { "type": "string" },
34
+ "artist": { "type": "string" },
35
+ "year": { "type": "string" },
36
+ "medium": { "type": "string" },
37
+ "dimensions": { "type": "string" },
38
+ "location": { "type": "string" },
39
+ "link": { "type": "string", "format": "uri" },
64
40
  "figure": {
65
41
  "type": "array",
66
42
  "items": {
67
43
  "type": "object",
68
44
  "properties": {
69
- "id": {
70
- "type": "string"
71
- }
45
+ "id": { "type": "string" }
72
46
  },
73
47
  "required": [
74
48
  "id"
@@ -2,7 +2,6 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "title": "Publication Schema",
4
4
  "type": "object",
5
-
6
5
  "required": [
7
6
  "url",
8
7
  "title",
@@ -21,15 +20,12 @@
21
20
  "revision_history",
22
21
  "promo_image"
23
22
  ],
24
-
25
23
  "properties": {
26
24
  "url": { "type": "string" },
27
25
  "title": { "type": "string" },
28
26
  "subtitle": { "type": "string" },
29
-
30
27
  "reading_line": { "type": ["string", "null"] },
31
28
  "short_title": { "type": ["string", "null"] },
32
-
33
29
  "description": {
34
30
  "type": "object",
35
31
  "required": ["full"],
@@ -38,7 +34,6 @@
38
34
  "full": { "type": "string" }
39
35
  }
40
36
  },
41
-
42
37
  "pub_date": {
43
38
  "oneOf": [
44
39
  { "type": "string" },
@@ -46,50 +41,38 @@
46
41
  ] },
47
42
  "language": { "type": "string" },
48
43
  "pub_type": { "type": "string" },
49
-
50
44
  "identifier": {
51
45
  "type": "object",
52
46
  "properties": {
53
47
  "isbn": { "type": ["string", "null"] }
54
48
  }
55
49
  },
56
-
57
50
  "publisher": {
58
51
  "type": "array",
59
52
  "items": { "$ref": "#/definitions/publisher" }
60
53
  },
61
-
62
54
  "contributor_as_it_appears": { "type": ["string", "null"] },
63
-
64
55
  "contributor": {
65
56
  "type": "array",
66
57
  "items": { "$ref": "#/definitions/contributor" }
67
58
  },
68
-
69
59
  "copyright": { "type": "string" },
70
-
71
60
  "license": { "$ref": "#/definitions/license" },
72
-
73
61
  "resource_link": {
74
62
  "type": "array",
75
63
  "items": { "$ref": "#/definitions/resourceLink" }
76
64
  },
77
-
78
65
  "subject": {
79
66
  "type": "array",
80
67
  "items": { "$ref": "#/definitions/subject" }
81
68
  },
82
-
83
69
  "revision_history": {
84
70
  "type": "array",
85
71
  "items": { "$ref": "#/definitions/revision" }
86
72
  },
87
-
88
73
  "repository_url": { "type": ["string", "null"] },
89
-
90
74
  "promo_image": { "type": "string" }
91
75
  },
92
-
93
76
  "definitions": {
94
77
  "publisher": {
95
78
  "type": "object",
@@ -101,7 +84,6 @@
101
84
  "logo": { "type": ["string", "null"] }
102
85
  }
103
86
  },
104
-
105
87
  "contributor": {
106
88
  "type": "object",
107
89
  "required": ["id", "type", "first_name", "last_name"],
@@ -117,7 +99,6 @@
117
99
  "image": { "type": ["string", "null"] }
118
100
  }
119
101
  },
120
-
121
102
  "license": {
122
103
  "type": "object",
123
104
  "required": ["name", "abbreviation", "url", "scope"],
@@ -128,7 +109,6 @@
128
109
  "scope": { "type": "string" }
129
110
  }
130
111
  },
131
-
132
112
  "resourceLink": {
133
113
  "type": "object",
134
114
  "required": ["type", "name", "link_relation"],
@@ -140,7 +120,6 @@
140
120
  "url": { "type": ["string", "null"] }
141
121
  }
142
122
  },
143
-
144
123
  "subject": {
145
124
  "type": "object",
146
125
  "required": ["type", "name"],
@@ -150,7 +129,6 @@
150
129
  "identifier": { "type": ["string", "null"] }
151
130
  }
152
131
  },
153
-
154
132
  "revision": {
155
133
  "type": "object",
156
134
  "properties": {
@@ -2,7 +2,6 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "title": "References Schema",
4
4
  "type": "object",
5
-
6
5
  "required": [
7
6
  "entries"
8
7
  ],
package/src/Command.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import config from '#src/lib/conf/config.js'
2
+ import createLogger from '#lib/logger/index.js'
3
+ import createDebug from '#debug'
2
4
 
3
5
  /**
4
6
  * Command
@@ -13,10 +15,13 @@ export default class Command {
13
15
 
14
16
  /**
15
17
  * @typedef CommandDefinition
16
- * @property {String} name
17
- * @property {String} alias
18
- * @property {Array<String>} aliases
19
- * @property {String} descriptions
18
+ * @property {String} name - Command name used to invoke it
19
+ * @property {String} alias - Single alias for the command
20
+ * @property {Array<String>} aliases - Multiple aliases for the command
21
+ * @property {String} description - Full description shown in command's own help
22
+ * @property {String} summary - One-line summary shown in parent help listing
23
+ * @property {String} [docsLink] - Path appended to docs base URL (e.g., 'quire-commands/#output-files')
24
+ * @property {String} [helpText] - Custom help text shown after built-in help (examples, notes)
20
25
  * @property {Array<CommandArgument>} args
21
26
  * @property {Array<CommandOption>} options
22
27
  * @property {String} version
@@ -32,12 +37,24 @@ export default class Command {
32
37
  * @param {CommandDefinition} definition The definition
33
38
  */
34
39
  constructor(definition) {
35
- if (this.constructor.prototype === Command) {
40
+ if (this.constructor === Command) {
36
41
  throw new Error('Command is an *abstract* class')
37
42
  }
38
43
 
39
44
  this.config = config // quire-cli configuration
40
45
 
46
+ /**
47
+ * Command-specific debug instance for internal debugging
48
+ * Enable via: DEBUG=quire:commands:name or DEBUG=quire:commands:*
49
+ */
50
+ this.debug = createDebug(`commands:${definition.name}`)
51
+
52
+ /**
53
+ * Command-specific logger with prefix including command name
54
+ * Output format: [quire] LEVEL commands:name message
55
+ */
56
+ this.logger = createLogger(`commands:${definition.name}`)
57
+
41
58
  /**
42
59
  * Merge and deduplicate command definition alias and aliases
43
60
  * Nota bene: Only the first command alias is displayed in the help.
@@ -48,6 +65,9 @@ export default class Command {
48
65
  this.name = definition.name
49
66
  this.aliases = definition.aliases
50
67
  this.description = definition.description
68
+ this.summary = definition.summary
69
+ this.docsLink = definition.docsLink
70
+ this.helpText = definition.helpText
51
71
  this.args = definition.args
52
72
  this.options = definition.options
53
73
  this.version = definition.version
@@ -55,7 +75,7 @@ export default class Command {
55
75
  }
56
76
 
57
77
  definition() {
58
- return this.prototype.definition
78
+ return this.constructor.definition
59
79
  }
60
80
 
61
81
  action() {
@@ -0,0 +1,99 @@
1
+ import Command from './Command.js'
2
+ import test from 'ava'
3
+
4
+ /**
5
+ * Command Base Class Unit Tests
6
+ *
7
+ * Tests the abstract Command base class API contract.
8
+ * These tests verify the class cannot be instantiated directly
9
+ * and that the base methods behave correctly.
10
+ */
11
+
12
+ test('Command cannot be instantiated directly', (t) => {
13
+ const error = t.throws(() => {
14
+ new Command({ name: 'test', description: 'test command' })
15
+ })
16
+
17
+ t.truthy(error)
18
+ t.regex(error.message, /abstract/i, 'error message should mention abstract')
19
+ })
20
+
21
+ test('Command.action() throws not-implemented error', (t) => {
22
+ // Create a minimal subclass that does not override action
23
+ class TestCommand extends Command {
24
+ constructor() {
25
+ super({ name: 'test', description: 'test command' })
26
+ }
27
+ }
28
+
29
+ const command = new TestCommand()
30
+ const error = t.throws(() => command.action())
31
+
32
+ t.truthy(error)
33
+ t.regex(error.message, /not been implemented/i, 'error message should indicate not implemented')
34
+ t.regex(error.message, /test/i, 'error message should include the command name')
35
+ })
36
+
37
+ test('subclass can override action without error', (t) => {
38
+ class TestCommand extends Command {
39
+ constructor() {
40
+ super({ name: 'test', description: 'test command' })
41
+ }
42
+
43
+ action() {
44
+ return 'action executed'
45
+ }
46
+ }
47
+
48
+ const command = new TestCommand()
49
+ const result = command.action()
50
+
51
+ t.is(result, 'action executed')
52
+ })
53
+
54
+ test('Command constructor sets properties from definition', (t) => {
55
+ const definition = {
56
+ name: 'test',
57
+ description: 'A test command',
58
+ summary: 'test summary',
59
+ aliases: ['t', 'tst'],
60
+ args: [['<input>', 'input file']],
61
+ options: [['--verbose', 'enable verbose output']],
62
+ version: '1.0.0',
63
+ hidden: true,
64
+ }
65
+
66
+ class TestCommand extends Command {
67
+ constructor() {
68
+ super(definition)
69
+ }
70
+
71
+ action() {}
72
+ }
73
+
74
+ const command = new TestCommand()
75
+
76
+ t.is(command.name, 'test')
77
+ t.is(command.description, 'A test command')
78
+ t.is(command.summary, 'test summary')
79
+ t.deepEqual(command.aliases, ['t', 'tst'])
80
+ t.deepEqual(command.args, [['<input>', 'input file']])
81
+ t.deepEqual(command.options, [['--verbose', 'enable verbose output']])
82
+ t.is(command.version, '1.0.0')
83
+ t.is(command.hidden, true)
84
+ })
85
+
86
+ test('Command constructor injects shared configuration', (t) => {
87
+ class TestCommand extends Command {
88
+ constructor() {
89
+ super({ name: 'test', description: 'test command' })
90
+ }
91
+
92
+ action() {}
93
+ }
94
+
95
+ const command = new TestCommand()
96
+
97
+ t.truthy(command.config, 'config should be injected')
98
+ t.is(typeof command.config.get, 'function', 'config should have get method')
99
+ })