@sqlrooms/utils 0.8.1 → 0.9.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.
@@ -11,6 +11,20 @@ export declare function splitFilePath(filePath: string): {
11
11
  ext: string;
12
12
  filename: string;
13
13
  };
14
+ /**
15
+ * Converts a filename into a valid column or table name for database use.
16
+ * - Removes file extension
17
+ * - Replaces invalid characters with underscores
18
+ * - Ensures the name starts with a letter or underscore
19
+ * - Truncates to max length of 63 characters
20
+ *
21
+ * @param filename - The original filename to convert
22
+ * @returns A valid table/column name
23
+ * @example
24
+ * convertToValidColumnOrTableName("my-file.csv") // returns "my_file"
25
+ * convertToValidColumnOrTableName("123data.csv") // returns "_123data"
26
+ */
27
+ export declare function convertToValidColumnOrTableName(filename: string): string;
14
28
  /**
15
29
  * Converts a filename into a valid and unique column or table name for database use.
16
30
  * - Removes file extension
@@ -1 +1 @@
1
- {"version":3,"file":"filepaths.d.ts","sourceRoot":"","sources":["../src/filepaths.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB,CAYA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAChB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,MAAM,CAoBR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAsBpE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EAAE,GACtB,MAAM,CAqBR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,MAAM,CAeR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,MAAM,CAaR"}
1
+ {"version":3,"file":"filepaths.d.ts","sourceRoot":"","sources":["../src/filepaths.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB,CAYA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkBxE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAChB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,MAAM,CAGR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAsBpE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EAAE,GACtB,MAAM,CAqBR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,MAAM,CAeR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,MAAM,CAaR"}
package/dist/filepaths.js CHANGED
@@ -16,21 +16,19 @@ export function splitFilePath(filePath) {
16
16
  return { dir: pathParts.join('/'), name, ext, filename: `${name}.${ext}` };
17
17
  }
18
18
  /**
19
- * Converts a filename into a valid and unique column or table name for database use.
19
+ * Converts a filename into a valid column or table name for database use.
20
20
  * - Removes file extension
21
21
  * - Replaces invalid characters with underscores
22
22
  * - Ensures the name starts with a letter or underscore
23
23
  * - Truncates to max length of 63 characters
24
- * - Ensures uniqueness among existing names
25
24
  *
26
25
  * @param filename - The original filename to convert
27
- * @param existingTables - Optional array of existing table names to ensure uniqueness
28
- * @returns A valid and unique table/column name
26
+ * @returns A valid table/column name
29
27
  * @example
30
- * convertToUniqueColumnOrTableName("my-file.csv") // returns "my_file"
31
- * convertToUniqueColumnOrTableName("123data.csv") // returns "_123data"
28
+ * convertToValidColumnOrTableName("my-file.csv") // returns "my_file"
29
+ * convertToValidColumnOrTableName("123data.csv") // returns "_123data"
32
30
  */
33
- export function convertToUniqueColumnOrTableName(filename, existingTables) {
31
+ export function convertToValidColumnOrTableName(filename) {
34
32
  // Remove file extension
35
33
  const base = filename.replace(/\.[^/.]+$/, '');
36
34
  // Replace any invalid character with underscore, and convert to lowercase
@@ -43,9 +41,27 @@ export function convertToUniqueColumnOrTableName(filename, existingTables) {
43
41
  if (tableName.length > 63) {
44
42
  tableName = tableName.substring(0, 63);
45
43
  }
46
- tableName = generateUniqueName(tableName, existingTables);
47
44
  return tableName;
48
45
  }
46
+ /**
47
+ * Converts a filename into a valid and unique column or table name for database use.
48
+ * - Removes file extension
49
+ * - Replaces invalid characters with underscores
50
+ * - Ensures the name starts with a letter or underscore
51
+ * - Truncates to max length of 63 characters
52
+ * - Ensures uniqueness among existing names
53
+ *
54
+ * @param filename - The original filename to convert
55
+ * @param existingTables - Optional array of existing table names to ensure uniqueness
56
+ * @returns A valid and unique table/column name
57
+ * @example
58
+ * convertToUniqueColumnOrTableName("my-file.csv") // returns "my_file"
59
+ * convertToUniqueColumnOrTableName("123data.csv") // returns "_123data"
60
+ */
61
+ export function convertToUniqueColumnOrTableName(filename, existingTables) {
62
+ const tableName = convertToValidColumnOrTableName(filename);
63
+ return generateUniqueName(tableName, existingTables);
64
+ }
49
65
  /**
50
66
  * Generates a unique name by appending a numeric suffix if the name already exists.
51
67
  * @param name - The base name to make unique
@@ -1 +1 @@
1
- {"version":3,"file":"filepaths.js","sourceRoot":"","sources":["../src/filepaths.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Splits a file path into its directory, name, and extension components.\n * @param filePath - The full file path to split\n * @returns An object containing the directory path, file name (without extension), and extension\n * @example\n * splitFilePath(\"path/to/file.txt\") // returns { dir: \"path/to\", name: \"file\", ext: \"txt\" }\n */\nexport function splitFilePath(filePath: string): {\n dir: string;\n name: string;\n ext: string;\n filename: string;\n} {\n const pathParts = filePath.split('/');\n const file = pathParts.pop() || '';\n\n const dotIndex = file.lastIndexOf('.');\n if (dotIndex === -1 || dotIndex === 0)\n return {dir: pathParts.join('/'), name: file, ext: '', filename: file};\n\n const name = file.substring(0, dotIndex);\n const ext = file.substring(dotIndex + 1);\n\n return {dir: pathParts.join('/'), name, ext, filename: `${name}.${ext}`};\n}\n\n/**\n * Converts a filename into a valid and unique column or table name for database use.\n * - Removes file extension\n * - Replaces invalid characters with underscores\n * - Ensures the name starts with a letter or underscore\n * - Truncates to max length of 63 characters\n * - Ensures uniqueness among existing names\n *\n * @param filename - The original filename to convert\n * @param existingTables - Optional array of existing table names to ensure uniqueness\n * @returns A valid and unique table/column name\n * @example\n * convertToUniqueColumnOrTableName(\"my-file.csv\") // returns \"my_file\"\n * convertToUniqueColumnOrTableName(\"123data.csv\") // returns \"_123data\"\n */\nexport function convertToUniqueColumnOrTableName(\n filename: string,\n existingTables?: string[],\n): string {\n // Remove file extension\n const base = filename.replace(/\\.[^/.]+$/, '');\n\n // Replace any invalid character with underscore, and convert to lowercase\n let tableName = base.replace(/[^a-z0-9_]/gi, '_');\n\n // If the first character is a number, prepend an underscore\n if (/^\\d/.test(tableName)) {\n tableName = '_' + tableName;\n }\n\n // Truncate to the max length 63\n if (tableName.length > 63) {\n tableName = tableName.substring(0, 63);\n }\n\n tableName = generateUniqueName(tableName, existingTables);\n\n return tableName;\n}\n\n/**\n * Generates a unique name by appending a numeric suffix if the name already exists.\n * @param name - The base name to make unique\n * @param usedNames - Optional array of existing names to check against\n * @returns A unique name, potentially with a numeric suffix\n * @example\n * generateUniqueName(\"table\", [\"table\"]) // returns \"table_1\"\n * generateUniqueName(\"table_1\", [\"table_1\"]) // returns \"table_2\"\n */\nexport function generateUniqueName(name: string, usedNames?: string[]) {\n const usedNamesLower = usedNames?.map((n) => n.toLowerCase());\n\n // If tableName exists in the list\n if (usedNamesLower?.includes(name.toLowerCase())) {\n let baseName: string | undefined = name;\n let i = 0;\n\n // If tableName ends with `_${i}` pattern, update the baseTableName and i\n const matched = name.match(/^(.+)_(\\d+)$/);\n if (matched) {\n baseName = matched[1];\n i = Number(matched[2]);\n }\n\n do {\n i++;\n name = `${baseName}_${i}`;\n } while (usedNamesLower.includes(name.toLowerCase()));\n }\n\n return name;\n}\n\n/**\n * Generates a unique file path by appending a numeric suffix if the path already exists.\n * @param filePath - The original file path\n * @param existingPaths - Array of existing file paths to check against\n * @returns A unique file path\n * @example\n * generateUniquePath(\"file.txt\", [\"file.txt\"]) // returns \"file_1.txt\"\n */\nexport function generateUniquePath(\n filePath: string,\n existingPaths: string[],\n): string {\n let nextPath = filePath;\n if (existingPaths?.includes(filePath)) {\n const {dir, name, ext} = splitFilePath(filePath);\n\n let i = 0;\n let baseName: string | undefined = name;\n const matched = name.match(/^(.+)_(\\d+)$/);\n if (matched) {\n baseName = matched[1];\n i = Number(matched[2]);\n }\n\n do {\n i++;\n const fname = `${baseName}_${i}${ext ? `.${ext}` : ''}`;\n nextPath = `${dir}${dir ? '/' : ''}${fname}`;\n } while (existingPaths.includes(nextPath));\n }\n\n return nextPath;\n}\n\n/**\n * Converts a string into a valid and unique S3 object name.\n * - Replaces special characters with underscores\n * - Ensures name is within S3's length limits\n * - Ensures uniqueness among existing objects\n *\n * @param str - The string to convert into an S3 object name\n * @param existingObjects - Optional array of existing S3 object names to ensure uniqueness\n * @returns A valid and unique S3 object name\n * @example\n * convertToUniqueS3ObjectName(\"my file.txt\") // returns \"my_file.txt\"\n */\nexport function convertToUniqueS3ObjectName(\n str: string,\n existingObjects?: string[],\n): string {\n let rv = str\n .trim() // Remove leading and trailing white spaces\n .replace(/[^\\w\\s-\\.]/g, '_') // Replace special characters with underscores\n .replace(/\\s+/g, '_') // Replace consecutive spaces with a single underscore\n // .replace(/_+/g, '_') // Remove consecutive underscores\n // .replace(/^_/, '') // Remove leading underscores\n // .replace(/_$/, '') // Remove trailing underscores\n .slice(0, 255); // Truncate the string if it exceeds 255 characters\n\n if (existingObjects?.length) {\n rv = generateUniquePath(rv, existingObjects);\n }\n\n return rv;\n}\n\n/**\n * Converts a string into a valid and unique S3 folder path.\n * - Ensures the path ends with a forward slash\n * - Replaces special characters with underscores\n * - Ensures uniqueness among existing paths\n *\n * @param str - The string to convert into an S3 folder path\n * @param existingObjects - Optional array of existing S3 paths to ensure uniqueness\n * @returns A valid and unique S3 folder path ending with a forward slash\n * @example\n * convertToUniqueS3FolderPath(\"my folder\") // returns \"my_folder/\"\n */\nexport function convertToUniqueS3FolderPath(\n str: string,\n existingObjects?: string[],\n): string {\n let next = convertToUniqueS3ObjectName(str, existingObjects);\n if (!next.endsWith('/')) next += '/'; // Add trailing slash if not present\n return next;\n // return (\n // str\n // .trim() // Remove leading and trailing white spaces\n // .replace(/\\/+/g, '/') // Replace consecutive slashes with a single slash\n // .replace(/[^\\w\\s-\\/]/g, '_') // Replace special characters with underscores\n // .replace(/\\s+/g, '_') // Replace consecutive spaces with a single underscore\n // .replace(/^\\//, '') + // Remove leading slash\n // (str.endsWith('/') ? '' : '/')\n // );\n}\n"]}
1
+ {"version":3,"file":"filepaths.js","sourceRoot":"","sources":["../src/filepaths.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Splits a file path into its directory, name, and extension components.\n * @param filePath - The full file path to split\n * @returns An object containing the directory path, file name (without extension), and extension\n * @example\n * splitFilePath(\"path/to/file.txt\") // returns { dir: \"path/to\", name: \"file\", ext: \"txt\" }\n */\nexport function splitFilePath(filePath: string): {\n dir: string;\n name: string;\n ext: string;\n filename: string;\n} {\n const pathParts = filePath.split('/');\n const file = pathParts.pop() || '';\n\n const dotIndex = file.lastIndexOf('.');\n if (dotIndex === -1 || dotIndex === 0)\n return {dir: pathParts.join('/'), name: file, ext: '', filename: file};\n\n const name = file.substring(0, dotIndex);\n const ext = file.substring(dotIndex + 1);\n\n return {dir: pathParts.join('/'), name, ext, filename: `${name}.${ext}`};\n}\n\n/**\n * Converts a filename into a valid column or table name for database use.\n * - Removes file extension\n * - Replaces invalid characters with underscores\n * - Ensures the name starts with a letter or underscore\n * - Truncates to max length of 63 characters\n *\n * @param filename - The original filename to convert\n * @returns A valid table/column name\n * @example\n * convertToValidColumnOrTableName(\"my-file.csv\") // returns \"my_file\"\n * convertToValidColumnOrTableName(\"123data.csv\") // returns \"_123data\"\n */\nexport function convertToValidColumnOrTableName(filename: string): string {\n // Remove file extension\n const base = filename.replace(/\\.[^/.]+$/, '');\n\n // Replace any invalid character with underscore, and convert to lowercase\n let tableName = base.replace(/[^a-z0-9_]/gi, '_');\n\n // If the first character is a number, prepend an underscore\n if (/^\\d/.test(tableName)) {\n tableName = '_' + tableName;\n }\n\n // Truncate to the max length 63\n if (tableName.length > 63) {\n tableName = tableName.substring(0, 63);\n }\n\n return tableName;\n}\n\n/**\n * Converts a filename into a valid and unique column or table name for database use.\n * - Removes file extension\n * - Replaces invalid characters with underscores\n * - Ensures the name starts with a letter or underscore\n * - Truncates to max length of 63 characters\n * - Ensures uniqueness among existing names\n *\n * @param filename - The original filename to convert\n * @param existingTables - Optional array of existing table names to ensure uniqueness\n * @returns A valid and unique table/column name\n * @example\n * convertToUniqueColumnOrTableName(\"my-file.csv\") // returns \"my_file\"\n * convertToUniqueColumnOrTableName(\"123data.csv\") // returns \"_123data\"\n */\nexport function convertToUniqueColumnOrTableName(\n filename: string,\n existingTables?: string[],\n): string {\n const tableName = convertToValidColumnOrTableName(filename);\n return generateUniqueName(tableName, existingTables);\n}\n\n/**\n * Generates a unique name by appending a numeric suffix if the name already exists.\n * @param name - The base name to make unique\n * @param usedNames - Optional array of existing names to check against\n * @returns A unique name, potentially with a numeric suffix\n * @example\n * generateUniqueName(\"table\", [\"table\"]) // returns \"table_1\"\n * generateUniqueName(\"table_1\", [\"table_1\"]) // returns \"table_2\"\n */\nexport function generateUniqueName(name: string, usedNames?: string[]) {\n const usedNamesLower = usedNames?.map((n) => n.toLowerCase());\n\n // If tableName exists in the list\n if (usedNamesLower?.includes(name.toLowerCase())) {\n let baseName: string | undefined = name;\n let i = 0;\n\n // If tableName ends with `_${i}` pattern, update the baseTableName and i\n const matched = name.match(/^(.+)_(\\d+)$/);\n if (matched) {\n baseName = matched[1];\n i = Number(matched[2]);\n }\n\n do {\n i++;\n name = `${baseName}_${i}`;\n } while (usedNamesLower.includes(name.toLowerCase()));\n }\n\n return name;\n}\n\n/**\n * Generates a unique file path by appending a numeric suffix if the path already exists.\n * @param filePath - The original file path\n * @param existingPaths - Array of existing file paths to check against\n * @returns A unique file path\n * @example\n * generateUniquePath(\"file.txt\", [\"file.txt\"]) // returns \"file_1.txt\"\n */\nexport function generateUniquePath(\n filePath: string,\n existingPaths: string[],\n): string {\n let nextPath = filePath;\n if (existingPaths?.includes(filePath)) {\n const {dir, name, ext} = splitFilePath(filePath);\n\n let i = 0;\n let baseName: string | undefined = name;\n const matched = name.match(/^(.+)_(\\d+)$/);\n if (matched) {\n baseName = matched[1];\n i = Number(matched[2]);\n }\n\n do {\n i++;\n const fname = `${baseName}_${i}${ext ? `.${ext}` : ''}`;\n nextPath = `${dir}${dir ? '/' : ''}${fname}`;\n } while (existingPaths.includes(nextPath));\n }\n\n return nextPath;\n}\n\n/**\n * Converts a string into a valid and unique S3 object name.\n * - Replaces special characters with underscores\n * - Ensures name is within S3's length limits\n * - Ensures uniqueness among existing objects\n *\n * @param str - The string to convert into an S3 object name\n * @param existingObjects - Optional array of existing S3 object names to ensure uniqueness\n * @returns A valid and unique S3 object name\n * @example\n * convertToUniqueS3ObjectName(\"my file.txt\") // returns \"my_file.txt\"\n */\nexport function convertToUniqueS3ObjectName(\n str: string,\n existingObjects?: string[],\n): string {\n let rv = str\n .trim() // Remove leading and trailing white spaces\n .replace(/[^\\w\\s-\\.]/g, '_') // Replace special characters with underscores\n .replace(/\\s+/g, '_') // Replace consecutive spaces with a single underscore\n // .replace(/_+/g, '_') // Remove consecutive underscores\n // .replace(/^_/, '') // Remove leading underscores\n // .replace(/_$/, '') // Remove trailing underscores\n .slice(0, 255); // Truncate the string if it exceeds 255 characters\n\n if (existingObjects?.length) {\n rv = generateUniquePath(rv, existingObjects);\n }\n\n return rv;\n}\n\n/**\n * Converts a string into a valid and unique S3 folder path.\n * - Ensures the path ends with a forward slash\n * - Replaces special characters with underscores\n * - Ensures uniqueness among existing paths\n *\n * @param str - The string to convert into an S3 folder path\n * @param existingObjects - Optional array of existing S3 paths to ensure uniqueness\n * @returns A valid and unique S3 folder path ending with a forward slash\n * @example\n * convertToUniqueS3FolderPath(\"my folder\") // returns \"my_folder/\"\n */\nexport function convertToUniqueS3FolderPath(\n str: string,\n existingObjects?: string[],\n): string {\n let next = convertToUniqueS3ObjectName(str, existingObjects);\n if (!next.endsWith('/')) next += '/'; // Add trailing slash if not present\n return next;\n // return (\n // str\n // .trim() // Remove leading and trailing white spaces\n // .replace(/\\/+/g, '/') // Replace consecutive slashes with a single slash\n // .replace(/[^\\w\\s-\\/]/g, '_') // Replace special characters with underscores\n // .replace(/\\s+/g, '_') // Replace consecutive spaces with a single underscore\n // .replace(/^\\//, '') + // Remove leading slash\n // (str.endsWith('/') ? '' : '/')\n // );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/utils",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
@@ -41,5 +41,5 @@
41
41
  "react": "^19.0.0",
42
42
  "usehooks-ts": "^3.1.1"
43
43
  },
44
- "gitHead": "7b5e727b79d675c17b93412c109d1ba1b22699c8"
44
+ "gitHead": "03b1163a54c237d09632b07396f9b4f9a47aed15"
45
45
  }