@knapsack/utils 5.0.0--canary.6593.4738696.0 → 5.0.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 (65) hide show
  1. package/.lintstagedrc.mjs +2 -2
  2. package/CHANGELOG.md +151 -0
  3. package/dist/.tsbuildinfo-es +1 -1
  4. package/dist/arrays.d.ts.map +1 -1
  5. package/dist/arrays.js.map +1 -1
  6. package/dist/arrays.mjs.map +1 -1
  7. package/dist/dates.js.map +1 -1
  8. package/dist/dates.mjs +1 -1
  9. package/dist/dates.mjs.map +1 -1
  10. package/dist/fetcher.js.map +1 -1
  11. package/dist/fetcher.mjs.map +1 -1
  12. package/dist/functions.d.ts +15 -1
  13. package/dist/functions.d.ts.map +1 -1
  14. package/dist/functions.js +1 -1
  15. package/dist/functions.js.map +1 -1
  16. package/dist/functions.mjs +1 -1
  17. package/dist/functions.mjs.map +1 -1
  18. package/dist/ids.d.ts +1 -0
  19. package/dist/ids.d.ts.map +1 -1
  20. package/dist/ids.js +1 -1
  21. package/dist/ids.js.map +1 -1
  22. package/dist/ids.mjs +1 -1
  23. package/dist/ids.mjs.map +1 -1
  24. package/dist/immer.d.ts +1 -1
  25. package/dist/immer.d.ts.map +1 -1
  26. package/dist/immer.js +1 -1
  27. package/dist/immer.js.map +1 -1
  28. package/dist/immer.mjs +1 -1
  29. package/dist/immer.mjs.map +1 -1
  30. package/dist/index.js +2 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/index.mjs +2 -2
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/is-types.js.map +1 -1
  35. package/dist/is-types.mjs.map +1 -1
  36. package/dist/js-env.js.map +1 -1
  37. package/dist/js-env.mjs.map +1 -1
  38. package/dist/loose-equal.js.map +1 -1
  39. package/dist/loose-equal.mjs.map +1 -1
  40. package/dist/misc.js.map +1 -1
  41. package/dist/misc.mjs.map +1 -1
  42. package/dist/objects.d.ts.map +1 -1
  43. package/dist/objects.js +1 -1
  44. package/dist/objects.js.map +1 -1
  45. package/dist/objects.mjs +1 -1
  46. package/dist/objects.mjs.map +1 -1
  47. package/dist/paths.js.map +1 -1
  48. package/dist/paths.mjs.map +1 -1
  49. package/dist/strings.js.map +1 -1
  50. package/dist/strings.mjs.map +1 -1
  51. package/dist/type-tools.d.ts.map +1 -1
  52. package/dist/type-tools.js.map +1 -1
  53. package/dist/type-tools.mjs.map +1 -1
  54. package/dist/urls.d.ts +12 -0
  55. package/dist/urls.d.ts.map +1 -1
  56. package/dist/urls.js +2 -2
  57. package/dist/urls.js.map +1 -1
  58. package/dist/urls.mjs +2 -2
  59. package/dist/urls.mjs.map +1 -1
  60. package/dist/validation.js.map +1 -1
  61. package/dist/validation.mjs.map +1 -1
  62. package/package.json +15 -17
  63. package/vitest.config.ts +7 -0
  64. package/.eslintrc.js +0 -4
  65. package/ava.config.cjs +0 -3
package/dist/urls.js CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var g=require('slugify');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var g__default=/*#__PURE__*/_interopDefault(g);var o=Object.defineProperty;var s=(t,r)=>o(t,"name",{value:r,configurable:true});function c({params:t,urlSearchParams:r}){return Object.entries(t??{}).forEach(([n,e])=>{if(e!=null)if(e instanceof URL)r.set(n,e.toString());else if(Array.isArray(e))r.set(n,e.join(" "));else {let i=`${e}`;if(i==="")return;r.set(n,i);}}),r}s(c,"addQueryParams");function l({url:t,origin:r,queryParams:n}){if(!r&&typeof t=="string"&&!t.startsWith("http"))throw new Error('When using "createUrl" either pass in a full "url" or provide an "origin"');let e=typeof t=="string"?new URL(t,r):r?new URL(t.toString(),r):t;return c({params:n,urlSearchParams:e.searchParams}),e}s(l,"createUrlWithParams");function m({a:t,b:r}){return new URL(t).toString()===new URL(r).toString()}s(m,"areUrlsSame");function f(t){if(typeof t!="string")return false;try{let r=new URL(t);return r.protocol.startsWith("http:")||r.protocol.startsWith("https:")}catch{return t.startsWith("//")}}s(f,"isRemoteUrl");var p=s(t=>t.startsWith("data:"),"isDataUrl"),h=s(t=>{let{string:r,strict:n=true,lowerCase:e=true}=typeof t=="string"?{string:t}:t;return g__default.default(r,{lower:e,trim:true,strict:n})},"slugify"),w=s(t=>{let r=/^\/([^/]+)\/([^/]+)/,n=t.match(r);if(!n)return null;let[e,i,a]=n;return [i,a]},"extractPathParts");function P({fileId:t,nodeId:r,version:n}){if(!t||t.trim().length===0)throw new Error(`Invalid Figma URL, missing file id: ${t}`);let e=new URL(`https://www.figma.com/file/${t}`);return r&&e.searchParams.set("node-id",r),n&&e.searchParams.set("version-id",n.toString()),e.toString()}s(P,"createFigmaUrl");function U(t){let r=new URL(t);if(r.hostname!=="www.figma.com"&&r.hostname!=="figma.com"||!f(t))throw new Error(`Please provide a valid Figma URL, got ${t}`);let n=r.searchParams.get("node-id")||void 0,e=r.searchParams.get("version-id")||void 0,[,i,a]=r.pathname.split("/");switch(i){case "proto":case "file":case "board":case "design":{if(!a)throw new Error(`Invalid Figma URL, missing file id: ${t}`);return {type:i,fileId:a,nodeId:n,version:e}}default:throw new Error(`Please provide a valid Figma URL, got ${t}`)}}s(U,"parseFigmaUrl");function y(t){return new URLSearchParams(Object.fromEntries(Object.entries(t).filter(([,r])=>typeof r=="string"?r.length>0:r!=null).map(([r,n])=>[r,`${n}`]))).toString()}s(y,"createQueryParams");
2
- exports.addQueryParams=c;exports.areUrlsSame=m;exports.createFigmaUrl=P;exports.createQueryParams=y;exports.createUrlWithParams=l;exports.extractPathParts=w;exports.isDataUrl=p;exports.isRemoteUrl=f;exports.parseFigmaUrl=U;exports.slugify=h;//# sourceMappingURL=urls.js.map
1
+ 'use strict';var c=require('slugify');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var c__default=/*#__PURE__*/_interopDefault(c);var g=Object.defineProperty;var s=(t,r)=>g(t,"name",{value:r,configurable:true});function u({params:t,urlSearchParams:r}){return Object.entries(t??{}).forEach(([e,n])=>{if(n!=null)if(n instanceof URL)r.set(e,n.toString());else if(Array.isArray(n))r.set(e,n.join(" "));else {let i=`${n}`;if(i==="")return;r.set(e,i);}}),r}s(u,"addQueryParams");function p({url:t,origin:r,queryParams:e}){if(!r&&typeof t=="string"&&!t.startsWith("http"))throw new Error('When using "createUrl" either pass in a full "url" or provide an "origin"');let n=typeof t=="string"?new URL(t,r):r?new URL(t.toString(),r):t;return u({params:e,urlSearchParams:n.searchParams}),n}s(p,"createUrlWithParams");function m({a:t,b:r}){return new URL(t).toString()===new URL(r).toString()}s(m,"areUrlsSame");function f(t){if(typeof t!="string")return false;try{let r=new URL(t);return r.protocol.startsWith("http:")||r.protocol.startsWith("https:")}catch{return t.startsWith("//")}}s(f,"isRemoteUrl");var h=s(t=>t.startsWith("data:"),"isDataUrl"),o=s(t=>{let{string:r,strict:e=true,lowerCase:n=true}=typeof t=="string"?{string:t}:t;return c__default.default(r,{lower:n,trim:true,strict:e})},"slugify"),w=s(t=>{let r=/^\/([^/]+)\/([^/]+)/,e=t.match(r);if(!e)return null;let[n,i,a]=e;return [i,a]},"extractPathParts");function P({fileId:t,nodeId:r,version:e}){if(!t||t.trim().length===0)throw new Error(`Invalid Figma URL, missing file id: ${t}`);let n=new URL(`https://www.figma.com/file/${t}`);return r&&n.searchParams.set("node-id",r),e&&n.searchParams.set("version-id",e.toString()),n.toString()}s(P,"createFigmaUrl");function U(t){let r=new URL(t);if(r.hostname!=="www.figma.com"&&r.hostname!=="figma.com"||!f(t))throw new Error(`Please provide a valid Figma URL, got ${t}`);let e=r.searchParams.get("node-id")||void 0,n=r.searchParams.get("version-id")||void 0,[,i,a]=r.pathname.split("/");switch(i){case "proto":case "file":case "board":case "design":{if(!a)throw new Error(`Invalid Figma URL, missing file id: ${t}`);return {type:i,fileId:a,nodeId:e,version:n}}default:throw new Error(`Please provide a valid Figma URL, got ${t}`)}}s(U,"parseFigmaUrl");function x(t){return new URLSearchParams(Object.fromEntries(Object.entries(t).filter(([,r])=>typeof r=="string"?r.length>0:r!=null).map(([r,e])=>[r,`${e}`]))).toString()}s(x,"createQueryParams");function b({filename:t}){let r=o([...t.split(".")].pop()||""),e=o(r?t.substring(0,t.lastIndexOf(".")):t);if(!e)throw new Error(`Invalid filename: ${t}`);return r?`${e}.${r}`:e}s(b,"createSafeFilename");
2
+ exports.addQueryParams=u;exports.areUrlsSame=m;exports.createFigmaUrl=P;exports.createQueryParams=x;exports.createSafeFilename=b;exports.createUrlWithParams=p;exports.extractPathParts=w;exports.isDataUrl=h;exports.isRemoteUrl=f;exports.parseFigmaUrl=U;exports.slugify=o;//# sourceMappingURL=urls.js.map
3
3
  //# sourceMappingURL=urls.js.map
package/dist/urls.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/urls.ts"],"names":["addQueryParams","params","urlSearchParams","key","value","v","__name","createUrlWithParams","url","origin","queryParams","u","areUrlsSame","a","b","isRemoteUrl","pathUrl","isDataUrl","dataString","slugify","opt","string","strict","lowerCase","slugifyBase","extractPathParts","path","regex","match","_","entityType","entityId","createFigmaUrl","fileId","nodeId","version","parseFigmaUrl","figmaUrl","type","createQueryParams","k"],"mappings":"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","file":"urls.js","sourcesContent":["import slugifyBase from 'slugify';\n\nexport type QueryParamsInput = Record<\n string,\n string | number | boolean | undefined | null | string[] | URL\n>;\n\n/**\n * Util to add query params in a type safe way\n * URL's will be stringified\n * `booleans` & `numbers` will be stringified\n * `null` & `undefined` will be ommitted\n * Arrays of strings will be joined with a space\n *\n * @example\n * ```ts\n * const urlSearchParams = new URLSearchParams();\n * addQueryParams({\n * params: { foo: 'bar', count: 42, tags: ['one', 'two'] },\n * urlSearchParams,\n * });\n * ```\n *\n * @see {@link createUrlWithParams} for creating a full URL\n */\nexport function addQueryParams<Params extends QueryParamsInput>({\n params,\n urlSearchParams,\n}: {\n params: Params;\n /**\n * This will be mutated in place AND returned\n */\n urlSearchParams: URLSearchParams;\n}) {\n Object.entries(params ?? {}).forEach(([key, value]) => {\n if (value === undefined || value === null) return;\n if (value instanceof URL) {\n urlSearchParams.set(key, value.toString());\n } else if (Array.isArray(value)) {\n urlSearchParams.set(key, value.join(' '));\n } else {\n const v = `${value}`;\n if (v === '') return;\n urlSearchParams.set(key, v);\n }\n });\n return urlSearchParams;\n}\n\n/**\n * Creates a URL with query parameters, supporting both full URLs and relative paths\n * @example\n * ```ts\n * createUrlWithParams({\n * url: 'https://example.com',\n * queryParams: { foo: 'bar', count: 42, tags: ['one', 'two'] }\n * })\n * // => URL('https://example.com?foo=bar&count=42&tags=one%20two')\n * ```\n *\n * @see {@link addQueryParams} for adding just query params\n */\nexport function createUrlWithParams<Params extends QueryParamsInput>({\n /** Can either be a full URL or a relative one (but that requires passing in \"origin\") */\n url,\n /** Base URL to use when url is a relative path */\n origin,\n /**\n * URL's will be stringified\n * Arrays of strings will be joined with a space\n * Other values will be stringified\n */\n queryParams,\n}: {\n /**\n * Can either be a full URL or a relative one (but that requires passing in \"origin\")\n */\n url: string | URL;\n /**\n * URL's will be stringified\n * Arrays of strings will be joined with a space\n * Other values will be stringified\n */\n queryParams: Params;\n origin?: string;\n}) {\n if (!origin && typeof url === 'string' && !url.startsWith('http')) {\n throw new Error(\n `When using \"createUrl\" either pass in a full \"url\" or provide an \"origin\"`,\n );\n }\n\n const u =\n // eslint-disable-next-line no-nested-ternary\n typeof url === 'string'\n ? new URL(url, origin)\n : origin\n ? new URL(url.toString(), origin)\n : url;\n addQueryParams({ params: queryParams, urlSearchParams: u.searchParams });\n return u;\n}\n\nexport interface GitLabParsedUrl {\n fullPath: string;\n}\n\nexport interface BitbucketParsedUrl {\n fullPath: string;\n}\n\nexport interface GitHubParsedUrl {\n owner: string;\n repoName: string;\n}\n\nexport function areUrlsSame({ a, b }: { a: string; b: string }) {\n return new URL(a).toString() === new URL(b).toString();\n}\n\nexport function isRemoteUrl(url: string): boolean {\n if (typeof url !== 'string') return false;\n try {\n // Throws here if malformed URL\n const pathUrl = new URL(url);\n // Be VERY specific with protocols here, since URL() does no protocol validation\n return (\n pathUrl.protocol.startsWith('http:') ||\n pathUrl.protocol.startsWith('https:')\n );\n } catch (e) {\n // Starting a url with '//' is invalid to URL(), but we support it\n return url.startsWith('//');\n }\n}\n\n/**\n * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs\n */\nexport const isDataUrl = (dataString: string): boolean =>\n dataString.startsWith('data:');\n\nexport const slugify = (\n opt:\n | string\n | {\n string: string;\n /**\n * Removes all special characters. Necessary when used to create JS targets\n * that are invalid when special characters are present.\n */\n strict?: boolean;\n lowerCase?: boolean;\n },\n): string => {\n const {\n string,\n strict = true,\n lowerCase = true,\n } = typeof opt === 'string' ? { string: opt } : opt;\n return slugifyBase(string, {\n lower: lowerCase,\n trim: true,\n strict,\n });\n};\n\n/**\n * When dealing with nav paths, we need to find the entity type of the link (first\n * part, e.g. 'page' or 'pattern') and the entity id (second part, e.g. 'home').\n */\nexport const extractPathParts = (path: string): string[] | null => {\n const regex = /^\\/([^/]+)\\/([^/]+)/;\n const match = path.match(regex);\n\n if (!match) return null;\n\n const [_, entityType, entityId] = match;\n return [entityType, entityId];\n};\n\nexport function createFigmaUrl({\n fileId,\n nodeId,\n version,\n}: {\n fileId: string;\n nodeId?: string;\n version?: string | number;\n}) {\n if (!fileId || fileId.trim().length === 0) {\n throw new Error(`Invalid Figma URL, missing file id: ${fileId}`);\n }\n const url = new URL(`https://www.figma.com/file/${fileId}`);\n if (nodeId) {\n url.searchParams.set('node-id', nodeId);\n }\n if (version) {\n url.searchParams.set('version-id', version.toString());\n }\n return url.toString();\n}\n\nexport function parseFigmaUrl(figmaUrl: string): {\n type: 'proto' | 'file' | 'design' | 'board';\n fileId: string;\n nodeId?: string;\n version?: string;\n} {\n const url = new URL(figmaUrl);\n // tried to update to use the regex from figma, but it ended up being too strict\n // noting here in case we revisit\n // /https:\\/\\/[\\w\\.-]+\\.?figma.com\\/([\\w-]+)\\/([0-9a-zA-Z]{22,128})(?:\\/.*)?$/;\n if (\n (url.hostname !== 'www.figma.com' && url.hostname !== 'figma.com') ||\n !isRemoteUrl(figmaUrl) // Ensure it's a http/https URL.\n ) {\n throw new Error(`Please provide a valid Figma URL, got ${figmaUrl}`);\n }\n const nodeId = url.searchParams.get('node-id') || undefined;\n const version = url.searchParams.get('version-id') || undefined;\n const [, type, fileId] = url.pathname.split('/');\n switch (type) {\n case 'proto':\n case 'file':\n case 'board':\n case 'design': {\n if (!fileId) {\n throw new Error(`Invalid Figma URL, missing file id: ${figmaUrl}`);\n }\n return {\n type,\n fileId,\n nodeId,\n version,\n };\n }\n default:\n throw new Error(`Please provide a valid Figma URL, got ${figmaUrl}`);\n }\n}\n\n/**\n * Create a query string from an object of params\n * Does not include undefined, null, or empty string values\n * Does not include leading `?`\n */\nexport function createQueryParams(\n params: Record<string, string | number | boolean | undefined | null>,\n) {\n return new URLSearchParams(\n Object.fromEntries(\n Object.entries(params)\n .filter(([, v]) => {\n if (typeof v === 'string') {\n // removing empty strings\n return v.length > 0;\n }\n // removing null or undefined\n return v !== undefined && v !== null;\n })\n .map(([k, v]): [string, string] => [\n k,\n // sending up non-strings as strings\n `${v}`,\n ]),\n ),\n ).toString();\n}\n"]}
1
+ {"version":3,"sources":["../src/urls.ts"],"names":["addQueryParams","params","urlSearchParams","key","value","v","__name","createUrlWithParams","url","origin","queryParams","u","areUrlsSame","a","b","isRemoteUrl","pathUrl","isDataUrl","dataString","slugify","opt","string","strict","lowerCase","slugifyBase","extractPathParts","path","regex","match","_","entityType","entityId","createFigmaUrl","fileId","nodeId","version","parseFigmaUrl","figmaUrl","type","createQueryParams","k","createSafeFilename","filename","ext","base"],"mappings":"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","file":"urls.js","sourcesContent":["import slugifyBase from 'slugify';\n\nexport type QueryParamsInput = Record<\n string,\n string | number | boolean | undefined | null | string[] | URL\n>;\n\n/**\n * Util to add query params in a type safe way\n * URL's will be stringified\n * `booleans` & `numbers` will be stringified\n * `null` & `undefined` will be ommitted\n * Arrays of strings will be joined with a space\n *\n * @example\n * ```ts\n * const urlSearchParams = new URLSearchParams();\n * addQueryParams({\n * params: { foo: 'bar', count: 42, tags: ['one', 'two'] },\n * urlSearchParams,\n * });\n * ```\n *\n * @see {@link createUrlWithParams} for creating a full URL\n */\nexport function addQueryParams<Params extends QueryParamsInput>({\n params,\n urlSearchParams,\n}: {\n params: Params;\n /**\n * This will be mutated in place AND returned\n */\n urlSearchParams: URLSearchParams;\n}) {\n Object.entries(params ?? {}).forEach(([key, value]) => {\n if (value === undefined || value === null) return;\n if (value instanceof URL) {\n urlSearchParams.set(key, value.toString());\n } else if (Array.isArray(value)) {\n urlSearchParams.set(key, value.join(' '));\n } else {\n const v = `${value}`;\n if (v === '') return;\n urlSearchParams.set(key, v);\n }\n });\n return urlSearchParams;\n}\n\n/**\n * Creates a URL with query parameters, supporting both full URLs and relative paths\n * @example\n * ```ts\n * createUrlWithParams({\n * url: 'https://example.com',\n * queryParams: { foo: 'bar', count: 42, tags: ['one', 'two'] }\n * })\n * // => URL('https://example.com?foo=bar&count=42&tags=one%20two')\n * ```\n *\n * @see {@link addQueryParams} for adding just query params\n */\nexport function createUrlWithParams<Params extends QueryParamsInput>({\n /** Can either be a full URL or a relative one (but that requires passing in \"origin\") */\n url,\n /** Base URL to use when url is a relative path */\n origin,\n /**\n * URL's will be stringified\n * Arrays of strings will be joined with a space\n * Other values will be stringified\n */\n queryParams,\n}: {\n /**\n * Can either be a full URL or a relative one (but that requires passing in \"origin\")\n */\n url: string | URL;\n /**\n * URL's will be stringified\n * Arrays of strings will be joined with a space\n * Other values will be stringified\n */\n queryParams: Params;\n origin?: string;\n}) {\n if (!origin && typeof url === 'string' && !url.startsWith('http')) {\n throw new Error(\n `When using \"createUrl\" either pass in a full \"url\" or provide an \"origin\"`,\n );\n }\n\n const u =\n // eslint-disable-next-line no-nested-ternary\n typeof url === 'string'\n ? new URL(url, origin)\n : origin\n ? new URL(url.toString(), origin)\n : url;\n addQueryParams({ params: queryParams, urlSearchParams: u.searchParams });\n return u;\n}\n\nexport interface GitLabParsedUrl {\n fullPath: string;\n}\n\nexport interface BitbucketParsedUrl {\n fullPath: string;\n}\n\nexport interface GitHubParsedUrl {\n owner: string;\n repoName: string;\n}\n\nexport function areUrlsSame({ a, b }: { a: string; b: string }) {\n return new URL(a).toString() === new URL(b).toString();\n}\n\nexport function isRemoteUrl(url: string): boolean {\n if (typeof url !== 'string') return false;\n try {\n // Throws here if malformed URL\n const pathUrl = new URL(url);\n // Be VERY specific with protocols here, since URL() does no protocol validation\n return (\n pathUrl.protocol.startsWith('http:') ||\n pathUrl.protocol.startsWith('https:')\n );\n } catch (e) {\n // Starting a url with '//' is invalid to URL(), but we support it\n return url.startsWith('//');\n }\n}\n\n/**\n * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs\n */\nexport const isDataUrl = (dataString: string): boolean =>\n dataString.startsWith('data:');\n\nexport const slugify = (\n opt:\n | string\n | {\n string: string;\n /**\n * Removes all special characters. Necessary when used to create JS targets\n * that are invalid when special characters are present.\n */\n strict?: boolean;\n lowerCase?: boolean;\n },\n): string => {\n const {\n string,\n strict = true,\n lowerCase = true,\n } = typeof opt === 'string' ? { string: opt } : opt;\n return slugifyBase(string, {\n lower: lowerCase,\n trim: true,\n strict,\n });\n};\n\n/**\n * When dealing with nav paths, we need to find the entity type of the link (first\n * part, e.g. 'page' or 'pattern') and the entity id (second part, e.g. 'home').\n */\nexport const extractPathParts = (path: string): string[] | null => {\n const regex = /^\\/([^/]+)\\/([^/]+)/;\n const match = path.match(regex);\n\n if (!match) return null;\n\n const [_, entityType, entityId] = match;\n return [entityType, entityId];\n};\n\nexport function createFigmaUrl({\n fileId,\n nodeId,\n version,\n}: {\n fileId: string;\n nodeId?: string;\n version?: string | number;\n}) {\n if (!fileId || fileId.trim().length === 0) {\n throw new Error(`Invalid Figma URL, missing file id: ${fileId}`);\n }\n const url = new URL(`https://www.figma.com/file/${fileId}`);\n if (nodeId) {\n url.searchParams.set('node-id', nodeId);\n }\n if (version) {\n url.searchParams.set('version-id', version.toString());\n }\n return url.toString();\n}\n\nexport function parseFigmaUrl(figmaUrl: string): {\n type: 'proto' | 'file' | 'design' | 'board';\n fileId: string;\n nodeId?: string;\n version?: string;\n} {\n const url = new URL(figmaUrl);\n // tried to update to use the regex from figma, but it ended up being too strict\n // noting here in case we revisit\n // /https:\\/\\/[\\w\\.-]+\\.?figma.com\\/([\\w-]+)\\/([0-9a-zA-Z]{22,128})(?:\\/.*)?$/;\n if (\n (url.hostname !== 'www.figma.com' && url.hostname !== 'figma.com') ||\n !isRemoteUrl(figmaUrl) // Ensure it's a http/https URL.\n ) {\n throw new Error(`Please provide a valid Figma URL, got ${figmaUrl}`);\n }\n const nodeId = url.searchParams.get('node-id') || undefined;\n const version = url.searchParams.get('version-id') || undefined;\n const [, type, fileId] = url.pathname.split('/');\n switch (type) {\n case 'proto':\n case 'file':\n case 'board':\n case 'design': {\n if (!fileId) {\n throw new Error(`Invalid Figma URL, missing file id: ${figmaUrl}`);\n }\n return {\n type,\n fileId,\n nodeId,\n version,\n };\n }\n default:\n throw new Error(`Please provide a valid Figma URL, got ${figmaUrl}`);\n }\n}\n\n/**\n * Create a query string from an object of params\n * Does not include undefined, null, or empty string values\n * Does not include leading `?`\n */\nexport function createQueryParams(\n params: Record<string, string | number | boolean | undefined | null>,\n) {\n return new URLSearchParams(\n Object.fromEntries(\n Object.entries(params)\n .filter(([, v]) => {\n if (typeof v === 'string') {\n // removing empty strings\n return v.length > 0;\n }\n // removing null or undefined\n return v !== undefined && v !== null;\n })\n .map(([k, v]): [string, string] => [\n k,\n // sending up non-strings as strings\n `${v}`,\n ]),\n ),\n ).toString();\n}\n\n/**\n * Creates a safe filename by slugifying the filename and removing any special characters\n * Will throw if the filename does not exist or is just an extension (e.g. '.jpg')\n * @example\n * ```ts\n * createSafeFilename({ filename: 'test.jpg' }) // => 'test.jpg'\n * createSafeFilename({ filename: 'test.jpg.png' }) // => 'testjpg.png'\n * createSafeFilename({ filename: 'test jpg.pdf' }) // => 'test-jpg.pdf'\n */\nexport function createSafeFilename({ filename }: { filename: string }): string {\n const ext = slugify([...filename.split('.')].pop() || '');\n const base = ext\n ? slugify(filename.substring(0, filename.lastIndexOf('.')))\n : slugify(filename);\n if (!base) {\n throw new Error(`Invalid filename: ${filename}`);\n }\n return ext ? `${base}.${ext}` : base;\n}\n"]}
package/dist/urls.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import g from'slugify';var o=Object.defineProperty;var s=(t,r)=>o(t,"name",{value:r,configurable:true});function c({params:t,urlSearchParams:r}){return Object.entries(t??{}).forEach(([n,e])=>{if(e!=null)if(e instanceof URL)r.set(n,e.toString());else if(Array.isArray(e))r.set(n,e.join(" "));else {let i=`${e}`;if(i==="")return;r.set(n,i);}}),r}s(c,"addQueryParams");function l({url:t,origin:r,queryParams:n}){if(!r&&typeof t=="string"&&!t.startsWith("http"))throw new Error('When using "createUrl" either pass in a full "url" or provide an "origin"');let e=typeof t=="string"?new URL(t,r):r?new URL(t.toString(),r):t;return c({params:n,urlSearchParams:e.searchParams}),e}s(l,"createUrlWithParams");function m({a:t,b:r}){return new URL(t).toString()===new URL(r).toString()}s(m,"areUrlsSame");function f(t){if(typeof t!="string")return false;try{let r=new URL(t);return r.protocol.startsWith("http:")||r.protocol.startsWith("https:")}catch{return t.startsWith("//")}}s(f,"isRemoteUrl");var p=s(t=>t.startsWith("data:"),"isDataUrl"),h=s(t=>{let{string:r,strict:n=true,lowerCase:e=true}=typeof t=="string"?{string:t}:t;return g(r,{lower:e,trim:true,strict:n})},"slugify"),w=s(t=>{let r=/^\/([^/]+)\/([^/]+)/,n=t.match(r);if(!n)return null;let[e,i,a]=n;return [i,a]},"extractPathParts");function P({fileId:t,nodeId:r,version:n}){if(!t||t.trim().length===0)throw new Error(`Invalid Figma URL, missing file id: ${t}`);let e=new URL(`https://www.figma.com/file/${t}`);return r&&e.searchParams.set("node-id",r),n&&e.searchParams.set("version-id",n.toString()),e.toString()}s(P,"createFigmaUrl");function U(t){let r=new URL(t);if(r.hostname!=="www.figma.com"&&r.hostname!=="figma.com"||!f(t))throw new Error(`Please provide a valid Figma URL, got ${t}`);let n=r.searchParams.get("node-id")||void 0,e=r.searchParams.get("version-id")||void 0,[,i,a]=r.pathname.split("/");switch(i){case "proto":case "file":case "board":case "design":{if(!a)throw new Error(`Invalid Figma URL, missing file id: ${t}`);return {type:i,fileId:a,nodeId:n,version:e}}default:throw new Error(`Please provide a valid Figma URL, got ${t}`)}}s(U,"parseFigmaUrl");function y(t){return new URLSearchParams(Object.fromEntries(Object.entries(t).filter(([,r])=>typeof r=="string"?r.length>0:r!=null).map(([r,n])=>[r,`${n}`]))).toString()}s(y,"createQueryParams");
2
- export{c as addQueryParams,m as areUrlsSame,P as createFigmaUrl,y as createQueryParams,l as createUrlWithParams,w as extractPathParts,p as isDataUrl,f as isRemoteUrl,U as parseFigmaUrl,h as slugify};//# sourceMappingURL=urls.mjs.map
1
+ import c from'slugify';var g=Object.defineProperty;var s=(t,r)=>g(t,"name",{value:r,configurable:true});function u({params:t,urlSearchParams:r}){return Object.entries(t??{}).forEach(([e,n])=>{if(n!=null)if(n instanceof URL)r.set(e,n.toString());else if(Array.isArray(n))r.set(e,n.join(" "));else {let i=`${n}`;if(i==="")return;r.set(e,i);}}),r}s(u,"addQueryParams");function p({url:t,origin:r,queryParams:e}){if(!r&&typeof t=="string"&&!t.startsWith("http"))throw new Error('When using "createUrl" either pass in a full "url" or provide an "origin"');let n=typeof t=="string"?new URL(t,r):r?new URL(t.toString(),r):t;return u({params:e,urlSearchParams:n.searchParams}),n}s(p,"createUrlWithParams");function m({a:t,b:r}){return new URL(t).toString()===new URL(r).toString()}s(m,"areUrlsSame");function f(t){if(typeof t!="string")return false;try{let r=new URL(t);return r.protocol.startsWith("http:")||r.protocol.startsWith("https:")}catch{return t.startsWith("//")}}s(f,"isRemoteUrl");var h=s(t=>t.startsWith("data:"),"isDataUrl"),o=s(t=>{let{string:r,strict:e=true,lowerCase:n=true}=typeof t=="string"?{string:t}:t;return c(r,{lower:n,trim:true,strict:e})},"slugify"),w=s(t=>{let r=/^\/([^/]+)\/([^/]+)/,e=t.match(r);if(!e)return null;let[n,i,a]=e;return [i,a]},"extractPathParts");function P({fileId:t,nodeId:r,version:e}){if(!t||t.trim().length===0)throw new Error(`Invalid Figma URL, missing file id: ${t}`);let n=new URL(`https://www.figma.com/file/${t}`);return r&&n.searchParams.set("node-id",r),e&&n.searchParams.set("version-id",e.toString()),n.toString()}s(P,"createFigmaUrl");function U(t){let r=new URL(t);if(r.hostname!=="www.figma.com"&&r.hostname!=="figma.com"||!f(t))throw new Error(`Please provide a valid Figma URL, got ${t}`);let e=r.searchParams.get("node-id")||void 0,n=r.searchParams.get("version-id")||void 0,[,i,a]=r.pathname.split("/");switch(i){case "proto":case "file":case "board":case "design":{if(!a)throw new Error(`Invalid Figma URL, missing file id: ${t}`);return {type:i,fileId:a,nodeId:e,version:n}}default:throw new Error(`Please provide a valid Figma URL, got ${t}`)}}s(U,"parseFigmaUrl");function x(t){return new URLSearchParams(Object.fromEntries(Object.entries(t).filter(([,r])=>typeof r=="string"?r.length>0:r!=null).map(([r,e])=>[r,`${e}`]))).toString()}s(x,"createQueryParams");function b({filename:t}){let r=o([...t.split(".")].pop()||""),e=o(r?t.substring(0,t.lastIndexOf(".")):t);if(!e)throw new Error(`Invalid filename: ${t}`);return r?`${e}.${r}`:e}s(b,"createSafeFilename");
2
+ export{u as addQueryParams,m as areUrlsSame,P as createFigmaUrl,x as createQueryParams,b as createSafeFilename,p as createUrlWithParams,w as extractPathParts,h as isDataUrl,f as isRemoteUrl,U as parseFigmaUrl,o as slugify};//# sourceMappingURL=urls.mjs.map
3
3
  //# sourceMappingURL=urls.mjs.map
package/dist/urls.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/urls.ts"],"names":["addQueryParams","params","urlSearchParams","key","value","v","__name","createUrlWithParams","url","origin","queryParams","u","areUrlsSame","a","b","isRemoteUrl","pathUrl","isDataUrl","dataString","slugify","opt","string","strict","lowerCase","slugifyBase","extractPathParts","path","regex","match","_","entityType","entityId","createFigmaUrl","fileId","nodeId","version","parseFigmaUrl","figmaUrl","type","createQueryParams","k"],"mappings":"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","file":"urls.mjs","sourcesContent":["import slugifyBase from 'slugify';\n\nexport type QueryParamsInput = Record<\n string,\n string | number | boolean | undefined | null | string[] | URL\n>;\n\n/**\n * Util to add query params in a type safe way\n * URL's will be stringified\n * `booleans` & `numbers` will be stringified\n * `null` & `undefined` will be ommitted\n * Arrays of strings will be joined with a space\n *\n * @example\n * ```ts\n * const urlSearchParams = new URLSearchParams();\n * addQueryParams({\n * params: { foo: 'bar', count: 42, tags: ['one', 'two'] },\n * urlSearchParams,\n * });\n * ```\n *\n * @see {@link createUrlWithParams} for creating a full URL\n */\nexport function addQueryParams<Params extends QueryParamsInput>({\n params,\n urlSearchParams,\n}: {\n params: Params;\n /**\n * This will be mutated in place AND returned\n */\n urlSearchParams: URLSearchParams;\n}) {\n Object.entries(params ?? {}).forEach(([key, value]) => {\n if (value === undefined || value === null) return;\n if (value instanceof URL) {\n urlSearchParams.set(key, value.toString());\n } else if (Array.isArray(value)) {\n urlSearchParams.set(key, value.join(' '));\n } else {\n const v = `${value}`;\n if (v === '') return;\n urlSearchParams.set(key, v);\n }\n });\n return urlSearchParams;\n}\n\n/**\n * Creates a URL with query parameters, supporting both full URLs and relative paths\n * @example\n * ```ts\n * createUrlWithParams({\n * url: 'https://example.com',\n * queryParams: { foo: 'bar', count: 42, tags: ['one', 'two'] }\n * })\n * // => URL('https://example.com?foo=bar&count=42&tags=one%20two')\n * ```\n *\n * @see {@link addQueryParams} for adding just query params\n */\nexport function createUrlWithParams<Params extends QueryParamsInput>({\n /** Can either be a full URL or a relative one (but that requires passing in \"origin\") */\n url,\n /** Base URL to use when url is a relative path */\n origin,\n /**\n * URL's will be stringified\n * Arrays of strings will be joined with a space\n * Other values will be stringified\n */\n queryParams,\n}: {\n /**\n * Can either be a full URL or a relative one (but that requires passing in \"origin\")\n */\n url: string | URL;\n /**\n * URL's will be stringified\n * Arrays of strings will be joined with a space\n * Other values will be stringified\n */\n queryParams: Params;\n origin?: string;\n}) {\n if (!origin && typeof url === 'string' && !url.startsWith('http')) {\n throw new Error(\n `When using \"createUrl\" either pass in a full \"url\" or provide an \"origin\"`,\n );\n }\n\n const u =\n // eslint-disable-next-line no-nested-ternary\n typeof url === 'string'\n ? new URL(url, origin)\n : origin\n ? new URL(url.toString(), origin)\n : url;\n addQueryParams({ params: queryParams, urlSearchParams: u.searchParams });\n return u;\n}\n\nexport interface GitLabParsedUrl {\n fullPath: string;\n}\n\nexport interface BitbucketParsedUrl {\n fullPath: string;\n}\n\nexport interface GitHubParsedUrl {\n owner: string;\n repoName: string;\n}\n\nexport function areUrlsSame({ a, b }: { a: string; b: string }) {\n return new URL(a).toString() === new URL(b).toString();\n}\n\nexport function isRemoteUrl(url: string): boolean {\n if (typeof url !== 'string') return false;\n try {\n // Throws here if malformed URL\n const pathUrl = new URL(url);\n // Be VERY specific with protocols here, since URL() does no protocol validation\n return (\n pathUrl.protocol.startsWith('http:') ||\n pathUrl.protocol.startsWith('https:')\n );\n } catch (e) {\n // Starting a url with '//' is invalid to URL(), but we support it\n return url.startsWith('//');\n }\n}\n\n/**\n * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs\n */\nexport const isDataUrl = (dataString: string): boolean =>\n dataString.startsWith('data:');\n\nexport const slugify = (\n opt:\n | string\n | {\n string: string;\n /**\n * Removes all special characters. Necessary when used to create JS targets\n * that are invalid when special characters are present.\n */\n strict?: boolean;\n lowerCase?: boolean;\n },\n): string => {\n const {\n string,\n strict = true,\n lowerCase = true,\n } = typeof opt === 'string' ? { string: opt } : opt;\n return slugifyBase(string, {\n lower: lowerCase,\n trim: true,\n strict,\n });\n};\n\n/**\n * When dealing with nav paths, we need to find the entity type of the link (first\n * part, e.g. 'page' or 'pattern') and the entity id (second part, e.g. 'home').\n */\nexport const extractPathParts = (path: string): string[] | null => {\n const regex = /^\\/([^/]+)\\/([^/]+)/;\n const match = path.match(regex);\n\n if (!match) return null;\n\n const [_, entityType, entityId] = match;\n return [entityType, entityId];\n};\n\nexport function createFigmaUrl({\n fileId,\n nodeId,\n version,\n}: {\n fileId: string;\n nodeId?: string;\n version?: string | number;\n}) {\n if (!fileId || fileId.trim().length === 0) {\n throw new Error(`Invalid Figma URL, missing file id: ${fileId}`);\n }\n const url = new URL(`https://www.figma.com/file/${fileId}`);\n if (nodeId) {\n url.searchParams.set('node-id', nodeId);\n }\n if (version) {\n url.searchParams.set('version-id', version.toString());\n }\n return url.toString();\n}\n\nexport function parseFigmaUrl(figmaUrl: string): {\n type: 'proto' | 'file' | 'design' | 'board';\n fileId: string;\n nodeId?: string;\n version?: string;\n} {\n const url = new URL(figmaUrl);\n // tried to update to use the regex from figma, but it ended up being too strict\n // noting here in case we revisit\n // /https:\\/\\/[\\w\\.-]+\\.?figma.com\\/([\\w-]+)\\/([0-9a-zA-Z]{22,128})(?:\\/.*)?$/;\n if (\n (url.hostname !== 'www.figma.com' && url.hostname !== 'figma.com') ||\n !isRemoteUrl(figmaUrl) // Ensure it's a http/https URL.\n ) {\n throw new Error(`Please provide a valid Figma URL, got ${figmaUrl}`);\n }\n const nodeId = url.searchParams.get('node-id') || undefined;\n const version = url.searchParams.get('version-id') || undefined;\n const [, type, fileId] = url.pathname.split('/');\n switch (type) {\n case 'proto':\n case 'file':\n case 'board':\n case 'design': {\n if (!fileId) {\n throw new Error(`Invalid Figma URL, missing file id: ${figmaUrl}`);\n }\n return {\n type,\n fileId,\n nodeId,\n version,\n };\n }\n default:\n throw new Error(`Please provide a valid Figma URL, got ${figmaUrl}`);\n }\n}\n\n/**\n * Create a query string from an object of params\n * Does not include undefined, null, or empty string values\n * Does not include leading `?`\n */\nexport function createQueryParams(\n params: Record<string, string | number | boolean | undefined | null>,\n) {\n return new URLSearchParams(\n Object.fromEntries(\n Object.entries(params)\n .filter(([, v]) => {\n if (typeof v === 'string') {\n // removing empty strings\n return v.length > 0;\n }\n // removing null or undefined\n return v !== undefined && v !== null;\n })\n .map(([k, v]): [string, string] => [\n k,\n // sending up non-strings as strings\n `${v}`,\n ]),\n ),\n ).toString();\n}\n"]}
1
+ {"version":3,"sources":["../src/urls.ts"],"names":["addQueryParams","params","urlSearchParams","key","value","v","__name","createUrlWithParams","url","origin","queryParams","u","areUrlsSame","a","b","isRemoteUrl","pathUrl","isDataUrl","dataString","slugify","opt","string","strict","lowerCase","slugifyBase","extractPathParts","path","regex","match","_","entityType","entityId","createFigmaUrl","fileId","nodeId","version","parseFigmaUrl","figmaUrl","type","createQueryParams","k","createSafeFilename","filename","ext","base"],"mappings":"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","file":"urls.mjs","sourcesContent":["import slugifyBase from 'slugify';\n\nexport type QueryParamsInput = Record<\n string,\n string | number | boolean | undefined | null | string[] | URL\n>;\n\n/**\n * Util to add query params in a type safe way\n * URL's will be stringified\n * `booleans` & `numbers` will be stringified\n * `null` & `undefined` will be ommitted\n * Arrays of strings will be joined with a space\n *\n * @example\n * ```ts\n * const urlSearchParams = new URLSearchParams();\n * addQueryParams({\n * params: { foo: 'bar', count: 42, tags: ['one', 'two'] },\n * urlSearchParams,\n * });\n * ```\n *\n * @see {@link createUrlWithParams} for creating a full URL\n */\nexport function addQueryParams<Params extends QueryParamsInput>({\n params,\n urlSearchParams,\n}: {\n params: Params;\n /**\n * This will be mutated in place AND returned\n */\n urlSearchParams: URLSearchParams;\n}) {\n Object.entries(params ?? {}).forEach(([key, value]) => {\n if (value === undefined || value === null) return;\n if (value instanceof URL) {\n urlSearchParams.set(key, value.toString());\n } else if (Array.isArray(value)) {\n urlSearchParams.set(key, value.join(' '));\n } else {\n const v = `${value}`;\n if (v === '') return;\n urlSearchParams.set(key, v);\n }\n });\n return urlSearchParams;\n}\n\n/**\n * Creates a URL with query parameters, supporting both full URLs and relative paths\n * @example\n * ```ts\n * createUrlWithParams({\n * url: 'https://example.com',\n * queryParams: { foo: 'bar', count: 42, tags: ['one', 'two'] }\n * })\n * // => URL('https://example.com?foo=bar&count=42&tags=one%20two')\n * ```\n *\n * @see {@link addQueryParams} for adding just query params\n */\nexport function createUrlWithParams<Params extends QueryParamsInput>({\n /** Can either be a full URL or a relative one (but that requires passing in \"origin\") */\n url,\n /** Base URL to use when url is a relative path */\n origin,\n /**\n * URL's will be stringified\n * Arrays of strings will be joined with a space\n * Other values will be stringified\n */\n queryParams,\n}: {\n /**\n * Can either be a full URL or a relative one (but that requires passing in \"origin\")\n */\n url: string | URL;\n /**\n * URL's will be stringified\n * Arrays of strings will be joined with a space\n * Other values will be stringified\n */\n queryParams: Params;\n origin?: string;\n}) {\n if (!origin && typeof url === 'string' && !url.startsWith('http')) {\n throw new Error(\n `When using \"createUrl\" either pass in a full \"url\" or provide an \"origin\"`,\n );\n }\n\n const u =\n // eslint-disable-next-line no-nested-ternary\n typeof url === 'string'\n ? new URL(url, origin)\n : origin\n ? new URL(url.toString(), origin)\n : url;\n addQueryParams({ params: queryParams, urlSearchParams: u.searchParams });\n return u;\n}\n\nexport interface GitLabParsedUrl {\n fullPath: string;\n}\n\nexport interface BitbucketParsedUrl {\n fullPath: string;\n}\n\nexport interface GitHubParsedUrl {\n owner: string;\n repoName: string;\n}\n\nexport function areUrlsSame({ a, b }: { a: string; b: string }) {\n return new URL(a).toString() === new URL(b).toString();\n}\n\nexport function isRemoteUrl(url: string): boolean {\n if (typeof url !== 'string') return false;\n try {\n // Throws here if malformed URL\n const pathUrl = new URL(url);\n // Be VERY specific with protocols here, since URL() does no protocol validation\n return (\n pathUrl.protocol.startsWith('http:') ||\n pathUrl.protocol.startsWith('https:')\n );\n } catch (e) {\n // Starting a url with '//' is invalid to URL(), but we support it\n return url.startsWith('//');\n }\n}\n\n/**\n * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs\n */\nexport const isDataUrl = (dataString: string): boolean =>\n dataString.startsWith('data:');\n\nexport const slugify = (\n opt:\n | string\n | {\n string: string;\n /**\n * Removes all special characters. Necessary when used to create JS targets\n * that are invalid when special characters are present.\n */\n strict?: boolean;\n lowerCase?: boolean;\n },\n): string => {\n const {\n string,\n strict = true,\n lowerCase = true,\n } = typeof opt === 'string' ? { string: opt } : opt;\n return slugifyBase(string, {\n lower: lowerCase,\n trim: true,\n strict,\n });\n};\n\n/**\n * When dealing with nav paths, we need to find the entity type of the link (first\n * part, e.g. 'page' or 'pattern') and the entity id (second part, e.g. 'home').\n */\nexport const extractPathParts = (path: string): string[] | null => {\n const regex = /^\\/([^/]+)\\/([^/]+)/;\n const match = path.match(regex);\n\n if (!match) return null;\n\n const [_, entityType, entityId] = match;\n return [entityType, entityId];\n};\n\nexport function createFigmaUrl({\n fileId,\n nodeId,\n version,\n}: {\n fileId: string;\n nodeId?: string;\n version?: string | number;\n}) {\n if (!fileId || fileId.trim().length === 0) {\n throw new Error(`Invalid Figma URL, missing file id: ${fileId}`);\n }\n const url = new URL(`https://www.figma.com/file/${fileId}`);\n if (nodeId) {\n url.searchParams.set('node-id', nodeId);\n }\n if (version) {\n url.searchParams.set('version-id', version.toString());\n }\n return url.toString();\n}\n\nexport function parseFigmaUrl(figmaUrl: string): {\n type: 'proto' | 'file' | 'design' | 'board';\n fileId: string;\n nodeId?: string;\n version?: string;\n} {\n const url = new URL(figmaUrl);\n // tried to update to use the regex from figma, but it ended up being too strict\n // noting here in case we revisit\n // /https:\\/\\/[\\w\\.-]+\\.?figma.com\\/([\\w-]+)\\/([0-9a-zA-Z]{22,128})(?:\\/.*)?$/;\n if (\n (url.hostname !== 'www.figma.com' && url.hostname !== 'figma.com') ||\n !isRemoteUrl(figmaUrl) // Ensure it's a http/https URL.\n ) {\n throw new Error(`Please provide a valid Figma URL, got ${figmaUrl}`);\n }\n const nodeId = url.searchParams.get('node-id') || undefined;\n const version = url.searchParams.get('version-id') || undefined;\n const [, type, fileId] = url.pathname.split('/');\n switch (type) {\n case 'proto':\n case 'file':\n case 'board':\n case 'design': {\n if (!fileId) {\n throw new Error(`Invalid Figma URL, missing file id: ${figmaUrl}`);\n }\n return {\n type,\n fileId,\n nodeId,\n version,\n };\n }\n default:\n throw new Error(`Please provide a valid Figma URL, got ${figmaUrl}`);\n }\n}\n\n/**\n * Create a query string from an object of params\n * Does not include undefined, null, or empty string values\n * Does not include leading `?`\n */\nexport function createQueryParams(\n params: Record<string, string | number | boolean | undefined | null>,\n) {\n return new URLSearchParams(\n Object.fromEntries(\n Object.entries(params)\n .filter(([, v]) => {\n if (typeof v === 'string') {\n // removing empty strings\n return v.length > 0;\n }\n // removing null or undefined\n return v !== undefined && v !== null;\n })\n .map(([k, v]): [string, string] => [\n k,\n // sending up non-strings as strings\n `${v}`,\n ]),\n ),\n ).toString();\n}\n\n/**\n * Creates a safe filename by slugifying the filename and removing any special characters\n * Will throw if the filename does not exist or is just an extension (e.g. '.jpg')\n * @example\n * ```ts\n * createSafeFilename({ filename: 'test.jpg' }) // => 'test.jpg'\n * createSafeFilename({ filename: 'test.jpg.png' }) // => 'testjpg.png'\n * createSafeFilename({ filename: 'test jpg.pdf' }) // => 'test-jpg.pdf'\n */\nexport function createSafeFilename({ filename }: { filename: string }): string {\n const ext = slugify([...filename.split('.')].pop() || '');\n const base = ext\n ? slugify(filename.substring(0, filename.lastIndexOf('.')))\n : slugify(filename);\n if (!base) {\n throw new Error(`Invalid filename: ${filename}`);\n }\n return ext ? `${base}.${ext}` : base;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/validation.ts"],"names":["getSuperstructErrorMsg","structError","StructError","failure","path","message","__name"],"mappings":"qIAEO,SAASA,CAAAA,CACdC,EACQ,CACR,GAAIA,CAAuBC,YAAAA,uBAAAA,CAAa,CAEtC,GAAM,CAACC,CAAO,CAAA,CAAIF,CAAY,CAAA,QAAA,EAC9B,CAAA,GAAI,CAACE,CAAS,CAAA,OAAO,EACrB,CAAA,GAAM,CAAE,IAAA,CAAAC,EAAM,OAAAC,CAAAA,CAAQ,CAAIF,CAAAA,CAAAA,CAG1B,OADEC,CAAAA,CAAK,SAAW,CAAIC,CAAAA,CAAAA,CAAU,CAAYD,SAAAA,EAAAA,CAAAA,CAAK,IAAK,CAAA,GAAG,CAAC,CAAOC,IAAAA,EAAAA,CAAO,CAE1E,CAAA,CACA,OAAIJ,CAAAA,YAAuB,KAClBA,CAAAA,CAAAA,CAAY,OAEd,CAAA,EACT,CAhBgBK,CAAAA,CAAAN,CAAA,CAAA,wBAAA,CAAA","file":"validation.js","sourcesContent":["import { StructError } from 'superstruct';\n\nexport function getSuperstructErrorMsg(\n structError: StructError | Error | unknown,\n): string {\n if (structError instanceof StructError) {\n // just doing first error b/c showing all can be kinda crazy. may want to change in future\n const [failure] = structError.failures();\n if (!failure) return '';\n const { path, message } = failure;\n const msg =\n path.length === 0 ? message : `At path: ${path.join('.')} -- ${message}`;\n return msg;\n }\n if (structError instanceof Error) {\n return structError.message;\n }\n return '';\n}\n"]}
1
+ {"version":3,"sources":["../src/validation.ts"],"names":["getSuperstructErrorMsg","structError","StructError","failure","path","message","__name"],"mappings":"qIAEO,SAASA,CAAAA,CACdC,EACQ,CACR,GAAIA,CAAAA,YAAuBC,uBAAAA,CAAa,CAEtC,GAAM,CAACC,CAAO,CAAA,CAAIF,CAAAA,CAAY,QAAA,EAAS,CACvC,GAAI,CAACE,CAAAA,CAAS,OAAO,EAAA,CACrB,GAAM,CAAE,IAAA,CAAAC,EAAM,OAAA,CAAAC,CAAQ,CAAA,CAAIF,CAAAA,CAG1B,OADEC,CAAAA,CAAK,SAAW,CAAA,CAAIC,CAAAA,CAAU,CAAA,SAAA,EAAYD,CAAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAA,IAAA,EAAOC,CAAO,CAAA,CAE1E,CACA,OAAIJ,CAAAA,YAAuB,KAAA,CAClBA,CAAAA,CAAY,OAAA,CAEd,EACT,CAhBgBK,CAAAA,CAAAN,CAAAA,CAAA,wBAAA,CAAA","file":"validation.js","sourcesContent":["import { StructError } from 'superstruct';\n\nexport function getSuperstructErrorMsg(\n structError: StructError | Error | unknown,\n): string {\n if (structError instanceof StructError) {\n // just doing first error b/c showing all can be kinda crazy. may want to change in future\n const [failure] = structError.failures();\n if (!failure) return '';\n const { path, message } = failure;\n const msg =\n path.length === 0 ? message : `At path: ${path.join('.')} -- ${message}`;\n return msg;\n }\n if (structError instanceof Error) {\n return structError.message;\n }\n return '';\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/validation.ts"],"names":["getSuperstructErrorMsg","structError","StructError","failure","path","message","__name"],"mappings":"uHAEO,SAASA,CAAAA,CACdC,EACQ,CACR,GAAIA,CAAuBC,YAAAA,WAAAA,CAAa,CAEtC,GAAM,CAACC,CAAO,CAAA,CAAIF,CAAY,CAAA,QAAA,EAC9B,CAAA,GAAI,CAACE,CAAS,CAAA,OAAO,EACrB,CAAA,GAAM,CAAE,IAAA,CAAAC,EAAM,OAAAC,CAAAA,CAAQ,CAAIF,CAAAA,CAAAA,CAG1B,OADEC,CAAAA,CAAK,SAAW,CAAIC,CAAAA,CAAAA,CAAU,CAAYD,SAAAA,EAAAA,CAAAA,CAAK,IAAK,CAAA,GAAG,CAAC,CAAOC,IAAAA,EAAAA,CAAO,CAE1E,CAAA,CACA,OAAIJ,CAAAA,YAAuB,KAClBA,CAAAA,CAAAA,CAAY,OAEd,CAAA,EACT,CAhBgBK,CAAAA,CAAAN,CAAA,CAAA,wBAAA,CAAA","file":"validation.mjs","sourcesContent":["import { StructError } from 'superstruct';\n\nexport function getSuperstructErrorMsg(\n structError: StructError | Error | unknown,\n): string {\n if (structError instanceof StructError) {\n // just doing first error b/c showing all can be kinda crazy. may want to change in future\n const [failure] = structError.failures();\n if (!failure) return '';\n const { path, message } = failure;\n const msg =\n path.length === 0 ? message : `At path: ${path.join('.')} -- ${message}`;\n return msg;\n }\n if (structError instanceof Error) {\n return structError.message;\n }\n return '';\n}\n"]}
1
+ {"version":3,"sources":["../src/validation.ts"],"names":["getSuperstructErrorMsg","structError","StructError","failure","path","message","__name"],"mappings":"uHAEO,SAASA,CAAAA,CACdC,EACQ,CACR,GAAIA,CAAAA,YAAuBC,WAAAA,CAAa,CAEtC,GAAM,CAACC,CAAO,CAAA,CAAIF,CAAAA,CAAY,QAAA,EAAS,CACvC,GAAI,CAACE,CAAAA,CAAS,OAAO,EAAA,CACrB,GAAM,CAAE,IAAA,CAAAC,EAAM,OAAA,CAAAC,CAAQ,CAAA,CAAIF,CAAAA,CAG1B,OADEC,CAAAA,CAAK,SAAW,CAAA,CAAIC,CAAAA,CAAU,CAAA,SAAA,EAAYD,CAAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAA,IAAA,EAAOC,CAAO,CAAA,CAE1E,CACA,OAAIJ,CAAAA,YAAuB,KAAA,CAClBA,CAAAA,CAAY,OAAA,CAEd,EACT,CAhBgBK,CAAAA,CAAAN,CAAAA,CAAA,wBAAA,CAAA","file":"validation.mjs","sourcesContent":["import { StructError } from 'superstruct';\n\nexport function getSuperstructErrorMsg(\n structError: StructError | Error | unknown,\n): string {\n if (structError instanceof StructError) {\n // just doing first error b/c showing all can be kinda crazy. may want to change in future\n const [failure] = structError.failures();\n if (!failure) return '';\n const { path, message } = failure;\n const msg =\n path.length === 0 ? message : `At path: ${path.join('.')} -- ${message}`;\n return msg;\n }\n if (structError instanceof Error) {\n return structError.message;\n }\n return '';\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@knapsack/utils",
3
3
  "description": "Universal JS Utils that work in browers or Node",
4
- "version": "5.0.0--canary.6593.4738696.0",
4
+ "version": "5.0.0",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",
@@ -23,39 +23,37 @@
23
23
  "build-inc": "npm run build",
24
24
  "clean": "rm -rf dist",
25
25
  "lint": "eslint ./src --quiet",
26
- "test": "time ava"
26
+ "test": "vitest run"
27
27
  },
28
28
  "author": "Knapsack (https://www.knapsack.cloud)",
29
29
  "dependencies": {
30
- "@types/lodash": "^4.17.20",
30
+ "@types/lodash": "^4.17.23",
31
31
  "@types/memoizee": "^0.4.12",
32
32
  "clean-deep": "^3.4.0",
33
33
  "date-fns": "^2.30.0",
34
34
  "deepmerge": "^4.3.1",
35
35
  "fp-ts": "^2.16.11",
36
- "immer": "^10.1.1",
36
+ "immer": "^10.2.0",
37
37
  "just-kebab-case": "^4.2.0",
38
- "lodash": "^4.17.21",
38
+ "lodash": "^4.18.1",
39
39
  "memoizee": "^0.4.17",
40
40
  "nanoid": "^3.3.11",
41
41
  "slugify": "^1.6.6",
42
42
  "superstruct": "^0.16.7",
43
43
  "ts-expect": "^1.3.0",
44
44
  "type-fest": "^2.19.0",
45
- "uuid": "^8.3.2"
45
+ "uuid": "^11.1.1"
46
46
  },
47
47
  "devDependencies": {
48
- "@knapsack/eslint-config-starter": "5.0.0--canary.6593.4738696.0",
49
- "@knapsack/test-ava": "5.0.0--canary.6593.4738696.0",
50
- "@knapsack/typescript-config-starter": "5.0.0--canary.6593.4738696.0",
51
- "@types/node": "^20.19.22",
52
- "@types/react": "^18.3.26",
53
- "@types/uuid": "^8.3.4",
54
- "ava": "^6.4.1",
55
- "eslint": "^8.57.0",
48
+ "@knapsack/eslint-config-starter": "5.0.0",
49
+ "@knapsack/typescript-config-starter": "5.0.0",
50
+ "@types/node": "^22.19.11",
51
+ "@types/react": "^19.2.3",
52
+ "eslint": "^9.20.0",
56
53
  "ts-toolbelt": "^9.6.0",
57
- "tsup": "^8.5.0",
58
- "typescript": "^5.9.2"
54
+ "tsup": "^8.5.1",
55
+ "typescript": "^5.9.3",
56
+ "vitest": "^4.1.9"
59
57
  },
60
58
  "license": "GPL-2.0-or-later",
61
59
  "publishConfig": {
@@ -66,5 +64,5 @@
66
64
  "directory": "libs/utils",
67
65
  "type": "git"
68
66
  },
69
- "gitHead": "4738696cd5d75f977543e5484622c251b26db3a4"
67
+ "gitHead": "31e09ba72245b95bef52e73ce5076de51936286c"
70
68
  }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ['src/**/*.test.ts', 'tests/**/*.test.ts'],
6
+ },
7
+ });
package/.eslintrc.js DELETED
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- extends: ['@knapsack/eslint-config-starter'],
3
- parserOptions: { tsconfigRootDir: __dirname },
4
- };
package/ava.config.cjs DELETED
@@ -1,3 +0,0 @@
1
- const config = require('@knapsack/test-ava');
2
-
3
- module.exports = config;