shelfware 0.0.1 → 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.
Files changed (206) hide show
  1. package/.output/nitro.json +15 -0
  2. package/.output/public/_nuxt/6IstVYrV.js +1 -0
  3. package/.output/public/_nuxt/9C5WUlLE.js +36 -0
  4. package/.output/public/_nuxt/BDNMzG2s.js +1 -0
  5. package/.output/public/_nuxt/BW3xJdEx.js +1 -0
  6. package/.output/public/_nuxt/BXXtFil5.js +1 -0
  7. package/.output/public/_nuxt/BZuUK3cr.js +1 -0
  8. package/.output/public/_nuxt/BeLyMmd4.js +1 -0
  9. package/.output/public/_nuxt/C_VgD9ZI.js +3 -0
  10. package/.output/public/_nuxt/DB5Vxbte.js +2 -0
  11. package/.output/public/_nuxt/DMg0j7gv.js +14 -0
  12. package/.output/public/_nuxt/builds/latest.json +1 -0
  13. package/.output/public/_nuxt/builds/meta/4c307968-4837-497b-a570-d6ee336accc4.json +1 -0
  14. package/.output/public/_nuxt/entry.b3_DJTEt.css +2 -0
  15. package/.output/public/_nuxt/error-404.CHsn7XF-.css +1 -0
  16. package/.output/public/_nuxt/error-500.Bawx2bLr.css +1 -0
  17. package/.output/server/chunks/_/api-handler.mjs +44 -0
  18. package/.output/server/chunks/_/batch.mjs +27 -0
  19. package/.output/server/chunks/_/catalog.mjs +1115 -0
  20. package/.output/server/chunks/_/detail.mjs +16 -0
  21. package/.output/server/chunks/_/error-500.mjs +19 -0
  22. package/.output/server/chunks/_/quarantine.mjs +159 -0
  23. package/.output/server/chunks/nitro/nitro.mjs +5399 -0
  24. package/.output/server/chunks/routes/api/_..._.mjs +16 -0
  25. package/.output/server/chunks/routes/api/health.get.mjs +13 -0
  26. package/.output/server/chunks/routes/api/skills/_id/file.get.mjs +25 -0
  27. package/.output/server/chunks/routes/api/skills/_id_.get.mjs +25 -0
  28. package/.output/server/chunks/routes/api/skills/_id_.put.mjs +74 -0
  29. package/.output/server/chunks/routes/api/skills/delete.post.mjs +48 -0
  30. package/.output/server/chunks/routes/api/skills/quarantine.post.mjs +26 -0
  31. package/.output/server/chunks/routes/api/skills/restore.post.mjs +26 -0
  32. package/.output/server/chunks/routes/api/skills.get.mjs +41 -0
  33. package/.output/server/chunks/routes/renderer.mjs +341 -0
  34. package/.output/server/chunks/virtual/_virtual_spa-template.mjs +3 -0
  35. package/.output/server/chunks/virtual/precomputed.mjs +3 -0
  36. package/.output/server/index.mjs +9 -0
  37. package/.output/server/node_modules/@babel/parser/lib/index.js +14611 -0
  38. package/.output/server/node_modules/@babel/parser/package.json +50 -0
  39. package/.output/server/node_modules/@vue/compiler-core/dist/compiler-core.cjs.prod.js +6801 -0
  40. package/.output/server/node_modules/@vue/compiler-core/package.json +58 -0
  41. package/.output/server/node_modules/@vue/compiler-dom/dist/compiler-dom.cjs.prod.js +692 -0
  42. package/.output/server/node_modules/@vue/compiler-dom/package.json +57 -0
  43. package/.output/server/node_modules/@vue/compiler-ssr/dist/compiler-ssr.cjs.js +1420 -0
  44. package/.output/server/node_modules/@vue/compiler-ssr/package.json +34 -0
  45. package/.output/server/node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js +1903 -0
  46. package/.output/server/node_modules/@vue/reactivity/package.json +55 -0
  47. package/.output/server/node_modules/@vue/runtime-core/dist/runtime-core.cjs.prod.js +6980 -0
  48. package/.output/server/node_modules/@vue/runtime-core/package.json +52 -0
  49. package/.output/server/node_modules/@vue/runtime-dom/dist/runtime-dom.cjs.prod.js +1867 -0
  50. package/.output/server/node_modules/@vue/runtime-dom/package.json +60 -0
  51. package/.output/server/node_modules/@vue/server-renderer/dist/server-renderer.cjs.prod.js +904 -0
  52. package/.output/server/node_modules/@vue/server-renderer/package.json +53 -0
  53. package/.output/server/node_modules/@vue/shared/dist/shared.cjs.prod.js +636 -0
  54. package/.output/server/node_modules/@vue/shared/package.json +47 -0
  55. package/.output/server/node_modules/devalue/index.js +17 -0
  56. package/.output/server/node_modules/devalue/package.json +39 -0
  57. package/.output/server/node_modules/devalue/src/base64.js +60 -0
  58. package/.output/server/node_modules/devalue/src/constants.js +12 -0
  59. package/.output/server/node_modules/devalue/src/operations.js +193 -0
  60. package/.output/server/node_modules/devalue/src/parse.js +274 -0
  61. package/.output/server/node_modules/devalue/src/stringify.js +428 -0
  62. package/.output/server/node_modules/devalue/src/uneval.js +606 -0
  63. package/.output/server/node_modules/devalue/src/utils.js +185 -0
  64. package/.output/server/node_modules/entities/dist/commonjs/decode-codepoint.js +77 -0
  65. package/.output/server/node_modules/entities/dist/commonjs/decode.js +568 -0
  66. package/.output/server/node_modules/entities/dist/commonjs/generated/decode-data-html.js +7 -0
  67. package/.output/server/node_modules/entities/dist/commonjs/generated/decode-data-xml.js +7 -0
  68. package/.output/server/node_modules/entities/dist/commonjs/internal/bin-trie-flags.js +21 -0
  69. package/.output/server/node_modules/entities/dist/commonjs/internal/decode-shared.js +31 -0
  70. package/.output/server/node_modules/entities/dist/commonjs/package.json +3 -0
  71. package/.output/server/node_modules/entities/package.json +120 -0
  72. package/.output/server/node_modules/estree-walker/dist/umd/estree-walker.js +344 -0
  73. package/.output/server/node_modules/estree-walker/package.json +37 -0
  74. package/.output/server/node_modules/hookable/dist/index.mjs +257 -0
  75. package/.output/server/node_modules/hookable/package.json +53 -0
  76. package/.output/server/node_modules/nostics/dist/formatters/ansi.mjs +19 -0
  77. package/.output/server/node_modules/nostics/dist/index.mjs +187 -0
  78. package/.output/server/node_modules/nostics/package.json +125 -0
  79. package/.output/server/node_modules/source-map-js/lib/array-set.js +121 -0
  80. package/.output/server/node_modules/source-map-js/lib/base64-vlq.js +140 -0
  81. package/.output/server/node_modules/source-map-js/lib/base64.js +67 -0
  82. package/.output/server/node_modules/source-map-js/lib/binary-search.js +111 -0
  83. package/.output/server/node_modules/source-map-js/lib/mapping-list.js +79 -0
  84. package/.output/server/node_modules/source-map-js/lib/quick-sort.js +132 -0
  85. package/.output/server/node_modules/source-map-js/lib/source-map-consumer.js +1188 -0
  86. package/.output/server/node_modules/source-map-js/lib/source-map-generator.js +444 -0
  87. package/.output/server/node_modules/source-map-js/lib/source-node.js +413 -0
  88. package/.output/server/node_modules/source-map-js/lib/util.js +594 -0
  89. package/.output/server/node_modules/source-map-js/package.json +71 -0
  90. package/.output/server/node_modules/source-map-js/source-map.js +8 -0
  91. package/.output/server/node_modules/ufo/dist/index.mjs +645 -0
  92. package/.output/server/node_modules/ufo/package.json +48 -0
  93. package/.output/server/node_modules/unhead/dist/client.mjs +22 -0
  94. package/.output/server/node_modules/unhead/dist/legacy.mjs +33 -0
  95. package/.output/server/node_modules/unhead/dist/minify.mjs +183 -0
  96. package/.output/server/node_modules/unhead/dist/parser.mjs +518 -0
  97. package/.output/server/node_modules/unhead/dist/plugins.mjs +720 -0
  98. package/.output/server/node_modules/unhead/dist/server.mjs +99 -0
  99. package/.output/server/node_modules/unhead/dist/shared/unhead.-hZVKou0.mjs +400 -0
  100. package/.output/server/node_modules/unhead/dist/shared/unhead.BEmVMkeA.mjs +673 -0
  101. package/.output/server/node_modules/unhead/dist/shared/unhead.BGFxPGPQ.mjs +47 -0
  102. package/.output/server/node_modules/unhead/dist/shared/unhead.BQWSw36o.mjs +192 -0
  103. package/.output/server/node_modules/unhead/dist/shared/unhead.Bf_fPVYA.mjs +6 -0
  104. package/.output/server/node_modules/unhead/dist/shared/unhead.Bjbp1C8D.mjs +224 -0
  105. package/.output/server/node_modules/unhead/dist/shared/unhead.Bm4Y6XQI.mjs +17 -0
  106. package/.output/server/node_modules/unhead/dist/shared/unhead.C5Bksi2B.mjs +49 -0
  107. package/.output/server/node_modules/unhead/dist/shared/unhead.CGPOfp5O.mjs +32 -0
  108. package/.output/server/node_modules/unhead/dist/shared/unhead.CHEy9ana.mjs +7 -0
  109. package/.output/server/node_modules/unhead/dist/shared/unhead.D7HkBzZn.mjs +59 -0
  110. package/.output/server/node_modules/unhead/dist/shared/unhead.Dssd7L5I.mjs +196 -0
  111. package/.output/server/node_modules/unhead/dist/shared/unhead.jEy9BmRq.mjs +264 -0
  112. package/.output/server/node_modules/unhead/dist/shared/unhead.oZ7pkTV1.mjs +19 -0
  113. package/.output/server/node_modules/unhead/dist/shared/unhead.tQnRaXfX.mjs +240 -0
  114. package/.output/server/node_modules/unhead/dist/stream/client.mjs +33 -0
  115. package/.output/server/node_modules/unhead/dist/stream/iife.mjs +2 -0
  116. package/.output/server/node_modules/unhead/dist/stream/server.mjs +445 -0
  117. package/.output/server/node_modules/unhead/dist/utils.mjs +7 -0
  118. package/.output/server/node_modules/unhead/package.json +179 -0
  119. package/.output/server/node_modules/vue/dist/vue.cjs.js +80 -0
  120. package/.output/server/node_modules/vue/dist/vue.cjs.prod.js +66 -0
  121. package/.output/server/node_modules/vue/index.js +7 -0
  122. package/.output/server/node_modules/vue/index.mjs +1 -0
  123. package/.output/server/node_modules/vue/package.json +112 -0
  124. package/.output/server/node_modules/vue/server-renderer/index.mjs +1 -0
  125. package/.output/server/node_modules/vue-bundle-renderer/dist/runtime.mjs +278 -0
  126. package/.output/server/node_modules/vue-bundle-renderer/package.json +54 -0
  127. package/.output/server/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  128. package/.output/server/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  129. package/.output/server/node_modules/yaml/dist/compose/compose-node.js +112 -0
  130. package/.output/server/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  131. package/.output/server/node_modules/yaml/dist/compose/composer.js +224 -0
  132. package/.output/server/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  133. package/.output/server/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  134. package/.output/server/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  135. package/.output/server/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  136. package/.output/server/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  137. package/.output/server/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
  138. package/.output/server/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  139. package/.output/server/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  140. package/.output/server/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  141. package/.output/server/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  142. package/.output/server/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  143. package/.output/server/node_modules/yaml/dist/doc/Document.js +337 -0
  144. package/.output/server/node_modules/yaml/dist/doc/anchors.js +76 -0
  145. package/.output/server/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  146. package/.output/server/node_modules/yaml/dist/doc/createNode.js +90 -0
  147. package/.output/server/node_modules/yaml/dist/doc/directives.js +178 -0
  148. package/.output/server/node_modules/yaml/dist/errors.js +62 -0
  149. package/.output/server/node_modules/yaml/dist/index.js +50 -0
  150. package/.output/server/node_modules/yaml/dist/log.js +19 -0
  151. package/.output/server/node_modules/yaml/dist/nodes/Alias.js +118 -0
  152. package/.output/server/node_modules/yaml/dist/nodes/Collection.js +151 -0
  153. package/.output/server/node_modules/yaml/dist/nodes/Node.js +40 -0
  154. package/.output/server/node_modules/yaml/dist/nodes/Pair.js +39 -0
  155. package/.output/server/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  156. package/.output/server/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  157. package/.output/server/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  158. package/.output/server/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  159. package/.output/server/node_modules/yaml/dist/nodes/identity.js +53 -0
  160. package/.output/server/node_modules/yaml/dist/nodes/toJS.js +39 -0
  161. package/.output/server/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  162. package/.output/server/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  163. package/.output/server/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  164. package/.output/server/node_modules/yaml/dist/parse/cst.js +112 -0
  165. package/.output/server/node_modules/yaml/dist/parse/lexer.js +723 -0
  166. package/.output/server/node_modules/yaml/dist/parse/line-counter.js +41 -0
  167. package/.output/server/node_modules/yaml/dist/parse/parser.js +980 -0
  168. package/.output/server/node_modules/yaml/dist/public-api.js +107 -0
  169. package/.output/server/node_modules/yaml/dist/schema/Schema.js +39 -0
  170. package/.output/server/node_modules/yaml/dist/schema/common/map.js +19 -0
  171. package/.output/server/node_modules/yaml/dist/schema/common/null.js +17 -0
  172. package/.output/server/node_modules/yaml/dist/schema/common/seq.js +19 -0
  173. package/.output/server/node_modules/yaml/dist/schema/common/string.js +16 -0
  174. package/.output/server/node_modules/yaml/dist/schema/core/bool.js +21 -0
  175. package/.output/server/node_modules/yaml/dist/schema/core/float.js +47 -0
  176. package/.output/server/node_modules/yaml/dist/schema/core/int.js +42 -0
  177. package/.output/server/node_modules/yaml/dist/schema/core/schema.js +25 -0
  178. package/.output/server/node_modules/yaml/dist/schema/json/schema.js +64 -0
  179. package/.output/server/node_modules/yaml/dist/schema/tags.js +99 -0
  180. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  181. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  182. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  183. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  184. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  185. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  186. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  187. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  188. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  189. package/.output/server/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  190. package/.output/server/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  191. package/.output/server/node_modules/yaml/dist/stringify/stringify.js +132 -0
  192. package/.output/server/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  193. package/.output/server/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  194. package/.output/server/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  195. package/.output/server/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  196. package/.output/server/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  197. package/.output/server/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  198. package/.output/server/node_modules/yaml/dist/visit.js +236 -0
  199. package/.output/server/node_modules/yaml/package.json +97 -0
  200. package/.output/server/package.json +28 -0
  201. package/LICENSE +21 -0
  202. package/README.md +57 -1
  203. package/bin/launch.mjs +158 -0
  204. package/bin/shelfware.mjs +6 -0
  205. package/package.json +64 -5
  206. package/cli.mjs +0 -3
@@ -0,0 +1,236 @@
1
+ 'use strict';
2
+
3
+ var identity = require('./nodes/identity.js');
4
+
5
+ const BREAK = Symbol('break visit');
6
+ const SKIP = Symbol('skip children');
7
+ const REMOVE = Symbol('remove node');
8
+ /**
9
+ * Apply a visitor to an AST node or document.
10
+ *
11
+ * Walks through the tree (depth-first) starting from `node`, calling a
12
+ * `visitor` function with three arguments:
13
+ * - `key`: For sequence values and map `Pair`, the node's index in the
14
+ * collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
15
+ * `null` for the root node.
16
+ * - `node`: The current node.
17
+ * - `path`: The ancestry of the current node.
18
+ *
19
+ * The return value of the visitor may be used to control the traversal:
20
+ * - `undefined` (default): Do nothing and continue
21
+ * - `visit.SKIP`: Do not visit the children of this node, continue with next
22
+ * sibling
23
+ * - `visit.BREAK`: Terminate traversal completely
24
+ * - `visit.REMOVE`: Remove the current node, then continue with the next one
25
+ * - `Node`: Replace the current node, then continue by visiting it
26
+ * - `number`: While iterating the items of a sequence or map, set the index
27
+ * of the next step. This is useful especially if the index of the current
28
+ * node has changed.
29
+ *
30
+ * If `visitor` is a single function, it will be called with all values
31
+ * encountered in the tree, including e.g. `null` values. Alternatively,
32
+ * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
33
+ * `Alias` and `Scalar` node. To define the same visitor function for more than
34
+ * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
35
+ * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
36
+ * specific defined one will be used for each node.
37
+ */
38
+ function visit(node, visitor) {
39
+ const visitor_ = initVisitor(visitor);
40
+ if (identity.isDocument(node)) {
41
+ const cd = visit_(null, node.contents, visitor_, Object.freeze([node]));
42
+ if (cd === REMOVE)
43
+ node.contents = null;
44
+ }
45
+ else
46
+ visit_(null, node, visitor_, Object.freeze([]));
47
+ }
48
+ // Without the `as symbol` casts, TS declares these in the `visit`
49
+ // namespace using `var`, but then complains about that because
50
+ // `unique symbol` must be `const`.
51
+ /** Terminate visit traversal completely */
52
+ visit.BREAK = BREAK;
53
+ /** Do not visit the children of the current node */
54
+ visit.SKIP = SKIP;
55
+ /** Remove the current node */
56
+ visit.REMOVE = REMOVE;
57
+ function visit_(key, node, visitor, path) {
58
+ const ctrl = callVisitor(key, node, visitor, path);
59
+ if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
60
+ replaceNode(key, path, ctrl);
61
+ return visit_(key, ctrl, visitor, path);
62
+ }
63
+ if (typeof ctrl !== 'symbol') {
64
+ if (identity.isCollection(node)) {
65
+ path = Object.freeze(path.concat(node));
66
+ for (let i = 0; i < node.items.length; ++i) {
67
+ const ci = visit_(i, node.items[i], visitor, path);
68
+ if (typeof ci === 'number')
69
+ i = ci - 1;
70
+ else if (ci === BREAK)
71
+ return BREAK;
72
+ else if (ci === REMOVE) {
73
+ node.items.splice(i, 1);
74
+ i -= 1;
75
+ }
76
+ }
77
+ }
78
+ else if (identity.isPair(node)) {
79
+ path = Object.freeze(path.concat(node));
80
+ const ck = visit_('key', node.key, visitor, path);
81
+ if (ck === BREAK)
82
+ return BREAK;
83
+ else if (ck === REMOVE)
84
+ node.key = null;
85
+ const cv = visit_('value', node.value, visitor, path);
86
+ if (cv === BREAK)
87
+ return BREAK;
88
+ else if (cv === REMOVE)
89
+ node.value = null;
90
+ }
91
+ }
92
+ return ctrl;
93
+ }
94
+ /**
95
+ * Apply an async visitor to an AST node or document.
96
+ *
97
+ * Walks through the tree (depth-first) starting from `node`, calling a
98
+ * `visitor` function with three arguments:
99
+ * - `key`: For sequence values and map `Pair`, the node's index in the
100
+ * collection. Within a `Pair`, `'key'` or `'value'`, correspondingly.
101
+ * `null` for the root node.
102
+ * - `node`: The current node.
103
+ * - `path`: The ancestry of the current node.
104
+ *
105
+ * The return value of the visitor may be used to control the traversal:
106
+ * - `Promise`: Must resolve to one of the following values
107
+ * - `undefined` (default): Do nothing and continue
108
+ * - `visit.SKIP`: Do not visit the children of this node, continue with next
109
+ * sibling
110
+ * - `visit.BREAK`: Terminate traversal completely
111
+ * - `visit.REMOVE`: Remove the current node, then continue with the next one
112
+ * - `Node`: Replace the current node, then continue by visiting it
113
+ * - `number`: While iterating the items of a sequence or map, set the index
114
+ * of the next step. This is useful especially if the index of the current
115
+ * node has changed.
116
+ *
117
+ * If `visitor` is a single function, it will be called with all values
118
+ * encountered in the tree, including e.g. `null` values. Alternatively,
119
+ * separate visitor functions may be defined for each `Map`, `Pair`, `Seq`,
120
+ * `Alias` and `Scalar` node. To define the same visitor function for more than
121
+ * one node type, use the `Collection` (map and seq), `Value` (map, seq & scalar)
122
+ * and `Node` (alias, map, seq & scalar) targets. Of all these, only the most
123
+ * specific defined one will be used for each node.
124
+ */
125
+ async function visitAsync(node, visitor) {
126
+ const visitor_ = initVisitor(visitor);
127
+ if (identity.isDocument(node)) {
128
+ const cd = await visitAsync_(null, node.contents, visitor_, Object.freeze([node]));
129
+ if (cd === REMOVE)
130
+ node.contents = null;
131
+ }
132
+ else
133
+ await visitAsync_(null, node, visitor_, Object.freeze([]));
134
+ }
135
+ // Without the `as symbol` casts, TS declares these in the `visit`
136
+ // namespace using `var`, but then complains about that because
137
+ // `unique symbol` must be `const`.
138
+ /** Terminate visit traversal completely */
139
+ visitAsync.BREAK = BREAK;
140
+ /** Do not visit the children of the current node */
141
+ visitAsync.SKIP = SKIP;
142
+ /** Remove the current node */
143
+ visitAsync.REMOVE = REMOVE;
144
+ async function visitAsync_(key, node, visitor, path) {
145
+ const ctrl = await callVisitor(key, node, visitor, path);
146
+ if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
147
+ replaceNode(key, path, ctrl);
148
+ return visitAsync_(key, ctrl, visitor, path);
149
+ }
150
+ if (typeof ctrl !== 'symbol') {
151
+ if (identity.isCollection(node)) {
152
+ path = Object.freeze(path.concat(node));
153
+ for (let i = 0; i < node.items.length; ++i) {
154
+ const ci = await visitAsync_(i, node.items[i], visitor, path);
155
+ if (typeof ci === 'number')
156
+ i = ci - 1;
157
+ else if (ci === BREAK)
158
+ return BREAK;
159
+ else if (ci === REMOVE) {
160
+ node.items.splice(i, 1);
161
+ i -= 1;
162
+ }
163
+ }
164
+ }
165
+ else if (identity.isPair(node)) {
166
+ path = Object.freeze(path.concat(node));
167
+ const ck = await visitAsync_('key', node.key, visitor, path);
168
+ if (ck === BREAK)
169
+ return BREAK;
170
+ else if (ck === REMOVE)
171
+ node.key = null;
172
+ const cv = await visitAsync_('value', node.value, visitor, path);
173
+ if (cv === BREAK)
174
+ return BREAK;
175
+ else if (cv === REMOVE)
176
+ node.value = null;
177
+ }
178
+ }
179
+ return ctrl;
180
+ }
181
+ function initVisitor(visitor) {
182
+ if (typeof visitor === 'object' &&
183
+ (visitor.Collection || visitor.Node || visitor.Value)) {
184
+ return Object.assign({
185
+ Alias: visitor.Node,
186
+ Map: visitor.Node,
187
+ Scalar: visitor.Node,
188
+ Seq: visitor.Node
189
+ }, visitor.Value && {
190
+ Map: visitor.Value,
191
+ Scalar: visitor.Value,
192
+ Seq: visitor.Value
193
+ }, visitor.Collection && {
194
+ Map: visitor.Collection,
195
+ Seq: visitor.Collection
196
+ }, visitor);
197
+ }
198
+ return visitor;
199
+ }
200
+ function callVisitor(key, node, visitor, path) {
201
+ if (typeof visitor === 'function')
202
+ return visitor(key, node, path);
203
+ if (identity.isMap(node))
204
+ return visitor.Map?.(key, node, path);
205
+ if (identity.isSeq(node))
206
+ return visitor.Seq?.(key, node, path);
207
+ if (identity.isPair(node))
208
+ return visitor.Pair?.(key, node, path);
209
+ if (identity.isScalar(node))
210
+ return visitor.Scalar?.(key, node, path);
211
+ if (identity.isAlias(node))
212
+ return visitor.Alias?.(key, node, path);
213
+ return undefined;
214
+ }
215
+ function replaceNode(key, path, node) {
216
+ const parent = path[path.length - 1];
217
+ if (identity.isCollection(parent)) {
218
+ parent.items[key] = node;
219
+ }
220
+ else if (identity.isPair(parent)) {
221
+ if (key === 'key')
222
+ parent.key = node;
223
+ else
224
+ parent.value = node;
225
+ }
226
+ else if (identity.isDocument(parent)) {
227
+ parent.contents = node;
228
+ }
229
+ else {
230
+ const pt = identity.isAlias(parent) ? 'alias' : 'scalar';
231
+ throw new Error(`Cannot replace node with ${pt} parent`);
232
+ }
233
+ }
234
+
235
+ exports.visit = visit;
236
+ exports.visitAsync = visitAsync;
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "yaml",
3
+ "version": "2.9.0",
4
+ "license": "ISC",
5
+ "author": "Eemeli Aro <eemeli@gmail.com>",
6
+ "funding": "https://github.com/sponsors/eemeli",
7
+ "repository": "github:eemeli/yaml",
8
+ "description": "JavaScript parser and stringifier for YAML",
9
+ "keywords": [
10
+ "YAML",
11
+ "parser",
12
+ "stringifier"
13
+ ],
14
+ "homepage": "https://eemeli.org/yaml/",
15
+ "files": [
16
+ "browser/",
17
+ "dist/",
18
+ "util.js"
19
+ ],
20
+ "type": "commonjs",
21
+ "main": "./dist/index.js",
22
+ "bin": "./bin.mjs",
23
+ "browser": {
24
+ "./dist/index.js": "./browser/index.js",
25
+ "./dist/util.js": "./browser/dist/util.js",
26
+ "./util.js": "./browser/dist/util.js"
27
+ },
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "node": "./dist/index.js",
32
+ "default": "./browser/index.js"
33
+ },
34
+ "./package.json": "./package.json",
35
+ "./util": {
36
+ "types": "./dist/util.d.ts",
37
+ "node": "./dist/util.js",
38
+ "default": "./browser/dist/util.js"
39
+ }
40
+ },
41
+ "scripts": {
42
+ "build": "npm run build:node && npm run build:browser",
43
+ "build:browser": "rollup -c config/rollup.browser-config.mjs",
44
+ "build:node": "rollup -c config/rollup.node-config.mjs",
45
+ "clean": "git clean -fdxe node_modules",
46
+ "lint": "eslint config/ src/",
47
+ "prettier": "prettier --write .",
48
+ "prestart": "rollup --sourcemap -c config/rollup.node-config.mjs",
49
+ "start": "node --enable-source-maps -i -e 'YAML=require(\"./dist/index.js\");const{parse,parseDocument,parseAllDocuments}=YAML'",
50
+ "test": "jest --config config/jest.config.js",
51
+ "test:all": "npm test && npm run test:types && npm run test:dist && npm run test:dist:types",
52
+ "test:browsers": "cd playground && npm test",
53
+ "test:dist": "npm run build:node && jest --config config/jest.config.js",
54
+ "test:dist:types": "tsc --allowJs --moduleResolution node --noEmit --target es5 dist/index.js",
55
+ "test:types": "tsc --noEmit && tsc --noEmit -p tests/tsconfig.json",
56
+ "docs:install": "cd docs-slate && bundle install",
57
+ "predocs:deploy": "node docs/prepare-docs.mjs",
58
+ "docs:deploy": "cd docs-slate && ./deploy.sh",
59
+ "predocs": "node docs/prepare-docs.mjs",
60
+ "docs": "cd docs-slate && bundle exec middleman server",
61
+ "preversion": "npm test && npm run build",
62
+ "prepublishOnly": "npm run clean && npm test && npm run build"
63
+ },
64
+ "browserslist": "defaults, not ie 11",
65
+ "prettier": {
66
+ "arrowParens": "avoid",
67
+ "semi": false,
68
+ "singleQuote": true,
69
+ "trailingComma": "none"
70
+ },
71
+ "devDependencies": {
72
+ "@babel/core": "^7.12.10",
73
+ "@babel/plugin-transform-typescript": "^7.12.17",
74
+ "@babel/preset-env": "^7.12.11",
75
+ "@eslint/js": "^9.9.1",
76
+ "@rollup/plugin-babel": "^6.0.3",
77
+ "@rollup/plugin-replace": "^6.0.3",
78
+ "@rollup/plugin-typescript": "^12.1.1",
79
+ "@types/jest": "^29.2.4",
80
+ "@types/node": "^20.11.20",
81
+ "babel-jest": "^29.0.1",
82
+ "eslint": "^9.9.1",
83
+ "eslint-config-prettier": "^10.1.8",
84
+ "fast-check": "^2.12.0",
85
+ "jest": "^29.0.1",
86
+ "jest-resolve": "^29.7.0",
87
+ "jest-ts-webcompat-resolver": "^1.0.0",
88
+ "prettier": "^3.0.2",
89
+ "rollup": "^4.12.0",
90
+ "tslib": "^2.8.1",
91
+ "typescript": "^5.7.2",
92
+ "typescript-eslint": "^8.4.0"
93
+ },
94
+ "engines": {
95
+ "node": ">= 14.6"
96
+ }
97
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "shelfware-prod",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "private": true,
6
+ "dependencies": {
7
+ "@babel/parser": "7.29.8",
8
+ "@vue/compiler-core": "3.5.42",
9
+ "@vue/compiler-dom": "3.5.42",
10
+ "@vue/compiler-ssr": "3.5.42",
11
+ "@vue/reactivity": "3.5.42",
12
+ "@vue/runtime-core": "3.5.42",
13
+ "@vue/runtime-dom": "3.5.42",
14
+ "@vue/server-renderer": "3.5.42",
15
+ "@vue/shared": "3.5.42",
16
+ "devalue": "5.9.2",
17
+ "entities": "7.0.1",
18
+ "estree-walker": "2.0.2",
19
+ "hookable": "6.1.1",
20
+ "nostics": "1.2.0",
21
+ "source-map-js": "1.2.1",
22
+ "ufo": "1.6.4",
23
+ "unhead": "3.4.0",
24
+ "vue": "3.5.42",
25
+ "vue-bundle-renderer": "2.3.2",
26
+ "yaml": "2.9.0"
27
+ }
28
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Grygorii Liashenko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,59 @@
1
1
  # shelfware
2
2
 
3
- Finds the shelfware in your skill drawers. Coming soon.
3
+ shelfware finds the shelfware in your skill drawers.
4
+
5
+ A local catalog of the AI-agent skills installed on this machine: every `~/.<tool>/skills` drawer (`~/.claude/skills`, `~/.cursor/skills`, `~/.codex/skills`, `~/.agents/skills`, a custom `~/.claude-work/skills`, …), Cursor plugins, Gemini Antigravity, Hermes profiles, and friends. It scans, lists, searches, renders, **edits**, audits, quarantines, restores, and permanently deletes skills, from a browser tab that only your machine can reach.
6
+
7
+ ## Run it
8
+
9
+ ```bash
10
+ npx shelfware@latest
11
+ ```
12
+
13
+ Options: `--port <n>` (or `PORT`), `--no-open` (or `SHELFWARE_NO_OPEN=1`), `--help`. The server binds `127.0.0.1` on the first free port from 3781 and opens your browser. Stop it with Ctrl-C.
14
+
15
+ Node 20 or newer. No build step: the package ships the prebuilt app. For a permanent install, `npm i -g shelfware` and then `shelfware`.
16
+
17
+ ### First run
18
+
19
+ Starting shelfware only reads. It walks the hidden directories directly under your home (`$HOME`), skipping caches and toolchains, and picks up every `skills/` (or `skill/`) folder it finds, plus the Cursor, Gemini Antigravity and Hermes locations above. Nothing on disk changes until you quarantine, restore, delete or save a skill yourself.
20
+
21
+ Skills outside your home directory (project-level `.claude/skills` inside a repository, an arbitrary path) are not scanned in v0.1; a `--root <path>` flag is planned. To scan a different home, run `HOME=/other/home npx shelfware@latest`.
22
+
23
+ ### Troubleshooting
24
+
25
+ - **`npx shelfware` prints "coming soon".** Your npx cache still holds the `0.0.1` placeholder. Run `npx shelfware@latest` once; npx then caches the real release.
26
+ - **The browser did not open.** Copy the URL from the `shelfware at http://127.0.0.1:<port>` line, or start with `--no-open` and open it yourself.
27
+ - **Port in use.** Pass `--port <n>`; without it shelfware tries 3781 through 3800.
28
+ - **The catalog is empty.** Check that your skills live under `$HOME/.<tool>/skills`; other locations are not scanned yet.
29
+
30
+ ## What you get
31
+
32
+ - **Drawers**: one per install scope, with counts; a house census (physical cards, copies and wasted bytes, references, broken links, a rough token total).
33
+ - **Cards**: kind, form (file / link / broken), origin with its certainty, copies, static audit risk, invocation mode, `~tokens`.
34
+ - **Reader**: rendered manuscript, raw source, file folio with text previews, and a raw editor for `SKILL.md` with an optimistic save (409 when the file changed on disk).
35
+ - **Quarantine**: cards move to `~/.skill-cabinet/quarantine/` and can be restored to the exact path they came from. Permanent delete only from the quarantine shelf. The manifest format is the one skill-cabinet uses, so both tools can read each other's trash.
36
+ - **Keyboard**: `/` find, `j`/`k` move, `x` mark, `q` quarantine, `r` restore, `d` delete, `e` edit, `⌘S` / `Ctrl+S` save.
37
+
38
+ ## Security model
39
+
40
+ - Every request that reaches the app must carry a loopback `Host` (`127.0.0.1`, `localhost`, `[::1]`) on the bound port; anything else is refused. This closes DNS-rebinding reads.
41
+ - Every mutation must carry a loopback `Origin` and a per-run session token that only the served page knows.
42
+ - No CORS headers, ever. File reads and saves are contained to the skill's directory; symlinks are never followed for destructive actions.
43
+ - Nothing leaves the machine. There is no network feature.
44
+
45
+ ## Credits
46
+
47
+ Scanner rules, audit heuristics and the quarantine format are ported from [skill-cabinet](https://github.com/subsy/skill-cabinet) (MIT), whose audit rules were adapted from [Adaptive Skills](https://github.com/wangsoft/Adaptive-Skills) (MIT). shelfware is a rebuild in Nuxt 4 with an editor and a hardened local security model.
48
+
49
+ ## Development
50
+
51
+ ```bash
52
+ pnpm install
53
+ pnpm dev # http://localhost:3000
54
+ pnpm test # unit + nuxt + e2e
55
+ pnpm build
56
+ pnpm pack:verify # packs and runs the tarball through npx
57
+ ```
58
+
59
+ MIT.
package/bin/launch.mjs ADDED
@@ -0,0 +1,158 @@
1
+ // Pure launcher helpers for `npx shelfware`. Node built-ins only (spec §13.1).
2
+ import { spawn as spawnProcess } from 'node:child_process'
3
+ import crypto from 'node:crypto'
4
+ import fs from 'node:fs'
5
+ import http from 'node:http'
6
+ import net from 'node:net'
7
+ import path from 'node:path'
8
+ import { fileURLToPath } from 'node:url'
9
+
10
+ export const DEFAULT_PORT = 3781
11
+ export const PORT_ATTEMPTS = 20
12
+ export const HOST = '127.0.0.1'
13
+
14
+ export const HELP = `shelfware — a local catalog of the AI-agent skills on this machine
15
+
16
+ Usage: shelfware [--port <n>] [--no-open]
17
+
18
+ --port <n> bind 127.0.0.1:<n> instead of the first free port from ${DEFAULT_PORT}
19
+ --no-open do not open the browser (also SHELFWARE_NO_OPEN=1)
20
+ --help, -h print this help and exit
21
+ PORT=<n> same as --port
22
+ `
23
+
24
+ /** Spec §10.3: `sw_` + 32 random bytes as hex. The letter prefix keeps destr from casting it. */
25
+ export function makeToken() {
26
+ return `sw_${crypto.randomBytes(32).toString('hex')}`
27
+ }
28
+
29
+ export function parseArgs(argv = [], env = {}) {
30
+ let port = null
31
+ let open = env.SHELFWARE_NO_OPEN !== '1'
32
+ for (let i = 0; i < argv.length; i += 1) {
33
+ const arg = argv[i]
34
+ if (arg === '--no-open') {
35
+ open = false
36
+ } else if (arg === '--port') {
37
+ port = Number(argv[i + 1])
38
+ i += 1
39
+ } else if (arg.startsWith('--port=')) {
40
+ port = Number(arg.slice('--port='.length))
41
+ } else if (arg === '--help' || arg === '-h') {
42
+ return { help: true, port: null, open }
43
+ }
44
+ }
45
+ if (port === null && env.PORT) port = Number(env.PORT)
46
+ if (port !== null && (!Number.isInteger(port) || port < 1 || port > 65535)) {
47
+ throw new Error(`Invalid port: ${port}`)
48
+ }
49
+ return { help: false, port, open }
50
+ }
51
+
52
+ export function isPortFree(port, host = HOST) {
53
+ return new Promise((resolve) => {
54
+ const server = net.createServer()
55
+ server.unref()
56
+ server.once('error', () => resolve(false))
57
+ server.listen({ port, host }, () => server.close(() => resolve(true)))
58
+ })
59
+ }
60
+
61
+ export async function pickPort(start = DEFAULT_PORT, { attempts = PORT_ATTEMPTS, host = HOST } = {}) {
62
+ for (let port = start; port < start + attempts; port += 1) {
63
+ if (await isPortFree(port, host)) return port
64
+ }
65
+ throw new Error(`No free port between ${start} and ${start + attempts - 1} on ${host}`)
66
+ }
67
+
68
+ /** GET /api/health with the loopback Host the server insists on (spec §10.1). */
69
+ export function probeHealth(port, host = HOST) {
70
+ return new Promise((resolve) => {
71
+ const req = http.get(
72
+ { host, port, path: '/api/health', headers: { Host: `${host}:${port}` }, timeout: 1000 },
73
+ (res) => {
74
+ let body = ''
75
+ res.setEncoding('utf8')
76
+ res.on('data', (chunk) => {
77
+ body += chunk
78
+ })
79
+ res.on('end', () => resolve(res.statusCode === 200 && body.includes('"ok":true')))
80
+ },
81
+ )
82
+ req.on('error', () => resolve(false))
83
+ req.on('timeout', () => {
84
+ req.destroy()
85
+ resolve(false)
86
+ })
87
+ })
88
+ }
89
+
90
+ export async function waitForHealth(port, { timeoutMs = 10_000, intervalMs = 100, host = HOST, probe = probeHealth } = {}) {
91
+ const deadline = Date.now() + timeoutMs
92
+ while (Date.now() < deadline) {
93
+ if (await probe(port, host)) return true
94
+ await new Promise(resolve => setTimeout(resolve, intervalMs))
95
+ }
96
+ return false
97
+ }
98
+
99
+ export function openBrowser(url, { platform = process.platform, spawn = spawnProcess } = {}) {
100
+ const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'cmd' : 'xdg-open'
101
+ const args = platform === 'win32' ? ['/c', 'start', '', url] : [url]
102
+ // A missing browser opener (e.g. no xdg-open on a headless box) must never take
103
+ // the running server down with it: spawn can throw synchronously (rare) or emit
104
+ // an async 'error' (the common ENOENT case), and an unhandled 'error' on an
105
+ // EventEmitter is fatal. Swallow both.
106
+ try {
107
+ const child = spawn(cmd, args, { stdio: 'ignore', detached: true })
108
+ child.on?.('error', () => {})
109
+ child.unref?.()
110
+ } catch {
111
+ // ignore: failing to open a browser is not a launch failure
112
+ }
113
+ return { cmd, args }
114
+ }
115
+
116
+ export function serverEntry(binDir = path.dirname(fileURLToPath(import.meta.url))) {
117
+ return path.resolve(binDir, '..', '.output', 'server', 'index.mjs')
118
+ }
119
+
120
+ /**
121
+ * Orchestration with injectable I/O so it can be unit-tested end to end:
122
+ * flags → port → env → import the prebuilt server → wait for health → open.
123
+ */
124
+ export async function launch({
125
+ argv = process.argv.slice(2),
126
+ env = process.env,
127
+ importServer,
128
+ log = console.log,
129
+ exit = process.exit,
130
+ entry = serverEntry(),
131
+ spawn = spawnProcess,
132
+ } = {}) {
133
+ const args = parseArgs(argv, env)
134
+ if (args.help) {
135
+ log(HELP)
136
+ return null
137
+ }
138
+ if (!fs.existsSync(entry)) {
139
+ log(`shelfware: missing ${entry}. This copy was not built; install the published package or run \`pnpm build\`.`)
140
+ exit(1)
141
+ return null
142
+ }
143
+ const port = args.port ?? await pickPort(DEFAULT_PORT)
144
+ env.NUXT_PUBLIC_SHELFWARE_TOKEN = makeToken()
145
+ env.NITRO_HOST = HOST
146
+ env.NITRO_PORT = String(port)
147
+ env.NODE_ENV = 'production'
148
+ await importServer()
149
+ if (!(await waitForHealth(port))) {
150
+ log(`shelfware: the server did not answer on http://${HOST}:${port} within 10 s`)
151
+ exit(1)
152
+ return null
153
+ }
154
+ const url = `http://${HOST}:${port}`
155
+ log(`shelfware at ${url}`)
156
+ if (args.open) openBrowser(url, { spawn })
157
+ return { port, url }
158
+ }
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { launch } from './launch.mjs'
3
+
4
+ await launch({
5
+ importServer: () => import('../.output/server/index.mjs'),
6
+ })