name: sanitiseTypescriptPackageName()

in packages/type-safe-api/src/project/codegen/generate.ts [620:827]


        name: sanitiseTypescriptPackageName(packageName),
        ...options.typescriptReactQueryHooksOptions,
        isWithinMonorepo: options.isWithinMonorepo,
      });
    }
    default:
      throw new Error(`Unknown library ${library}`);
  }
};

/**
 * Create library projects
 * @param libraries the libraries to generate for
 * @param options options for the projects to be created
 */
export const generateLibraryProjects = (
  libraries: Library[],
  options: GenerateLibraryProjectsOptions
): { [library: string]: Project } => {
  if (libraries.length > 0) {
    new TextFile(
      options.parent,
      path.join(options.generatedCodeDir, "README.md"),
      {
        lines: [
          "## Generated Libraries",
          "",
          "This directory contains generated libraries based on your API model.",
        ],
        readonly: true,
      }
    );
  }

  const generatedLibraries: { [language: string]: Project } = {};
  libraries.forEach((library) => {
    const project = generateLibraryProject(library, options);
    if (project != null) {
      generatedLibraries[library] = project;
    }
  });

  return generatedLibraries;
};

export interface CommonModelProjectOptions {
  readonly name: string;
  readonly parent?: Project;
  readonly outdir: string;
  readonly defaultReleaseBranch: string;
  readonly packageManager: NodePackageManager;
}

export interface GenerateModelProjectOptions
  extends CommonModelProjectOptions,
    TypeSafeApiModelProjectOptions,
    TypeSafeApiModelBuildOutputOptions {}

export const generateModelProject = ({
  modelLanguage,
  modelOptions,
  ...options
}: GenerateModelProjectOptions): ModelProject => {
  if (modelLanguage === ModelLanguage.SMITHY) {
    if (!modelOptions.smithy) {
      throw new Error(
        `modelOptions.smithy is required when selected model language is ${ModelLanguage.SMITHY}`
      );
    }

    const smithy = new SmithyModelProject({
      ...options,
      smithyOptions: modelOptions.smithy,
    });
    return {
      smithy,
      parsedSpecFile: options.parsedSpecFile,
      apiName: smithy.apiName,
      outdir: smithy.outdir,
    };
  } else if (modelLanguage === ModelLanguage.OPENAPI) {
    if (!modelOptions.openapi) {
      throw new Error(
        `modelOptions.openapi is required when selected model language is ${ModelLanguage.OPENAPI}`
      );
    }

    const openapi = new OpenApiModelProject({
      ...options,
      openApiOptions: modelOptions.openapi,
    });
    return {
      openapi,
      parsedSpecFile: options.parsedSpecFile,
      apiName: openapi.apiName,
      outdir: openapi.outdir,
    };
  } else if (modelLanguage === ModelLanguage.TYPESPEC) {
    if (!modelOptions.typeSpec) {
      throw new Error(
        `modelOptions.typeSpec is required when selected model language is ${ModelLanguage.TYPESPEC}`
      );
    }

    const typeSpec = new TypeSpecModelProject({
      ...options,
      name: sanitiseTypescriptPackageName(options.name),
      typeSpecOptions: modelOptions.typeSpec,
    });
    return {
      typeSpec,
      parsedSpecFile: options.parsedSpecFile,
      apiName: typeSpec.apiName,
      outdir: typeSpec.outdir,
    };
  } else {
    throw new Error(`Unknown model language ${modelLanguage}`);
  }
};

export interface GenerateAsyncModelProjectOptions
  extends CommonModelProjectOptions,
    TypeSafeWebSocketApiModelProjectOptions,
    TypeSafeApiAsyncModelBuildOutputOptions,
    TypeSafeApiModelBuildOutputOptions {}

export const generateAsyncModelProject = ({
  modelLanguage,
  modelOptions,
  ...options
}: GenerateAsyncModelProjectOptions): WebSocketModelProject => {
  if (modelLanguage === ModelLanguage.SMITHY) {
    if (!modelOptions.smithy) {
      throw new Error(
        `modelOptions.smithy is required when selected model language is ${ModelLanguage.SMITHY}`
      );
    }

    const smithy = new SmithyAsyncModelProject({
      ...options,
      smithyOptions: modelOptions.smithy,
    });
    return {
      smithy,
      parsedSpecFile: options.parsedSpecFile,
      asyncApiSpecFile: options.asyncApiSpecFile,
      apiName: smithy.apiName,
      outdir: smithy.outdir,
    };
  } else if (modelLanguage === ModelLanguage.OPENAPI) {
    if (!modelOptions.openapi) {
      throw new Error(
        `modelOptions.openapi is required when selected model language is ${ModelLanguage.OPENAPI}`
      );
    }

    const openapi = new OpenApiAsyncModelProject({
      ...options,
      openApiOptions: modelOptions.openapi,
    });
    return {
      openapi,
      parsedSpecFile: options.parsedSpecFile,
      asyncApiSpecFile: options.asyncApiSpecFile,
      apiName: openapi.apiName,
      outdir: openapi.outdir,
    };
  } else if (modelLanguage === ModelLanguage.TYPESPEC) {
    if (!modelOptions.typeSpec) {
      throw new Error(
        `modelOptions.typeSpec is required when selected model language is ${ModelLanguage.TYPESPEC}`
      );
    }

    const typeSpec = new TypeSpecAsyncModelProject({
      ...options,
      name: sanitiseTypescriptPackageName(options.name),
      typeSpecOptions: modelOptions.typeSpec,
    });
    return {
      typeSpec,
      parsedSpecFile: options.parsedSpecFile,
      asyncApiSpecFile: options.asyncApiSpecFile,
      apiName: typeSpec.apiName,
      outdir: typeSpec.outdir,
    };
  } else {
    throw new Error(`Unknown model language ${modelLanguage}`);
  }
};

/**
 * Returns a generated client project for the given language
 */
const generateAsyncLibraryProject = (
  library: WebSocketLibrary,
  options: GenerateAsyncLibraryProjectsOptions
): Project => {
  const packageName = `${options.parentPackageName}-${library}`;
  const commonOptions = {
    outdir: path.join(options.generatedCodeDir, library),
    specPath: options.parsedSpecPath,
    parent: options.parent,
  };

  switch (library) {
    case WebSocketLibrary.TYPESCRIPT_WEBSOCKET_CLIENT: {
      return new TypescriptWebsocketClientLibrary({