@grafema/api 0.2.5-beta

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 (70) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +219 -0
  3. package/dist/context.d.ts +22 -0
  4. package/dist/context.d.ts.map +1 -0
  5. package/dist/context.js +18 -0
  6. package/dist/context.js.map +1 -0
  7. package/dist/dataloaders/index.d.ts +18 -0
  8. package/dist/dataloaders/index.d.ts.map +1 -0
  9. package/dist/dataloaders/index.js +17 -0
  10. package/dist/dataloaders/index.js.map +1 -0
  11. package/dist/dataloaders/nodeLoader.d.ts +19 -0
  12. package/dist/dataloaders/nodeLoader.d.ts.map +1 -0
  13. package/dist/dataloaders/nodeLoader.js +31 -0
  14. package/dist/dataloaders/nodeLoader.js.map +1 -0
  15. package/dist/index.d.ts +11 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +9 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/pagination.d.ts +50 -0
  20. package/dist/pagination.d.ts.map +1 -0
  21. package/dist/pagination.js +71 -0
  22. package/dist/pagination.js.map +1 -0
  23. package/dist/resolvers/edge.d.ts +22 -0
  24. package/dist/resolvers/edge.d.ts.map +1 -0
  25. package/dist/resolvers/edge.js +36 -0
  26. package/dist/resolvers/edge.js.map +1 -0
  27. package/dist/resolvers/index.d.ts +159 -0
  28. package/dist/resolvers/index.d.ts.map +1 -0
  29. package/dist/resolvers/index.js +21 -0
  30. package/dist/resolvers/index.js.map +1 -0
  31. package/dist/resolvers/mutation.d.ts +69 -0
  32. package/dist/resolvers/mutation.d.ts.map +1 -0
  33. package/dist/resolvers/mutation.js +82 -0
  34. package/dist/resolvers/mutation.js.map +1 -0
  35. package/dist/resolvers/node.d.ts +50 -0
  36. package/dist/resolvers/node.d.ts.map +1 -0
  37. package/dist/resolvers/node.js +69 -0
  38. package/dist/resolvers/node.js.map +1 -0
  39. package/dist/resolvers/query.d.ts +169 -0
  40. package/dist/resolvers/query.d.ts.map +1 -0
  41. package/dist/resolvers/query.js +188 -0
  42. package/dist/resolvers/query.js.map +1 -0
  43. package/dist/schema/enums.graphql +27 -0
  44. package/dist/schema/mutations.graphql +53 -0
  45. package/dist/schema/queries.graphql +213 -0
  46. package/dist/schema/scalars.graphql +2 -0
  47. package/dist/schema/subscriptions.graphql +84 -0
  48. package/dist/schema/types.graphql +440 -0
  49. package/dist/server.d.ts +31 -0
  50. package/dist/server.d.ts.map +1 -0
  51. package/dist/server.js +109 -0
  52. package/dist/server.js.map +1 -0
  53. package/package.json +51 -0
  54. package/src/context.ts +33 -0
  55. package/src/dataloaders/index.ts +24 -0
  56. package/src/dataloaders/nodeLoader.ts +41 -0
  57. package/src/index.ts +11 -0
  58. package/src/pagination.ts +109 -0
  59. package/src/resolvers/edge.ts +39 -0
  60. package/src/resolvers/index.ts +24 -0
  61. package/src/resolvers/mutation.ts +108 -0
  62. package/src/resolvers/node.ts +118 -0
  63. package/src/resolvers/query.ts +307 -0
  64. package/src/schema/enums.graphql +27 -0
  65. package/src/schema/mutations.graphql +53 -0
  66. package/src/schema/queries.graphql +213 -0
  67. package/src/schema/scalars.graphql +2 -0
  68. package/src/schema/subscriptions.graphql +84 -0
  69. package/src/schema/types.graphql +440 -0
  70. package/src/server.ts +140 -0
@@ -0,0 +1,84 @@
1
+ type Subscription {
2
+ """
3
+ Stream nodes matching filter as they're found.
4
+ Useful for UI visualization of large datasets.
5
+ """
6
+ nodesStream(
7
+ """Filter criteria"""
8
+ filter: NodeFilter
9
+
10
+ """Batch size for streaming (default: 100)"""
11
+ batchSize: Int
12
+ ): NodeBatch!
13
+
14
+ """
15
+ Stream BFS traversal results level by level.
16
+ Each batch contains all nodes at one depth level.
17
+ """
18
+ bfsStream(
19
+ """Starting node IDs"""
20
+ startIds: [ID!]!
21
+
22
+ """Maximum traversal depth"""
23
+ maxDepth: Int!
24
+
25
+ """Edge types to traverse"""
26
+ edgeTypes: [String!]!
27
+ ): TraversalBatch!
28
+
29
+ """
30
+ Stream analysis progress events.
31
+ """
32
+ analysisProgress(
33
+ """Optional: filter to specific service"""
34
+ service: String
35
+ ): AnalysisEvent!
36
+ }
37
+
38
+ """
39
+ Batch of nodes for streaming responses.
40
+ """
41
+ type NodeBatch {
42
+ """Nodes in this batch"""
43
+ nodes: [Node!]!
44
+
45
+ """Progress from 0.0 to 1.0"""
46
+ progress: Float!
47
+
48
+ """Whether streaming is complete"""
49
+ done: Boolean!
50
+ }
51
+
52
+ """
53
+ Batch of traversal results at a specific depth.
54
+ """
55
+ type TraversalBatch {
56
+ """Current depth level"""
57
+ depth: Int!
58
+
59
+ """Node IDs at this depth"""
60
+ nodeIds: [ID!]!
61
+
62
+ """Whether traversal is complete"""
63
+ done: Boolean!
64
+ }
65
+
66
+ """
67
+ Analysis progress event.
68
+ """
69
+ type AnalysisEvent {
70
+ """Current phase name"""
71
+ phase: String!
72
+
73
+ """Human-readable message"""
74
+ message: String!
75
+
76
+ """Progress from 0.0 to 1.0"""
77
+ progress: Float!
78
+
79
+ """Number of services completed"""
80
+ servicesCompleted: Int!
81
+
82
+ """Total number of services"""
83
+ servicesTotal: Int!
84
+ }
@@ -0,0 +1,440 @@
1
+ """
2
+ A node in the code graph representing a code entity.
3
+ """
4
+ type Node {
5
+ """Unique identifier for the node (e.g., "fn:src/api.ts:login:42")"""
6
+ id: ID!
7
+
8
+ """Node type (e.g., FUNCTION, CLASS, MODULE, http:route)"""
9
+ type: String!
10
+
11
+ """Human-readable name"""
12
+ name: String!
13
+
14
+ """Source file path (relative to project root)"""
15
+ file: String
16
+
17
+ """Line number in source file (1-indexed)"""
18
+ line: Int
19
+
20
+ """Column number in source file (1-indexed)"""
21
+ column: Int
22
+
23
+ """Whether this entity is exported from its module"""
24
+ exported: Boolean
25
+
26
+ """Arbitrary metadata as JSON object"""
27
+ metadata: JSON
28
+
29
+ # Relationship fields
30
+
31
+ """
32
+ Outgoing edges from this node.
33
+ Optional filter by edge types.
34
+ """
35
+ outgoingEdges(
36
+ types: [String!]
37
+ first: Int
38
+ after: String
39
+ ): GraphEdgeConnection!
40
+
41
+ """
42
+ Incoming edges to this node.
43
+ Optional filter by edge types.
44
+ """
45
+ incomingEdges(
46
+ types: [String!]
47
+ first: Int
48
+ after: String
49
+ ): GraphEdgeConnection!
50
+
51
+ """
52
+ Child nodes (via CONTAINS edges).
53
+ For hierarchical traversal: SERVICE -> MODULE -> FUNCTION -> SCOPE
54
+ """
55
+ children(first: Int, after: String): NodeConnection!
56
+
57
+ """
58
+ Parent node (via incoming CONTAINS edge).
59
+ Returns null for root nodes (SERVICE, PROJECT).
60
+ """
61
+ parent: Node
62
+ }
63
+
64
+ """
65
+ An edge in the code graph representing a relationship between nodes.
66
+ """
67
+ type Edge {
68
+ """Source node"""
69
+ src: Node!
70
+
71
+ """Destination node"""
72
+ dst: Node!
73
+
74
+ """Edge type (e.g., CALLS, CONTAINS, IMPORTS)"""
75
+ type: String!
76
+
77
+ """Ordering index for ordered relationships"""
78
+ index: Int
79
+
80
+ """Arbitrary metadata as JSON object"""
81
+ metadata: JSON
82
+ }
83
+
84
+ # ============================================================================
85
+ # Pagination Types (Relay Connection Spec)
86
+ # ============================================================================
87
+
88
+ """
89
+ Connection type for paginated node results (Relay spec).
90
+ """
91
+ type NodeConnection {
92
+ """Edges containing nodes and cursors"""
93
+ edges: [NodeEdge!]!
94
+
95
+ """Pagination info"""
96
+ pageInfo: PageInfo!
97
+
98
+ """Total count of matching nodes"""
99
+ totalCount: Int!
100
+ }
101
+
102
+ """
103
+ Edge wrapper for cursor-based pagination.
104
+ """
105
+ type NodeEdge {
106
+ """The node"""
107
+ node: Node!
108
+
109
+ """Cursor for this node (use with after/before args)"""
110
+ cursor: String!
111
+ }
112
+
113
+ """
114
+ Connection type for paginated graph edge results.
115
+ """
116
+ type GraphEdgeConnection {
117
+ """Edges containing graph edges and cursors"""
118
+ edges: [GraphEdgeEdge!]!
119
+
120
+ """Pagination info"""
121
+ pageInfo: PageInfo!
122
+
123
+ """Total count of matching edges"""
124
+ totalCount: Int!
125
+ }
126
+
127
+ """
128
+ Edge wrapper for graph edges.
129
+ """
130
+ type GraphEdgeEdge {
131
+ """The graph edge"""
132
+ node: Edge!
133
+
134
+ """Cursor for this edge"""
135
+ cursor: String!
136
+ }
137
+
138
+ """
139
+ Pagination info (Relay spec).
140
+ """
141
+ type PageInfo {
142
+ """Has more items after endCursor"""
143
+ hasNextPage: Boolean!
144
+
145
+ """Has more items before startCursor"""
146
+ hasPreviousPage: Boolean!
147
+
148
+ """Cursor of first item in current page"""
149
+ startCursor: String
150
+
151
+ """Cursor of last item in current page"""
152
+ endCursor: String
153
+ }
154
+
155
+ # ============================================================================
156
+ # Query Result Types
157
+ # ============================================================================
158
+
159
+ """
160
+ Result of a Datalog query.
161
+ """
162
+ type DatalogResult {
163
+ """Whether the query executed successfully"""
164
+ success: Boolean!
165
+
166
+ """Number of results"""
167
+ count: Int!
168
+
169
+ """Query results with variable bindings"""
170
+ results: [DatalogBinding!]!
171
+
172
+ """Error message if query failed"""
173
+ error: String
174
+ }
175
+
176
+ """
177
+ Variable bindings from a Datalog query result.
178
+ """
179
+ type DatalogBinding {
180
+ """Map of variable names to values"""
181
+ bindings: JSON!
182
+
183
+ """Enriched node data if X binding is a node ID"""
184
+ node: Node
185
+ }
186
+
187
+ """
188
+ Function details including call graph information.
189
+ """
190
+ type FunctionDetails {
191
+ """The function node"""
192
+ function: Node!
193
+
194
+ """Functions/methods this function calls"""
195
+ calls: [CallInfo!]!
196
+
197
+ """Functions that call this function"""
198
+ calledBy: [CallerInfo!]!
199
+ }
200
+
201
+ """
202
+ Information about a call made by a function.
203
+ """
204
+ type CallInfo {
205
+ """The CALL node"""
206
+ call: Node!
207
+
208
+ """Name of the called function/method"""
209
+ name: String!
210
+
211
+ """Object name for method calls (e.g., "console" in console.log)"""
212
+ object: String
213
+
214
+ """Whether the target was resolved"""
215
+ resolved: Boolean!
216
+
217
+ """Target function if resolved"""
218
+ target: Node
219
+
220
+ """Call type: CALL or METHOD_CALL"""
221
+ callType: String!
222
+
223
+ """Depth in transitive call chain (0 = direct)"""
224
+ depth: Int!
225
+ }
226
+
227
+ """
228
+ Information about a function that calls another function.
229
+ """
230
+ type CallerInfo {
231
+ """The calling function"""
232
+ function: Node!
233
+
234
+ """File containing the caller"""
235
+ file: String!
236
+
237
+ """Line number of the call"""
238
+ line: Int!
239
+ }
240
+
241
+ """
242
+ Guard (conditional scope) protecting a node.
243
+ """
244
+ type GuardInfo {
245
+ """The SCOPE node ID"""
246
+ scopeId: ID!
247
+
248
+ """Type of conditional (if_statement, else_statement, etc.)"""
249
+ scopeType: String!
250
+
251
+ """Raw condition text"""
252
+ condition: String
253
+
254
+ """Parsed constraints as JSON"""
255
+ constraints: JSON
256
+
257
+ """Source file"""
258
+ file: String!
259
+
260
+ """Line number"""
261
+ line: Int!
262
+ }
263
+
264
+ """
265
+ Guarantee definition.
266
+ """
267
+ type Guarantee {
268
+ """Unique identifier"""
269
+ id: ID!
270
+
271
+ """Human-readable name"""
272
+ name: String!
273
+
274
+ """Datalog rule or contract condition"""
275
+ rule: String
276
+
277
+ """Severity level"""
278
+ severity: String
279
+
280
+ """Guarantee type for contract-based"""
281
+ type: String
282
+
283
+ """Priority level"""
284
+ priority: String
285
+
286
+ """Lifecycle status"""
287
+ status: String
288
+
289
+ """Description"""
290
+ description: String
291
+ }
292
+
293
+ """
294
+ Result of checking guarantees.
295
+ """
296
+ type GuaranteeCheckResult {
297
+ """Total guarantees checked"""
298
+ total: Int!
299
+
300
+ """Number that passed"""
301
+ passed: Int!
302
+
303
+ """Number that failed"""
304
+ failed: Int!
305
+
306
+ """Individual results"""
307
+ results: [GuaranteeResult!]!
308
+ }
309
+
310
+ """
311
+ Result of checking a single guarantee.
312
+ """
313
+ type GuaranteeResult {
314
+ """Guarantee ID"""
315
+ guaranteeId: ID!
316
+
317
+ """Whether the guarantee passed"""
318
+ passed: Boolean!
319
+
320
+ """Number of violations (for Datalog guarantees)"""
321
+ violationCount: Int
322
+
323
+ """Sample violations"""
324
+ violations: [Violation!]
325
+ }
326
+
327
+ """
328
+ A violation of a guarantee.
329
+ """
330
+ type Violation {
331
+ """Node that violated the guarantee"""
332
+ node: Node
333
+
334
+ """File containing the violation"""
335
+ file: String
336
+
337
+ """Line number"""
338
+ line: Int
339
+ }
340
+
341
+ """
342
+ Graph statistics.
343
+ """
344
+ type GraphStats {
345
+ """Total node count"""
346
+ nodeCount: Int!
347
+
348
+ """Total edge count"""
349
+ edgeCount: Int!
350
+
351
+ """Nodes grouped by type"""
352
+ nodesByType: JSON!
353
+
354
+ """Edges grouped by type"""
355
+ edgesByType: JSON!
356
+ }
357
+
358
+ """
359
+ Analysis status.
360
+ """
361
+ type AnalysisStatus {
362
+ """Whether analysis is currently running"""
363
+ running: Boolean!
364
+
365
+ """Current phase"""
366
+ phase: String
367
+
368
+ """Status message"""
369
+ message: String
370
+
371
+ """Number of services discovered"""
372
+ servicesDiscovered: Int!
373
+
374
+ """Number of services analyzed"""
375
+ servicesAnalyzed: Int!
376
+
377
+ """Error message if analysis failed"""
378
+ error: String
379
+ }
380
+
381
+ """
382
+ Result of analyze mutation.
383
+ """
384
+ type AnalysisResult {
385
+ """Whether analysis succeeded"""
386
+ success: Boolean!
387
+
388
+ """Status after analysis"""
389
+ status: AnalysisStatus!
390
+ }
391
+
392
+ # ============================================================================
393
+ # Input Types
394
+ # ============================================================================
395
+
396
+ """
397
+ Filter for node queries.
398
+ """
399
+ input NodeFilter {
400
+ """Filter by node type"""
401
+ type: String
402
+
403
+ """Filter by name (exact match)"""
404
+ name: String
405
+
406
+ """Filter by file path (partial match)"""
407
+ file: String
408
+
409
+ """Filter by exported status"""
410
+ exported: Boolean
411
+ }
412
+
413
+ """
414
+ Input for creating a guarantee.
415
+ """
416
+ input CreateGuaranteeInput {
417
+ """Unique name"""
418
+ name: String!
419
+
420
+ """Datalog rule defining violation/1"""
421
+ rule: String
422
+
423
+ """Severity: error, warning, info"""
424
+ severity: Severity
425
+
426
+ """Type: guarantee:queue, guarantee:api, guarantee:permission"""
427
+ type: String
428
+
429
+ """Priority: critical, important, observed, tracked"""
430
+ priority: Priority
431
+
432
+ """Description"""
433
+ description: String
434
+
435
+ """Owner (team or person)"""
436
+ owner: String
437
+
438
+ """Node IDs this guarantee governs"""
439
+ governs: [String!]
440
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * GraphQL API Server using graphql-yoga
3
+ *
4
+ * Provides a GraphQL endpoint on top of Grafema's graph database.
5
+ * Supports cursor-based pagination and query complexity limiting.
6
+ */
7
+ import { createServer } from 'node:http';
8
+ import type { RFDBServerBackend } from '@grafema/core';
9
+ export interface GraphQLServerOptions {
10
+ /** Graph backend (RFDBServerBackend) */
11
+ backend: RFDBServerBackend;
12
+ /** Port to listen on (default: 4000) */
13
+ port?: number;
14
+ /** Hostname to bind to (default: localhost) */
15
+ hostname?: string;
16
+ /** Maximum query depth (default: 10) */
17
+ maxDepth?: number;
18
+ /** Maximum query complexity cost (default: 1000) */
19
+ maxComplexity?: number;
20
+ /** Request timeout in ms (default: 30000) */
21
+ timeout?: number;
22
+ }
23
+ export declare function createGraphQLServer(options: GraphQLServerOptions): import("graphql-yoga").YogaServerInstance<{}, import("./context.js").GraphQLContext>;
24
+ /**
25
+ * Start a standalone GraphQL server.
26
+ *
27
+ * @param options Server options
28
+ * @returns HTTP server instance
29
+ */
30
+ export declare function startServer(options: GraphQLServerOptions): ReturnType<typeof createServer>;
31
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAwB,MAAM,WAAW,CAAC;AAQ/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AA6BvD,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,wFAuDhE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,oBAAoB,GAC5B,UAAU,CAAC,OAAO,YAAY,CAAC,CAejC"}
package/dist/server.js ADDED
@@ -0,0 +1,109 @@
1
+ /**
2
+ * GraphQL API Server using graphql-yoga
3
+ *
4
+ * Provides a GraphQL endpoint on top of Grafema's graph database.
5
+ * Supports cursor-based pagination and query complexity limiting.
6
+ */
7
+ import { createServer } from 'node:http';
8
+ import { createYoga, createSchema } from 'graphql-yoga';
9
+ import { readFileSync } from 'node:fs';
10
+ import { join, dirname } from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { resolvers } from './resolvers/index.js';
13
+ import { createContext } from './context.js';
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ // Load schema files
16
+ function loadTypeDefs() {
17
+ const schemaDir = join(__dirname, 'schema');
18
+ const files = [
19
+ 'scalars.graphql',
20
+ 'enums.graphql',
21
+ 'types.graphql',
22
+ 'queries.graphql',
23
+ 'mutations.graphql',
24
+ 'subscriptions.graphql',
25
+ ];
26
+ return files
27
+ .map((file) => {
28
+ try {
29
+ return readFileSync(join(schemaDir, file), 'utf-8');
30
+ }
31
+ catch {
32
+ // File might not exist in dist yet, try src
33
+ const srcPath = join(__dirname, '..', 'src', 'schema', file);
34
+ return readFileSync(srcPath, 'utf-8');
35
+ }
36
+ })
37
+ .join('\n');
38
+ }
39
+ export function createGraphQLServer(options) {
40
+ const { backend } = options;
41
+ const typeDefs = loadTypeDefs();
42
+ const schema = createSchema({
43
+ typeDefs,
44
+ resolvers,
45
+ });
46
+ const yoga = createYoga({
47
+ schema,
48
+ context: ({ request }) => {
49
+ // Create a minimal request object for context
50
+ const req = {
51
+ headers: Object.fromEntries(request.headers.entries()),
52
+ };
53
+ return createContext(backend, req);
54
+ },
55
+ graphiql: {
56
+ title: 'Grafema GraphQL API',
57
+ defaultQuery: `# Welcome to Grafema GraphQL API
58
+ #
59
+ # Example queries:
60
+ #
61
+ # Get all functions:
62
+ # query { nodes(filter: {type: "FUNCTION"}, first: 10) {
63
+ # edges { node { id name file line } }
64
+ # pageInfo { hasNextPage endCursor }
65
+ # totalCount
66
+ # }}
67
+ #
68
+ # Find a specific node:
69
+ # query { node(id: "your-node-id") { id name type file } }
70
+ #
71
+ # Execute Datalog:
72
+ # query { datalog(query: "violation(X) :- node(X, \\"FUNCTION\\").") {
73
+ # count
74
+ # results { node { name } }
75
+ # }}
76
+
77
+ query Stats {
78
+ stats {
79
+ nodeCount
80
+ edgeCount
81
+ nodesByType
82
+ }
83
+ }
84
+ `,
85
+ },
86
+ // Subscriptions enabled for streaming
87
+ // (graphql-yoga uses SSE by default)
88
+ });
89
+ return yoga;
90
+ }
91
+ /**
92
+ * Start a standalone GraphQL server.
93
+ *
94
+ * @param options Server options
95
+ * @returns HTTP server instance
96
+ */
97
+ export function startServer(options) {
98
+ const { port = 4000, hostname = 'localhost' } = options;
99
+ const yoga = createGraphQLServer(options);
100
+ const server = createServer((req, res) => {
101
+ yoga(req, res);
102
+ });
103
+ server.listen(port, hostname, () => {
104
+ console.log(`Grafema GraphQL API running at http://${hostname}:${port}/graphql`);
105
+ console.log(`GraphiQL IDE available at http://${hostname}:${port}/graphql`);
106
+ });
107
+ return server;
108
+ }
109
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}