Ver código fonte

fix(create-pyth-package): updated the generator to use the correct output path

benduran 1 semana atrás
pai
commit
a36d751957
2 arquivos alterados com 145 adições e 141 exclusões
  1. 134 105
      packages/create-pyth-package/src/create-pyth-package.ts
  2. 11 36
      pnpm-lock.yaml

+ 134 - 105
packages/create-pyth-package/src/create-pyth-package.ts

@@ -1,3 +1,4 @@
+/* eslint-disable tsdoc/syntax */
 // this rule is absolutely broken for the typings the prompts library
 // provides, so we need to hard-disable it for all usages of prompts
 
@@ -21,10 +22,28 @@ import type {
 } from "./types.js";
 import { PACKAGE_PREFIX, PackageType, TEMPLATES_FOLDER } from "./types.js";
 
-function getPackageNameWithoutOrg(
-  packageNameWithOrg: string | null | undefined,
-) {
-  return packageNameWithOrg?.split("/")[1] ?? "";
+/**
+ * Given either a raw name ("foo") or a scoped name ("@pythnetwork/foo"),
+ * returns the normalized pair { raw, withOrg } where:
+ * - raw is the unscoped package name ("foo")
+ * - withOrg is the scoped package name ("@pythnetwork/foo")
+ */
+function normalizePackageNameInput(val: string | null | undefined = "") {
+  // if the user passed a scoped name already, extract the part after `/`
+  if (val?.startsWith("@")) {
+    const parts = val.split("/");
+    const raw = parts[1] ?? "";
+    return {
+      raw,
+      withOrg: `${PACKAGE_PREFIX}${raw}`,
+    };
+  }
+  // otherwise treat input as raw
+  const raw = val ?? "";
+  return {
+    raw,
+    withOrg: `${PACKAGE_PREFIX}${raw}`,
+  };
 }
 
 /**
@@ -51,98 +70,99 @@ function getTemplatesInputFolder(packageType: PackageType) {
 }
 
 async function createPythApp() {
-  const { confirm, description, folder, isPublic, packageName, packageType } =
-    (await prompts([
-      {
-        choices: Object.values(PackageType).map((val) => ({
-          title: val,
-          value: val,
-        })),
-        message: "Which type of package do you want to create?",
-        name: "packageType",
-        type: "select",
-      },
-      {
-        format: (val: string) => `${PACKAGE_PREFIX}${val}`,
-        message: (_, responses: InProgressCreatePythAppResponses) =>
-          `Enter the name for your ${responses.packageType ?? ""} package. ${chalk.magenta(PACKAGE_PREFIX)}`,
-        name: "packageName",
-        type: "text",
-        validate: (name: string) => {
-          const proposedName = `${PACKAGE_PREFIX}${name}`;
-          const pjsonNameRegexp = /^@pythnetwork\/(\w)(\w|\d|_|-)+$/;
-          return (
-            pjsonNameRegexp.test(proposedName) ||
-            "Please enter a valid package name (you do not need to add @pythnetwork/ as a prefix, it will be added automatically)"
-          );
-        },
-      },
-      {
-        message: "Enter a brief, friendly description for your package",
-        name: "description",
-        type: "text",
+  const responses = (await prompts([
+    {
+      choices: Object.values(PackageType).map((val) => ({
+        title: val,
+        value: val,
+      })),
+      message: "Which type of package do you want to create?",
+      name: "packageType",
+      type: "select",
+    },
+    {
+      // Store the raw name (no format). We'll normalize after prompts
+      message: (_, responses: InProgressCreatePythAppResponses) =>
+        `Enter the name for your ${responses.packageType ?? ""} package. ${chalk.magenta(PACKAGE_PREFIX)}`,
+      name: "packageName",
+      type: "text",
+      validate: (name: string) => {
+        // validate using the full scoped candidate so we ensure the raw name is valid
+        const proposedName = `${PACKAGE_PREFIX}${name.replace(/^@.*\//, "")}`;
+        const pjsonNameRegexp = /^@pythnetwork\/(\w)(\w|\d|_|-)+$/;
+        return (
+          pjsonNameRegexp.test(proposedName) ||
+          "Please enter a valid package name (you do not need to add @pythnetwork/ as a prefix, it will be added automatically)"
+        );
       },
-      {
-        choices: (_, { packageType }: InProgressCreatePythAppResponses) =>
-          getAvailableFolders()
-            .map((val) => ({
-              title: val,
-              value: val,
-            }))
-            .filter(
-              ({ value: relPath }) =>
-                packageType !== PackageType.WEBAPP &&
-                !relPath.startsWith("apps"),
-            ),
-        message: "Where do you want your package to live?",
-        name: "folder",
-        type: (_, { packageType }: InProgressCreatePythAppResponses) =>
-          packageType === PackageType.WEBAPP ? false : "select",
+    },
+    {
+      message: "Enter a brief, friendly description for your package",
+      name: "description",
+      type: "text",
+    },
+    {
+      choices: (_, { packageType }: InProgressCreatePythAppResponses) =>
+        getAvailableFolders()
+          .map((val) => ({
+            title: val,
+            value: val,
+          }))
+          .filter(
+            ({ value: relPath }) =>
+              packageType !== PackageType.WEBAPP && !relPath.startsWith("apps"),
+          ),
+      message: "Where do you want your package to live?",
+      name: "folder",
+      type: (_, { packageType }: InProgressCreatePythAppResponses) =>
+        packageType === PackageType.WEBAPP ? false : "select",
+    },
+    {
+      message:
+        "Are you intending on publishing this, publicly on NPM, for users outside of our org to use?",
+      name: "isPublic",
+      type: (_, { packageType }: InProgressCreatePythAppResponses) =>
+        packageType === PackageType.WEBAPP ? false : "confirm",
+    },
+    {
+      message: (
+        _,
+        { folder, packageName, packageType }: InProgressCreatePythAppResponses,
+      ) => {
+        // normalize for display
+        const { raw: pkgRaw, withOrg: pkgWithOrg } =
+          normalizePackageNameInput(packageName);
+
+        let msg = `Please confirm your choices:${os.EOL}`;
+        msg += `Creating a ${chalk.magenta(packageType)} package, named ${chalk.magenta(pkgWithOrg)}, in ${chalk.magenta(packageType === PackageType.WEBAPP ? "apps" : folder)}/${pkgRaw}.${os.EOL}`;
+        msg += "Look good?";
+
+        return msg;
       },
-      {
-        message:
-          "Are you intending on publishing this, publicly on NPM, for users outside of our org to use?",
-        name: "isPublic",
-        type: "confirm",
-      },
-      {
-        message: (
-          _,
-          {
-            folder,
-            packageName,
-            packageType,
-          }: InProgressCreatePythAppResponses,
-        ) => {
-          let msg = `Please confirm your choices:${os.EOL}`;
-          msg += `Creating a ${chalk.magenta(packageType)} package, named ${chalk.magenta(packageName)}, in ${chalk.magenta(packageType === PackageType.WEBAPP ? "apps" : folder)}/${getPackageNameWithoutOrg(packageName)}.${os.EOL}`;
-          msg += "Look good?";
-
-          return msg;
-        },
-        name: "confirm",
-        type: "confirm",
-      },
-    ])) as CreatePythAppResponses;
+      name: "confirm",
+      type: "confirm",
+    },
+  ])) as CreatePythAppResponses;
+
+  const { confirm, description, folder, isPublic, packageName, packageType } =
+    responses;
 
   if (!confirm) {
     Logger.warn("oops, you did not confirm your choices.");
     return;
   }
 
-  const packageNameWithoutOrg = getPackageNameWithoutOrg(packageName);
+  // normalize package-name inputs to deterministic values
+  const { raw: packageNameWithoutOrg, withOrg: packageNameWithOrg } =
+    normalizePackageNameInput(packageName);
 
   const relDest =
     packageType === PackageType.WEBAPP
       ? path.join("apps", packageNameWithoutOrg)
-      : folder;
-  const absDest = path.join(
-    appRootPath.toString(),
-    relDest,
-    packageNameWithoutOrg,
-  );
+      : path.join(folder, packageNameWithoutOrg);
+  const absDest = path.join(appRootPath.toString(), relDest);
 
-  Logger.info("ensuring", relDest, "exists");
+  Logger.info("ensuring", relDest, `exists (abs path: ${absDest})`);
   await fs.ensureDir(absDest);
 
   Logger.info("copying files");
@@ -159,34 +179,43 @@ async function createPythApp() {
     "updating files with the choices you made in the initial prompts",
   );
   await Promise.all(
-    destFiles.filter(fp => !fp.includes('node_module')).map(async (fp) => {
-      const contents = await fs.readFile(fp, "utf8");
-      const updatedContents = renderTemplate(contents, {
-        description,
-        name: packageName,
-        packageNameWithoutOrg,
-        relativeFolder: relDest,
-      });
-      await fs.writeFile(fp, updatedContents, "utf8");
-
-      if (fp.endsWith("package.json")) {
-        const pjson = JSON.parse(updatedContents) as PackageJson;
-        pjson.private = !isPublic;
-        if (isPublic) {
-          pjson.publishConfig = {
-            access: "public",
-          };
+    destFiles
+      .filter((fp) => !fp.includes("node_module"))
+      .map(async (fp) => {
+        const contents = await fs.readFile(fp, "utf8");
+        const updatedContents = renderTemplate(contents, {
+          description,
+          name: packageNameWithOrg,
+          packageNameWithoutOrg,
+          relativeFolder: relDest,
+        });
+        await fs.writeFile(fp, updatedContents, "utf8");
+
+        if (fp.endsWith("package.json")) {
+          const pjson = JSON.parse(updatedContents) as PackageJson;
+          // ensure package name in package.json is the scoped name
+          pjson.name = packageNameWithOrg;
+          pjson.private = !isPublic;
+          if (isPublic) {
+            pjson.publishConfig = {
+              access: "public",
+            };
+          } else {
+            // ensure publishConfig is removed if present and not public
+            if (pjson.publishConfig) {
+              delete pjson.publishConfig;
+            }
+          }
+
+          await fs.writeFile(fp, JSON.stringify(pjson, undefined, 2), "utf8");
         }
-
-        await fs.writeFile(fp, JSON.stringify(pjson, undefined, 2), "utf8");
-      }
-    }),
+      }),
   );
 
   Logger.info("installing deps");
   execSync("pnpm i", { cwd: appRootPath.toString(), stdio: "inherit" });
 
-  Logger.info(`Done! ${packageName} is ready for development`);
+  Logger.info(`Done! ${packageNameWithOrg} is ready for development`);
 }
 
 await createPythApp();

+ 11 - 36
pnpm-lock.yaml

@@ -34776,7 +34776,7 @@ snapshots:
       '@alloc/quick-lru': 5.2.0
       '@tailwindcss/node': 4.1.6
       '@tailwindcss/oxide': 4.1.6
-      postcss: 8.5.3
+      postcss: 8.5.6
       tailwindcss: 4.1.6
 
   '@tanstack/query-core@5.71.5': {}
@@ -39274,12 +39274,12 @@ snapshots:
 
   css-loader@7.1.2(webpack@5.98.0(@swc/core@1.15.0)(esbuild@0.25.9)):
     dependencies:
-      icss-utils: 5.1.0(postcss@8.5.3)
-      postcss: 8.5.3
-      postcss-modules-extract-imports: 3.1.0(postcss@8.5.3)
-      postcss-modules-local-by-default: 4.2.0(postcss@8.5.3)
-      postcss-modules-scope: 3.2.1(postcss@8.5.3)
-      postcss-modules-values: 4.0.0(postcss@8.5.3)
+      icss-utils: 5.1.0(postcss@8.5.6)
+      postcss: 8.5.6
+      postcss-modules-extract-imports: 3.1.0(postcss@8.5.6)
+      postcss-modules-local-by-default: 4.2.0(postcss@8.5.6)
+      postcss-modules-scope: 3.2.1(postcss@8.5.6)
+      postcss-modules-values: 4.0.0(postcss@8.5.6)
       postcss-value-parser: 4.2.0
       semver: 7.7.2
     optionalDependencies:
@@ -42961,10 +42961,6 @@ snapshots:
     dependencies:
       safer-buffer: 2.1.2
 
-  icss-utils@5.1.0(postcss@8.5.3):
-    dependencies:
-      postcss: 8.5.3
-
   icss-utils@5.1.0(postcss@8.5.6):
     dependencies:
       postcss: 8.5.6
@@ -46830,21 +46826,10 @@ snapshots:
 
   postcss-media-query-parser@0.2.3: {}
 
-  postcss-modules-extract-imports@3.1.0(postcss@8.5.3):
-    dependencies:
-      postcss: 8.5.3
-
   postcss-modules-extract-imports@3.1.0(postcss@8.5.6):
     dependencies:
       postcss: 8.5.6
 
-  postcss-modules-local-by-default@4.2.0(postcss@8.5.3):
-    dependencies:
-      icss-utils: 5.1.0(postcss@8.5.3)
-      postcss: 8.5.3
-      postcss-selector-parser: 7.1.0
-      postcss-value-parser: 4.2.0
-
   postcss-modules-local-by-default@4.2.0(postcss@8.5.6):
     dependencies:
       icss-utils: 5.1.0(postcss@8.5.6)
@@ -46852,21 +46837,11 @@ snapshots:
       postcss-selector-parser: 7.1.0
       postcss-value-parser: 4.2.0
 
-  postcss-modules-scope@3.2.1(postcss@8.5.3):
-    dependencies:
-      postcss: 8.5.3
-      postcss-selector-parser: 7.1.0
-
   postcss-modules-scope@3.2.1(postcss@8.5.6):
     dependencies:
       postcss: 8.5.6
       postcss-selector-parser: 7.1.0
 
-  postcss-modules-values@4.0.0(postcss@8.5.3):
-    dependencies:
-      icss-utils: 5.1.0(postcss@8.5.3)
-      postcss: 8.5.3
-
   postcss-modules-values@4.0.0(postcss@8.5.6):
     dependencies:
       icss-utils: 5.1.0(postcss@8.5.6)
@@ -46879,9 +46854,9 @@ snapshots:
 
   postcss-resolve-nested-selector@0.1.6: {}
 
-  postcss-safe-parser@7.0.1(postcss@8.5.3):
+  postcss-safe-parser@7.0.1(postcss@8.5.6):
     dependencies:
-      postcss: 8.5.3
+      postcss: 8.5.6
 
   postcss-scss@4.0.9(postcss@8.5.3):
     dependencies:
@@ -49208,9 +49183,9 @@ snapshots:
       micromatch: 4.0.8
       normalize-path: 3.0.0
       picocolors: 1.1.1
-      postcss: 8.5.3
+      postcss: 8.5.6
       postcss-resolve-nested-selector: 0.1.6
-      postcss-safe-parser: 7.0.1(postcss@8.5.3)
+      postcss-safe-parser: 7.0.1(postcss@8.5.6)
       postcss-selector-parser: 7.1.0
       postcss-value-parser: 4.2.0
       resolve-from: 5.0.0