true-pg 0.4.4 → 0.5.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.
package/lib/index.js CHANGED
@@ -17,7 +17,9 @@ const filter_overloaded_functions = (functions) => {
17
17
  }, {});
18
18
  return [
19
19
  functions.filter(func => counts[func.name] === 1),
20
- functions.filter(func => counts[func.name] > 1),
20
+ Object.entries(counts)
21
+ .filter(([_, count]) => count > 1)
22
+ .map(([name]) => name),
21
23
  ];
22
24
  };
23
25
  const filter_function = (func) => {
@@ -93,9 +95,9 @@ const multifile = async (generators, schemas, opts) => {
93
95
  for (const schema of Object.values(schemas)) {
94
96
  console.log("Selected schema '%s':\n", schema.name);
95
97
  const schemaDir = joinpath(out, schema.name);
96
- const [supported_functions, unsupported_functions] = filter_unsupported_functions(schema.functions);
97
- const [unique_functions, overloaded_functions] = filter_overloaded_functions(supported_functions);
98
- schema.functions = unique_functions;
98
+ const [unique_functions, overloaded_functions] = filter_overloaded_functions(schema.functions);
99
+ const [supported_functions, unsupported_functions] = filter_unsupported_functions(unique_functions);
100
+ schema.functions = supported_functions;
99
101
  {
100
102
  const skipped = unsupported_functions.map(f => ` - ${f.name}`);
101
103
  if (skipped.length) {
@@ -104,7 +106,7 @@ const multifile = async (generators, schemas, opts) => {
104
106
  }
105
107
  }
106
108
  {
107
- const skipped = overloaded_functions.map(f => ` - ${f.name}`);
109
+ const skipped = overloaded_functions.map(f => ` - ${f}`);
108
110
  if (skipped.length) {
109
111
  warnings.push(`Skipping ${skipped.length} overloaded functions (not supported):\n` + skipped.join("\n"));
110
112
  }
@@ -1,13 +1,7 @@
1
1
  import { Canonical, FunctionReturnTypeKind, } from "../extractor/index.js";
2
2
  import { allowed_kind_names, createGenerator, Nodes } from "../types.js";
3
3
  import { builtins } from "./builtins.js";
4
- import { join, quote, quoteI } from "../util.js";
5
- const toPascalCase = (str) => str
6
- .replace(/^[^a-zA-Z]+/, "") // remove leading non-alphabetic characters
7
- .replace(/[^a-zA-Z0-9_]+/g, "") // remove non-alphanumeric/underscore characters
8
- .replace(" ", "_") // replace spaces with underscores
9
- .replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()) // capitalize letters after underscores
10
- .replace(/^([a-z])/, (_, letter) => letter.toUpperCase()); // capitalize first letter
4
+ import { toPascalCase, join, quote, quoteI } from "../util.js";
11
5
  export const Kysely = createGenerator(opts => {
12
6
  const defaultSchema = opts?.defaultSchema ?? "public";
13
7
  const ky = (imports, name) => imports.add(new Nodes.ExternalImport({
package/lib/util.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export declare const toPascalCase: (str: string) => string;
2
+ export declare const to_snake_case: (str: string) => string;
1
3
  export declare const join: (parts: Iterable<string>, joiner?: string) => string;
2
4
  export type UnionKeys<T> = T extends unknown ? keyof T : never;
3
5
  type AddOptionalKeys<K extends PropertyKey> = {
package/lib/util.js CHANGED
@@ -1,3 +1,113 @@
1
+ export const toPascalCase = (str) => {
2
+ let result = "";
3
+ let index = 0;
4
+ let space = false;
5
+ let leading = true;
6
+ const len = str.length;
7
+ while (index < len) {
8
+ const char = str[index];
9
+ // keep trailing underscores
10
+ if (index === len - 1 && char === "_") {
11
+ // iterate backwards until a non-underscore character is found
12
+ let index = len - 1;
13
+ while (index >= 0 && str[index] === "_") {
14
+ result += "_";
15
+ index--;
16
+ }
17
+ break;
18
+ }
19
+ if (leading) {
20
+ if (char === "_") {
21
+ result += char;
22
+ }
23
+ else if (/[a-zA-Z]/.test(char)) {
24
+ result += char.toUpperCase();
25
+ leading = false;
26
+ }
27
+ else {
28
+ // skip leading non-alphabetic characters
29
+ }
30
+ }
31
+ else if (/[a-zA-Z0-9]/.test(char)) {
32
+ // valid characters
33
+ if (space)
34
+ result += char.toUpperCase();
35
+ else
36
+ result += char;
37
+ space = false;
38
+ }
39
+ else {
40
+ // invalid characters, space, underscore, or hyphen
41
+ // treat as space
42
+ space = true;
43
+ }
44
+ index++;
45
+ }
46
+ return result;
47
+ };
48
+ export const to_snake_case = (str) => {
49
+ let result = "";
50
+ let index = 0;
51
+ let space = false;
52
+ let leading = true;
53
+ let upper = false;
54
+ const len = str.length;
55
+ while (index < len) {
56
+ const char = str[index];
57
+ // keep trailing underscores
58
+ if (index === len - 1 && char === "_") {
59
+ // iterate backwards until a non-underscore character is found
60
+ let index = len - 1;
61
+ while (index >= 0 && str[index] === "_") {
62
+ result += "_";
63
+ index--;
64
+ }
65
+ break;
66
+ }
67
+ if (leading) {
68
+ if (char === "_") {
69
+ result += char;
70
+ }
71
+ else if (/[A-Z]/.test(char)) {
72
+ result += char.toLowerCase();
73
+ leading = false;
74
+ upper = true;
75
+ }
76
+ else if (/[a-z]/.test(char)) {
77
+ result += char.toLowerCase();
78
+ leading = false;
79
+ }
80
+ else {
81
+ // skip leading non-alphabetic characters
82
+ }
83
+ }
84
+ else if (/[A-Z]/.test(char)) {
85
+ if (!upper)
86
+ result += "_";
87
+ if (space)
88
+ result += "_";
89
+ // uppercase characters
90
+ result += char.toLowerCase();
91
+ space = false;
92
+ upper = true;
93
+ }
94
+ else if (/[a-z0-9]/.test(char)) {
95
+ // valid characters
96
+ if (space)
97
+ result += "_";
98
+ result += char;
99
+ space = false;
100
+ upper = false;
101
+ }
102
+ else {
103
+ // invalid characters, space, underscore, or hyphen
104
+ // treat as space
105
+ space = true;
106
+ }
107
+ index++;
108
+ }
109
+ return result;
110
+ };
1
111
  export const join = (parts, joiner = "\n\n") => Array.from(parts).filter(Boolean).join(joiner);
2
112
  const isIdentifierInvalid = (str) => {
3
113
  const invalid = str.match(/[^a-zA-Z0-9_]/);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,78 @@
1
+ import { describe, it, expect } from "bun:test";
2
+ import { toPascalCase, to_snake_case } from "./util.js";
3
+ describe("toPascalCase", () => {
4
+ it("should convert a string to PascalCase", () => {
5
+ expect(toPascalCase("hello-world")).toBe("HelloWorld");
6
+ });
7
+ it("should skip leading invalid characters", () => {
8
+ expect(toPascalCase("123hello-world")).toBe("HelloWorld");
9
+ });
10
+ it("should skip leading spaces", () => {
11
+ expect(toPascalCase(" hello-world")).toBe("HelloWorld");
12
+ });
13
+ it("should keep leading underscores", () => {
14
+ expect(toPascalCase("__hello-world")).toBe("__HelloWorld");
15
+ });
16
+ it("should keep trailing underscores", () => {
17
+ expect(toPascalCase("hello_world___")).toBe("HelloWorld___");
18
+ });
19
+ it("should keep leading and trailing underscores", () => {
20
+ expect(toPascalCase("__hello_world__")).toBe("__HelloWorld__");
21
+ });
22
+ it("should convert spaces to uppercase", () => {
23
+ expect(toPascalCase("hello world")).toBe("HelloWorld");
24
+ });
25
+ it("should convert hyphens to uppercase", () => {
26
+ expect(toPascalCase("hello-world")).toBe("HelloWorld");
27
+ });
28
+ it("should convert camelCase to PascalCase", () => {
29
+ expect(toPascalCase("helloWorld")).toBe("HelloWorld");
30
+ });
31
+ it("should convert snake_case to PascalCase", () => {
32
+ expect(toPascalCase("hello_world")).toBe("HelloWorld");
33
+ });
34
+ it("should skip invalid characters", () => {
35
+ expect(toPascalCase("hello?world!")).toBe("HelloWorld");
36
+ });
37
+ it("should generate valid identifier", () => {
38
+ expect(toPascalCase(" _ hello ? world !")).toBe("_HelloWorld");
39
+ });
40
+ });
41
+ describe("to_snake_case", () => {
42
+ it("should convert a string to snake_case", () => {
43
+ expect(to_snake_case("hello-world")).toBe("hello_world");
44
+ });
45
+ it("should skip leading invalid characters", () => {
46
+ expect(to_snake_case("123hello-world")).toBe("hello_world");
47
+ });
48
+ it("should skip leading spaces", () => {
49
+ expect(to_snake_case(" hello-world")).toBe("hello_world");
50
+ });
51
+ it("should keep leading underscores", () => {
52
+ expect(to_snake_case("__hello-world")).toBe("__hello_world");
53
+ });
54
+ it("should keep trailing underscores", () => {
55
+ expect(to_snake_case("hello_world___")).toBe("hello_world___");
56
+ });
57
+ it("should keep leading and trailing underscores", () => {
58
+ expect(to_snake_case("__hello_world__")).toBe("__hello_world__");
59
+ });
60
+ it("should convert spaces to underscores", () => {
61
+ expect(to_snake_case("hello world")).toBe("hello_world");
62
+ });
63
+ it("should convert camelCase to snake_case", () => {
64
+ expect(to_snake_case("helloWorld")).toBe("hello_world");
65
+ });
66
+ it("should convert PascalCase to snake_case", () => {
67
+ expect(to_snake_case("HelloWorld")).toBe("hello_world");
68
+ });
69
+ it("should skip invalid characters", () => {
70
+ expect(to_snake_case("hello?world!")).toBe("hello_world");
71
+ });
72
+ it("should generate valid identifier", () => {
73
+ expect(to_snake_case(" _ hello ? world !")).toBe("_hello_world");
74
+ });
75
+ it("should convert uppercase characters to underscores", () => {
76
+ expect(to_snake_case("HELLO_WORLD")).toBe("hello_world");
77
+ });
78
+ });
package/lib/zod/index.js CHANGED
@@ -1,13 +1,8 @@
1
1
  import { FunctionReturnTypeKind, } from "../extractor/index.js";
2
2
  import { allowed_kind_names, createGenerator, Nodes } from "../types.js";
3
3
  import { builtins } from "./builtins.js";
4
- import { join, quote, quoteI } from "../util.js";
5
- const to_snake_case = (str) => str
6
- .replace(/^[^a-zA-Z]+/, "") // remove leading non-alphabetic characters
7
- .replace(/[^a-zA-Z0-9]+/g, "_") // replace non-alphanumeric characters with underscores
8
- .replace(/([A-Z])/g, "_$1") // insert underscores before uppercase letters
9
- .toLowerCase();
10
- // TODO: create an insert and update zod interface for each type
4
+ import { to_snake_case, join, quote, quoteI } from "../util.js";
5
+ // TODO: create an insert and update zod interface for each type?
11
6
  export const Zod = createGenerator(opts => {
12
7
  const defaultSchema = opts?.defaultSchema ?? "public";
13
8
  const zod = (imports, name) => imports.add(new Nodes.ExternalImport({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "true-pg",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "module": "lib/index.js",
6
6
  "main": "lib/index.js",