shelfware 0.1.1 → 0.1.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/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{BZuUK3cr.js → Bzmuhhqm.js} +1 -1
- package/.output/public/_nuxt/{6IstVYrV.js → CJmYvhe6.js} +1 -1
- package/.output/public/_nuxt/CMk5jOCS.js +1 -0
- package/.output/public/_nuxt/DJQqUjJu.js +2 -0
- package/.output/public/_nuxt/DfJzPSBi.js +1 -0
- package/.output/public/_nuxt/EBA28doP.js +14 -0
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/bc384f67-a2f8-4b6b-9aa1-cb68fb93d366.json +1 -0
- package/.output/public/_nuxt/entry.CKteCcdN.css +2 -0
- package/.output/public/_nuxt/error-404.1qC5mjOI.css +1 -0
- package/.output/public/_nuxt/error-500.BcOmuN7K.css +1 -0
- package/.output/public/_nuxt/rWsrwf2L.js +36 -0
- package/.output/public/_nuxt/{C_VgD9ZI.js → sK9Xse3o.js} +1 -1
- package/.output/server/chunks/nitro/nitro.mjs +98 -98
- package/.output/server/chunks/routes/renderer.mjs +1 -1
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README.md +10 -0
- package/bin/launch.d.mts +54 -0
- package/bin/launch.mjs +46 -17
- package/package.json +7 -3
- package/.output/public/_nuxt/9C5WUlLE.js +0 -36
- package/.output/public/_nuxt/BXXtFil5.js +0 -1
- package/.output/public/_nuxt/BeLyMmd4.js +0 -1
- package/.output/public/_nuxt/DB5Vxbte.js +0 -2
- package/.output/public/_nuxt/DMg0j7gv.js +0 -14
- package/.output/public/_nuxt/builds/meta/e0d2b6a3-3a30-44b7-8c79-a56f66400005.json +0 -1
- package/.output/public/_nuxt/entry.b3_DJTEt.css +0 -2
- package/.output/public/_nuxt/error-404.CHsn7XF-.css +0 -1
- package/.output/public/_nuxt/error-500.Bawx2bLr.css +0 -1
|
@@ -4056,7 +4056,7 @@ function _expandFromEnv(value) {
|
|
|
4056
4056
|
const _inlineRuntimeConfig = {
|
|
4057
4057
|
"app": {
|
|
4058
4058
|
"baseURL": "/",
|
|
4059
|
-
"buildId": "
|
|
4059
|
+
"buildId": "bc384f67-a2f8-4b6b-9aa1-cb68fb93d366",
|
|
4060
4060
|
"buildAssetsDir": "/_nuxt/",
|
|
4061
4061
|
"cdnURL": ""
|
|
4062
4062
|
},
|
|
@@ -4500,7 +4500,7 @@ async function errorHandler(error, event) {
|
|
|
4500
4500
|
|
|
4501
4501
|
const script = "\"use strict\";(()=>{const o=window,e=document.documentElement,c=[\"dark\",\"light\"],s=getStorageValue(\"localStorage\",\"nuxt-color-mode\")||\"system\";let r=s===\"system\"?f():s;const l=e.getAttribute(\"data-color-mode-forced\");l&&(r=l),i(r),o[\"__NUXT_COLOR_MODE__\"]={preference:s,value:r,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(t){const a=\"\"+t+\"\",n=\"\";e.classList?e.classList.add(a):e.className+=\" \"+a,n&&e.setAttribute(\"data-\"+n,t)}function d(t){const a=\"\"+t+\"\",n=\"\";e.classList?e.classList.remove(a):e.className=e.className.replace(new RegExp(a,\"g\"),\"\"),n&&e.removeAttribute(\"data-\"+n)}function u(t){return o.matchMedia(\"(prefers-color-scheme\"+t+\")\")}function f(){if(o.matchMedia&&u(\"\").media!==\"not all\"){for(const t of c)if(u(\":\"+t).matches)return t}return\"light\"}})();function getStorageValue(o,e){switch(o){case\"localStorage\":try{return window.localStorage.getItem(e)}catch{return null}case\"sessionStorage\":try{return window.sessionStorage.getItem(e)}catch{return null}case\"cookie\":try{return getCookie(e)}catch{return null}default:return null}}function getCookie(o){const c=(\"; \"+window.document.cookie).split(\"; \"+o+\"=\");if(c.length===2){const s=c.pop();return s?s.split(\";\").shift():null}}";
|
|
4502
4502
|
|
|
4503
|
-
const
|
|
4503
|
+
const _4H4culGvQ1Dp8myD2WdjQ3S6IGUumm_St2Zw0wwTTE = (function(nitro) {
|
|
4504
4504
|
nitro.hooks.hook("render:html", (htmlContext) => {
|
|
4505
4505
|
htmlContext.head.push(`<script>${script}<\/script>`);
|
|
4506
4506
|
});
|
|
@@ -4559,122 +4559,122 @@ function tokenMatches(actual, expected) {
|
|
|
4559
4559
|
return timingSafeEqual(a, b);
|
|
4560
4560
|
}
|
|
4561
4561
|
|
|
4562
|
-
const
|
|
4562
|
+
const _YY93QxfadySKCpwmDM6dAIPqjH6q5NYi1I7q0CwP0w = defineNitroPlugin(() => {
|
|
4563
4563
|
if (!isWellFormedToken(process.env.NUXT_PUBLIC_SHELFWARE_TOKEN)) {
|
|
4564
4564
|
process.env.NUXT_PUBLIC_SHELFWARE_TOKEN = `sw_${randomBytes(32).toString("hex")}`;
|
|
4565
4565
|
}
|
|
4566
4566
|
});
|
|
4567
4567
|
|
|
4568
4568
|
const plugins = [
|
|
4569
|
-
|
|
4570
|
-
|
|
4569
|
+
_4H4culGvQ1Dp8myD2WdjQ3S6IGUumm_St2Zw0wwTTE,
|
|
4570
|
+
_YY93QxfadySKCpwmDM6dAIPqjH6q5NYi1I7q0CwP0w
|
|
4571
4571
|
];
|
|
4572
4572
|
|
|
4573
4573
|
const assets = {
|
|
4574
|
-
"/_nuxt/6IstVYrV.js": {
|
|
4575
|
-
"type": "text/javascript; charset=utf-8",
|
|
4576
|
-
"etag": "\"e90-QSo0QKAvkvHEus5Dhcj+CyKCqD4\"",
|
|
4577
|
-
"mtime": "2026-09-06T14:46:29.734Z",
|
|
4578
|
-
"size": 3728,
|
|
4579
|
-
"path": "../public/_nuxt/6IstVYrV.js"
|
|
4580
|
-
},
|
|
4581
4574
|
"/_nuxt/BDNMzG2s.js": {
|
|
4582
4575
|
"type": "text/javascript; charset=utf-8",
|
|
4583
4576
|
"etag": "\"54-MasMfSk/A98C3Gn9uIOxtFxkWNw\"",
|
|
4584
|
-
"mtime": "2026-09-
|
|
4577
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4585
4578
|
"size": 84,
|
|
4586
4579
|
"path": "../public/_nuxt/BDNMzG2s.js"
|
|
4587
4580
|
},
|
|
4588
4581
|
"/_nuxt/BW3xJdEx.js": {
|
|
4589
4582
|
"type": "text/javascript; charset=utf-8",
|
|
4590
4583
|
"etag": "\"2da-zDmvCG/tLW/peRiDRHBkm+3Edw4\"",
|
|
4591
|
-
"mtime": "2026-09-
|
|
4584
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4592
4585
|
"size": 730,
|
|
4593
4586
|
"path": "../public/_nuxt/BW3xJdEx.js"
|
|
4594
4587
|
},
|
|
4595
|
-
"/_nuxt/
|
|
4588
|
+
"/_nuxt/Bzmuhhqm.js": {
|
|
4596
4589
|
"type": "text/javascript; charset=utf-8",
|
|
4597
|
-
"etag": "\"
|
|
4598
|
-
"mtime": "2026-09-
|
|
4599
|
-
"size":
|
|
4600
|
-
"path": "../public/_nuxt/
|
|
4590
|
+
"etag": "\"d4e-gP63vGSa9YNUx8rX9IMYEHDofck\"",
|
|
4591
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4592
|
+
"size": 3406,
|
|
4593
|
+
"path": "../public/_nuxt/Bzmuhhqm.js"
|
|
4601
4594
|
},
|
|
4602
|
-
"/_nuxt/
|
|
4595
|
+
"/_nuxt/CJmYvhe6.js": {
|
|
4603
4596
|
"type": "text/javascript; charset=utf-8",
|
|
4604
|
-
"etag": "\"
|
|
4605
|
-
"mtime": "2026-09-
|
|
4606
|
-
"size":
|
|
4607
|
-
"path": "../public/_nuxt/
|
|
4597
|
+
"etag": "\"e90-WCRBrvGTpCy77xWxtXI2/olAzuA\"",
|
|
4598
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4599
|
+
"size": 3728,
|
|
4600
|
+
"path": "../public/_nuxt/CJmYvhe6.js"
|
|
4608
4601
|
},
|
|
4609
|
-
"/_nuxt/
|
|
4602
|
+
"/_nuxt/CMk5jOCS.js": {
|
|
4610
4603
|
"type": "text/javascript; charset=utf-8",
|
|
4611
|
-
"etag": "\"
|
|
4612
|
-
"mtime": "2026-09-
|
|
4613
|
-
"size":
|
|
4614
|
-
"path": "../public/_nuxt/
|
|
4604
|
+
"etag": "\"1c01-lGS5cFf7bjhmRvkeRxUtYYhz3dw\"",
|
|
4605
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4606
|
+
"size": 7169,
|
|
4607
|
+
"path": "../public/_nuxt/CMk5jOCS.js"
|
|
4615
4608
|
},
|
|
4616
|
-
"/_nuxt/
|
|
4609
|
+
"/_nuxt/DJQqUjJu.js": {
|
|
4617
4610
|
"type": "text/javascript; charset=utf-8",
|
|
4618
|
-
"etag": "\"
|
|
4619
|
-
"mtime": "2026-09-
|
|
4620
|
-
"size":
|
|
4621
|
-
"path": "../public/_nuxt/
|
|
4611
|
+
"etag": "\"9f1d-Ja0Ka8FFBfh/wxDphcm6zq2k/Aw\"",
|
|
4612
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4613
|
+
"size": 40733,
|
|
4614
|
+
"path": "../public/_nuxt/DJQqUjJu.js"
|
|
4622
4615
|
},
|
|
4623
|
-
"/_nuxt/
|
|
4616
|
+
"/_nuxt/DfJzPSBi.js": {
|
|
4624
4617
|
"type": "text/javascript; charset=utf-8",
|
|
4625
|
-
"etag": "\"
|
|
4626
|
-
"mtime": "2026-09-
|
|
4627
|
-
"size":
|
|
4628
|
-
"path": "../public/_nuxt/
|
|
4618
|
+
"etag": "\"1c1-4bfhhLtFN8RKoheWCeIIphoXgv0\"",
|
|
4619
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4620
|
+
"size": 449,
|
|
4621
|
+
"path": "../public/_nuxt/DfJzPSBi.js"
|
|
4629
4622
|
},
|
|
4630
|
-
"/_nuxt/error-404.
|
|
4623
|
+
"/_nuxt/error-404.1qC5mjOI.css": {
|
|
4631
4624
|
"type": "text/css; charset=utf-8",
|
|
4632
|
-
"etag": "\"97d-
|
|
4633
|
-
"mtime": "2026-09-
|
|
4625
|
+
"etag": "\"97d-ClY1xVMSVUOi3w+npB6k6oGQGlM\"",
|
|
4626
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4634
4627
|
"size": 2429,
|
|
4635
|
-
"path": "../public/_nuxt/error-404.
|
|
4628
|
+
"path": "../public/_nuxt/error-404.1qC5mjOI.css"
|
|
4636
4629
|
},
|
|
4637
|
-
"/_nuxt/error-500.
|
|
4630
|
+
"/_nuxt/error-500.BcOmuN7K.css": {
|
|
4638
4631
|
"type": "text/css; charset=utf-8",
|
|
4639
|
-
"etag": "\"772-
|
|
4640
|
-
"mtime": "2026-09-
|
|
4632
|
+
"etag": "\"772-O0XjmZiN9Tmmh4xccNArXpeMXMg\"",
|
|
4633
|
+
"mtime": "2026-09-06T17:42:02.390Z",
|
|
4641
4634
|
"size": 1906,
|
|
4642
|
-
"path": "../public/_nuxt/error-500.
|
|
4635
|
+
"path": "../public/_nuxt/error-500.BcOmuN7K.css"
|
|
4643
4636
|
},
|
|
4644
|
-
"/_nuxt/
|
|
4637
|
+
"/_nuxt/EBA28doP.js": {
|
|
4645
4638
|
"type": "text/javascript; charset=utf-8",
|
|
4646
|
-
"etag": "\"
|
|
4647
|
-
"mtime": "2026-09-
|
|
4648
|
-
"size":
|
|
4649
|
-
"path": "../public/_nuxt/
|
|
4639
|
+
"etag": "\"25526-S2M2g51QVQiD0lfERMcQ2TJCNvo\"",
|
|
4640
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4641
|
+
"size": 152870,
|
|
4642
|
+
"path": "../public/_nuxt/EBA28doP.js"
|
|
4643
|
+
},
|
|
4644
|
+
"/_nuxt/entry.CKteCcdN.css": {
|
|
4645
|
+
"type": "text/css; charset=utf-8",
|
|
4646
|
+
"etag": "\"300c8-0WAu9DRw8xrNZdnpJNGrjxOdjtk\"",
|
|
4647
|
+
"mtime": "2026-09-06T17:42:02.389Z",
|
|
4648
|
+
"size": 196808,
|
|
4649
|
+
"path": "../public/_nuxt/entry.CKteCcdN.css"
|
|
4650
|
+
},
|
|
4651
|
+
"/_nuxt/sK9Xse3o.js": {
|
|
4652
|
+
"type": "text/javascript; charset=utf-8",
|
|
4653
|
+
"etag": "\"16ebc-llACAH/LeVfHtbCyV/Od8ae+rn8\"",
|
|
4654
|
+
"mtime": "2026-09-06T17:42:02.390Z",
|
|
4655
|
+
"size": 93884,
|
|
4656
|
+
"path": "../public/_nuxt/sK9Xse3o.js"
|
|
4650
4657
|
},
|
|
4651
4658
|
"/_nuxt/builds/latest.json": {
|
|
4652
4659
|
"type": "application/json",
|
|
4653
|
-
"etag": "\"47-
|
|
4654
|
-
"mtime": "2026-09-
|
|
4660
|
+
"etag": "\"47-y/Uibk2CT3wmZ2jWKLpHXHWksOc\"",
|
|
4661
|
+
"mtime": "2026-09-06T17:42:02.382Z",
|
|
4655
4662
|
"size": 71,
|
|
4656
4663
|
"path": "../public/_nuxt/builds/latest.json"
|
|
4657
4664
|
},
|
|
4658
|
-
"/_nuxt/
|
|
4659
|
-
"type": "text/
|
|
4660
|
-
"etag": "\"
|
|
4661
|
-
"mtime": "2026-09-
|
|
4662
|
-
"size":
|
|
4663
|
-
"path": "../public/_nuxt/
|
|
4665
|
+
"/_nuxt/rWsrwf2L.js": {
|
|
4666
|
+
"type": "text/javascript; charset=utf-8",
|
|
4667
|
+
"etag": "\"7606d-30wm5zPsBwgXACgEnaCLHx2ZHVk\"",
|
|
4668
|
+
"mtime": "2026-09-06T17:42:02.390Z",
|
|
4669
|
+
"size": 483437,
|
|
4670
|
+
"path": "../public/_nuxt/rWsrwf2L.js"
|
|
4664
4671
|
},
|
|
4665
|
-
"/_nuxt/builds/meta/
|
|
4672
|
+
"/_nuxt/builds/meta/bc384f67-a2f8-4b6b-9aa1-cb68fb93d366.json": {
|
|
4666
4673
|
"type": "application/json",
|
|
4667
|
-
"etag": "\"58
|
|
4668
|
-
"mtime": "2026-09-
|
|
4674
|
+
"etag": "\"58-t+Qo1Xc7SXVzy2SU0Q6z9Np3At0\"",
|
|
4675
|
+
"mtime": "2026-09-06T17:42:02.343Z",
|
|
4669
4676
|
"size": 88,
|
|
4670
|
-
"path": "../public/_nuxt/builds/meta/
|
|
4671
|
-
},
|
|
4672
|
-
"/_nuxt/DMg0j7gv.js": {
|
|
4673
|
-
"type": "text/javascript; charset=utf-8",
|
|
4674
|
-
"etag": "\"25529-MrmjBHZKW5MJ6UC+MAR50nTTq7U\"",
|
|
4675
|
-
"mtime": "2026-09-06T14:46:29.735Z",
|
|
4676
|
-
"size": 152873,
|
|
4677
|
-
"path": "../public/_nuxt/DMg0j7gv.js"
|
|
4677
|
+
"path": "../public/_nuxt/builds/meta/bc384f67-a2f8-4b6b-9aa1-cb68fb93d366.json"
|
|
4678
4678
|
}
|
|
4679
4679
|
};
|
|
4680
4680
|
|
|
@@ -4821,7 +4821,7 @@ function getAsset (id) {
|
|
|
4821
4821
|
|
|
4822
4822
|
const METHODS = /* @__PURE__ */ new Set(["HEAD", "GET"]);
|
|
4823
4823
|
const EncodingMap = { gzip: ".gz", br: ".br" };
|
|
4824
|
-
const
|
|
4824
|
+
const _WmhSKo = eventHandler((event) => {
|
|
4825
4825
|
if (event.method && !METHODS.has(event.method)) {
|
|
4826
4826
|
return;
|
|
4827
4827
|
}
|
|
@@ -4885,14 +4885,14 @@ const _tlswgW = eventHandler((event) => {
|
|
|
4885
4885
|
return readAsset(id);
|
|
4886
4886
|
});
|
|
4887
4887
|
|
|
4888
|
-
const
|
|
4888
|
+
const _bZ6qrV = defineEventHandler((event) => {
|
|
4889
4889
|
if (!isAllowedHost(getRequestHeader(event, "host"), expectedPort(process.env))) {
|
|
4890
4890
|
setResponseStatus(event, 403);
|
|
4891
4891
|
return { error: "Host not allowed" };
|
|
4892
4892
|
}
|
|
4893
4893
|
});
|
|
4894
4894
|
|
|
4895
|
-
const
|
|
4895
|
+
const _IXLPhU = defineEventHandler((event) => {
|
|
4896
4896
|
var _a;
|
|
4897
4897
|
const method = event.method.toUpperCase();
|
|
4898
4898
|
if (method === "GET" || method === "HEAD" || method === "OPTIONS") return;
|
|
@@ -4915,33 +4915,33 @@ const _5cPz3u = defineEventHandler((event) => {
|
|
|
4915
4915
|
|
|
4916
4916
|
const _SxA8c9 = defineEventHandler(() => {});
|
|
4917
4917
|
|
|
4918
|
-
const
|
|
4919
|
-
const
|
|
4920
|
-
const
|
|
4921
|
-
const
|
|
4922
|
-
const
|
|
4923
|
-
const
|
|
4924
|
-
const
|
|
4925
|
-
const
|
|
4926
|
-
const
|
|
4927
|
-
const
|
|
4918
|
+
const _lazy_i3xXvc = () => import('../routes/api/_..._.mjs');
|
|
4919
|
+
const _lazy_ODywhX = () => import('../routes/api/health.get.mjs');
|
|
4920
|
+
const _lazy_QLBXsz = () => import('../routes/api/skills.get.mjs');
|
|
4921
|
+
const _lazy_phqsH7 = () => import('../routes/api/skills/_id_.get.mjs');
|
|
4922
|
+
const _lazy_E5xWx6 = () => import('../routes/api/skills/_id_.put.mjs');
|
|
4923
|
+
const _lazy_zp4eSy = () => import('../routes/api/skills/_id/file.get.mjs');
|
|
4924
|
+
const _lazy_GSqKbk = () => import('../routes/api/skills/delete.post.mjs');
|
|
4925
|
+
const _lazy_8aROGo = () => import('../routes/api/skills/quarantine.post.mjs');
|
|
4926
|
+
const _lazy_Z7y_Vb = () => import('../routes/api/skills/restore.post.mjs');
|
|
4927
|
+
const _lazy_ZyvLhi = () => import('../routes/renderer.mjs');
|
|
4928
4928
|
|
|
4929
4929
|
const handlers = [
|
|
4930
|
-
{ route: '', handler:
|
|
4931
|
-
{ route: '', handler:
|
|
4932
|
-
{ route: '', handler:
|
|
4933
|
-
{ route: '/api/**', handler:
|
|
4934
|
-
{ route: '/api/health', handler:
|
|
4935
|
-
{ route: '/api/skills', handler:
|
|
4936
|
-
{ route: '/api/skills/:id', handler:
|
|
4937
|
-
{ route: '/api/skills/:id', handler:
|
|
4938
|
-
{ route: '/api/skills/:id/file', handler:
|
|
4939
|
-
{ route: '/api/skills/delete', handler:
|
|
4940
|
-
{ route: '/api/skills/quarantine', handler:
|
|
4941
|
-
{ route: '/api/skills/restore', handler:
|
|
4942
|
-
{ route: '/__nuxt_error', handler:
|
|
4930
|
+
{ route: '', handler: _WmhSKo, lazy: false, middleware: true, method: undefined },
|
|
4931
|
+
{ route: '', handler: _bZ6qrV, lazy: false, middleware: true, method: undefined },
|
|
4932
|
+
{ route: '', handler: _IXLPhU, lazy: false, middleware: true, method: undefined },
|
|
4933
|
+
{ route: '/api/**', handler: _lazy_i3xXvc, lazy: true, middleware: false, method: undefined },
|
|
4934
|
+
{ route: '/api/health', handler: _lazy_ODywhX, lazy: true, middleware: false, method: "get" },
|
|
4935
|
+
{ route: '/api/skills', handler: _lazy_QLBXsz, lazy: true, middleware: false, method: "get" },
|
|
4936
|
+
{ route: '/api/skills/:id', handler: _lazy_phqsH7, lazy: true, middleware: false, method: "get" },
|
|
4937
|
+
{ route: '/api/skills/:id', handler: _lazy_E5xWx6, lazy: true, middleware: false, method: "put" },
|
|
4938
|
+
{ route: '/api/skills/:id/file', handler: _lazy_zp4eSy, lazy: true, middleware: false, method: "get" },
|
|
4939
|
+
{ route: '/api/skills/delete', handler: _lazy_GSqKbk, lazy: true, middleware: false, method: "post" },
|
|
4940
|
+
{ route: '/api/skills/quarantine', handler: _lazy_8aROGo, lazy: true, middleware: false, method: "post" },
|
|
4941
|
+
{ route: '/api/skills/restore', handler: _lazy_Z7y_Vb, lazy: true, middleware: false, method: "post" },
|
|
4942
|
+
{ route: '/__nuxt_error', handler: _lazy_ZyvLhi, lazy: true, middleware: false, method: undefined },
|
|
4943
4943
|
{ route: '/__nuxt_island/**', handler: _SxA8c9, lazy: false, middleware: false, method: undefined },
|
|
4944
|
-
{ route: '/**', handler:
|
|
4944
|
+
{ route: '/**', handler: _lazy_ZyvLhi, lazy: true, middleware: false, method: undefined }
|
|
4945
4945
|
];
|
|
4946
4946
|
|
|
4947
4947
|
function createNitroApp() {
|
|
@@ -185,7 +185,7 @@ function encodeForwardSlashes(str) {
|
|
|
185
185
|
|
|
186
186
|
const renderSSRHeadOptions = {"omitLineBreaks":true};
|
|
187
187
|
|
|
188
|
-
const entryFileName = "
|
|
188
|
+
const entryFileName = "rWsrwf2L.js";
|
|
189
189
|
|
|
190
190
|
//#region src/runtime/handlers/renderer.ts
|
|
191
191
|
globalThis.__buildAssetsURL = buildAssetsURL;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const client_precomputed = ((h,j,k,m,o,q,u,x,z,A)=>({dependencies:{"
|
|
1
|
+
const client_precomputed = ((h,j,k,m,o,q,u,x,z,A)=>({dependencies:{"_sK9Xse3o.js":{scripts:{},styles:{},preload:{"_sK9Xse3o.js":h={resourceType:"script",module:true,prefetch:true,preload:true,file:"sK9Xse3o.js",name:"nuxt"}},prefetch:{}},"_BW3xJdEx.js":{scripts:{},styles:{},preload:{"_BW3xJdEx.js":j={resourceType:"script",module:true,prefetch:true,preload:true,file:"BW3xJdEx.js",name:"defu"}},prefetch:{}},"_DJQqUjJu.js":{scripts:{},styles:{},preload:{"_DJQqUjJu.js":k={resourceType:"script",module:true,prefetch:true,preload:true,file:"DJQqUjJu.js",name:"ready",imports:["_sK9Xse3o.js","_BW3xJdEx.js"]},"_sK9Xse3o.js":h,"_BW3xJdEx.js":j},prefetch:{}},"_CMk5jOCS.js":{scripts:{},styles:{},preload:{"_CMk5jOCS.js":m={resourceType:"script",module:true,prefetch:true,preload:true,file:"CMk5jOCS.js",name:"config",imports:["_sK9Xse3o.js","_BW3xJdEx.js"]},"_sK9Xse3o.js":h,"_BW3xJdEx.js":j},prefetch:{}},"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js":{scripts:{"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js":q={resourceType:"script",module:true,prefetch:true,preload:true,file:"rWsrwf2L.js",name:"entry",src:"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js",isEntry:true,imports:["_sK9Xse3o.js","_DJQqUjJu.js","_BW3xJdEx.js","_CMk5jOCS.js"],dynamicImports:o=["../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js","../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-404.vue","../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-500.vue"],css:["entry.CKteCcdN.css"]}},styles:{"entry.CKteCcdN.css":u={file:"entry.CKteCcdN.css",resourceType:"style",prefetch:true,preload:true}},preload:{"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js":q,"entry.CKteCcdN.css":u,"_sK9Xse3o.js":h,"_DJQqUjJu.js":k,"_BW3xJdEx.js":j,"_CMk5jOCS.js":m},prefetch:{"entry.CKteCcdN.css":u}},"_BDNMzG2s.js":{scripts:{},styles:{},preload:{"_BDNMzG2s.js":x={resourceType:"script",module:true,prefetch:true,preload:true,file:"BDNMzG2s.js",name:"_plugin-vue_export-helper"}},prefetch:{}},"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-404.vue":{scripts:{},styles:{"error-404.1qC5mjOI.css":z={file:"error-404.1qC5mjOI.css",resourceType:"style",prefetch:true,preload:true},"entry.CKteCcdN.css":u},preload:{"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-404.vue":{resourceType:"script",module:true,prefetch:true,preload:true,file:"CJmYvhe6.js",name:"error-404",src:"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-404.vue",isDynamicEntry:true,imports:["_sK9Xse3o.js","../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js","_BDNMzG2s.js"],css:["error-404.1qC5mjOI.css"]},"error-404.1qC5mjOI.css":z,"_sK9Xse3o.js":h,"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js":q,"entry.CKteCcdN.css":u,"_DJQqUjJu.js":k,"_BW3xJdEx.js":j,"_CMk5jOCS.js":m,"_BDNMzG2s.js":x},prefetch:{"error-404.1qC5mjOI.css":z,"entry.CKteCcdN.css":u}},"error-404.1qC5mjOI.css":{scripts:{},styles:{},preload:{"error-404.1qC5mjOI.css":z},prefetch:{}},"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-500.vue":{scripts:{},styles:{"error-500.BcOmuN7K.css":A={file:"error-500.BcOmuN7K.css",resourceType:"style",prefetch:true,preload:true},"entry.CKteCcdN.css":u},preload:{"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-500.vue":{resourceType:"script",module:true,prefetch:true,preload:true,file:"Bzmuhhqm.js",name:"error-500",src:"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-500.vue",isDynamicEntry:true,imports:["_sK9Xse3o.js","../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js","_BDNMzG2s.js"],css:["error-500.BcOmuN7K.css"]},"error-500.BcOmuN7K.css":A,"_sK9Xse3o.js":h,"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js":q,"entry.CKteCcdN.css":u,"_DJQqUjJu.js":k,"_BW3xJdEx.js":j,"_CMk5jOCS.js":m,"_BDNMzG2s.js":x},prefetch:{"error-500.BcOmuN7K.css":A,"entry.CKteCcdN.css":u}},"error-500.BcOmuN7K.css":{scripts:{},styles:{},preload:{"error-500.BcOmuN7K.css":A},prefetch:{}},"entry.CKteCcdN.css":{scripts:{},styles:{},preload:{"entry.CKteCcdN.css":u},prefetch:{}},"pages/index.vue":{scripts:{},styles:{"entry.CKteCcdN.css":u},preload:{"pages/index.vue":{resourceType:"script",module:true,prefetch:true,preload:true,file:"DfJzPSBi.js",name:"pages",src:"pages/index.vue",isDynamicEntry:true,imports:["_sK9Xse3o.js","../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js","_BDNMzG2s.js"]},"_sK9Xse3o.js":h,"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js":q,"entry.CKteCcdN.css":u,"_DJQqUjJu.js":k,"_BW3xJdEx.js":j,"_CMk5jOCS.js":m,"_BDNMzG2s.js":x},prefetch:{"entry.CKteCcdN.css":u}},"pages/skills/[id].vue":{scripts:{},styles:{"entry.CKteCcdN.css":u},preload:{"pages/skills/[id].vue":{resourceType:"script",module:true,prefetch:true,preload:true,file:"EBA28doP.js",name:"_id_",src:"pages/skills/[id].vue",isDynamicEntry:true,imports:["_sK9Xse3o.js","_DJQqUjJu.js","_CMk5jOCS.js","../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js"]},"_sK9Xse3o.js":h,"_DJQqUjJu.js":k,"_BW3xJdEx.js":j,"_CMk5jOCS.js":m,"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js":q,"entry.CKteCcdN.css":u},prefetch:{"entry.CKteCcdN.css":u}}},entrypoints:["../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js"],modules:{"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-404.vue":{file:"CJmYvhe6.js",resourceType:"script",mimeType:void 0,module:true},"error-404.1qC5mjOI.css":{file:"error-404.1qC5mjOI.css",resourceType:"style",mimeType:void 0,module:void 0},"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/components/error-500.vue":{file:"Bzmuhhqm.js",resourceType:"script",mimeType:void 0,module:true},"error-500.BcOmuN7K.css":{file:"error-500.BcOmuN7K.css",resourceType:"style",mimeType:void 0,module:void 0},"../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_fa55ea51c020cff6ad35d86710859083/node_modules/nuxt/dist/app/entry.js":{file:"rWsrwf2L.js",resourceType:"script",mimeType:void 0,module:true,dynamicImports:o},"entry.CKteCcdN.css":{file:"entry.CKteCcdN.css",resourceType:"style",mimeType:void 0,module:void 0},"_BDNMzG2s.js":{file:"BDNMzG2s.js",resourceType:"script",mimeType:void 0,module:true},"_BW3xJdEx.js":{file:"BW3xJdEx.js",resourceType:"script",mimeType:void 0,module:true},"_CMk5jOCS.js":{file:"CMk5jOCS.js",resourceType:"script",mimeType:void 0,module:true},"_DJQqUjJu.js":{file:"DJQqUjJu.js",resourceType:"script",mimeType:void 0,module:true},"_sK9Xse3o.js":{file:"sK9Xse3o.js",resourceType:"script",mimeType:void 0,module:true},"pages/index.vue":{file:"DfJzPSBi.js",resourceType:"script",mimeType:void 0,module:true},"pages/skills/[id].vue":{file:"EBA28doP.js",resourceType:"script",mimeType:void 0,module:true}}}))();
|
|
2
2
|
|
|
3
3
|
export { client_precomputed as default };
|
package/README.md
CHANGED
|
@@ -42,6 +42,16 @@ Skills outside your home directory (project-level `.claude/skills` inside a repo
|
|
|
42
42
|
- No CORS headers, ever. File reads and saves are contained to the skill's directory; symlinks are never followed for destructive actions.
|
|
43
43
|
- Nothing leaves the machine. There is no network feature.
|
|
44
44
|
|
|
45
|
+
## Security scanners
|
|
46
|
+
|
|
47
|
+
Supply-chain scanners such as Socket.dev raise a few alerts on this package. None of them is shelfware's own code; all come from the prebuilt Nuxt server that ships in `.output/`:
|
|
48
|
+
|
|
49
|
+
- **"Obfuscated code"** in `entities/…/decode-data-html.js`: the HTML entity table of the `entities` library, stored as Base64 and decoded into a `Uint16Array` at load time. Byte-identical to the published `entities` package.
|
|
50
|
+
- **"Dynamic code execution"** in `source-map-js` and the Vue compiler: `new Function` used by a sort routine and by Vue's template compiler. shelfware never compiles templates at runtime (`ssr: false`, no runtime compiler).
|
|
51
|
+
- **"URL strings"**: the Iconify API hosts baked into `@nuxt/icon` (the provider is disabled and every icon is bundled), XML namespaces, documentation links in framework error messages, and file names such as `SKILL.md` that merely contain a dot.
|
|
52
|
+
|
|
53
|
+
The launcher itself uses only Node built-ins, binds `127.0.0.1`, spawns nothing but your browser opener, and has no `preinstall`/`install`/`postinstall` scripts. `pnpm pack:verify` packs and runs the exact tarball through `npx` before every release, refusing to run against a stale build, and releases are published from GitHub Actions with npm provenance.
|
|
54
|
+
|
|
45
55
|
## Credits
|
|
46
56
|
|
|
47
57
|
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.
|
package/bin/launch.d.mts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Types for bin/launch.mjs. Hand-written: keep every export here in step with the .mjs.
|
|
2
|
+
|
|
3
|
+
export const DEFAULT_PORT: 3781
|
|
4
|
+
export const PORT_ATTEMPTS: 20
|
|
5
|
+
export const HOST: '127.0.0.1'
|
|
6
|
+
export const TOKEN_ENV: 'NUXT_PUBLIC_SHELFWARE_TOKEN'
|
|
7
|
+
export const HELP: string
|
|
8
|
+
|
|
9
|
+
export type Env = Record<string, string | undefined>
|
|
10
|
+
|
|
11
|
+
export interface ParsedArgs {
|
|
12
|
+
help: boolean
|
|
13
|
+
port: number | null
|
|
14
|
+
open: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** The subset of child_process.spawn the launcher relies on, so tests can pass a stub. */
|
|
18
|
+
export type SpawnLike = (
|
|
19
|
+
cmd: string,
|
|
20
|
+
args: string[],
|
|
21
|
+
options: { stdio: 'ignore', detached: true, env: Env },
|
|
22
|
+
) => { unref?: () => void, on?: (event: 'error', listener: (err: Error) => unknown) => unknown }
|
|
23
|
+
|
|
24
|
+
export interface LaunchOptions {
|
|
25
|
+
argv?: string[]
|
|
26
|
+
env?: Env
|
|
27
|
+
importServer: () => Promise<unknown>
|
|
28
|
+
log?: (line: string) => void
|
|
29
|
+
exit?: (code: number) => unknown
|
|
30
|
+
entry?: string
|
|
31
|
+
spawn?: SpawnLike
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function makeToken(): string
|
|
35
|
+
export function parseArgs(argv?: string[], env?: Env): ParsedArgs
|
|
36
|
+
export function portReason(code: string): string
|
|
37
|
+
export function checkPort(port: number, host?: string): Promise<string | null>
|
|
38
|
+
export function isPortFree(port: number, host?: string): Promise<boolean>
|
|
39
|
+
export function pickPort(start?: number, options?: { attempts?: number, host?: string }): Promise<number>
|
|
40
|
+
export function probeHealth(port: number, host?: string): Promise<boolean>
|
|
41
|
+
export function waitForHealth(
|
|
42
|
+
port: number,
|
|
43
|
+
options?: {
|
|
44
|
+
timeoutMs?: number
|
|
45
|
+
intervalMs?: number
|
|
46
|
+
host?: string
|
|
47
|
+
probe?: (port: number, host: string) => Promise<boolean>
|
|
48
|
+
signal?: AbortSignal
|
|
49
|
+
},
|
|
50
|
+
): Promise<boolean>
|
|
51
|
+
export function openBrowser(url: string, options?: { platform?: string, spawn?: SpawnLike, env?: Env }): { cmd: string, args: string[] }
|
|
52
|
+
export function serverEntry(binDir?: string): string
|
|
53
|
+
export function describeError(err: unknown): string
|
|
54
|
+
export function launch(options: LaunchOptions): Promise<{ port: number, url: string } | null>
|
package/bin/launch.mjs
CHANGED
|
@@ -11,6 +11,9 @@ export const DEFAULT_PORT = 3781
|
|
|
11
11
|
export const PORT_ATTEMPTS = 20
|
|
12
12
|
export const HOST = '127.0.0.1'
|
|
13
13
|
|
|
14
|
+
/** Spec §10.3: the env var the server reads the session token from. */
|
|
15
|
+
export const TOKEN_ENV = 'NUXT_PUBLIC_SHELFWARE_TOKEN'
|
|
16
|
+
|
|
14
17
|
export const HELP = `shelfware — a local catalog of the AI-agent skills on this machine
|
|
15
18
|
|
|
16
19
|
Usage: shelfware [--port <n>] [--no-open] [--help]
|
|
@@ -28,22 +31,27 @@ export function makeToken() {
|
|
|
28
31
|
|
|
29
32
|
/**
|
|
30
33
|
* The raw text stays in the message so `--port abc` reads back as "abc", not NaN.
|
|
31
|
-
*
|
|
32
|
-
* none of which the help text (`--port <n>`) promises.
|
|
34
|
+
* Decimal digits without a leading zero: `Number()` would otherwise accept `0x10`,
|
|
35
|
+
* `1e3`, `' 4000 '` and `065535`, none of which the help text (`--port <n>`) promises.
|
|
33
36
|
*/
|
|
34
37
|
function parsePort(raw) {
|
|
35
|
-
if (
|
|
38
|
+
if (!/^[1-9]\d*$/.test(raw)) throw new Error(`Invalid port: ${JSON.stringify(raw)}`)
|
|
36
39
|
const port = Number(raw)
|
|
37
|
-
if (port
|
|
40
|
+
if (port > 65535) throw new Error(`Invalid port: ${JSON.stringify(raw)}`)
|
|
38
41
|
return port
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
export function parseArgs(argv = [], env = {}) {
|
|
42
45
|
let port = null
|
|
43
46
|
let open = env.SHELFWARE_NO_OPEN !== '1'
|
|
47
|
+
let optionsEnded = false
|
|
44
48
|
for (let i = 0; i < argv.length; i += 1) {
|
|
45
49
|
const arg = argv[i]
|
|
46
|
-
if (
|
|
50
|
+
if (optionsEnded || !arg.startsWith('-')) {
|
|
51
|
+
throw new Error(`Unexpected argument: ${arg}`)
|
|
52
|
+
} else if (arg === '--') {
|
|
53
|
+
optionsEnded = true
|
|
54
|
+
} else if (arg === '--no-open') {
|
|
47
55
|
open = false
|
|
48
56
|
} else if (arg === '--port') {
|
|
49
57
|
if (i + 1 >= argv.length) throw new Error('--port needs a value')
|
|
@@ -57,19 +65,32 @@ export function parseArgs(argv = [], env = {}) {
|
|
|
57
65
|
throw new Error(`Unknown option: ${arg}`)
|
|
58
66
|
}
|
|
59
67
|
}
|
|
60
|
-
|
|
68
|
+
// Unset or empty means unset; anything else must be a real port.
|
|
69
|
+
if (port === null && env.PORT !== undefined && env.PORT !== '') port = parsePort(env.PORT)
|
|
61
70
|
return { help: false, port, open }
|
|
62
71
|
}
|
|
63
72
|
|
|
64
|
-
|
|
73
|
+
/** Why `port` cannot be bound, in words a user can act on. */
|
|
74
|
+
export function portReason(code) {
|
|
75
|
+
if (code === 'EADDRINUSE') return 'is already in use'
|
|
76
|
+
if (code === 'EACCES') return 'needs elevated privileges (EACCES)'
|
|
77
|
+
return `cannot be bound (${code})`
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Resolves null when `port` can be bound on `host`, otherwise the reason (see `portReason`). */
|
|
81
|
+
export function checkPort(port, host = HOST) {
|
|
65
82
|
return new Promise((resolve) => {
|
|
66
83
|
const server = net.createServer()
|
|
67
84
|
server.unref()
|
|
68
|
-
server.once('error',
|
|
69
|
-
server.listen({ port, host }, () => server.close(() => resolve(
|
|
85
|
+
server.once('error', err => resolve(portReason(err.code ?? 'UNKNOWN')))
|
|
86
|
+
server.listen({ port, host }, () => server.close(() => resolve(null)))
|
|
70
87
|
})
|
|
71
88
|
}
|
|
72
89
|
|
|
90
|
+
export async function isPortFree(port, host = HOST) {
|
|
91
|
+
return (await checkPort(port, host)) === null
|
|
92
|
+
}
|
|
93
|
+
|
|
73
94
|
export async function pickPort(start = DEFAULT_PORT, { attempts = PORT_ATTEMPTS, host = HOST } = {}) {
|
|
74
95
|
for (let port = start; port < start + attempts; port += 1) {
|
|
75
96
|
if (await isPortFree(port, host)) return port
|
|
@@ -132,7 +153,7 @@ export function openBrowser(url, { platform = process.platform, spawn = spawnPro
|
|
|
132
153
|
const args = platform === 'win32' ? ['/c', 'start', '', url] : [url]
|
|
133
154
|
// The opener execs the browser; strip the session token so it never sits in the
|
|
134
155
|
// browser's environment (the served page is the only place it belongs).
|
|
135
|
-
const {
|
|
156
|
+
const { [TOKEN_ENV]: _token, ...childEnv } = env
|
|
136
157
|
// A missing browser opener (e.g. no xdg-open on a headless box) must never take
|
|
137
158
|
// the running server down with it: spawn can throw synchronously (rare) or emit
|
|
138
159
|
// an async 'error' (the common ENOENT case), and an unhandled 'error' on an
|
|
@@ -151,6 +172,11 @@ export function serverEntry(binDir = path.dirname(fileURLToPath(import.meta.url)
|
|
|
151
172
|
return path.resolve(binDir, '..', '.output', 'server', 'index.mjs')
|
|
152
173
|
}
|
|
153
174
|
|
|
175
|
+
/** One line for the user whatever was thrown: Error, string, or nothing at all. */
|
|
176
|
+
export function describeError(err) {
|
|
177
|
+
return err instanceof Error ? err.message : String(err)
|
|
178
|
+
}
|
|
179
|
+
|
|
154
180
|
/**
|
|
155
181
|
* Orchestration with injectable I/O so it can be unit-tested end to end:
|
|
156
182
|
* flags → port → env → import the prebuilt server → wait for health → open.
|
|
@@ -168,7 +194,7 @@ export async function launch({
|
|
|
168
194
|
try {
|
|
169
195
|
args = parseArgs(argv, env)
|
|
170
196
|
} catch (err) {
|
|
171
|
-
log(`shelfware: ${err
|
|
197
|
+
log(`shelfware: ${describeError(err)}`)
|
|
172
198
|
log(HELP)
|
|
173
199
|
exit(1)
|
|
174
200
|
return null
|
|
@@ -182,10 +208,13 @@ export async function launch({
|
|
|
182
208
|
exit(1)
|
|
183
209
|
return null
|
|
184
210
|
}
|
|
185
|
-
if (args.port !== null
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
211
|
+
if (args.port !== null) {
|
|
212
|
+
const problem = await checkPort(args.port)
|
|
213
|
+
if (problem) {
|
|
214
|
+
log(`shelfware: port ${args.port} ${problem} on ${HOST}; pick another (--port or PORT)`)
|
|
215
|
+
exit(1)
|
|
216
|
+
return null
|
|
217
|
+
}
|
|
189
218
|
}
|
|
190
219
|
// Both of these can fail for reasons the user can act on — every port in the
|
|
191
220
|
// range is taken, or the server throws at import (a Nitro crash, or an
|
|
@@ -194,13 +223,13 @@ export async function launch({
|
|
|
194
223
|
let port
|
|
195
224
|
try {
|
|
196
225
|
port = args.port ?? await pickPort(DEFAULT_PORT)
|
|
197
|
-
env
|
|
226
|
+
env[TOKEN_ENV] = makeToken()
|
|
198
227
|
env.NITRO_HOST = HOST
|
|
199
228
|
env.NITRO_PORT = String(port)
|
|
200
229
|
env.NODE_ENV = 'production'
|
|
201
230
|
await importServer()
|
|
202
231
|
} catch (err) {
|
|
203
|
-
log(`shelfware: ${err
|
|
232
|
+
log(`shelfware: ${describeError(err)}`)
|
|
204
233
|
exit(1)
|
|
205
234
|
return null
|
|
206
235
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shelfware",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "shelfware finds the shelfware in your skill drawers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"skills",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dev": "nuxt dev",
|
|
38
38
|
"build": "nuxt build",
|
|
39
39
|
"prepare": "nuxt prepare",
|
|
40
|
-
"typecheck": "nuxt typecheck",
|
|
40
|
+
"typecheck": "nuxt typecheck && tsc -p tsconfig.unit.json",
|
|
41
41
|
"test": "vitest run",
|
|
42
42
|
"test:unit": "vitest run --project unit --passWithNoTests",
|
|
43
43
|
"test:nuxt": "vitest run --project nuxt --passWithNoTests",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"@nuxt/test-utils": "^4.2.0",
|
|
52
52
|
"@nuxt/ui": "^4.11.0",
|
|
53
53
|
"@types/markdown-it": "^14.2.0",
|
|
54
|
+
"@types/node": "^20.19.43",
|
|
54
55
|
"@vue/test-utils": "^2.5.0",
|
|
55
56
|
"@vueuse/core": "^14.4.0",
|
|
56
57
|
"happy-dom": "^20.14.0",
|
|
@@ -63,6 +64,9 @@
|
|
|
63
64
|
"yaml": "^2.9.0"
|
|
64
65
|
},
|
|
65
66
|
"pnpm": {
|
|
66
|
-
"onlyBuiltDependencies": [
|
|
67
|
+
"onlyBuiltDependencies": [
|
|
68
|
+
"esbuild",
|
|
69
|
+
"vue-demi"
|
|
70
|
+
]
|
|
67
71
|
}
|
|
68
72
|
}
|