@geexcode/geex-angular 0.0.1

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.
@@ -0,0 +1,65 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
6
+ var __typeError = (msg) => {
7
+ throw TypeError(msg);
8
+ };
9
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
11
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
12
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
13
+ }) : x)(function(x) {
14
+ if (typeof require !== "undefined") return require.apply(this, arguments);
15
+ throw Error('Dynamic require of "' + x + '" is not supported');
16
+ });
17
+ var __commonJS = (cb, mod) => function __require2() {
18
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
19
+ };
20
+ var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
21
+ var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
22
+ var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
23
+ var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
24
+ var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
25
+ var __runInitializers = (array, flags, self, value) => {
26
+ for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
27
+ return value;
28
+ };
29
+ var __decorateElement = (array, flags, name, decorators, target, extra) => {
30
+ var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
31
+ var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
32
+ var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
33
+ var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
34
+ return __privateGet(this, extra);
35
+ }, set [name](x) {
36
+ return __privateSet(this, extra, x);
37
+ } }, name));
38
+ k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
39
+ for (var i = decorators.length - 1; i >= 0; i--) {
40
+ ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
41
+ if (k) {
42
+ ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
43
+ if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
44
+ if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
45
+ }
46
+ it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
47
+ if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
48
+ else if (typeof it !== "object" || it === null) __typeError("Object expected");
49
+ else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
50
+ }
51
+ return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
52
+ };
53
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
54
+ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
55
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
56
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
57
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
58
+
59
+ export {
60
+ __require,
61
+ __commonJS,
62
+ __decoratorStart,
63
+ __runInitializers,
64
+ __decorateElement
65
+ };
@@ -0,0 +1,15 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+ var __commonJS = (cb, mod) => function __require2() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+
12
+ export {
13
+ __require,
14
+ __commonJS
15
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ESBuild plugin to handle .gql imports and redirect them to .gql.ts files
3
+ *
4
+ * This plugin resolves .gql imports by checking if a corresponding .gql.ts file exists.
5
+ * If it does, it redirects the import to the .gql.ts file. Otherwise, it lets esbuild
6
+ * handle the .gql file normally.
7
+ *
8
+ * Now supports TypeScript path aliases for proper module resolution.
9
+ *
10
+ * @param {GqlRedirectPluginOptions} [options]
11
+ * @returns {Plugin}
12
+ */
13
+ declare function gqlRedirectPlugin(options?: GqlRedirectPluginOptions): Plugin;
14
+ declare namespace gqlRedirectPlugin {
15
+ export { gqlRedirectPlugin as default, gqlRedirectPlugin, type Plugin, type GqlRedirectPluginOptions, type PathMapping };
16
+ }
17
+ type Plugin = any;
18
+ type GqlRedirectPluginOptions = {
19
+ /**
20
+ * Whether to enable verbose logging
21
+ */
22
+ verbose?: boolean | undefined;
23
+ /**
24
+ * Path to tsconfig.json file for path alias resolution
25
+ */
26
+ tsconfigPath?: string | undefined;
27
+ /**
28
+ * Whether to automatically run pnpm gqlgen when .gql.ts files are missing
29
+ */
30
+ autoGqlGen?: boolean | undefined;
31
+ };
32
+ type PathMapping = {
33
+ alias: string;
34
+ paths: string[];
35
+ };
36
+
37
+ export { gqlRedirectPlugin as default };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ESBuild plugin to handle .gql imports and redirect them to .gql.ts files
3
+ *
4
+ * This plugin resolves .gql imports by checking if a corresponding .gql.ts file exists.
5
+ * If it does, it redirects the import to the .gql.ts file. Otherwise, it lets esbuild
6
+ * handle the .gql file normally.
7
+ *
8
+ * Now supports TypeScript path aliases for proper module resolution.
9
+ *
10
+ * @param {GqlRedirectPluginOptions} [options]
11
+ * @returns {Plugin}
12
+ */
13
+ declare function gqlRedirectPlugin(options?: GqlRedirectPluginOptions): Plugin;
14
+ declare namespace gqlRedirectPlugin {
15
+ export { gqlRedirectPlugin as default, gqlRedirectPlugin, type Plugin, type GqlRedirectPluginOptions, type PathMapping };
16
+ }
17
+ type Plugin = any;
18
+ type GqlRedirectPluginOptions = {
19
+ /**
20
+ * Whether to enable verbose logging
21
+ */
22
+ verbose?: boolean | undefined;
23
+ /**
24
+ * Path to tsconfig.json file for path alias resolution
25
+ */
26
+ tsconfigPath?: string | undefined;
27
+ /**
28
+ * Whether to automatically run pnpm gqlgen when .gql.ts files are missing
29
+ */
30
+ autoGqlGen?: boolean | undefined;
31
+ };
32
+ type PathMapping = {
33
+ alias: string;
34
+ paths: string[];
35
+ };
36
+
37
+ export { gqlRedirectPlugin as default };
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+
3
+ // src/esbuild/gql-redirect.plugin.js
4
+ var path = require("path");
5
+ var fs = require("fs");
6
+ var json5 = require("json5");
7
+ var crypto = require("crypto");
8
+ var { execSync } = require("child_process");
9
+ var { glob } = require("glob");
10
+ var yaml = require("yaml");
11
+ var graphqlrcContent = void 0;
12
+ function loadTsconfigPaths(tsconfigPath) {
13
+ try {
14
+ const tsconfig = json5.parse(fs.readFileSync(tsconfigPath, "utf8"));
15
+ const baseUrl = tsconfig.compilerOptions && tsconfig.compilerOptions.baseUrl || "./";
16
+ const paths = tsconfig.compilerOptions && tsconfig.compilerOptions.paths || {};
17
+ return Object.entries(paths).map(([alias, pathList]) => ({
18
+ alias: alias.replace(/\/\*$/, ""),
19
+ paths: (
20
+ /** @type {string[]} */
21
+ pathList.map(
22
+ (p) => path.resolve(path.dirname(tsconfigPath), baseUrl, p.replace(/\/\*$/, ""))
23
+ )
24
+ )
25
+ }));
26
+ } catch (error) {
27
+ console.warn(`[gql-redirect] Failed to load tsconfig from ${tsconfigPath}:`, error);
28
+ return [];
29
+ }
30
+ }
31
+ function findAngularJsonDir(startDir) {
32
+ try {
33
+ let dir = startDir;
34
+ while (true) {
35
+ if (fs.existsSync(path.join(dir, "angular.json"))) return dir;
36
+ const parent = path.dirname(dir);
37
+ if (parent === dir) return startDir;
38
+ dir = parent;
39
+ }
40
+ } catch {
41
+ return startDir;
42
+ }
43
+ }
44
+ function parseGraphqlrcDocuments(projectRoot) {
45
+ try {
46
+ const graphqlrcPath = path.join(projectRoot, ".graphqlrc.yml");
47
+ if (!fs.existsSync(graphqlrcPath)) {
48
+ console.warn("[gql-redirect] .graphqlrc.yml not found, falling back to default patterns");
49
+ return [];
50
+ }
51
+ graphqlrcContent ?? (graphqlrcContent = fs.readFileSync(graphqlrcPath, "utf8"));
52
+ const cleanContent = graphqlrcContent.replace(/^# gql-hash:.*\n/, "");
53
+ const config = yaml.parse(cleanContent);
54
+ if (!config || !config.documents) {
55
+ console.warn("[gql-redirect] No documents section found in .graphqlrc.yml");
56
+ return [];
57
+ }
58
+ const documents = config.documents;
59
+ if (Array.isArray(documents)) {
60
+ return documents.filter((doc) => typeof doc === "string");
61
+ } else if (typeof documents === "string") {
62
+ return [documents];
63
+ } else {
64
+ console.warn("[gql-redirect] Unexpected documents format in .graphqlrc.yml");
65
+ return [];
66
+ }
67
+ } catch (error) {
68
+ console.warn(`[gql-redirect] Failed to parse .graphqlrc.yml:`, error.message);
69
+ return [];
70
+ }
71
+ }
72
+ function findGqlFilesByDocuments(projectRoot) {
73
+ try {
74
+ const documentPatterns = parseGraphqlrcDocuments(projectRoot);
75
+ const allFiles = /* @__PURE__ */ new Set();
76
+ for (const pattern of documentPatterns) {
77
+ if (pattern.startsWith("!")) {
78
+ continue;
79
+ }
80
+ try {
81
+ const matches = glob.sync(pattern, {
82
+ cwd: projectRoot,
83
+ absolute: true,
84
+ nodir: true
85
+ });
86
+ matches.forEach((file) => allFiles.add(file));
87
+ } catch (error) {
88
+ console.warn(`[gql-redirect] Failed to process pattern "${pattern}":`, error.message);
89
+ }
90
+ }
91
+ const negationPatterns = documentPatterns.filter((pattern) => pattern.startsWith("!"));
92
+ let filteredFiles = Array.from(allFiles);
93
+ for (const negPattern of negationPatterns) {
94
+ const pattern = negPattern.substring(1);
95
+ try {
96
+ const excludeMatches = glob.sync(pattern, {
97
+ cwd: projectRoot,
98
+ absolute: true,
99
+ nodir: true
100
+ });
101
+ const excludeSet = new Set(excludeMatches);
102
+ filteredFiles = filteredFiles.filter((file) => !excludeSet.has(file));
103
+ } catch (error) {
104
+ console.warn(`[gql-redirect] Failed to process negation pattern "${negPattern}":`, error.message);
105
+ }
106
+ }
107
+ return filteredFiles.sort();
108
+ } catch (error) {
109
+ console.warn(`[gql-redirect] Failed to find GQL files:`, error.message);
110
+ return [];
111
+ }
112
+ }
113
+ function calculateGqlHash(projectRoot) {
114
+ try {
115
+ const hash = crypto.createHash("md5");
116
+ const gqlFiles = findGqlFilesByDocuments(projectRoot);
117
+ for (const filePath of gqlFiles) {
118
+ try {
119
+ const content = fs.readFileSync(filePath, "utf8");
120
+ hash.update(`${path.relative(projectRoot, filePath)}:${content}`);
121
+ } catch (error) {
122
+ console.warn(`[gql-redirect] Failed to read ${filePath}:`, error.message);
123
+ }
124
+ }
125
+ const graphqlrcPath = path.join(projectRoot, ".graphqlrc.yml");
126
+ if (fs.existsSync(graphqlrcPath)) {
127
+ try {
128
+ graphqlrcContent ?? (graphqlrcContent = fs.readFileSync(graphqlrcPath, "utf8"));
129
+ const cleanContent = graphqlrcContent.replace(/^# gql-hash: .*/m, "");
130
+ hash.update(`.graphqlrc.yml:${cleanContent}`);
131
+ } catch (error) {
132
+ console.warn(`[gql-redirect] Failed to read .graphqlrc.yml:`, error.message);
133
+ }
134
+ }
135
+ return hash.digest("hex");
136
+ } catch (error) {
137
+ console.warn(`[gql-redirect] Failed to calculate GQL hash:`, error.message);
138
+ return "";
139
+ }
140
+ }
141
+ function getPreviousGqlHash(projectRoot) {
142
+ try {
143
+ const graphqlrcPath = path.join(projectRoot, ".graphqlrc.yml");
144
+ if (!fs.existsSync(graphqlrcPath)) {
145
+ return "";
146
+ }
147
+ graphqlrcContent ?? (graphqlrcContent = fs.readFileSync(graphqlrcPath, "utf8"));
148
+ const match = graphqlrcContent.match(/^# gql-hash: (.*)$/m);
149
+ return match ? match[1].trim() : "";
150
+ } catch (error) {
151
+ console.warn(`[gql-redirect] Failed to read previous GQL hash:`, error.message);
152
+ return "";
153
+ }
154
+ }
155
+ function updateGraphqlrcHash(projectRoot, newHash) {
156
+ try {
157
+ const graphqlrcPath = path.join(projectRoot, ".graphqlrc.yml");
158
+ if (!fs.existsSync(graphqlrcPath)) {
159
+ return;
160
+ }
161
+ const currentContent = fs.readFileSync(graphqlrcPath, "utf8");
162
+ const newContent = currentContent.replace(/^# gql-hash: .*/m, `# gql-hash: ${newHash}`);
163
+ fs.writeFileSync(graphqlrcPath, newContent, "utf8");
164
+ } catch (error) {
165
+ console.warn(`[gql-redirect] Failed to update .graphqlrc.yml hash:`, error.message);
166
+ }
167
+ }
168
+ function runGqlGen(projectRoot, verbose) {
169
+ try {
170
+ const currentGqlHash = calculateGqlHash(projectRoot);
171
+ const previousGqlHash = getPreviousGqlHash(projectRoot);
172
+ if (currentGqlHash && currentGqlHash === previousGqlHash) {
173
+ console.log("[gql-redirect] GQL files unchanged, skipping pnpm gqlgen");
174
+ return true;
175
+ }
176
+ console.log(`[gql-redirect] GQL files changed (${previousGqlHash}) => (${currentGqlHash}), running pnpm gqlgen in ${projectRoot}...`);
177
+ try {
178
+ execSync("pnpm gqlgen", {
179
+ cwd: projectRoot,
180
+ stdio: verbose ? "inherit" : "pipe",
181
+ timeout: 3e4
182
+ // 30 second timeout
183
+ });
184
+ } catch (error) {
185
+ if (error.message.includes("NODE_TLS_REJECT_UNAUTHORIZED")) {
186
+ }
187
+ }
188
+ if (currentGqlHash) {
189
+ updateGraphqlrcHash(projectRoot, currentGqlHash);
190
+ }
191
+ if (verbose) {
192
+ console.log("[gql-redirect] Successfully executed pnpm gqlgen and updated hash");
193
+ }
194
+ return true;
195
+ } catch (error) {
196
+ console.error(`[gql-redirect] Failed to execute pnpm gqlgen:`, error.message);
197
+ return false;
198
+ }
199
+ }
200
+ function resolvePathAlias(modulePath, pathMappings, resolveDir) {
201
+ const possiblePaths = [];
202
+ for (const mapping of pathMappings) {
203
+ if (modulePath.startsWith(mapping.alias)) {
204
+ const remainingPath = modulePath.slice(mapping.alias.length);
205
+ const cleanRemainingPath = remainingPath.startsWith("/") ? remainingPath.slice(1) : remainingPath;
206
+ for (const basePath of mapping.paths) {
207
+ const resolvedPath = cleanRemainingPath ? path.join(basePath, cleanRemainingPath) : basePath;
208
+ possiblePaths.push(resolvedPath);
209
+ }
210
+ }
211
+ }
212
+ if (possiblePaths.length === 0) {
213
+ possiblePaths.push(path.resolve(resolveDir, modulePath));
214
+ }
215
+ return possiblePaths;
216
+ }
217
+ function gqlRedirectPlugin(options = {}) {
218
+ const { verbose = false, tsconfigPath = "./tsconfig.json", autoGqlGen = true } = options;
219
+ return {
220
+ name: "gql-redirect",
221
+ setup(build) {
222
+ const angularJsonDir = findAngularJsonDir(process.cwd());
223
+ const pathMappings = loadTsconfigPaths(tsconfigPath);
224
+ if (verbose && pathMappings.length > 0) {
225
+ console.log(`[gql-redirect] Loaded ${pathMappings.length} path mappings from ${tsconfigPath}`);
226
+ }
227
+ if (autoGqlGen) {
228
+ runGqlGen(angularJsonDir, verbose);
229
+ }
230
+ build.onResolve({ filter: /\.gql$/ }, (args) => {
231
+ try {
232
+ const possiblePaths = resolvePathAlias(args.path, pathMappings, args.resolveDir);
233
+ for (const resolvedPath of possiblePaths) {
234
+ const gqlTsPath = resolvedPath + ".ts";
235
+ if (fs.existsSync(gqlTsPath)) {
236
+ if (verbose) {
237
+ const displayPath = path.relative(angularJsonDir, gqlTsPath) || ".";
238
+ console.log(`[gql-redirect] Redirecting "${args.path}" to "${displayPath}"`);
239
+ }
240
+ return { path: gqlTsPath };
241
+ }
242
+ }
243
+ if (verbose) {
244
+ console.warn(`[gql-redirect] No .gql.ts found for ${args.path} in any of the resolved paths: ${possiblePaths.join(", ")}`);
245
+ } else {
246
+ console.warn(`[gql-redirect] No .gql.ts found for ${args.path}, please run pnpm gqlgen to ensure it.`);
247
+ }
248
+ return null;
249
+ } catch (error) {
250
+ if (verbose) {
251
+ console.error(`[gql-redirect] Error processing ${args.path}:`, error);
252
+ }
253
+ return null;
254
+ }
255
+ });
256
+ }
257
+ };
258
+ }
259
+ module.exports = gqlRedirectPlugin;
260
+ module.exports.default = gqlRedirectPlugin;
261
+ module.exports.gqlRedirectPlugin = gqlRedirectPlugin;
@@ -0,0 +1,269 @@
1
+ import {
2
+ __commonJS,
3
+ __require
4
+ } from "../chunk-EBO3CZXG.mjs";
5
+
6
+ // src/esbuild/gql-redirect.plugin.js
7
+ var require_gql_redirect_plugin = __commonJS({
8
+ "src/esbuild/gql-redirect.plugin.js"(exports, module) {
9
+ var path = __require("path");
10
+ var fs = __require("fs");
11
+ var json5 = __require("json5");
12
+ var crypto = __require("crypto");
13
+ var { execSync } = __require("child_process");
14
+ var { glob } = __require("glob");
15
+ var yaml = __require("yaml");
16
+ var graphqlrcContent = void 0;
17
+ function loadTsconfigPaths(tsconfigPath) {
18
+ try {
19
+ const tsconfig = json5.parse(fs.readFileSync(tsconfigPath, "utf8"));
20
+ const baseUrl = tsconfig.compilerOptions && tsconfig.compilerOptions.baseUrl || "./";
21
+ const paths = tsconfig.compilerOptions && tsconfig.compilerOptions.paths || {};
22
+ return Object.entries(paths).map(([alias, pathList]) => ({
23
+ alias: alias.replace(/\/\*$/, ""),
24
+ paths: (
25
+ /** @type {string[]} */
26
+ pathList.map(
27
+ (p) => path.resolve(path.dirname(tsconfigPath), baseUrl, p.replace(/\/\*$/, ""))
28
+ )
29
+ )
30
+ }));
31
+ } catch (error) {
32
+ console.warn(`[gql-redirect] Failed to load tsconfig from ${tsconfigPath}:`, error);
33
+ return [];
34
+ }
35
+ }
36
+ function findAngularJsonDir(startDir) {
37
+ try {
38
+ let dir = startDir;
39
+ while (true) {
40
+ if (fs.existsSync(path.join(dir, "angular.json"))) return dir;
41
+ const parent = path.dirname(dir);
42
+ if (parent === dir) return startDir;
43
+ dir = parent;
44
+ }
45
+ } catch {
46
+ return startDir;
47
+ }
48
+ }
49
+ function parseGraphqlrcDocuments(projectRoot) {
50
+ try {
51
+ const graphqlrcPath = path.join(projectRoot, ".graphqlrc.yml");
52
+ if (!fs.existsSync(graphqlrcPath)) {
53
+ console.warn("[gql-redirect] .graphqlrc.yml not found, falling back to default patterns");
54
+ return [];
55
+ }
56
+ graphqlrcContent ?? (graphqlrcContent = fs.readFileSync(graphqlrcPath, "utf8"));
57
+ const cleanContent = graphqlrcContent.replace(/^# gql-hash:.*\n/, "");
58
+ const config = yaml.parse(cleanContent);
59
+ if (!config || !config.documents) {
60
+ console.warn("[gql-redirect] No documents section found in .graphqlrc.yml");
61
+ return [];
62
+ }
63
+ const documents = config.documents;
64
+ if (Array.isArray(documents)) {
65
+ return documents.filter((doc) => typeof doc === "string");
66
+ } else if (typeof documents === "string") {
67
+ return [documents];
68
+ } else {
69
+ console.warn("[gql-redirect] Unexpected documents format in .graphqlrc.yml");
70
+ return [];
71
+ }
72
+ } catch (error) {
73
+ console.warn(`[gql-redirect] Failed to parse .graphqlrc.yml:`, error.message);
74
+ return [];
75
+ }
76
+ }
77
+ function findGqlFilesByDocuments(projectRoot) {
78
+ try {
79
+ const documentPatterns = parseGraphqlrcDocuments(projectRoot);
80
+ const allFiles = /* @__PURE__ */ new Set();
81
+ for (const pattern of documentPatterns) {
82
+ if (pattern.startsWith("!")) {
83
+ continue;
84
+ }
85
+ try {
86
+ const matches = glob.sync(pattern, {
87
+ cwd: projectRoot,
88
+ absolute: true,
89
+ nodir: true
90
+ });
91
+ matches.forEach((file) => allFiles.add(file));
92
+ } catch (error) {
93
+ console.warn(`[gql-redirect] Failed to process pattern "${pattern}":`, error.message);
94
+ }
95
+ }
96
+ const negationPatterns = documentPatterns.filter((pattern) => pattern.startsWith("!"));
97
+ let filteredFiles = Array.from(allFiles);
98
+ for (const negPattern of negationPatterns) {
99
+ const pattern = negPattern.substring(1);
100
+ try {
101
+ const excludeMatches = glob.sync(pattern, {
102
+ cwd: projectRoot,
103
+ absolute: true,
104
+ nodir: true
105
+ });
106
+ const excludeSet = new Set(excludeMatches);
107
+ filteredFiles = filteredFiles.filter((file) => !excludeSet.has(file));
108
+ } catch (error) {
109
+ console.warn(`[gql-redirect] Failed to process negation pattern "${negPattern}":`, error.message);
110
+ }
111
+ }
112
+ return filteredFiles.sort();
113
+ } catch (error) {
114
+ console.warn(`[gql-redirect] Failed to find GQL files:`, error.message);
115
+ return [];
116
+ }
117
+ }
118
+ function calculateGqlHash(projectRoot) {
119
+ try {
120
+ const hash = crypto.createHash("md5");
121
+ const gqlFiles = findGqlFilesByDocuments(projectRoot);
122
+ for (const filePath of gqlFiles) {
123
+ try {
124
+ const content = fs.readFileSync(filePath, "utf8");
125
+ hash.update(`${path.relative(projectRoot, filePath)}:${content}`);
126
+ } catch (error) {
127
+ console.warn(`[gql-redirect] Failed to read ${filePath}:`, error.message);
128
+ }
129
+ }
130
+ const graphqlrcPath = path.join(projectRoot, ".graphqlrc.yml");
131
+ if (fs.existsSync(graphqlrcPath)) {
132
+ try {
133
+ graphqlrcContent ?? (graphqlrcContent = fs.readFileSync(graphqlrcPath, "utf8"));
134
+ const cleanContent = graphqlrcContent.replace(/^# gql-hash: .*/m, "");
135
+ hash.update(`.graphqlrc.yml:${cleanContent}`);
136
+ } catch (error) {
137
+ console.warn(`[gql-redirect] Failed to read .graphqlrc.yml:`, error.message);
138
+ }
139
+ }
140
+ return hash.digest("hex");
141
+ } catch (error) {
142
+ console.warn(`[gql-redirect] Failed to calculate GQL hash:`, error.message);
143
+ return "";
144
+ }
145
+ }
146
+ function getPreviousGqlHash(projectRoot) {
147
+ try {
148
+ const graphqlrcPath = path.join(projectRoot, ".graphqlrc.yml");
149
+ if (!fs.existsSync(graphqlrcPath)) {
150
+ return "";
151
+ }
152
+ graphqlrcContent ?? (graphqlrcContent = fs.readFileSync(graphqlrcPath, "utf8"));
153
+ const match = graphqlrcContent.match(/^# gql-hash: (.*)$/m);
154
+ return match ? match[1].trim() : "";
155
+ } catch (error) {
156
+ console.warn(`[gql-redirect] Failed to read previous GQL hash:`, error.message);
157
+ return "";
158
+ }
159
+ }
160
+ function updateGraphqlrcHash(projectRoot, newHash) {
161
+ try {
162
+ const graphqlrcPath = path.join(projectRoot, ".graphqlrc.yml");
163
+ if (!fs.existsSync(graphqlrcPath)) {
164
+ return;
165
+ }
166
+ const currentContent = fs.readFileSync(graphqlrcPath, "utf8");
167
+ const newContent = currentContent.replace(/^# gql-hash: .*/m, `# gql-hash: ${newHash}`);
168
+ fs.writeFileSync(graphqlrcPath, newContent, "utf8");
169
+ } catch (error) {
170
+ console.warn(`[gql-redirect] Failed to update .graphqlrc.yml hash:`, error.message);
171
+ }
172
+ }
173
+ function runGqlGen(projectRoot, verbose) {
174
+ try {
175
+ const currentGqlHash = calculateGqlHash(projectRoot);
176
+ const previousGqlHash = getPreviousGqlHash(projectRoot);
177
+ if (currentGqlHash && currentGqlHash === previousGqlHash) {
178
+ console.log("[gql-redirect] GQL files unchanged, skipping pnpm gqlgen");
179
+ return true;
180
+ }
181
+ console.log(`[gql-redirect] GQL files changed (${previousGqlHash}) => (${currentGqlHash}), running pnpm gqlgen in ${projectRoot}...`);
182
+ try {
183
+ execSync("pnpm gqlgen", {
184
+ cwd: projectRoot,
185
+ stdio: verbose ? "inherit" : "pipe",
186
+ timeout: 3e4
187
+ // 30 second timeout
188
+ });
189
+ } catch (error) {
190
+ if (error.message.includes("NODE_TLS_REJECT_UNAUTHORIZED")) {
191
+ }
192
+ }
193
+ if (currentGqlHash) {
194
+ updateGraphqlrcHash(projectRoot, currentGqlHash);
195
+ }
196
+ if (verbose) {
197
+ console.log("[gql-redirect] Successfully executed pnpm gqlgen and updated hash");
198
+ }
199
+ return true;
200
+ } catch (error) {
201
+ console.error(`[gql-redirect] Failed to execute pnpm gqlgen:`, error.message);
202
+ return false;
203
+ }
204
+ }
205
+ function resolvePathAlias(modulePath, pathMappings, resolveDir) {
206
+ const possiblePaths = [];
207
+ for (const mapping of pathMappings) {
208
+ if (modulePath.startsWith(mapping.alias)) {
209
+ const remainingPath = modulePath.slice(mapping.alias.length);
210
+ const cleanRemainingPath = remainingPath.startsWith("/") ? remainingPath.slice(1) : remainingPath;
211
+ for (const basePath of mapping.paths) {
212
+ const resolvedPath = cleanRemainingPath ? path.join(basePath, cleanRemainingPath) : basePath;
213
+ possiblePaths.push(resolvedPath);
214
+ }
215
+ }
216
+ }
217
+ if (possiblePaths.length === 0) {
218
+ possiblePaths.push(path.resolve(resolveDir, modulePath));
219
+ }
220
+ return possiblePaths;
221
+ }
222
+ function gqlRedirectPlugin(options = {}) {
223
+ const { verbose = false, tsconfigPath = "./tsconfig.json", autoGqlGen = true } = options;
224
+ return {
225
+ name: "gql-redirect",
226
+ setup(build) {
227
+ const angularJsonDir = findAngularJsonDir(process.cwd());
228
+ const pathMappings = loadTsconfigPaths(tsconfigPath);
229
+ if (verbose && pathMappings.length > 0) {
230
+ console.log(`[gql-redirect] Loaded ${pathMappings.length} path mappings from ${tsconfigPath}`);
231
+ }
232
+ if (autoGqlGen) {
233
+ runGqlGen(angularJsonDir, verbose);
234
+ }
235
+ build.onResolve({ filter: /\.gql$/ }, (args) => {
236
+ try {
237
+ const possiblePaths = resolvePathAlias(args.path, pathMappings, args.resolveDir);
238
+ for (const resolvedPath of possiblePaths) {
239
+ const gqlTsPath = resolvedPath + ".ts";
240
+ if (fs.existsSync(gqlTsPath)) {
241
+ if (verbose) {
242
+ const displayPath = path.relative(angularJsonDir, gqlTsPath) || ".";
243
+ console.log(`[gql-redirect] Redirecting "${args.path}" to "${displayPath}"`);
244
+ }
245
+ return { path: gqlTsPath };
246
+ }
247
+ }
248
+ if (verbose) {
249
+ console.warn(`[gql-redirect] No .gql.ts found for ${args.path} in any of the resolved paths: ${possiblePaths.join(", ")}`);
250
+ } else {
251
+ console.warn(`[gql-redirect] No .gql.ts found for ${args.path}, please run pnpm gqlgen to ensure it.`);
252
+ }
253
+ return null;
254
+ } catch (error) {
255
+ if (verbose) {
256
+ console.error(`[gql-redirect] Error processing ${args.path}:`, error);
257
+ }
258
+ return null;
259
+ }
260
+ });
261
+ }
262
+ };
263
+ }
264
+ module.exports = gqlRedirectPlugin;
265
+ module.exports.default = gqlRedirectPlugin;
266
+ module.exports.gqlRedirectPlugin = gqlRedirectPlugin;
267
+ }
268
+ });
269
+ export default require_gql_redirect_plugin();
@@ -0,0 +1,97 @@
1
+ import { WritableSignal, Injector, Provider } from '@angular/core';
2
+ import { Observable } from 'rxjs';
3
+
4
+ interface Tenant {
5
+ code: string;
6
+ name: string;
7
+ }
8
+ interface Org {
9
+ code: string;
10
+ name: string;
11
+ [key: string]: any;
12
+ }
13
+ interface UserOrgMembership {
14
+ code: string;
15
+ }
16
+ interface User {
17
+ id: string;
18
+ orgs: UserOrgMembership[];
19
+ [key: string]: any;
20
+ }
21
+ interface SettingItem {
22
+ name: string;
23
+ value?: any;
24
+ }
25
+ interface TenantModule extends GeexModule {
26
+ /** Current tenant reactive state */
27
+ current: WritableSignal<Tenant | null>;
28
+ /**
29
+ * Load tenant information by code.
30
+ */
31
+ loadTenantData(code: string): Promise<Tenant>;
32
+ /**
33
+ * Switch current tenant.
34
+ */
35
+ switchTenant(targetTenantCode: string): void;
36
+ }
37
+ interface AuthModule extends GeexModule {
38
+ /** Current authenticated user */
39
+ user: WritableSignal<User | null>;
40
+ /**
41
+ * Load current user information. Returns undefined when unauthenticated.
42
+ */
43
+ loadUserData(): Promise<User | undefined>;
44
+ }
45
+ interface IdentityModule extends GeexModule {
46
+ /** All organizations */
47
+ orgs: WritableSignal<Org[]>;
48
+ /** Organizations owned by current user */
49
+ userOwnedOrgs: WritableSignal<Org[]>;
50
+ /**
51
+ * Initialize identity-related reactive state and listeners.
52
+ */
53
+ init(): void;
54
+ }
55
+ interface MessagingModule extends GeexModule {
56
+ /**
57
+ * Subscribe to server broadcast events.
58
+ */
59
+ onPublicNotify(): void;
60
+ }
61
+ interface SettingsModule extends GeexModule {
62
+ settings: WritableSignal<SettingItem[]>;
63
+ /**
64
+ * Initialize application settings.
65
+ */
66
+ init(): Promise<void>;
67
+ }
68
+ interface UiModule extends GeexModule {
69
+ /** Whether the app is currently in fullscreen mode */
70
+ fullScreen: WritableSignal<boolean>;
71
+ /** Responsive helper stream notifying if device is mobile-like */
72
+ isMobile$: Observable<boolean>;
73
+ /** Currently active routed component (framework dependent) */
74
+ activeRoutedComponent?: any;
75
+ }
76
+ type GeexModules<TExtensionModules extends Record<string, GeexModule> = {}> = {
77
+ tenant: TenantModule;
78
+ auth: AuthModule;
79
+ identity: IdentityModule;
80
+ messaging: MessagingModule;
81
+ settings: SettingsModule;
82
+ ui: UiModule;
83
+ } & TExtensionModules;
84
+ type GeexModule<TExtension = any> = {} & TExtension;
85
+
86
+ type GeexOverrides<TExtensionModules extends Record<string, GeexModule> = {}> = Partial<GeexModules<TExtensionModules>>;
87
+ declare let geex: GeexModules;
88
+ /**
89
+ * Initialize geex singleton with concrete dependencies
90
+ * @param deps Required runtime services
91
+ * @param overrides Custom module overrides – properties will be merged into generated modules
92
+ */
93
+ declare function configGeex<TExtensionModules extends Record<string, GeexModule> = {}>(injector: Injector, overrides?: GeexOverrides<TExtensionModules>): void;
94
+
95
+ declare function provideGeex(injector: any, overrides?: GeexOverrides): Provider[];
96
+
97
+ export { type GeexOverrides, configGeex, geex, provideGeex };
@@ -0,0 +1,97 @@
1
+ import { WritableSignal, Injector, Provider } from '@angular/core';
2
+ import { Observable } from 'rxjs';
3
+
4
+ interface Tenant {
5
+ code: string;
6
+ name: string;
7
+ }
8
+ interface Org {
9
+ code: string;
10
+ name: string;
11
+ [key: string]: any;
12
+ }
13
+ interface UserOrgMembership {
14
+ code: string;
15
+ }
16
+ interface User {
17
+ id: string;
18
+ orgs: UserOrgMembership[];
19
+ [key: string]: any;
20
+ }
21
+ interface SettingItem {
22
+ name: string;
23
+ value?: any;
24
+ }
25
+ interface TenantModule extends GeexModule {
26
+ /** Current tenant reactive state */
27
+ current: WritableSignal<Tenant | null>;
28
+ /**
29
+ * Load tenant information by code.
30
+ */
31
+ loadTenantData(code: string): Promise<Tenant>;
32
+ /**
33
+ * Switch current tenant.
34
+ */
35
+ switchTenant(targetTenantCode: string): void;
36
+ }
37
+ interface AuthModule extends GeexModule {
38
+ /** Current authenticated user */
39
+ user: WritableSignal<User | null>;
40
+ /**
41
+ * Load current user information. Returns undefined when unauthenticated.
42
+ */
43
+ loadUserData(): Promise<User | undefined>;
44
+ }
45
+ interface IdentityModule extends GeexModule {
46
+ /** All organizations */
47
+ orgs: WritableSignal<Org[]>;
48
+ /** Organizations owned by current user */
49
+ userOwnedOrgs: WritableSignal<Org[]>;
50
+ /**
51
+ * Initialize identity-related reactive state and listeners.
52
+ */
53
+ init(): void;
54
+ }
55
+ interface MessagingModule extends GeexModule {
56
+ /**
57
+ * Subscribe to server broadcast events.
58
+ */
59
+ onPublicNotify(): void;
60
+ }
61
+ interface SettingsModule extends GeexModule {
62
+ settings: WritableSignal<SettingItem[]>;
63
+ /**
64
+ * Initialize application settings.
65
+ */
66
+ init(): Promise<void>;
67
+ }
68
+ interface UiModule extends GeexModule {
69
+ /** Whether the app is currently in fullscreen mode */
70
+ fullScreen: WritableSignal<boolean>;
71
+ /** Responsive helper stream notifying if device is mobile-like */
72
+ isMobile$: Observable<boolean>;
73
+ /** Currently active routed component (framework dependent) */
74
+ activeRoutedComponent?: any;
75
+ }
76
+ type GeexModules<TExtensionModules extends Record<string, GeexModule> = {}> = {
77
+ tenant: TenantModule;
78
+ auth: AuthModule;
79
+ identity: IdentityModule;
80
+ messaging: MessagingModule;
81
+ settings: SettingsModule;
82
+ ui: UiModule;
83
+ } & TExtensionModules;
84
+ type GeexModule<TExtension = any> = {} & TExtension;
85
+
86
+ type GeexOverrides<TExtensionModules extends Record<string, GeexModule> = {}> = Partial<GeexModules<TExtensionModules>>;
87
+ declare let geex: GeexModules;
88
+ /**
89
+ * Initialize geex singleton with concrete dependencies
90
+ * @param deps Required runtime services
91
+ * @param overrides Custom module overrides – properties will be merged into generated modules
92
+ */
93
+ declare function configGeex<TExtensionModules extends Record<string, GeexModule> = {}>(injector: Injector, overrides?: GeexOverrides<TExtensionModules>): void;
94
+
95
+ declare function provideGeex(injector: any, overrides?: GeexOverrides): Provider[];
96
+
97
+ export { type GeexOverrides, configGeex, geex, provideGeex };
package/dist/index.js ADDED
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ configGeex: () => configGeex,
34
+ geex: () => geex,
35
+ provideGeex: () => provideGeex
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/geex.ts
40
+ var import_core2 = require("@angular/core");
41
+
42
+ // src/modules.ts
43
+ var import_apollo_angular = require("apollo-angular");
44
+ var import_core = require("@angular/core");
45
+ var import_angular_oauth2_oidc = require("angular-oauth2-oidc");
46
+ var import_util = require("@delon/util");
47
+ var import_graphql_tag = __toESM(require("graphql-tag"));
48
+ var import_rxjs = require("rxjs");
49
+ var import_operators = require("rxjs/operators");
50
+ var GQL_CHECK_TENANT = import_graphql_tag.default`mutation checkTenant($code: String!) { checkTenant(code: $code) { code name } }`;
51
+ var GQL_FEDERATE_AUTH = import_graphql_tag.default`mutation federateAuthenticate($code: String!, $loginProvider: LoginProviderEnum!) { federateAuthenticate(code: $code, loginProvider: $loginProvider) { id orgs { code } } }`;
52
+ var GQL_ON_PUBLIC_NOTIFY = import_graphql_tag.default`subscription onPublicNotify { onPublicNotify { __typename ... on DataChangeClientNotify { dataChangeType } } }`;
53
+ var GQL_ORGS_CACHE = import_graphql_tag.default`query orgsCache { orgs { items { code name } } }`;
54
+ var GQL_INIT_SETTINGS = import_graphql_tag.default`query initSettings { initSettings { name value } }`;
55
+ function createTenantModule(injector) {
56
+ const current = (0, import_core.signal)(null);
57
+ return {
58
+ current,
59
+ async loadTenantData(code) {
60
+ const res = await (0, import_rxjs.firstValueFrom)(
61
+ injector.get(import_apollo_angular.Apollo).mutate({ mutation: GQL_CHECK_TENANT, variables: { code } })
62
+ );
63
+ return res.data.checkTenant;
64
+ },
65
+ switchTenant(targetTenantCode) {
66
+ const domainParts = location.hostname.split(".");
67
+ if (domainParts.length > 2) {
68
+ domainParts.shift();
69
+ }
70
+ const rootDomain = domainParts.join(".");
71
+ injector.get(import_util.CookieService).put("__tenant", targetTenantCode, {
72
+ secure: false,
73
+ SameSite: "lax",
74
+ HttpOnly: false,
75
+ domain: rootDomain
76
+ });
77
+ }
78
+ };
79
+ }
80
+ function createAuthModule(injector) {
81
+ const user = (0, import_core.signal)(null);
82
+ return {
83
+ user,
84
+ async loadUserData() {
85
+ const oAuthService = injector.get(import_angular_oauth2_oidc.OAuthService);
86
+ try {
87
+ await oAuthService.loadUserProfile();
88
+ const profile = oAuthService.getIdentityClaims();
89
+ if (profile && oAuthService.hasValidAccessToken()) {
90
+ const result = await (0, import_rxjs.firstValueFrom)(injector.get(import_apollo_angular.Apollo).mutate({
91
+ mutation: GQL_FEDERATE_AUTH,
92
+ variables: {
93
+ code: oAuthService.getAccessToken(),
94
+ loginProvider: profile.login_provider
95
+ }
96
+ }).pipe((0, import_rxjs.map)((res) => res?.data?.federateAuthenticate)));
97
+ return result;
98
+ }
99
+ } catch (err) {
100
+ console.error(err);
101
+ oAuthService.logOut();
102
+ }
103
+ return void 0;
104
+ }
105
+ };
106
+ }
107
+ function createIdentityModule(injector) {
108
+ const orgsSignal = (0, import_core.signal)([]);
109
+ const userOwnedOrgsSignal = (0, import_core.signal)([]);
110
+ return {
111
+ orgs: orgsSignal,
112
+ userOwnedOrgs: userOwnedOrgsSignal,
113
+ init() {
114
+ const orgs$ = injector.get(import_apollo_angular.Apollo).watchQuery({ query: GQL_ORGS_CACHE }).valueChanges.pipe((0, import_rxjs.map)((res) => (0, import_util.deepCopy)(res.data.orgs.items)));
115
+ orgs$.subscribe((orgs) => {
116
+ (0, import_core.runInInjectionContext)(injector, () => {
117
+ orgsSignal.set(orgs);
118
+ const userData = geex.auth.user();
119
+ let allOwned = [];
120
+ if (orgs?.length && userData) {
121
+ if (userData.id === "000000000000000000000001") {
122
+ allOwned = (0, import_util.deepCopy)(orgs);
123
+ } else {
124
+ const ownedCodes = userData.orgs.map((x) => x.code);
125
+ allOwned = orgs.filter((o) => ownedCodes.some((code) => o.code.startsWith(code)));
126
+ }
127
+ }
128
+ userOwnedOrgsSignal.set(allOwned);
129
+ });
130
+ });
131
+ }
132
+ };
133
+ }
134
+ function createMessagingModule(injector) {
135
+ return {
136
+ onPublicNotify() {
137
+ const subClient = injector.get(import_apollo_angular.Apollo).use("subscription");
138
+ subClient.subscribe({ query: GQL_ON_PUBLIC_NOTIFY }).pipe((0, import_rxjs.map)((res) => res?.data?.onPublicNotify)).subscribe((notify) => {
139
+ console.log("Public notify", notify);
140
+ });
141
+ }
142
+ };
143
+ }
144
+ function createSettingsModule(injector) {
145
+ const settingsSignal = (0, import_core.signal)([]);
146
+ return {
147
+ settings: settingsSignal,
148
+ async init() {
149
+ const res = await (0, import_rxjs.firstValueFrom)(
150
+ injector.get(import_apollo_angular.Apollo).query({ query: GQL_INIT_SETTINGS })
151
+ );
152
+ const settings = res.data.initSettings;
153
+ settingsSignal.set(settings);
154
+ }
155
+ };
156
+ }
157
+ function createUiModule(injector) {
158
+ const fullScreenSignal = (0, import_core.signal)(false);
159
+ const isMobile$ = (0, import_rxjs.fromEvent)(window, "resize").pipe(
160
+ (0, import_operators.debounceTime)(200),
161
+ (0, import_operators.switchMap)(async () => window.innerHeight / window.innerWidth >= 1.5)
162
+ );
163
+ return {
164
+ fullScreen: fullScreenSignal,
165
+ isMobile$,
166
+ activeRoutedComponent: void 0
167
+ };
168
+ }
169
+
170
+ // src/geex.ts
171
+ var geex;
172
+ function configGeex(injector, overrides) {
173
+ (0, import_core2.runInInjectionContext)(injector, () => {
174
+ const modules = {
175
+ tenant: createTenantModule(injector),
176
+ auth: createAuthModule(injector),
177
+ identity: createIdentityModule(injector),
178
+ messaging: createMessagingModule(injector),
179
+ settings: createSettingsModule(injector),
180
+ ui: createUiModule(injector)
181
+ };
182
+ if (overrides) {
183
+ Object.assign(modules, overrides);
184
+ }
185
+ geex = modules;
186
+ });
187
+ }
188
+
189
+ // src/tokens.ts
190
+ var import_core3 = require("@angular/core");
191
+ var GEEX_CONFIG = new import_core3.InjectionToken("GEEX_CONFIG");
192
+
193
+ // src/provide-geex.ts
194
+ function provideGeex(injector, overrides) {
195
+ configGeex(injector, overrides);
196
+ return [
197
+ { provide: GEEX_CONFIG, useValue: { injector, overrides } },
198
+ { provide: geex, useExisting: geex }
199
+ ];
200
+ }
201
+ // Annotate the CommonJS export names for ESM import in node:
202
+ 0 && (module.exports = {
203
+ configGeex,
204
+ geex,
205
+ provideGeex
206
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,169 @@
1
+ import "./chunk-EBO3CZXG.mjs";
2
+
3
+ // src/geex.ts
4
+ import { runInInjectionContext as runInInjectionContext2 } from "@angular/core";
5
+
6
+ // src/modules.ts
7
+ import { Apollo } from "apollo-angular";
8
+ import { runInInjectionContext, signal } from "@angular/core";
9
+ import { OAuthService } from "angular-oauth2-oidc";
10
+ import { CookieService, deepCopy } from "@delon/util";
11
+ import gql from "graphql-tag";
12
+ import { firstValueFrom, map, fromEvent } from "rxjs";
13
+ import { debounceTime, switchMap } from "rxjs/operators";
14
+ var GQL_CHECK_TENANT = gql`mutation checkTenant($code: String!) { checkTenant(code: $code) { code name } }`;
15
+ var GQL_FEDERATE_AUTH = gql`mutation federateAuthenticate($code: String!, $loginProvider: LoginProviderEnum!) { federateAuthenticate(code: $code, loginProvider: $loginProvider) { id orgs { code } } }`;
16
+ var GQL_ON_PUBLIC_NOTIFY = gql`subscription onPublicNotify { onPublicNotify { __typename ... on DataChangeClientNotify { dataChangeType } } }`;
17
+ var GQL_ORGS_CACHE = gql`query orgsCache { orgs { items { code name } } }`;
18
+ var GQL_INIT_SETTINGS = gql`query initSettings { initSettings { name value } }`;
19
+ function createTenantModule(injector) {
20
+ const current = signal(null);
21
+ return {
22
+ current,
23
+ async loadTenantData(code) {
24
+ const res = await firstValueFrom(
25
+ injector.get(Apollo).mutate({ mutation: GQL_CHECK_TENANT, variables: { code } })
26
+ );
27
+ return res.data.checkTenant;
28
+ },
29
+ switchTenant(targetTenantCode) {
30
+ const domainParts = location.hostname.split(".");
31
+ if (domainParts.length > 2) {
32
+ domainParts.shift();
33
+ }
34
+ const rootDomain = domainParts.join(".");
35
+ injector.get(CookieService).put("__tenant", targetTenantCode, {
36
+ secure: false,
37
+ SameSite: "lax",
38
+ HttpOnly: false,
39
+ domain: rootDomain
40
+ });
41
+ }
42
+ };
43
+ }
44
+ function createAuthModule(injector) {
45
+ const user = signal(null);
46
+ return {
47
+ user,
48
+ async loadUserData() {
49
+ const oAuthService = injector.get(OAuthService);
50
+ try {
51
+ await oAuthService.loadUserProfile();
52
+ const profile = oAuthService.getIdentityClaims();
53
+ if (profile && oAuthService.hasValidAccessToken()) {
54
+ const result = await firstValueFrom(injector.get(Apollo).mutate({
55
+ mutation: GQL_FEDERATE_AUTH,
56
+ variables: {
57
+ code: oAuthService.getAccessToken(),
58
+ loginProvider: profile.login_provider
59
+ }
60
+ }).pipe(map((res) => res?.data?.federateAuthenticate)));
61
+ return result;
62
+ }
63
+ } catch (err) {
64
+ console.error(err);
65
+ oAuthService.logOut();
66
+ }
67
+ return void 0;
68
+ }
69
+ };
70
+ }
71
+ function createIdentityModule(injector) {
72
+ const orgsSignal = signal([]);
73
+ const userOwnedOrgsSignal = signal([]);
74
+ return {
75
+ orgs: orgsSignal,
76
+ userOwnedOrgs: userOwnedOrgsSignal,
77
+ init() {
78
+ const orgs$ = injector.get(Apollo).watchQuery({ query: GQL_ORGS_CACHE }).valueChanges.pipe(map((res) => deepCopy(res.data.orgs.items)));
79
+ orgs$.subscribe((orgs) => {
80
+ runInInjectionContext(injector, () => {
81
+ orgsSignal.set(orgs);
82
+ const userData = geex.auth.user();
83
+ let allOwned = [];
84
+ if (orgs?.length && userData) {
85
+ if (userData.id === "000000000000000000000001") {
86
+ allOwned = deepCopy(orgs);
87
+ } else {
88
+ const ownedCodes = userData.orgs.map((x) => x.code);
89
+ allOwned = orgs.filter((o) => ownedCodes.some((code) => o.code.startsWith(code)));
90
+ }
91
+ }
92
+ userOwnedOrgsSignal.set(allOwned);
93
+ });
94
+ });
95
+ }
96
+ };
97
+ }
98
+ function createMessagingModule(injector) {
99
+ return {
100
+ onPublicNotify() {
101
+ const subClient = injector.get(Apollo).use("subscription");
102
+ subClient.subscribe({ query: GQL_ON_PUBLIC_NOTIFY }).pipe(map((res) => res?.data?.onPublicNotify)).subscribe((notify) => {
103
+ console.log("Public notify", notify);
104
+ });
105
+ }
106
+ };
107
+ }
108
+ function createSettingsModule(injector) {
109
+ const settingsSignal = signal([]);
110
+ return {
111
+ settings: settingsSignal,
112
+ async init() {
113
+ const res = await firstValueFrom(
114
+ injector.get(Apollo).query({ query: GQL_INIT_SETTINGS })
115
+ );
116
+ const settings = res.data.initSettings;
117
+ settingsSignal.set(settings);
118
+ }
119
+ };
120
+ }
121
+ function createUiModule(injector) {
122
+ const fullScreenSignal = signal(false);
123
+ const isMobile$ = fromEvent(window, "resize").pipe(
124
+ debounceTime(200),
125
+ switchMap(async () => window.innerHeight / window.innerWidth >= 1.5)
126
+ );
127
+ return {
128
+ fullScreen: fullScreenSignal,
129
+ isMobile$,
130
+ activeRoutedComponent: void 0
131
+ };
132
+ }
133
+
134
+ // src/geex.ts
135
+ var geex;
136
+ function configGeex(injector, overrides) {
137
+ runInInjectionContext2(injector, () => {
138
+ const modules = {
139
+ tenant: createTenantModule(injector),
140
+ auth: createAuthModule(injector),
141
+ identity: createIdentityModule(injector),
142
+ messaging: createMessagingModule(injector),
143
+ settings: createSettingsModule(injector),
144
+ ui: createUiModule(injector)
145
+ };
146
+ if (overrides) {
147
+ Object.assign(modules, overrides);
148
+ }
149
+ geex = modules;
150
+ });
151
+ }
152
+
153
+ // src/tokens.ts
154
+ import { InjectionToken } from "@angular/core";
155
+ var GEEX_CONFIG = new InjectionToken("GEEX_CONFIG");
156
+
157
+ // src/provide-geex.ts
158
+ function provideGeex(injector, overrides) {
159
+ configGeex(injector, overrides);
160
+ return [
161
+ { provide: GEEX_CONFIG, useValue: { injector, overrides } },
162
+ { provide: geex, useExisting: geex }
163
+ ];
164
+ }
165
+ export {
166
+ configGeex,
167
+ geex,
168
+ provideGeex
169
+ };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@geexcode/geex-angular",
3
+ "version": "0.0.1",
4
+ "description": "Angular adapter for Geex core.",
5
+ "module": "dist/index.js",
6
+ "main": "dist/index.cjs",
7
+ "types": "dist/index.d.ts",
8
+ "peerDependencies": {
9
+ "@angular/core": "^20.0.0",
10
+ "@angular/router": "^20.0.0",
11
+ "@apollo/client": "^3.9.0",
12
+ "@delon/util": "^15.0.0",
13
+ "angular-oauth2-oidc": "^15.0.0",
14
+ "apollo-angular": "11.0.0",
15
+ "graphql": "^16.8.0",
16
+ "rxjs": "^7.8.0",
17
+ "json5": "^2.2.3",
18
+ "yaml": "^2.8.1",
19
+ "glob": "^11.0.3"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "clean": "rimraf dist",
26
+ "build": "tsup src/index.ts src/esbuild/gql-redirect.plugin.js --dts --format esm,cjs --out-dir dist",
27
+ "prepublishOnly": "npm run build",
28
+ "publish:public": "npm publish --access public",
29
+ "release": "standard-version"
30
+ },
31
+ "devDependencies": {
32
+ "typescript": "^5.6.3",
33
+ "tsup": "^8.0.0",
34
+ "rimraf": "^5.0.5",
35
+ "standard-version": "^9.5.0"
36
+ },
37
+ "dependencies": {
38
+ "graphql-tag": "^2.12.6"
39
+ }
40
+ }