@opensea/seadn 2.3.9 → 2.3.11
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/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -10
- package/src/boost.ts +10 -10
- package/src/index.ts +4 -4
- package/src/sdk.spec.ts +30 -28
- package/src/sdk.ts +52 -56
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var a=Object.defineProperty;var
|
|
1
|
+
"use strict";var a=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var L=(n,e)=>{for(var r in e)a(n,r,{get:e[r],enumerable:!0})},g=(n,e,r,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of R(e))!U.call(n,t)&&t!==r&&a(n,t,{get:()=>e[t],enumerable:!(i=S(e,t))||i.enumerable});return n};var w=n=>g(a({},"__esModule",{value:!0}),n);var y={};L(y,{optimize:()=>h,originalURL:()=>u});module.exports=w(y);var s=[80,250,500,750,1e3,2e3,4e3];function M(n,e){let r=s.find(t=>t>=n),i=s.find(t=>t>=e);if(i===r){let t=s.indexOf(i);i=s[t+1]}return i||s[s.length-1]}function c(n,e){if(e===void 0||e<=1)return n;let r=Number(n)*e;return M(Number(n),r)}function h(n,{width:e,height:r,format:i,quality:t,fit:p,frameTime:f,boost:m}){try{typeof n=="string"&&(n=new URL(n))}catch(B){return n.toString()}if(!(n instanceof URL))return n;n.host==="raw2.seadn.io"&&(n.host="i2.seadn.io");let l=F(n);if(!(v(n)||l)||d(n)&&f===void 0)return u(n);let o=new URLSearchParams;if(f!==void 0)l&&o.set("frame-time",String(f));else if(d(n))return n.toString();if(r!==void 0&&o.set("h",String(c(r,m))),e!==void 0&&o.set("w",String(c(e,m))),i!==void 0&&o.set("format",i),t){if(Number(t)<=0||Number(t)>100)throw new Error("Quality has to be a positive number between 1 and 100");o.set("q",String(t))}return p!==void 0&&o.set("fit",p),n.search=o.toString(),n.toString()}function d(n){let e=b(n);return e==="mp4"||e==="mov"||e==="webm"||e==="m4v"||e==="ogg"||e==="ogv"}function F(n){return d(n)||b(n)==="gif"}function v(n){if(!x(n))return!1;switch(b(n)){case"jpg":case"png":case"jpeg":case"webp":case"avif":case"ico":case"bmp":case"gif":case"tiff":case"tif":case void 0:return!0;default:return!1}}function b(n){let e=n.pathname.split(".");if(!(e.length<=1))return e[e.length-1]}function x(n){return n.hostname.endsWith("seadn.io")}function u(n){try{typeof n=="string"&&(n=new URL(n))}catch(e){return n.toString()}return x(n)&&(n.hostname=N(n)),n.toString()}function N(n){return n.hostname.replace("i2c","raw2").replace("i2","raw2")}0&&(module.exports={optimize,originalURL});
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/boost.ts","../src/sdk.ts"],"sourcesContent":["export {\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/boost.ts","../src/sdk.ts"],"sourcesContent":["export {\n MediaFit,\n MediaFormat,\n MediaParams,\n optimize,\n originalURL,\n} from \"./sdk\"\n","const DIMENSIONS_BUCKETS = [80, 250, 500, 750, 1000, 2000, 4000]\n\nfunction findNextBucket(originalSize: number, boosted: number): number {\n const originalBucket = DIMENSIONS_BUCKETS.find(\n bucket => bucket >= originalSize,\n )\n let nextBucket = DIMENSIONS_BUCKETS.find(bucket => bucket >= boosted)\n\n if (nextBucket === originalBucket) {\n const currentIndex = DIMENSIONS_BUCKETS.indexOf(nextBucket!)\n nextBucket = DIMENSIONS_BUCKETS[currentIndex + 1]\n }\n\n return nextBucket || DIMENSIONS_BUCKETS[DIMENSIONS_BUCKETS.length - 1]\n}\n\nexport function boostSize(\n size: number | `${number}`,\n boost: number | undefined,\n): number | `${number}` {\n if (boost === undefined || boost <= 1) {\n return size\n }\n const boosted = Number(size) * boost\n return findNextBucket(Number(size), boosted)\n}\n","import { boostSize } from \"./boost\"\n\nexport type MediaFormat = \"webp\" | \"avif\" | \"jpeg\" | \"png\"\nexport type MediaFit = \"cover\" | \"contain\" | \"fill\" | \"inside\" | \"outside\"\n\nexport type MediaParams = {\n width?: number | `${number}`\n height?: number | `${number}`\n format?: MediaFormat\n quality?: number | `${number}`\n fit?: MediaFit\n frameTime?: number\n boost?: number\n}\n\nexport function optimize(\n image: string | URL,\n { width, height, format, quality, fit, frameTime, boost }: MediaParams,\n): string {\n try {\n if (typeof image === \"string\") {\n image = new URL(image)\n }\n } catch {\n return image.toString()\n }\n\n if (!(image instanceof URL)) {\n return image\n }\n\n if (image.host === \"raw2.seadn.io\") {\n image.host = \"i2.seadn.io\"\n }\n\n const isFrameable = canExtractFrame(image)\n if (!(canBeResized(image) || isFrameable)) {\n return originalURL(image)\n }\n\n // for partial content stremaing\n if (isVideo(image) && frameTime === undefined) {\n return originalURL(image)\n }\n\n const params = new URLSearchParams()\n\n if (frameTime !== undefined) {\n if (isFrameable) {\n params.set(\"frame-time\", String(frameTime))\n }\n } else if (isVideo(image)) {\n return image.toString()\n }\n\n if (height !== undefined) {\n params.set(\"h\", String(boostSize(height, boost)))\n }\n if (width !== undefined) {\n params.set(\"w\", String(boostSize(width, boost)))\n }\n if (format !== undefined) {\n params.set(\"format\", format)\n }\n if (quality) {\n if (Number(quality) <= 0 || Number(quality) > 100) {\n throw new Error(\"Quality has to be a positive number between 1 and 100\")\n }\n params.set(\"q\", String(quality))\n }\n if (fit !== undefined) {\n params.set(\"fit\", fit)\n }\n\n image.search = params.toString()\n return image.toString()\n}\n\nfunction isVideo(url: URL): boolean {\n const extension = getExtension(url)\n return (\n extension === \"mp4\" ||\n extension === \"mov\" ||\n extension === \"webm\" ||\n extension === \"m4v\" ||\n extension === \"ogg\" ||\n extension === \"ogv\"\n )\n}\n\nfunction canExtractFrame(url: URL): boolean {\n return isVideo(url) || getExtension(url) === \"gif\"\n}\n\nfunction canBeResized(url: URL): boolean {\n if (!isSeadnURL(url)) {\n return false\n }\n const extension = getExtension(url)\n switch (extension) {\n case \"jpg\":\n case \"png\":\n case \"jpeg\":\n case \"webp\":\n case \"avif\":\n case \"ico\":\n case \"bmp\":\n case \"gif\":\n case \"tiff\":\n case \"tif\":\n case undefined:\n return true\n default:\n return false\n }\n}\n\nfunction getExtension(url: URL): string | undefined {\n const split = url.pathname.split(\".\")\n if (split.length <= 1) {\n return\n }\n return split[split.length - 1]\n}\n\nexport function isSeadnURL(url: URL): boolean {\n return url.hostname.endsWith(\"seadn.io\")\n}\n\nexport function originalURL(image: URL | string): string {\n try {\n if (typeof image === \"string\") {\n image = new URL(image)\n }\n } catch {\n return image.toString()\n }\n\n if (!isSeadnURL(image)) {\n return image.toString()\n }\n\n image.hostname = getOriginalHostname(image)\n return image.toString()\n}\n\nexport function getOriginalHostname(url: URL): string {\n return url.hostname.replace(\"i2c\", \"raw2\").replace(\"i2\", \"raw2\")\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,cAAAE,EAAA,gBAAAC,IAAA,eAAAC,EAAAJ,GCAA,IAAMK,EAAqB,CAAC,GAAI,IAAK,IAAK,IAAK,IAAM,IAAM,GAAI,EAE/D,SAASC,EAAeC,EAAsBC,EAAyB,CACrE,IAAMC,EAAiBJ,EAAmB,KACxCK,GAAUA,GAAUH,CACtB,EACII,EAAaN,EAAmB,KAAKK,GAAUA,GAAUF,CAAO,EAEpE,GAAIG,IAAeF,EAAgB,CACjC,IAAMG,EAAeP,EAAmB,QAAQM,CAAW,EAC3DA,EAAaN,EAAmBO,EAAe,CAAC,CAClD,CAEA,OAAOD,GAAcN,EAAmBA,EAAmB,OAAS,CAAC,CACvE,CAEO,SAASQ,EACdC,EACAC,EACsB,CACtB,GAAIA,IAAU,QAAaA,GAAS,EAClC,OAAOD,EAET,IAAMN,EAAU,OAAOM,CAAI,EAAIC,EAC/B,OAAOT,EAAe,OAAOQ,CAAI,EAAGN,CAAO,CAC7C,CCVO,SAASQ,EACdC,EACA,CAAE,MAAAC,EAAO,OAAAC,EAAQ,OAAAC,EAAQ,QAAAC,EAAS,IAAAC,EAAK,UAAAC,EAAW,MAAAC,CAAM,EAChD,CACR,GAAI,CACE,OAAOP,GAAU,WACnBA,EAAQ,IAAI,IAAIA,CAAK,EAEzB,OAAQQ,EAAA,CACN,OAAOR,EAAM,SAAS,CACxB,CAEA,GAAI,EAAEA,aAAiB,KACrB,OAAOA,EAGLA,EAAM,OAAS,kBACjBA,EAAM,KAAO,eAGf,IAAMS,EAAcC,EAAgBV,CAAK,EAMzC,GALI,EAAEW,EAAaX,CAAK,GAAKS,IAKzBG,EAAQZ,CAAK,GAAKM,IAAc,OAClC,OAAOO,EAAYb,CAAK,EAG1B,IAAMc,EAAS,IAAI,gBAEnB,GAAIR,IAAc,OACZG,GACFK,EAAO,IAAI,aAAc,OAAOR,CAAS,CAAC,UAEnCM,EAAQZ,CAAK,EACtB,OAAOA,EAAM,SAAS,EAYxB,GATIE,IAAW,QACbY,EAAO,IAAI,IAAK,OAAOC,EAAUb,EAAQK,CAAK,CAAC,CAAC,EAE9CN,IAAU,QACZa,EAAO,IAAI,IAAK,OAAOC,EAAUd,EAAOM,CAAK,CAAC,CAAC,EAE7CJ,IAAW,QACbW,EAAO,IAAI,SAAUX,CAAM,EAEzBC,EAAS,CACX,GAAI,OAAOA,CAAO,GAAK,GAAK,OAAOA,CAAO,EAAI,IAC5C,MAAM,IAAI,MAAM,uDAAuD,EAEzEU,EAAO,IAAI,IAAK,OAAOV,CAAO,CAAC,CACjC,CACA,OAAIC,IAAQ,QACVS,EAAO,IAAI,MAAOT,CAAG,EAGvBL,EAAM,OAASc,EAAO,SAAS,EACxBd,EAAM,SAAS,CACxB,CAEA,SAASY,EAAQI,EAAmB,CAClC,IAAMC,EAAYC,EAAaF,CAAG,EAClC,OACEC,IAAc,OACdA,IAAc,OACdA,IAAc,QACdA,IAAc,OACdA,IAAc,OACdA,IAAc,KAElB,CAEA,SAASP,EAAgBM,EAAmB,CAC1C,OAAOJ,EAAQI,CAAG,GAAKE,EAAaF,CAAG,IAAM,KAC/C,CAEA,SAASL,EAAaK,EAAmB,CACvC,GAAI,CAACG,EAAWH,CAAG,EACjB,MAAO,GAGT,OADkBE,EAAaF,CAAG,EACf,CACjB,IAAK,MACL,IAAK,MACL,IAAK,OACL,IAAK,OACL,IAAK,OACL,IAAK,MACL,IAAK,MACL,IAAK,MACL,IAAK,OACL,IAAK,MACL,KAAK,OACH,MAAO,GACT,QACE,MAAO,EACX,CACF,CAEA,SAASE,EAAaF,EAA8B,CAClD,IAAMI,EAAQJ,EAAI,SAAS,MAAM,GAAG,EACpC,GAAI,EAAAI,EAAM,QAAU,GAGpB,OAAOA,EAAMA,EAAM,OAAS,CAAC,CAC/B,CAEO,SAASD,EAAWH,EAAmB,CAC5C,OAAOA,EAAI,SAAS,SAAS,UAAU,CACzC,CAEO,SAASH,EAAYb,EAA6B,CACvD,GAAI,CACE,OAAOA,GAAU,WACnBA,EAAQ,IAAI,IAAIA,CAAK,EAEzB,OAAQ,GACN,OAAOA,EAAM,SAAS,CACxB,CAEA,OAAKmB,EAAWnB,CAAK,IAIrBA,EAAM,SAAWqB,EAAoBrB,CAAK,GACnCA,EAAM,SAAS,CACxB,CAEO,SAASqB,EAAoBL,EAAkB,CACpD,OAAOA,EAAI,SAAS,QAAQ,MAAO,MAAM,EAAE,QAAQ,KAAM,MAAM,CACjE","names":["index_exports","__export","optimize","originalURL","__toCommonJS","DIMENSIONS_BUCKETS","findNextBucket","originalSize","boosted","originalBucket","bucket","nextBucket","currentIndex","boostSize","size","boost","optimize","image","width","height","format","quality","fit","frameTime","boost","e","isFrameable","canExtractFrame","canBeResized","isVideo","originalURL","params","boostSize","url","extension","getExtension","isSeadnURL","split","getOriginalHostname"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var s=[80,250,500,750,1e3,2e3,4e3];function h(n,e){let o=s.find(t=>t>=n),r=s.find(t=>t>=e);if(r===o){let t=s.indexOf(r);r=s[t+1]}return r||s[s.length-1]}function f(n,e){if(e===void 0||e<=1)return n;let o=Number(n)*e;return h(Number(n),o)}function
|
|
1
|
+
var s=[80,250,500,750,1e3,2e3,4e3];function h(n,e){let o=s.find(t=>t>=n),r=s.find(t=>t>=e);if(r===o){let t=s.indexOf(r);r=s[t+1]}return r||s[s.length-1]}function f(n,e){if(e===void 0||e<=1)return n;let o=Number(n)*e;return h(Number(n),o)}function x(n,{width:e,height:o,format:r,quality:t,fit:b,frameTime:u,boost:p}){try{typeof n=="string"&&(n=new URL(n))}catch(L){return n.toString()}if(!(n instanceof URL))return n;n.host==="raw2.seadn.io"&&(n.host="i2.seadn.io");let m=S(n);if(!(R(n)||m)||a(n)&&u===void 0)return c(n);let i=new URLSearchParams;if(u!==void 0)m&&i.set("frame-time",String(u));else if(a(n))return n.toString();if(o!==void 0&&i.set("h",String(f(o,p))),e!==void 0&&i.set("w",String(f(e,p))),r!==void 0&&i.set("format",r),t){if(Number(t)<=0||Number(t)>100)throw new Error("Quality has to be a positive number between 1 and 100");i.set("q",String(t))}return b!==void 0&&i.set("fit",b),n.search=i.toString(),n.toString()}function a(n){let e=d(n);return e==="mp4"||e==="mov"||e==="webm"||e==="m4v"||e==="ogg"||e==="ogv"}function S(n){return a(n)||d(n)==="gif"}function R(n){if(!l(n))return!1;switch(d(n)){case"jpg":case"png":case"jpeg":case"webp":case"avif":case"ico":case"bmp":case"gif":case"tiff":case"tif":case void 0:return!0;default:return!1}}function d(n){let e=n.pathname.split(".");if(!(e.length<=1))return e[e.length-1]}function l(n){return n.hostname.endsWith("seadn.io")}function c(n){try{typeof n=="string"&&(n=new URL(n))}catch(e){return n.toString()}return l(n)&&(n.hostname=U(n)),n.toString()}function U(n){return n.hostname.replace("i2c","raw2").replace("i2","raw2")}export{x as optimize,c as originalURL};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/boost.ts","../src/sdk.ts"],"sourcesContent":["const DIMENSIONS_BUCKETS = [80, 250, 500, 750, 1000, 2000, 4000]
|
|
1
|
+
{"version":3,"sources":["../src/boost.ts","../src/sdk.ts"],"sourcesContent":["const DIMENSIONS_BUCKETS = [80, 250, 500, 750, 1000, 2000, 4000]\n\nfunction findNextBucket(originalSize: number, boosted: number): number {\n const originalBucket = DIMENSIONS_BUCKETS.find(\n bucket => bucket >= originalSize,\n )\n let nextBucket = DIMENSIONS_BUCKETS.find(bucket => bucket >= boosted)\n\n if (nextBucket === originalBucket) {\n const currentIndex = DIMENSIONS_BUCKETS.indexOf(nextBucket!)\n nextBucket = DIMENSIONS_BUCKETS[currentIndex + 1]\n }\n\n return nextBucket || DIMENSIONS_BUCKETS[DIMENSIONS_BUCKETS.length - 1]\n}\n\nexport function boostSize(\n size: number | `${number}`,\n boost: number | undefined,\n): number | `${number}` {\n if (boost === undefined || boost <= 1) {\n return size\n }\n const boosted = Number(size) * boost\n return findNextBucket(Number(size), boosted)\n}\n","import { boostSize } from \"./boost\"\n\nexport type MediaFormat = \"webp\" | \"avif\" | \"jpeg\" | \"png\"\nexport type MediaFit = \"cover\" | \"contain\" | \"fill\" | \"inside\" | \"outside\"\n\nexport type MediaParams = {\n width?: number | `${number}`\n height?: number | `${number}`\n format?: MediaFormat\n quality?: number | `${number}`\n fit?: MediaFit\n frameTime?: number\n boost?: number\n}\n\nexport function optimize(\n image: string | URL,\n { width, height, format, quality, fit, frameTime, boost }: MediaParams,\n): string {\n try {\n if (typeof image === \"string\") {\n image = new URL(image)\n }\n } catch {\n return image.toString()\n }\n\n if (!(image instanceof URL)) {\n return image\n }\n\n if (image.host === \"raw2.seadn.io\") {\n image.host = \"i2.seadn.io\"\n }\n\n const isFrameable = canExtractFrame(image)\n if (!(canBeResized(image) || isFrameable)) {\n return originalURL(image)\n }\n\n // for partial content stremaing\n if (isVideo(image) && frameTime === undefined) {\n return originalURL(image)\n }\n\n const params = new URLSearchParams()\n\n if (frameTime !== undefined) {\n if (isFrameable) {\n params.set(\"frame-time\", String(frameTime))\n }\n } else if (isVideo(image)) {\n return image.toString()\n }\n\n if (height !== undefined) {\n params.set(\"h\", String(boostSize(height, boost)))\n }\n if (width !== undefined) {\n params.set(\"w\", String(boostSize(width, boost)))\n }\n if (format !== undefined) {\n params.set(\"format\", format)\n }\n if (quality) {\n if (Number(quality) <= 0 || Number(quality) > 100) {\n throw new Error(\"Quality has to be a positive number between 1 and 100\")\n }\n params.set(\"q\", String(quality))\n }\n if (fit !== undefined) {\n params.set(\"fit\", fit)\n }\n\n image.search = params.toString()\n return image.toString()\n}\n\nfunction isVideo(url: URL): boolean {\n const extension = getExtension(url)\n return (\n extension === \"mp4\" ||\n extension === \"mov\" ||\n extension === \"webm\" ||\n extension === \"m4v\" ||\n extension === \"ogg\" ||\n extension === \"ogv\"\n )\n}\n\nfunction canExtractFrame(url: URL): boolean {\n return isVideo(url) || getExtension(url) === \"gif\"\n}\n\nfunction canBeResized(url: URL): boolean {\n if (!isSeadnURL(url)) {\n return false\n }\n const extension = getExtension(url)\n switch (extension) {\n case \"jpg\":\n case \"png\":\n case \"jpeg\":\n case \"webp\":\n case \"avif\":\n case \"ico\":\n case \"bmp\":\n case \"gif\":\n case \"tiff\":\n case \"tif\":\n case undefined:\n return true\n default:\n return false\n }\n}\n\nfunction getExtension(url: URL): string | undefined {\n const split = url.pathname.split(\".\")\n if (split.length <= 1) {\n return\n }\n return split[split.length - 1]\n}\n\nexport function isSeadnURL(url: URL): boolean {\n return url.hostname.endsWith(\"seadn.io\")\n}\n\nexport function originalURL(image: URL | string): string {\n try {\n if (typeof image === \"string\") {\n image = new URL(image)\n }\n } catch {\n return image.toString()\n }\n\n if (!isSeadnURL(image)) {\n return image.toString()\n }\n\n image.hostname = getOriginalHostname(image)\n return image.toString()\n}\n\nexport function getOriginalHostname(url: URL): string {\n return url.hostname.replace(\"i2c\", \"raw2\").replace(\"i2\", \"raw2\")\n}\n"],"mappings":"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","names":["DIMENSIONS_BUCKETS","findNextBucket","originalSize","boosted","originalBucket","bucket","nextBucket","currentIndex","boostSize","size","boost","optimize","image","width","height","format","quality","fit","frameTime","boost","e","isFrameable","canExtractFrame","canBeResized","isVideo","originalURL","params","boostSize","url","extension","getExtension","isSeadnURL","split","getOriginalHostname"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensea/seadn",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.11",
|
|
4
4
|
"description": "Javascript SDK to work with SeaDN",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "OpenSea Developers",
|
|
@@ -8,20 +8,17 @@
|
|
|
8
8
|
"main": "./src/index.ts",
|
|
9
9
|
"module": "./dist/index.mjs",
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
|
-
"files": [
|
|
12
|
-
"./dist",
|
|
13
|
-
"./src"
|
|
14
|
-
],
|
|
11
|
+
"files": ["./dist", "./src"],
|
|
15
12
|
"scripts": {
|
|
16
13
|
"build": "tsup",
|
|
17
14
|
"build:typecheck": "attw --pack",
|
|
18
15
|
"test": "vitest",
|
|
19
|
-
"
|
|
16
|
+
"type-check": "tsc"
|
|
20
17
|
},
|
|
21
18
|
"devDependencies": {
|
|
22
|
-
"@arethetypeswrong/cli": "0.
|
|
23
|
-
"tsup": "8.
|
|
24
|
-
"typescript": "5.
|
|
25
|
-
"vitest": "
|
|
19
|
+
"@arethetypeswrong/cli": "0.18.2",
|
|
20
|
+
"tsup": "8.5.1",
|
|
21
|
+
"typescript": "5.9.2",
|
|
22
|
+
"vitest": "3.2.4"
|
|
26
23
|
}
|
|
27
24
|
}
|
package/src/boost.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const DIMENSIONS_BUCKETS = [80, 250, 500, 750, 1000, 2000, 4000]
|
|
1
|
+
const DIMENSIONS_BUCKETS = [80, 250, 500, 750, 1000, 2000, 4000]
|
|
2
2
|
|
|
3
3
|
function findNextBucket(originalSize: number, boosted: number): number {
|
|
4
|
-
|
|
4
|
+
const originalBucket = DIMENSIONS_BUCKETS.find(
|
|
5
5
|
bucket => bucket >= originalSize,
|
|
6
|
-
)
|
|
7
|
-
let nextBucket = DIMENSIONS_BUCKETS.find(bucket => bucket >= boosted)
|
|
6
|
+
)
|
|
7
|
+
let nextBucket = DIMENSIONS_BUCKETS.find(bucket => bucket >= boosted)
|
|
8
8
|
|
|
9
9
|
if (nextBucket === originalBucket) {
|
|
10
|
-
const currentIndex = DIMENSIONS_BUCKETS.indexOf(nextBucket!)
|
|
11
|
-
nextBucket = DIMENSIONS_BUCKETS[currentIndex + 1]
|
|
10
|
+
const currentIndex = DIMENSIONS_BUCKETS.indexOf(nextBucket!)
|
|
11
|
+
nextBucket = DIMENSIONS_BUCKETS[currentIndex + 1]
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
return nextBucket || DIMENSIONS_BUCKETS[DIMENSIONS_BUCKETS.length - 1]
|
|
14
|
+
return nextBucket || DIMENSIONS_BUCKETS[DIMENSIONS_BUCKETS.length - 1]
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function boostSize(
|
|
@@ -19,8 +19,8 @@ export function boostSize(
|
|
|
19
19
|
boost: number | undefined,
|
|
20
20
|
): number | `${number}` {
|
|
21
21
|
if (boost === undefined || boost <= 1) {
|
|
22
|
-
return size
|
|
22
|
+
return size
|
|
23
23
|
}
|
|
24
|
-
const boosted = Number(size) * boost
|
|
25
|
-
return findNextBucket(Number(size), boosted)
|
|
24
|
+
const boosted = Number(size) * boost
|
|
25
|
+
return findNextBucket(Number(size), boosted)
|
|
26
26
|
}
|
package/src/index.ts
CHANGED
package/src/sdk.spec.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { expect, test } from "vitest"
|
|
2
|
+
import { isSeadnURL, type MediaParams, optimize, originalURL } from "./sdk"
|
|
3
3
|
|
|
4
4
|
test.each([
|
|
5
5
|
[undefined, {} satisfies MediaParams, undefined],
|
|
6
|
+
[null, {} satisfies MediaParams, null],
|
|
6
7
|
["", {} satisfies MediaParams, ""],
|
|
7
8
|
["random", {} satisfies MediaParams, "random"],
|
|
8
9
|
[[], {} satisfies MediaParams, []],
|
|
9
10
|
[{}, {} satisfies MediaParams, {}],
|
|
11
|
+
[
|
|
12
|
+
"https://random.io/image.png",
|
|
13
|
+
{ width: 24, height: 24, frameTime: 1 } satisfies MediaParams,
|
|
14
|
+
"https://random.io/image.png",
|
|
15
|
+
],
|
|
10
16
|
[
|
|
11
17
|
"https://i2.seadn.io/bored-ape.png",
|
|
12
18
|
{} satisfies MediaParams,
|
|
@@ -149,30 +155,32 @@ test.each([
|
|
|
149
155
|
"https://i2.seadn.io/bored-ape.png?h=4000&w=4000",
|
|
150
156
|
],
|
|
151
157
|
[
|
|
152
|
-
"https://
|
|
153
|
-
{ width:
|
|
154
|
-
"https://
|
|
158
|
+
"https://raw2.seadn.io/bored-ape.png",
|
|
159
|
+
{ width: 24, height: 24 } satisfies MediaParams,
|
|
160
|
+
"https://i2.seadn.io/bored-ape.png?h=24&w=24",
|
|
155
161
|
],
|
|
156
|
-
])("optimize(%o, %o) -> %o", (url, resizeParams, expected) => {
|
|
157
|
-
expect(optimize(url as string, resizeParams)).toEqual(expected);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test.each([
|
|
161
162
|
[
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
true,
|
|
163
|
+
"https://raw2.seadn.io/bored-ape.mp4",
|
|
164
|
+
{ width: 24, height: 24 } satisfies MediaParams,
|
|
165
|
+
"https://raw2.seadn.io/bored-ape.mp4",
|
|
166
166
|
],
|
|
167
167
|
[
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
true,
|
|
168
|
+
"https://raw2.seadn.io/bored-ape.mp4",
|
|
169
|
+
{ width: 24, height: 24, frameTime: 1 } satisfies MediaParams,
|
|
170
|
+
"https://i2.seadn.io/bored-ape.mp4?frame-time=1&h=24&w=24",
|
|
172
171
|
],
|
|
172
|
+
])("optimize(%o, %o) -> %o", (url, resizeParams, expected) => {
|
|
173
|
+
expect(optimize(url as string, resizeParams)).toEqual(expected)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
test.each([
|
|
177
|
+
[new URL("https://raw2.seadn.io"), true],
|
|
178
|
+
[new URL("https://i2.seadn.io"), true],
|
|
179
|
+
[new URL("https://i2c.seadn.io"), true],
|
|
180
|
+
[new URL("https://random.io"), false],
|
|
173
181
|
])("isSeadnURL(%s) -> %o", (url, expected) => {
|
|
174
|
-
expect(isSeadnURL(url)).toEqual(expected)
|
|
175
|
-
})
|
|
182
|
+
expect(isSeadnURL(url)).toEqual(expected)
|
|
183
|
+
})
|
|
176
184
|
|
|
177
185
|
test.each([
|
|
178
186
|
["https://i2.seadn.io/bored-ape.gif", "https://raw2.seadn.io/bored-ape.gif"],
|
|
@@ -181,12 +189,6 @@ test.each([
|
|
|
181
189
|
new URL("https://i2.seadn.io/bored-ape.gif"),
|
|
182
190
|
"https://raw2.seadn.io/bored-ape.gif",
|
|
183
191
|
],
|
|
184
|
-
[
|
|
185
|
-
new URL(
|
|
186
|
-
"https://i.seadn.io/s/raw/files/ac1a6cc163abcee90299a15d2ebbe746.html",
|
|
187
|
-
),
|
|
188
|
-
"https://raw.seadn.io/files/ac1a6cc163abcee90299a15d2ebbe746.html",
|
|
189
|
-
],
|
|
190
192
|
])("originalURL(%s) -> %o", (url, expected) => {
|
|
191
|
-
expect(originalURL(url)).toEqual(expected)
|
|
192
|
-
})
|
|
193
|
+
expect(originalURL(url)).toEqual(expected)
|
|
194
|
+
})
|
package/src/sdk.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { boostSize } from "./boost"
|
|
1
|
+
import { boostSize } from "./boost"
|
|
2
2
|
|
|
3
|
-
export type MediaFormat = "webp" | "avif" | "jpeg" | "png"
|
|
4
|
-
export type MediaFit = "cover" | "contain" | "fill" | "inside" | "outside"
|
|
3
|
+
export type MediaFormat = "webp" | "avif" | "jpeg" | "png"
|
|
4
|
+
export type MediaFit = "cover" | "contain" | "fill" | "inside" | "outside"
|
|
5
5
|
|
|
6
6
|
export type MediaParams = {
|
|
7
|
-
width?: number | `${number}
|
|
8
|
-
height?: number | `${number}
|
|
9
|
-
format?: MediaFormat
|
|
10
|
-
quality?: number | `${number}
|
|
11
|
-
fit?: MediaFit
|
|
12
|
-
frameTime?: number
|
|
13
|
-
boost?: number
|
|
14
|
-
}
|
|
7
|
+
width?: number | `${number}`
|
|
8
|
+
height?: number | `${number}`
|
|
9
|
+
format?: MediaFormat
|
|
10
|
+
quality?: number | `${number}`
|
|
11
|
+
fit?: MediaFit
|
|
12
|
+
frameTime?: number
|
|
13
|
+
boost?: number
|
|
14
|
+
}
|
|
15
15
|
|
|
16
16
|
export function optimize(
|
|
17
17
|
image: string | URL,
|
|
@@ -19,61 +19,65 @@ export function optimize(
|
|
|
19
19
|
): string {
|
|
20
20
|
try {
|
|
21
21
|
if (typeof image === "string") {
|
|
22
|
-
image = new URL(image)
|
|
22
|
+
image = new URL(image)
|
|
23
23
|
}
|
|
24
24
|
} catch {
|
|
25
|
-
return image.toString()
|
|
25
|
+
return image.toString()
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
if (!(image instanceof URL)) {
|
|
29
|
-
return image
|
|
29
|
+
return image
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (image.host === "raw2.seadn.io") {
|
|
33
|
+
image.host = "i2.seadn.io"
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
const isFrameable = canExtractFrame(image)
|
|
33
|
-
if (!canBeResized(image)
|
|
34
|
-
return originalURL(image)
|
|
36
|
+
const isFrameable = canExtractFrame(image)
|
|
37
|
+
if (!(canBeResized(image) || isFrameable)) {
|
|
38
|
+
return originalURL(image)
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
// for partial content stremaing
|
|
38
42
|
if (isVideo(image) && frameTime === undefined) {
|
|
39
|
-
return originalURL(image)
|
|
43
|
+
return originalURL(image)
|
|
40
44
|
}
|
|
41
45
|
|
|
42
|
-
const params = new URLSearchParams()
|
|
46
|
+
const params = new URLSearchParams()
|
|
43
47
|
|
|
44
48
|
if (frameTime !== undefined) {
|
|
45
49
|
if (isFrameable) {
|
|
46
|
-
params.set("frame-time", String(frameTime))
|
|
50
|
+
params.set("frame-time", String(frameTime))
|
|
47
51
|
}
|
|
48
52
|
} else if (isVideo(image)) {
|
|
49
|
-
return image.toString()
|
|
53
|
+
return image.toString()
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
if (height !== undefined) {
|
|
53
|
-
params.set("h", String(boostSize(height, boost)))
|
|
57
|
+
params.set("h", String(boostSize(height, boost)))
|
|
54
58
|
}
|
|
55
59
|
if (width !== undefined) {
|
|
56
|
-
params.set("w", String(boostSize(width, boost)))
|
|
60
|
+
params.set("w", String(boostSize(width, boost)))
|
|
57
61
|
}
|
|
58
62
|
if (format !== undefined) {
|
|
59
|
-
params.set("format", format)
|
|
63
|
+
params.set("format", format)
|
|
60
64
|
}
|
|
61
65
|
if (quality) {
|
|
62
66
|
if (Number(quality) <= 0 || Number(quality) > 100) {
|
|
63
|
-
throw new Error("Quality has to be a positive number between 1 and 100")
|
|
67
|
+
throw new Error("Quality has to be a positive number between 1 and 100")
|
|
64
68
|
}
|
|
65
|
-
params.set("q", String(quality))
|
|
69
|
+
params.set("q", String(quality))
|
|
66
70
|
}
|
|
67
71
|
if (fit !== undefined) {
|
|
68
|
-
params.set("fit", fit)
|
|
72
|
+
params.set("fit", fit)
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
image.search = params.toString()
|
|
72
|
-
return image.toString()
|
|
75
|
+
image.search = params.toString()
|
|
76
|
+
return image.toString()
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
function isVideo(url: URL): boolean {
|
|
76
|
-
const extension = getExtension(url)
|
|
80
|
+
const extension = getExtension(url)
|
|
77
81
|
return (
|
|
78
82
|
extension === "mp4" ||
|
|
79
83
|
extension === "mov" ||
|
|
@@ -81,18 +85,18 @@ function isVideo(url: URL): boolean {
|
|
|
81
85
|
extension === "m4v" ||
|
|
82
86
|
extension === "ogg" ||
|
|
83
87
|
extension === "ogv"
|
|
84
|
-
)
|
|
88
|
+
)
|
|
85
89
|
}
|
|
86
90
|
|
|
87
91
|
function canExtractFrame(url: URL): boolean {
|
|
88
|
-
return isVideo(url) || getExtension(url) === "gif"
|
|
92
|
+
return isVideo(url) || getExtension(url) === "gif"
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
function canBeResized(url: URL): boolean {
|
|
92
96
|
if (!isSeadnURL(url)) {
|
|
93
|
-
return false
|
|
97
|
+
return false
|
|
94
98
|
}
|
|
95
|
-
const extension = getExtension(url)
|
|
99
|
+
const extension = getExtension(url)
|
|
96
100
|
switch (extension) {
|
|
97
101
|
case "jpg":
|
|
98
102
|
case "png":
|
|
@@ -102,52 +106,44 @@ function canBeResized(url: URL): boolean {
|
|
|
102
106
|
case "ico":
|
|
103
107
|
case "bmp":
|
|
104
108
|
case "gif":
|
|
109
|
+
case "tiff":
|
|
110
|
+
case "tif":
|
|
105
111
|
case undefined:
|
|
106
|
-
return true
|
|
112
|
+
return true
|
|
107
113
|
default:
|
|
108
|
-
return false
|
|
114
|
+
return false
|
|
109
115
|
}
|
|
110
116
|
}
|
|
111
117
|
|
|
112
118
|
function getExtension(url: URL): string | undefined {
|
|
113
|
-
const split = url.pathname.split(".")
|
|
119
|
+
const split = url.pathname.split(".")
|
|
114
120
|
if (split.length <= 1) {
|
|
115
|
-
return
|
|
121
|
+
return
|
|
116
122
|
}
|
|
117
|
-
return split[split.length - 1]
|
|
123
|
+
return split[split.length - 1]
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
export function isSeadnURL(url: URL): boolean {
|
|
121
|
-
return url.hostname.endsWith("seadn.io")
|
|
127
|
+
return url.hostname.endsWith("seadn.io")
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
export function originalURL(image: URL | string): string {
|
|
125
131
|
try {
|
|
126
132
|
if (typeof image === "string") {
|
|
127
|
-
image = new URL(image)
|
|
133
|
+
image = new URL(image)
|
|
128
134
|
}
|
|
129
135
|
} catch {
|
|
130
|
-
return image.toString()
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (isSeadnV1URL(image)) {
|
|
134
|
-
image.hostname = image.hostname.replace("i.seadn.io", "raw.seadn.io");
|
|
135
|
-
image.pathname = image.pathname.replace("/s/raw/files/", "/files/");
|
|
136
|
-
return image.toString();
|
|
136
|
+
return image.toString()
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
if (!isSeadnURL(image)) {
|
|
140
|
-
return image.toString()
|
|
140
|
+
return image.toString()
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
image.hostname = getOriginalHostname(image)
|
|
144
|
-
return image.toString()
|
|
143
|
+
image.hostname = getOriginalHostname(image)
|
|
144
|
+
return image.toString()
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
export function getOriginalHostname(url: URL): string {
|
|
148
|
-
return url.hostname.replace("i2c", "raw2").replace("i2", "raw2")
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export function isSeadnV1URL(url: URL): boolean {
|
|
152
|
-
return url.hostname === "i.seadn.io" || url.hostname === "raw.seadn.io";
|
|
148
|
+
return url.hostname.replace("i2c", "raw2").replace("i2", "raw2")
|
|
153
149
|
}
|