diff --git a/cspell.json b/cspell.json index 5581f8c..3cdfcce 100644 --- a/cspell.json +++ b/cspell.json @@ -7,6 +7,7 @@ "intellij", "mkdocs", "nbundle", + "nolookalikes", "npmignore", "pnpm" ] diff --git a/package.json b/package.json index 64bb6d4..1aa115a 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@types/async-retry": "^1.4.4", "@types/got": "^9.6.12", "@types/ms": "^0.7.31", + "@types/nanoid-dictionary": "^4.2.0", "@types/node": "^14.18.12", "@types/tar": "^6.1.1", "async-retry": "^1.3.3", @@ -56,6 +57,10 @@ "got": "^12.1.0", "husky": "^8.0.1", "lint-staged": "^13.0.1", + "ms": "^2.1.3", + "nanoid": "^4.0.0", + "nanoid-dictionary": "^4.3.0", + "node-fetch": "^3.2.6", "prettier": "^2.6.2", "semantic-release": "^19.0.3", "tar": "^6.1.11", @@ -65,8 +70,5 @@ "update-check": "^1.5.4", "webpack": "^5.73.0", "webpack-cli": "^4.9.2" - }, - "dependencies": { - "ms": "^2.1.3" } } diff --git a/src/utils/format-project.ts b/src/utils/format-project.ts index fa6db97..de736d3 100644 --- a/src/utils/format-project.ts +++ b/src/utils/format-project.ts @@ -1,5 +1,20 @@ import fs from "fs/promises"; import path from "path"; +import fetch from "node-fetch"; +import { customAlphabet } from "nanoid/async"; +import { lowercase, numbers } from "nanoid-dictionary"; + +import { toJson } from "./to-json"; + +const nanoid = customAlphabet(lowercase + numbers, 5); + +async function createAppName(): Promise { + const name = `nbundle-app-${await nanoid()}`; + const res = await fetch(`https://developers.nbundle.com/api/v1/apps/${name}`); + if (res.status === 404) return name; + if (res.ok) return createAppName(); + throw new Error("Couldn't generate app name."); +} export async function formatProject(projectDirectory: string): Promise { await Promise.all( @@ -20,7 +35,7 @@ export async function formatProject(projectDirectory: string): Promise { const name = path.basename(projectDirectory); const pkgJsonPath = path.join(projectDirectory, "package.json"); const pkg = JSON.parse(await fs.readFile(pkgJsonPath, "utf8")); - pkg.name = name; + pkg.name = await createAppName(); pkg.productName = name; pkg.devDependencies = Object.fromEntries( Object.entries(pkg.devDependencies).filter(([key]) => @@ -28,5 +43,15 @@ export async function formatProject(projectDirectory: string): Promise { ) ); if (pkg.scripts.prepare) delete pkg.scripts.prepare; - await fs.writeFile(pkgJsonPath, JSON.stringify(pkg, null, 2), "utf8"); + await fs.writeFile( + pkgJsonPath, + toJson({ + name: pkg.name, + version: pkg.version, + productName: pkg.productName, + description: pkg.description, + ...pkg, + }), + "utf8" + ); } diff --git a/src/utils/index.ts b/src/utils/index.ts index 2efbd60..09ddf60 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,3 +1,4 @@ +export * from "./to-json"; export * from "./is-error-like"; export * from "./async-pipeline"; export * from "./async-exec"; diff --git a/src/utils/to-json.ts b/src/utils/to-json.ts new file mode 100644 index 0000000..17a109b --- /dev/null +++ b/src/utils/to-json.ts @@ -0,0 +1,3 @@ +export function toJson(obj: unknown): string { + return JSON.stringify(obj, null, 2); +} diff --git a/yarn.lock b/yarn.lock index ebdafe6..e75fba1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1049,6 +1049,11 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== +"@types/nanoid-dictionary@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@types/nanoid-dictionary/-/nanoid-dictionary-4.2.0.tgz#5a3ae86d7c0db2d3ecf5b1233fc27f5874903f77" + integrity sha512-DyQddKC2AYsInXBMqKSwhom4gpouV8SF1smsCPSzR8hp20vZJ5o5Yxg7qXThCHwr/H6VMq01UArEGbF0q2FXig== + "@types/node-fetch@^2.6.2": version "2.6.2" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" @@ -2082,6 +2087,11 @@ dargs@^7.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== +data-uri-to-buffer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" + integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== + dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" @@ -2409,6 +2419,14 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.1.5" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.5.tgz#0077bf5f3fcdbd9d75a0b5362f77dbb743489863" + integrity sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" @@ -2503,6 +2521,13 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + from2@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" @@ -3750,6 +3775,16 @@ mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +nanoid-dictionary@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/nanoid-dictionary/-/nanoid-dictionary-4.3.0.tgz#d4cefa1e4c06b1f576789eeb2646101f8c5419e8" + integrity sha512-Xw1+/QnRGWO1KJ0rLfU1xR85qXmAHyLbE3TUkklu9gOIDburP6CsUnLmTaNECGpBh5SHb2uPFmx0VT8UPyoeyw== + +nanoid@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.0.tgz#6e144dee117609232c3f415c34b0e550e64999a5" + integrity sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg== + negotiator@^0.6.2, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -3765,6 +3800,11 @@ nerf-dart@^1.0.0: resolved "https://registry.yarnpkg.com/nerf-dart/-/nerf-dart-1.0.0.tgz#e6dab7febf5ad816ea81cf5c629c5a0ebde72c1a" integrity sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g== +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-emoji@^1.11.0: version "1.11.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" @@ -3779,6 +3819,15 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.6.tgz#6d4627181697a9d9674aae0d61548e0d629b31b9" + integrity sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-gyp@^8.4.1: version "8.4.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" @@ -5427,6 +5476,11 @@ wcwidth@^1.0.0: dependencies: defaults "^1.0.3" +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"