@ts-for-gir/lib 4.0.0-beta.40 → 4.0.0-beta.42

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-for-gir/lib",
3
- "version": "4.0.0-beta.40",
3
+ "version": "4.0.0-beta.42",
4
4
  "description": "Typescript .d.ts generator from GIR for gjs",
5
5
  "main": "src/index.ts",
6
6
  "module": "src/index.ts",
@@ -41,18 +41,19 @@
41
41
  "type definitions"
42
42
  ],
43
43
  "devDependencies": {
44
+ "@ts-for-gir/tsconfig": "^4.0.0-beta.42",
44
45
  "@types/ejs": "^3.1.5",
45
46
  "@types/lodash": "^4.17.24",
46
- "@types/node": "^24.11.0",
47
+ "@types/node": "^24.12.0",
47
48
  "rimraf": "^6.1.3",
48
49
  "typescript": "^5.9.3"
49
50
  },
50
51
  "dependencies": {
51
- "@gi.ts/parser": "^4.0.0-beta.40",
52
- "@ts-for-gir/reporter": "^4.0.0-beta.40",
53
- "@ts-for-gir/templates": "^4.0.0-beta.40",
52
+ "@gi.ts/parser": "^4.0.0-beta.42",
53
+ "@ts-for-gir/reporter": "^4.0.0-beta.42",
54
+ "@ts-for-gir/templates": "^4.0.0-beta.42",
54
55
  "colorette": "^2.0.20",
55
- "ejs": "^4.0.1",
56
+ "ejs": "^5.0.1",
56
57
  "glob": "^13.0.6",
57
58
  "lodash": "^4.17.23"
58
59
  }
package/src/constants.ts CHANGED
@@ -8,61 +8,27 @@ export const PARAM_REG_EXP = /[0-9a-zA-Z_]*:/g;
8
8
  export const OPT_PARAM_REG_EXP = /[0-9a-zA-Z_]*\?:/g;
9
9
  export const NEW_LINE_REG_EXP = /[\n\r]+/g;
10
10
 
11
- /**
12
- * Package information interface for package.json
13
- */
14
- interface Package {
15
- name: string;
16
- version: string;
17
- description: string;
18
- license: string;
19
- homepage: string;
20
- author: string;
21
- }
11
+ declare const __TS_FOR_GIR_VERSION__: string;
22
12
 
23
13
  /**
24
- * Resolves the current package's package.json path
25
- * Uses import.meta.url for ES Module compatibility
26
- * Works both in workspace and after publishing
14
+ * Reads the package version, using the build-time injected value when bundled
15
+ * or falling back to reading package.json in development mode.
27
16
  */
28
- function resolvePackageJson(): string {
29
- try {
30
- // Get the directory of the current module
31
- const currentModulePath = fileURLToPath(import.meta.url);
32
- const currentDir = dirname(currentModulePath);
33
-
34
- // Go up to the package root (src/ -> package root)
35
- const packageRoot = join(currentDir, "..");
36
- const packageJsonPath = join(packageRoot, "package.json");
37
-
38
- return packageJsonPath;
39
- } catch (error) {
40
- throw new Error(`Unable to resolve package.json path: ${error instanceof Error ? error.message : "Unknown error"}`);
17
+ function getPackageVersion(): string {
18
+ if (typeof __TS_FOR_GIR_VERSION__ !== "undefined") {
19
+ return __TS_FOR_GIR_VERSION__;
41
20
  }
21
+ const currentModulePath = fileURLToPath(import.meta.url);
22
+ const currentDir = dirname(currentModulePath);
23
+ const packageJsonPath = join(currentDir, "..", "package.json");
24
+ const content = readFileSync(packageJsonPath, "utf-8");
25
+ return (JSON.parse(content) as { version: string }).version;
42
26
  }
43
27
 
44
- /**
45
- * Reads and parses the current package's package.json file synchronously
46
- * Contains version and metadata for this specific package
47
- */
48
- function readPackageSync(): Package {
49
- try {
50
- const packagePath = resolvePackageJson();
51
- const content = readFileSync(packagePath, "utf-8");
52
- return JSON.parse(content) as Package;
53
- } catch (error) {
54
- const message = error instanceof Error ? error.message : "Unknown error";
55
- throw new Error(`Failed to read package.json: ${message}`);
56
- }
57
- }
58
-
59
- // Read package information once at module load
60
- export const PACKAGE = readPackageSync();
61
-
62
28
  export const APP_NAME = "ts-for-gir";
63
29
  export const APP_USAGE = "TypeScript type definition generator for GObject introspection GIR files";
64
30
  export const APP_SOURCE = "https://github.com/gjsify/ts-for-gir";
65
- export const APP_VERSION = PACKAGE.version;
31
+ export const APP_VERSION = getPackageVersion();
66
32
 
67
33
  export const PACKAGE_DESC = (packageName: string, libraryVersion?: LibraryVersion) => {
68
34
  if (libraryVersion) {
@@ -149,4 +115,4 @@ export const RESERVED_CLASS_NAMES = [
149
115
 
150
116
  export const RESERVED_FUNCTION_NAMES = ["false", "true", "break"];
151
117
 
152
- export const RESERVED_NAMESPACE_NAMES = {};
118
+ export const RESERVED_NAMESPACE_NAMES: Record<string, boolean> = {};
package/src/gir/alias.ts CHANGED
@@ -2,7 +2,7 @@ import type { FormatGenerator, GenericDescriptor } from "../generators/generator
2
2
  import type { TypeExpression } from "../gir.ts";
3
3
  import type { GirAliasElement } from "../index.ts";
4
4
  import type { IntrospectedOptions, OptionsLoad } from "../types/index.ts";
5
- import { parseDoc, parseMetadata } from "../utils/gir-parsing.ts";
5
+ import { girParsingReporter, parseDoc, parseMetadata } from "../utils/gir-parsing.ts";
6
6
  import { isIntrospectable } from "../utils/girs.ts";
7
7
  import { sanitizeIdentifierName } from "../utils/naming.ts";
8
8
  import { getAliasType } from "../utils/types.ts";
@@ -52,7 +52,7 @@ export class IntrospectedAlias extends IntrospectedNamespaceMember {
52
52
 
53
53
  static fromXML(element: GirAliasElement, ns: IntrospectedNamespace, options: OptionsLoad): IntrospectedAlias | null {
54
54
  if (!element.$.name) {
55
- console.error(`Alias in ${ns.namespace} lacks name.`);
55
+ girParsingReporter.get().reportParsingFailure("alias", "alias", ns.namespace, "Alias lacks name attribute");
56
56
  return null;
57
57
  }
58
58
 
@@ -72,6 +72,8 @@ export class IntrospectedClassFunction<
72
72
  protected _generify: boolean = false;
73
73
  interfaceParent: IntrospectedBaseClass | IntrospectedEnum | null = null;
74
74
  returnTypeDoc?: string | null;
75
+ /** If this function was generated from a signal, stores the signal name. */
76
+ signalOrigin?: string;
75
77
 
76
78
  generics: Generic[] = [];
77
79
 
@@ -794,105 +796,66 @@ export class IntrospectedClass extends IntrospectedBaseClass {
794
796
  );
795
797
  }
796
798
 
797
- implementedProperties(potentialConflicts: IntrospectedBase<never>[] = []) {
799
+ private collectImplementedItems<T extends { name: string }>(
800
+ getItems: (node: IntrospectedBaseClass) => T[],
801
+ validate: (item: T) => boolean,
802
+ ): Map<string, T> {
798
803
  const resolution = this.resolveParents();
799
804
  const implementedOnParent = [...(resolution.extends() ?? [])].flatMap((r) => r.implements());
800
- const properties = new Map<string, IntrospectedProperty>();
801
-
802
- const validateProp = (prop: IntrospectedProperty) =>
803
- !this.hasInstanceSymbol(prop) &&
804
- !properties.has(prop.name) &&
805
- potentialConflicts.every((p) => prop.name !== p.name);
805
+ const items = new Map<string, T>();
806
806
 
807
807
  for (const implemented of resolution.implements()) {
808
808
  if (implemented.node instanceof IntrospectedClass) continue;
809
-
810
809
  if (implementedOnParent.find((p) => p.identifier.equals(implemented.identifier))?.node?.generics?.length === 0)
811
810
  continue;
812
- for (const prop of implemented.node.props) {
813
- if (!validateProp(prop)) continue;
814
- properties.set(prop.name, prop);
811
+ for (const item of getItems(implemented.node)) {
812
+ if (items.has(item.name) || !validate(item)) continue;
813
+ items.set(item.name, item);
815
814
  }
816
815
  }
817
816
 
818
817
  for (const implemented of resolution.implements()) {
819
818
  [...implemented].forEach((e) => {
820
819
  if (e.node instanceof IntrospectedClass) return;
821
-
822
820
  if (implementedOnParent.find((p) => p.identifier.equals(e.identifier))?.node.generics.length === 0) return;
823
- for (const prop of e.node.props) {
824
- if (!validateProp(prop)) continue;
825
-
826
- properties.set(prop.name, prop);
821
+ for (const item of getItems(e.node)) {
822
+ if (items.has(item.name) || !validate(item)) continue;
823
+ items.set(item.name, item);
827
824
  }
828
825
  });
829
826
  }
830
827
 
831
828
  // If an interface inherits from a class (such as Gtk.Widget)
832
- // we need to pull in every property from that class...
829
+ // we need to pull in every item from that class...
833
830
  for (const implemented of resolution.implements()) {
834
831
  const extended = implemented.extends();
835
-
836
832
  if (extended?.node instanceof IntrospectedClass) {
837
- for (const prop of extended.node.props) {
838
- if (!validateProp(prop)) continue;
839
-
840
- properties.set(prop.name, prop);
833
+ for (const item of getItems(extended.node)) {
834
+ if (items.has(item.name) || !validate(item)) continue;
835
+ items.set(item.name, item);
841
836
  }
842
837
  }
843
838
  }
844
839
 
840
+ return items;
841
+ }
842
+
843
+ implementedProperties(potentialConflicts: IntrospectedBase<never>[] = []) {
844
+ const properties = this.collectImplementedItems(
845
+ (node) => node.props,
846
+ (prop) => !this.hasInstanceSymbol(prop) && potentialConflicts.every((p) => prop.name !== p.name),
847
+ );
845
848
  return [...properties.values()];
846
849
  }
847
850
 
848
851
  implementedMethods(potentialConflicts: ClassMember[] = []) {
849
- const resolution = this.resolveParents();
850
- const implementedOnParent = [...(resolution.extends() ?? [])].flatMap((r) => r.implements());
851
- const methods = new Map<string, IntrospectedClassFunction>();
852
-
853
- const validateMethod = (method: IntrospectedClassFunction) =>
854
- !(method instanceof IntrospectedStaticClassFunction) &&
855
- !this.hasInstanceSymbol(method) &&
856
- !methods.has(method.name) &&
857
- potentialConflicts.every((m) => method.name !== m.name);
858
-
859
- for (const implemented of resolution.implements()) {
860
- if (implemented.node instanceof IntrospectedClass) continue;
861
-
862
- if (implementedOnParent.find((p) => p.identifier.equals(implemented.identifier))?.node?.generics?.length === 0)
863
- continue;
864
- for (const member of implemented.node.members) {
865
- if (!validateMethod(member)) continue;
866
- methods.set(member.name, member);
867
- }
868
- }
869
-
870
- for (const implemented of resolution.implements()) {
871
- [...implemented].forEach((e) => {
872
- if (e.node instanceof IntrospectedClass) return;
873
-
874
- if (implementedOnParent.find((p) => p.identifier.equals(e.identifier))?.node.generics.length === 0) return;
875
- for (const member of e.node.members) {
876
- if (!validateMethod(member)) continue;
877
-
878
- methods.set(member.name, member);
879
- }
880
- });
881
- }
882
-
883
- // If an interface inherits from a class (such as Gtk.Widget)
884
- // we need to pull in every method from that class...
885
- for (const implemented of resolution.implements()) {
886
- const extended = implemented.extends();
887
-
888
- if (extended?.node instanceof IntrospectedClass) {
889
- for (const member of extended.node.members) {
890
- if (!validateMethod(member)) continue;
891
-
892
- methods.set(member.name, member);
893
- }
894
- }
895
- }
852
+ const methods = this.collectImplementedItems(
853
+ (node) => node.members,
854
+ (method) =>
855
+ !(method instanceof IntrospectedStaticClassFunction) &&
856
+ !this.hasInstanceSymbol(method) &&
857
+ potentialConflicts.every((m) => method.name !== m.name),
858
+ );
896
859
 
897
860
  return [...methods.values()].map((f) => {
898
861
  const mapping = new Map<string, TypeExpression>();
package/src/gir/record.ts CHANGED
@@ -248,7 +248,7 @@ export class IntrospectedRecord extends IntrospectedBaseClass {
248
248
  namespace: IntrospectedNamespace,
249
249
  name: string,
250
250
  ): void {
251
- const gtypeStructFor = element.$["glib:is-gtype-struct-for"];
251
+ const gtypeStructFor = "glib:is-gtype-struct-for" in element.$ ? element.$["glib:is-gtype-struct-for"] : undefined;
252
252
 
253
253
  if (typeof gtypeStructFor === "string" && gtypeStructFor) {
254
254
  const structFor = parseTypeIdentifier(namespace.namespace, gtypeStructFor);
@@ -13,7 +13,6 @@ import { InterfaceVisitor } from "../validators/interface.ts";
13
13
  import type { GirVisitor } from "../visitor.ts";
14
14
  import type { IntrospectedNamespace } from "./namespace.ts";
15
15
 
16
- // TODO: Singleton
17
16
  export class NSRegistry {
18
17
  mapping: TwoKeyMap<string, string, IntrospectedNamespace> = new TwoKeyMap();
19
18
  private formatters: Map<string, Formatter> = new Map();
package/src/gir/signal.ts CHANGED
@@ -34,12 +34,20 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
34
34
  parameters: IntrospectedFunctionParameter[];
35
35
  return_type: TypeExpression;
36
36
  detailed: boolean;
37
+ action: boolean;
38
+ noRecurse: boolean;
39
+ noHooks: boolean;
40
+ when?: "first" | "last" | "cleanup";
37
41
 
38
42
  constructor({
39
43
  name,
40
44
  parameters = [],
41
45
  return_type = UnknownType,
42
46
  detailed = false,
47
+ action = false,
48
+ noRecurse = false,
49
+ noHooks = false,
50
+ when,
43
51
  parent,
44
52
  ...args
45
53
  }: Options<{
@@ -47,6 +55,10 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
47
55
  parameters?: IntrospectedFunctionParameter[];
48
56
  return_type?: TypeExpression;
49
57
  detailed?: boolean;
58
+ action?: boolean;
59
+ noRecurse?: boolean;
60
+ noHooks?: boolean;
61
+ when?: "first" | "last" | "cleanup";
50
62
  parent: IntrospectedClass;
51
63
  }>) {
52
64
  super(name, parent, { ...args });
@@ -54,6 +66,10 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
54
66
  this.parameters = parameters.map((p) => p.copy({ parent: this }));
55
67
  this.return_type = return_type;
56
68
  this.detailed = detailed;
69
+ this.action = action;
70
+ this.noRecurse = noRecurse;
71
+ this.noHooks = noHooks;
72
+ this.when = when;
57
73
  }
58
74
 
59
75
  accept(visitor: GirVisitor): IntrospectedSignal {
@@ -72,11 +88,19 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
72
88
  parameters,
73
89
  returnType,
74
90
  detailed,
91
+ action,
92
+ noRecurse,
93
+ noHooks,
94
+ when,
75
95
  }: {
76
96
  parent?: IntrospectedClass;
77
97
  parameters?: IntrospectedFunctionParameter[];
78
98
  returnType?: TypeExpression;
79
99
  detailed?: boolean;
100
+ action?: boolean;
101
+ noRecurse?: boolean;
102
+ noHooks?: boolean;
103
+ when?: "first" | "last" | "cleanup";
80
104
  } = {}): IntrospectedSignal {
81
105
  return new IntrospectedSignal({
82
106
  name: this.name,
@@ -84,6 +108,10 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
84
108
  parameters: parameters ?? this.parameters,
85
109
  return_type: returnType ?? this.return_type,
86
110
  detailed: detailed ?? this.detailed,
111
+ action: action ?? this.action,
112
+ noRecurse: noRecurse ?? this.noRecurse,
113
+ noHooks: noHooks ?? this.noHooks,
114
+ when: when ?? this.when,
87
115
  })._copyBaseProperties(this);
88
116
  }
89
117
 
@@ -93,6 +121,10 @@ export class IntrospectedSignal extends IntrospectedClassMember<IntrospectedClas
93
121
  name: element.$.name,
94
122
  parent,
95
123
  detailed: element.$.detailed === "1",
124
+ action: element.$.action === "1",
125
+ noRecurse: element.$["no-recurse"] === "1",
126
+ noHooks: element.$["no-hooks"] === "1",
127
+ when: element.$.when as "first" | "last" | "cleanup" | undefined,
96
128
  isIntrospectable: isIntrospectable(element),
97
129
  });
98
130