@yesprasad/fluent-graph 0.1.0 → 0.2.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.
@@ -0,0 +1,30 @@
1
+ interface TableInfo {
2
+ table: string;
3
+ pluginName: string;
4
+ isChild: boolean;
5
+ parentTable?: string;
6
+ parentVia?: string;
7
+ children: string[];
8
+ }
9
+ export declare class ArtifactTypeRegistry {
10
+ private tables;
11
+ load(sdkPath: string): void;
12
+ private register;
13
+ /**
14
+ * Parse the top-level relationships map:
15
+ * { parentTable: { childTable: { via, descendant, relationships: { grandchild: ... } } } }
16
+ */
17
+ private parseRelationships;
18
+ private processChildren;
19
+ get(table: string): TableInfo | undefined;
20
+ getPluginName(table: string): string;
21
+ getDisplayGroupName(table: string): string;
22
+ isChild(table: string): boolean;
23
+ getParentTable(table: string): string | undefined;
24
+ getChildren(table: string): string[];
25
+ getTablesByPlugin(pluginName: string): string[];
26
+ getAllPluginNames(): string[];
27
+ getAllTables(): string[];
28
+ isKnown(table: string): boolean;
29
+ }
30
+ export {};
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ArtifactTypeRegistry = void 0;
7
+ const module_1 = require("module");
8
+ const path_1 = __importDefault(require("path"));
9
+ class ArtifactTypeRegistry {
10
+ constructor() {
11
+ this.tables = new Map();
12
+ }
13
+ load(sdkPath) {
14
+ try {
15
+ const requireFromWorkspace = (0, module_1.createRequire)(path_1.default.join(sdkPath, 'package.json'));
16
+ const buildPlugins = requireFromWorkspace('@servicenow/sdk-build-plugins');
17
+ for (const [, value] of Object.entries(buildPlugins)) {
18
+ const plugin = value;
19
+ if (!plugin?.config?.name)
20
+ continue;
21
+ const pluginName = plugin.config.name;
22
+ const tables = Object.keys(plugin.config.records || {}).filter(k => k !== '*');
23
+ if (tables.length === 0)
24
+ continue;
25
+ for (const table of tables) {
26
+ this.register(table, pluginName);
27
+ }
28
+ try {
29
+ const rels = plugin.getRelationships();
30
+ if (rels && typeof rels === 'object') {
31
+ this.parseRelationships(rels, pluginName);
32
+ }
33
+ }
34
+ catch {
35
+ // safe to skip — needs compiler context
36
+ }
37
+ }
38
+ }
39
+ catch {
40
+ // sdk-build-plugins unavailable; registry stays empty, fallback behavior applies
41
+ }
42
+ }
43
+ register(table, pluginName) {
44
+ if (!this.tables.has(table)) {
45
+ this.tables.set(table, { table, pluginName, isChild: false, children: [] });
46
+ }
47
+ }
48
+ /**
49
+ * Parse the top-level relationships map:
50
+ * { parentTable: { childTable: { via, descendant, relationships: { grandchild: ... } } } }
51
+ */
52
+ parseRelationships(rels, pluginName) {
53
+ for (const [parentTable, childDefs] of Object.entries(rels)) {
54
+ this.register(parentTable, pluginName);
55
+ if (childDefs && typeof childDefs === 'object') {
56
+ this.processChildren(childDefs, pluginName, parentTable);
57
+ }
58
+ }
59
+ }
60
+ processChildren(childDefs, pluginName, parentTable) {
61
+ for (const [key, def] of Object.entries(childDefs)) {
62
+ // Skip meta-keys and self-referential entries
63
+ if (key === 'via' || key === 'descendant' || key === 'relationships')
64
+ continue;
65
+ if (key === parentTable)
66
+ continue;
67
+ const childTable = key;
68
+ this.register(childTable, pluginName);
69
+ const entry = this.tables.get(childTable);
70
+ if (!entry.isChild) {
71
+ entry.isChild = true;
72
+ entry.parentTable = parentTable;
73
+ if (def && typeof def === 'object' && typeof def.via === 'string') {
74
+ entry.parentVia = def.via;
75
+ }
76
+ }
77
+ // Add to parent's children list
78
+ const parentEntry = this.tables.get(parentTable);
79
+ if (parentEntry && !parentEntry.children.includes(childTable)) {
80
+ parentEntry.children.push(childTable);
81
+ }
82
+ // Recurse into nested relationships
83
+ if (def && typeof def === 'object' && def.relationships && typeof def.relationships === 'object') {
84
+ this.processChildren(def.relationships, pluginName, childTable);
85
+ }
86
+ }
87
+ }
88
+ get(table) {
89
+ return this.tables.get(table);
90
+ }
91
+ getPluginName(table) {
92
+ return this.tables.get(table)?.pluginName ?? 'Record';
93
+ }
94
+ getDisplayGroupName(table) {
95
+ const entry = this.tables.get(table);
96
+ if (!entry)
97
+ return 'Other';
98
+ return entry.pluginName
99
+ .replace(/Plugin$/, '')
100
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
101
+ .replace(/^./, c => c.toUpperCase())
102
+ .trim();
103
+ }
104
+ isChild(table) {
105
+ return this.tables.get(table)?.isChild ?? false;
106
+ }
107
+ getParentTable(table) {
108
+ return this.tables.get(table)?.parentTable;
109
+ }
110
+ getChildren(table) {
111
+ return this.tables.get(table)?.children ?? [];
112
+ }
113
+ getTablesByPlugin(pluginName) {
114
+ return [...this.tables.values()]
115
+ .filter(t => t.pluginName === pluginName)
116
+ .map(t => t.table);
117
+ }
118
+ getAllPluginNames() {
119
+ return [...new Set([...this.tables.values()].map(t => t.pluginName))].sort();
120
+ }
121
+ getAllTables() {
122
+ return [...this.tables.keys()];
123
+ }
124
+ isKnown(table) {
125
+ return this.tables.has(table);
126
+ }
127
+ }
128
+ exports.ArtifactTypeRegistry = ArtifactTypeRegistry;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@yesprasad/fluent-graph",
3
- "version": "0.1.0",
4
- "description": "Dependency/ Lineage graph extraction & Blast-radius/ impact analysis for ServiceNow Fluent Artifacts",
3
+ "version": "0.2.0",
4
+ "description": "Dependency visibility and impact analysis for ServiceNow Fluent SDK projects",
5
5
  "bin": {
6
6
  "fluent-graph": "./bin/fluent-graph.js"
7
7
  },
8
8
  "main": "dist/index.js",
9
- "types": "dist/index.d.ts",
9
+ "types": "dist/index.d.ts",
10
10
  "files": [
11
11
  "dist",
12
12
  "bin"
@@ -27,13 +27,13 @@
27
27
  ],
28
28
  "author": "Eshwar Sowbhagya Prasad Yaddanapudi",
29
29
  "repository": {
30
- "type": "git",
31
- "url": "https://github.com/yesprasad/fluent-graph.git"
32
- },
33
- "bugs": {
34
- "url": "https://github.com/yesprasad/fluent-graph/issues"
35
- },
36
- "homepage": "https://github.com/yesprasad/fluent-graph#readme",
30
+ "type": "git",
31
+ "url": "https://github.com/yesprasad/fluent-graph.git"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/yesprasad/fluent-graph/issues"
35
+ },
36
+ "homepage": "https://github.com/yesprasad/fluent-graph#readme",
37
37
  "license": "MIT",
38
38
  "type": "commonjs",
39
39
  "dependencies": {
@@ -43,11 +43,14 @@
43
43
  "ora": "^5.4.1"
44
44
  },
45
45
  "devDependencies": {
46
- "@types/node": "^20.0.0",
46
+ "@types/node": "^20.19.39",
47
47
  "tsx": "^4.0.0",
48
48
  "typescript": "^5.0.0"
49
49
  },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
50
53
  "peerDependencies": {
51
- "@servicenow/sdk": "4.1.0"
54
+ "@servicenow/sdk": "4.5.0"
52
55
  }
53
- }
56
+ }