@memberjunction/server 5.23.0 → 5.25.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.
Files changed (63) hide show
  1. package/dist/agents/skip-sdk.d.ts +12 -0
  2. package/dist/agents/skip-sdk.d.ts.map +1 -1
  3. package/dist/agents/skip-sdk.js +70 -1
  4. package/dist/agents/skip-sdk.js.map +1 -1
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/config.js +11 -0
  7. package/dist/config.js.map +1 -1
  8. package/dist/generated/generated.d.ts +954 -0
  9. package/dist/generated/generated.d.ts.map +1 -1
  10. package/dist/generated/generated.js +26108 -20749
  11. package/dist/generated/generated.js.map +1 -1
  12. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  13. package/dist/generic/RunViewResolver.js.map +1 -1
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/resolvers/ArtifactFileResolver.d.ts +15 -0
  19. package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -0
  20. package/dist/resolvers/ArtifactFileResolver.js +74 -0
  21. package/dist/resolvers/ArtifactFileResolver.js.map +1 -0
  22. package/dist/resolvers/AutotagPipelineResolver.d.ts +23 -1
  23. package/dist/resolvers/AutotagPipelineResolver.d.ts.map +1 -1
  24. package/dist/resolvers/AutotagPipelineResolver.js +197 -13
  25. package/dist/resolvers/AutotagPipelineResolver.js.map +1 -1
  26. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  27. package/dist/resolvers/FetchEntityVectorsResolver.js +6 -2
  28. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  29. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  30. package/dist/resolvers/FileResolver.js +12 -32
  31. package/dist/resolvers/FileResolver.js.map +1 -1
  32. package/dist/resolvers/GeoResolver.d.ts +58 -0
  33. package/dist/resolvers/GeoResolver.d.ts.map +1 -0
  34. package/dist/resolvers/GeoResolver.js +302 -0
  35. package/dist/resolvers/GeoResolver.js.map +1 -0
  36. package/dist/resolvers/RunAIAgentResolver.d.ts +34 -1
  37. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  38. package/dist/resolvers/RunAIAgentResolver.js +183 -48
  39. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  40. package/dist/resolvers/SearchKnowledgeResolver.d.ts +23 -41
  41. package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
  42. package/dist/resolvers/SearchKnowledgeResolver.js +133 -382
  43. package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
  44. package/dist/resolvers/SearchKnowledgeSystemUserResolver.d.ts +19 -0
  45. package/dist/resolvers/SearchKnowledgeSystemUserResolver.d.ts.map +1 -0
  46. package/dist/resolvers/SearchKnowledgeSystemUserResolver.js +149 -0
  47. package/dist/resolvers/SearchKnowledgeSystemUserResolver.js.map +1 -0
  48. package/package.json +63 -63
  49. package/src/__tests__/search-knowledge-tags.test.ts +255 -0
  50. package/src/__tests__/skip-sdk-organic-keys.test.ts +274 -0
  51. package/src/agents/skip-sdk.ts +83 -2
  52. package/src/config.ts +11 -0
  53. package/src/generated/generated.ts +3690 -1
  54. package/src/generic/RunViewResolver.ts +1 -0
  55. package/src/index.ts +2 -0
  56. package/src/resolvers/ArtifactFileResolver.ts +71 -0
  57. package/src/resolvers/AutotagPipelineResolver.ts +213 -10
  58. package/src/resolvers/FetchEntityVectorsResolver.ts +6 -2
  59. package/src/resolvers/FileResolver.ts +12 -41
  60. package/src/resolvers/GeoResolver.ts +258 -0
  61. package/src/resolvers/RunAIAgentResolver.ts +229 -76
  62. package/src/resolvers/SearchKnowledgeResolver.ts +118 -462
  63. package/src/resolvers/SearchKnowledgeSystemUserResolver.ts +138 -0
@@ -0,0 +1,258 @@
1
+ import { Resolver, Query, Arg, Ctx, ObjectType, Field, InputType, Float, Int } from 'type-graphql';
2
+ import { AppContext } from '../types.js';
3
+ import { ResolverBase } from '../generic/ResolverBase.js';
4
+ import { RunView, LogError, Metadata, UserInfo } from '@memberjunction/core';
5
+ import { MJCountryEntity, MJStateProvinceEntity } from '@memberjunction/core-entities';
6
+
7
+ // ---------------------------------------------------------------------------
8
+ // Types
9
+ // ---------------------------------------------------------------------------
10
+
11
+ @ObjectType()
12
+ export class GeoCountryResult {
13
+ @Field()
14
+ ID!: string;
15
+
16
+ @Field()
17
+ Name!: string;
18
+
19
+ @Field()
20
+ ISO2!: string;
21
+
22
+ @Field()
23
+ ISO3!: string;
24
+
25
+ @Field(() => Float, { nullable: true })
26
+ Latitude!: number | null;
27
+
28
+ @Field(() => Float, { nullable: true })
29
+ Longitude!: number | null;
30
+ }
31
+
32
+ @ObjectType()
33
+ export class GeoStateProvinceResult {
34
+ @Field()
35
+ ID!: string;
36
+
37
+ @Field()
38
+ CountryID!: string;
39
+
40
+ @Field()
41
+ Name!: string;
42
+
43
+ @Field()
44
+ Code!: string;
45
+
46
+ @Field()
47
+ ISO3166_2!: string;
48
+
49
+ @Field(() => Float, { nullable: true })
50
+ Latitude!: number | null;
51
+
52
+ @Field(() => Float, { nullable: true })
53
+ Longitude!: number | null;
54
+ }
55
+
56
+ @ObjectType()
57
+ export class GeoResolveResult {
58
+ @Field()
59
+ Success!: boolean;
60
+
61
+ @Field({ nullable: true })
62
+ CountryID?: string;
63
+
64
+ @Field({ nullable: true })
65
+ CountryName?: string;
66
+
67
+ @Field({ nullable: true })
68
+ StateProvinceID?: string;
69
+
70
+ @Field({ nullable: true })
71
+ StateProvinceName?: string;
72
+
73
+ @Field(() => Float, { nullable: true })
74
+ Latitude?: number;
75
+
76
+ @Field(() => Float, { nullable: true })
77
+ Longitude?: number;
78
+
79
+ @Field({ nullable: true })
80
+ ErrorMessage?: string;
81
+ }
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // Resolver
85
+ // ---------------------------------------------------------------------------
86
+
87
+ /**
88
+ * GraphQL resolver for geographic reference data resolution.
89
+ * Provides country/state text-to-reference matching via the GeoResolver service.
90
+ * Used by clients that need to resolve free-text location strings to structured
91
+ * reference data (Country/StateProvince IDs, centroids) without a full geocoding API call.
92
+ */
93
+ @Resolver()
94
+ export class GeoResolver extends ResolverBase {
95
+ private _countries: MJCountryEntity[] | null = null;
96
+ private _states: MJStateProvinceEntity[] | null = null;
97
+
98
+ /**
99
+ * Lazily load all countries into memory (~250 records).
100
+ */
101
+ private async GetCountries(contextUser: UserInfo | undefined): Promise<MJCountryEntity[]> {
102
+ if (this._countries) return this._countries;
103
+ const rv = new RunView();
104
+ const result = await rv.RunView<MJCountryEntity>({
105
+ EntityName: 'MJ: Countries',
106
+ ResultType: 'entity_object'
107
+ }, contextUser);
108
+ if (result.Success) {
109
+ this._countries = result.Results;
110
+ }
111
+ return this._countries ?? [];
112
+ }
113
+
114
+ /**
115
+ * Lazily load all state/provinces into memory (~5000 records).
116
+ */
117
+ private async GetStates(contextUser: UserInfo | undefined): Promise<MJStateProvinceEntity[]> {
118
+ if (this._states) return this._states;
119
+ const rv = new RunView();
120
+ const result = await rv.RunView<MJStateProvinceEntity>({
121
+ EntityName: 'MJ: State Provinces',
122
+ ResultType: 'entity_object'
123
+ }, contextUser);
124
+ if (result.Success) {
125
+ this._states = result.Results;
126
+ }
127
+ return this._states ?? [];
128
+ }
129
+
130
+ /**
131
+ * Resolve a free-text country string to a Country reference record.
132
+ * Matches by Name, ISO2, ISO3, or CommonAliases.
133
+ */
134
+ @Query(() => GeoResolveResult)
135
+ async ResolveCountry(
136
+ @Arg('input', () => String) input: string,
137
+ @Ctx() { userPayload }: AppContext
138
+ ): Promise<GeoResolveResult> {
139
+ try {
140
+ const user = this.GetUserFromPayload(userPayload);
141
+ const countries = await this.GetCountries(user);
142
+ const normalized = input.trim().toLowerCase();
143
+
144
+ // 1. Exact match on Name, ISO2, ISO3
145
+ const exact = countries.find(c =>
146
+ c.Name.toLowerCase() === normalized ||
147
+ c.ISO2.toLowerCase() === normalized ||
148
+ c.ISO3.toLowerCase() === normalized
149
+ );
150
+ if (exact) {
151
+ return {
152
+ Success: true,
153
+ CountryID: exact.ID,
154
+ CountryName: exact.Name,
155
+ Latitude: exact.Latitude ?? undefined,
156
+ Longitude: exact.Longitude ?? undefined
157
+ };
158
+ }
159
+
160
+ // 2. CommonAliases search
161
+ const aliasMatch = countries.find(c => {
162
+ if (!c.CommonAliases) return false;
163
+ try {
164
+ const aliases: string[] = JSON.parse(c.CommonAliases);
165
+ return aliases.some(a => a.toLowerCase() === normalized);
166
+ } catch {
167
+ return false;
168
+ }
169
+ });
170
+ if (aliasMatch) {
171
+ return {
172
+ Success: true,
173
+ CountryID: aliasMatch.ID,
174
+ CountryName: aliasMatch.Name,
175
+ Latitude: aliasMatch.Latitude ?? undefined,
176
+ Longitude: aliasMatch.Longitude ?? undefined
177
+ };
178
+ }
179
+
180
+ return { Success: false, ErrorMessage: `No country match for "${input}"` };
181
+ } catch (e: unknown) {
182
+ const msg = e instanceof Error ? e.message : String(e);
183
+ LogError(`GeoResolver.ResolveCountry error: ${msg}`);
184
+ return { Success: false, ErrorMessage: msg };
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Resolve a free-text state/province string with country context.
190
+ * Country context is critical: "CA" = California (US) vs Canada (ISO2).
191
+ */
192
+ @Query(() => GeoResolveResult)
193
+ async ResolveStateProvince(
194
+ @Arg('stateInput', () => String) stateInput: string,
195
+ @Arg('countryInput', () => String) countryInput: string,
196
+ @Ctx() { userPayload }: AppContext
197
+ ): Promise<GeoResolveResult> {
198
+ try {
199
+ const user = this.GetUserFromPayload(userPayload);
200
+
201
+ // First resolve country
202
+ const countryResult = await this.ResolveCountry(countryInput, { userPayload } as AppContext);
203
+ if (!countryResult.Success || !countryResult.CountryID) {
204
+ return { Success: false, ErrorMessage: `Could not resolve country "${countryInput}"` };
205
+ }
206
+
207
+ const states = await this.GetStates(user);
208
+ const countryStates = states.filter(s => s.CountryID === countryResult.CountryID);
209
+ const normalized = stateInput.trim().toLowerCase();
210
+
211
+ // 1. Exact match on Name, Code, ISO3166_2
212
+ const exact = countryStates.find(s =>
213
+ s.Name.toLowerCase() === normalized ||
214
+ s.Code.toLowerCase() === normalized ||
215
+ s.ISO3166_2.toLowerCase() === normalized
216
+ );
217
+ if (exact) {
218
+ return {
219
+ Success: true,
220
+ CountryID: countryResult.CountryID,
221
+ CountryName: countryResult.CountryName,
222
+ StateProvinceID: exact.ID,
223
+ StateProvinceName: exact.Name,
224
+ Latitude: exact.Latitude ?? undefined,
225
+ Longitude: exact.Longitude ?? undefined
226
+ };
227
+ }
228
+
229
+ // 2. CommonAliases search
230
+ const aliasMatch = countryStates.find(s => {
231
+ if (!s.CommonAliases) return false;
232
+ try {
233
+ const aliases: string[] = JSON.parse(s.CommonAliases);
234
+ return aliases.some(a => a.toLowerCase() === normalized);
235
+ } catch {
236
+ return false;
237
+ }
238
+ });
239
+ if (aliasMatch) {
240
+ return {
241
+ Success: true,
242
+ CountryID: countryResult.CountryID,
243
+ CountryName: countryResult.CountryName,
244
+ StateProvinceID: aliasMatch.ID,
245
+ StateProvinceName: aliasMatch.Name,
246
+ Latitude: aliasMatch.Latitude ?? undefined,
247
+ Longitude: aliasMatch.Longitude ?? undefined
248
+ };
249
+ }
250
+
251
+ return { Success: false, ErrorMessage: `No state/province match for "${stateInput}" in ${countryResult.CountryName}` };
252
+ } catch (e: unknown) {
253
+ const msg = e instanceof Error ? e.message : String(e);
254
+ LogError(`GeoResolver.ResolveStateProvince error: ${msg}`);
255
+ return { Success: false, ErrorMessage: msg };
256
+ }
257
+ }
258
+ }