@vjeko.com/al-object-id-ninja-mcp 1.0.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 (65) hide show
  1. package/README.md +115 -0
  2. package/dist/src/al-app/ALApp.d.ts +52 -0
  3. package/dist/src/al-app/ALApp.js +130 -0
  4. package/dist/src/al-app/ALApp.js.map +1 -0
  5. package/dist/src/al-app/ALAppManifest.d.ts +39 -0
  6. package/dist/src/al-app/ALAppManifest.js +114 -0
  7. package/dist/src/al-app/ALAppManifest.js.map +1 -0
  8. package/dist/src/al-app/AppResolver.d.ts +24 -0
  9. package/dist/src/al-app/AppResolver.js +100 -0
  10. package/dist/src/al-app/AppResolver.js.map +1 -0
  11. package/dist/src/al-app/ObjIdConfig.d.ts +23 -0
  12. package/dist/src/al-app/ObjIdConfig.js +84 -0
  13. package/dist/src/al-app/ObjIdConfig.js.map +1 -0
  14. package/dist/src/al-app/index.d.ts +4 -0
  15. package/dist/src/al-app/index.js +12 -0
  16. package/dist/src/al-app/index.js.map +1 -0
  17. package/dist/src/backend/BackendClient.d.ts +35 -0
  18. package/dist/src/backend/BackendClient.js +129 -0
  19. package/dist/src/backend/BackendClient.js.map +1 -0
  20. package/dist/src/backend/index.d.ts +1 -0
  21. package/dist/src/backend/index.js +6 -0
  22. package/dist/src/backend/index.js.map +1 -0
  23. package/dist/src/index.d.ts +2 -0
  24. package/dist/src/index.js +9 -0
  25. package/dist/src/index.js.map +1 -0
  26. package/dist/src/server.d.ts +3 -0
  27. package/dist/src/server.js +108 -0
  28. package/dist/src/server.js.map +1 -0
  29. package/dist/src/tools/AssignObjectIdTool.d.ts +16 -0
  30. package/dist/src/tools/AssignObjectIdTool.js +83 -0
  31. package/dist/src/tools/AssignObjectIdTool.js.map +1 -0
  32. package/dist/src/tools/UnassignObjectIdTool.d.ts +16 -0
  33. package/dist/src/tools/UnassignObjectIdTool.js +50 -0
  34. package/dist/src/tools/UnassignObjectIdTool.js.map +1 -0
  35. package/dist/src/tools/index.d.ts +3 -0
  36. package/dist/src/tools/index.js +8 -0
  37. package/dist/src/tools/index.js.map +1 -0
  38. package/dist/src/types/ALObjectType.d.ts +15 -0
  39. package/dist/src/types/ALObjectType.js +20 -0
  40. package/dist/src/types/ALObjectType.js.map +1 -0
  41. package/dist/src/types/ALRange.d.ts +7 -0
  42. package/dist/src/types/ALRange.js +3 -0
  43. package/dist/src/types/ALRange.js.map +1 -0
  44. package/dist/src/types/NextObjectIdInfo.d.ts +9 -0
  45. package/dist/src/types/NextObjectIdInfo.js +3 -0
  46. package/dist/src/types/NextObjectIdInfo.js.map +1 -0
  47. package/dist/src/types/NinjaALRange.d.ts +4 -0
  48. package/dist/src/types/NinjaALRange.js +3 -0
  49. package/dist/src/types/NinjaALRange.js.map +1 -0
  50. package/dist/src/types/PropertyBag.d.ts +3 -0
  51. package/dist/src/types/PropertyBag.js +3 -0
  52. package/dist/src/types/PropertyBag.js.map +1 -0
  53. package/dist/src/types/index.d.ts +5 -0
  54. package/dist/src/types/index.js +6 -0
  55. package/dist/src/types/index.js.map +1 -0
  56. package/dist/src/utils/getSha256.d.ts +1 -0
  57. package/dist/src/utils/getSha256.js +43 -0
  58. package/dist/src/utils/getSha256.js.map +1 -0
  59. package/dist/src/utils/index.d.ts +2 -0
  60. package/dist/src/utils/index.js +9 -0
  61. package/dist/src/utils/index.js.map +1 -0
  62. package/dist/src/utils/validation.d.ts +2 -0
  63. package/dist/src/utils/validation.js +20 -0
  64. package/dist/src/utils/validation.js.map +1 -0
  65. package/package.json +59 -0
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # AL Object ID Ninja MCP Server
2
+
3
+ MCP (Model Context Protocol) server for [AL Object ID Ninja](https://marketplace.visualstudio.com/items?itemName=vjeko.vjeko-al-objid) - the VS Code extension for managing AL object IDs in Business Central development.
4
+
5
+ ## Features
6
+
7
+ This MCP server provides two tools for AI assistants:
8
+
9
+ - **ninja_assignObjectId** - Assigns and commits the next available AL object ID
10
+ - **ninja_unassignObjectId** - Releases a previously assigned object ID
11
+
12
+ ## Installation
13
+
14
+ ### VS Code (Insiders)
15
+
16
+ Search for "AL Object ID Ninja" in the MCP Servers gallery, or add to `.vscode/mcp.json`:
17
+
18
+ ```json
19
+ {
20
+ "servers": {
21
+ "al-object-id-ninja": {
22
+ "command": "npx",
23
+ "args": ["-y", "@vjeko.com/al-object-id-ninja-mcp"]
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ ### Claude Code
30
+
31
+ Add to `~/.claude/mcp.json` (global) or `.claude/mcp.json` in your project:
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "al-object-id-ninja": {
37
+ "command": "npx",
38
+ "args": ["-y", "@vjeko.com/al-object-id-ninja-mcp"]
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ Then restart Claude Code or run `/mcp` to reload MCP servers.
45
+
46
+ ### Cursor
47
+
48
+ Add to `~/.cursor/mcp.json`:
49
+
50
+ ```json
51
+ {
52
+ "mcpServers": {
53
+ "al-object-id-ninja": {
54
+ "command": "npx",
55
+ "args": ["-y", "@vjeko.com/al-object-id-ninja-mcp"]
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ ## Prerequisites
62
+
63
+ Your AL app must be set up with AL Object ID Ninja:
64
+
65
+ 1. Have a valid `app.json` with `idRanges` configured
66
+ 2. Have a `.objidconfig` file with `authKey` (created when you authorize with Ninja)
67
+
68
+ ## Usage
69
+
70
+ Once configured, AI assistants can use the tools to manage object IDs:
71
+
72
+ ### Assign an ID
73
+
74
+ ```
75
+ "Assign a new table ID for my AL app"
76
+ ```
77
+
78
+ The assistant will use `ninja_assignObjectId` with:
79
+ - `objectType`: The AL object type (table, page, codeunit, etc.)
80
+ - `targetFilePath`: Path to any file in your AL app
81
+ - `rangeName`: (Optional) Logical range name if multiple ranges exist
82
+
83
+ ### Unassign an ID
84
+
85
+ ```
86
+ "Release table ID 50100 - I deleted that object"
87
+ ```
88
+
89
+ The assistant will use `ninja_unassignObjectId` with:
90
+ - `objectType`: The AL object type
91
+ - `objectId`: The ID to release
92
+ - `targetFilePath`: Path to any file in your AL app
93
+
94
+ ## Supported Object Types
95
+
96
+ - `table`, `tableextension`
97
+ - `page`, `pageextension`
98
+ - `codeunit`
99
+ - `report`, `reportextension`
100
+ - `query`
101
+ - `xmlport`
102
+ - `enum`, `enumextension`
103
+ - `permissionset`, `permissionsetextension`
104
+ - `table_{id}` (for table fields)
105
+ - `enum_{id}` (for enum values)
106
+
107
+ ## Links
108
+
109
+ - [AL Object ID Ninja Extension](https://marketplace.visualstudio.com/items?itemName=vjeko.vjeko-al-objid)
110
+ - [Documentation](https://github.com/vjekob/al-objid)
111
+ - [Report Issues](https://github.com/vjekob/al-objid/issues)
112
+
113
+ ## License
114
+
115
+ MIT
@@ -0,0 +1,52 @@
1
+ import { ALAppManifest } from "./ALAppManifest";
2
+ import { ObjIdConfig } from "./ObjIdConfig";
3
+ import { NinjaALRange } from "../types/NinjaALRange";
4
+ /**
5
+ * Simplified ALApp representation for MCP server.
6
+ * No watchers, events, or disposables - just reads the app once.
7
+ */
8
+ export declare class ALApp {
9
+ private readonly _rootPath;
10
+ private readonly _manifest;
11
+ private readonly _config;
12
+ private _hash;
13
+ private constructor();
14
+ /**
15
+ * Tries to create an ALApp instance from the given root path.
16
+ * @param rootPath Root path of the AL app (folder containing app.json)
17
+ * @returns ALApp instance or undefined if not a valid AL app
18
+ */
19
+ static tryCreate(rootPath: string): ALApp | undefined;
20
+ /**
21
+ * Root path of this AL app.
22
+ */
23
+ get rootPath(): string;
24
+ /**
25
+ * App manifest (`app.json`) representation as an object.
26
+ */
27
+ get manifest(): ALAppManifest;
28
+ /**
29
+ * Ninja config file (`.objidconfig`) representation as an object.
30
+ */
31
+ get config(): ObjIdConfig;
32
+ /**
33
+ * SHA256 hash of the app ID (the `id` property from `app.json`).
34
+ */
35
+ get hash(): string;
36
+ /**
37
+ * Returns the `authKey` property from the `.objidconfig` file.
38
+ */
39
+ get authKey(): string;
40
+ /**
41
+ * Gets effective ranges for an object type with proper fallback.
42
+ *
43
+ * Priority:
44
+ * 1. Object-type-specific ranges from `.objidconfig`
45
+ * 2. General id ranges from `.objidconfig`
46
+ * 3. Ranges from `app.json` manifest
47
+ *
48
+ * @param objectType The object type to get ranges for (e.g., "table", "codeunit")
49
+ * @returns Array of ranges applicable for the object type
50
+ */
51
+ getObjectTypeRanges(objectType: string): NinjaALRange[];
52
+ }
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ALApp = void 0;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs"));
39
+ const getSha256_1 = require("../utils/getSha256");
40
+ const ALAppManifest_1 = require("./ALAppManifest");
41
+ const ObjIdConfig_1 = require("./ObjIdConfig");
42
+ const APP_FILE_NAME = "app.json";
43
+ const CONFIG_FILE_NAME = ".objidconfig";
44
+ /**
45
+ * Simplified ALApp representation for MCP server.
46
+ * No watchers, events, or disposables - just reads the app once.
47
+ */
48
+ class ALApp {
49
+ _rootPath;
50
+ _manifest;
51
+ _config;
52
+ _hash;
53
+ constructor(rootPath, manifest) {
54
+ this._rootPath = rootPath;
55
+ this._manifest = manifest;
56
+ const configPath = path.join(rootPath, CONFIG_FILE_NAME);
57
+ this._config = new ObjIdConfig_1.ObjIdConfig(configPath);
58
+ }
59
+ /**
60
+ * Tries to create an ALApp instance from the given root path.
61
+ * @param rootPath Root path of the AL app (folder containing app.json)
62
+ * @returns ALApp instance or undefined if not a valid AL app
63
+ */
64
+ static tryCreate(rootPath) {
65
+ const manifestPath = path.join(rootPath, APP_FILE_NAME);
66
+ if (!fs.existsSync(manifestPath)) {
67
+ return;
68
+ }
69
+ const manifest = ALAppManifest_1.ALAppManifest.tryCreate(manifestPath);
70
+ if (!manifest) {
71
+ return;
72
+ }
73
+ return new ALApp(rootPath, manifest);
74
+ }
75
+ /**
76
+ * Root path of this AL app.
77
+ */
78
+ get rootPath() {
79
+ return this._rootPath;
80
+ }
81
+ /**
82
+ * App manifest (`app.json`) representation as an object.
83
+ */
84
+ get manifest() {
85
+ return this._manifest;
86
+ }
87
+ /**
88
+ * Ninja config file (`.objidconfig`) representation as an object.
89
+ */
90
+ get config() {
91
+ return this._config;
92
+ }
93
+ /**
94
+ * SHA256 hash of the app ID (the `id` property from `app.json`).
95
+ */
96
+ get hash() {
97
+ return this._hash || (this._hash = (0, getSha256_1.getSha256)(this._manifest.id));
98
+ }
99
+ /**
100
+ * Returns the `authKey` property from the `.objidconfig` file.
101
+ */
102
+ get authKey() {
103
+ return this._config.authKey;
104
+ }
105
+ /**
106
+ * Gets effective ranges for an object type with proper fallback.
107
+ *
108
+ * Priority:
109
+ * 1. Object-type-specific ranges from `.objidconfig`
110
+ * 2. General id ranges from `.objidconfig`
111
+ * 3. Ranges from `app.json` manifest
112
+ *
113
+ * @param objectType The object type to get ranges for (e.g., "table", "codeunit")
114
+ * @returns Array of ranges applicable for the object type
115
+ */
116
+ getObjectTypeRanges(objectType) {
117
+ const configObjectRanges = this._config.objectRanges[objectType];
118
+ if (configObjectRanges && configObjectRanges.length > 0) {
119
+ return configObjectRanges;
120
+ }
121
+ const configIdRanges = this._config.idRanges;
122
+ if (configIdRanges.length > 0) {
123
+ return configIdRanges;
124
+ }
125
+ // Cast manifest ranges to NinjaALRange[] - they may lack description but that's ok
126
+ return this._manifest.idRanges;
127
+ }
128
+ }
129
+ exports.ALApp = ALApp;
130
+ //# sourceMappingURL=ALApp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ALApp.js","sourceRoot":"","sources":["../../../src/al-app/ALApp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAC7B,uCAAyB;AACzB,kDAA+C;AAC/C,mDAAgD;AAChD,+CAA4C;AAG5C,MAAM,aAAa,GAAG,UAAU,CAAC;AACjC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAExC;;;GAGG;AACH,MAAa,KAAK;IACG,SAAS,CAAS;IAClB,SAAS,CAAgB;IACzB,OAAO,CAAc;IAC9B,KAAK,CAAqB;IAElC,YAAoB,QAAgB,EAAE,QAAuB;QACzD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG,IAAI,yBAAW,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,SAAS,CAAC,QAAgB;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACxD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC/B,OAAO;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,6BAAa,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,OAAO;QACX,CAAC;QAED,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,IAAW,MAAM;QACb,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAA,qBAAS,EAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,IAAW,OAAO;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;IAChC,CAAC;IAED;;;;;;;;;;OAUG;IACI,mBAAmB,CAAC,UAAkB;QACzC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACjE,IAAI,kBAAkB,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtD,OAAO,kBAAkB,CAAC;QAC9B,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC7C,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,cAAc,CAAC;QAC1B,CAAC;QAED,mFAAmF;QACnF,OAAO,IAAI,CAAC,SAAS,CAAC,QAA0B,CAAC;IACrD,CAAC;CACJ;AA5FD,sBA4FC"}
@@ -0,0 +1,39 @@
1
+ import { ALRange } from "../types/ALRange";
2
+ export declare class ALAppManifest {
3
+ private readonly _path;
4
+ private readonly _manifest;
5
+ private constructor();
6
+ static tryCreate(appJsonPath: string): ALAppManifest | undefined;
7
+ /**
8
+ * Path of the `app.json` file.
9
+ */
10
+ get path(): string;
11
+ /**
12
+ * The `id` property from the `app.json` file.
13
+ *
14
+ * ***DO NOT USE THIS PROPERTY UNLESS YOU ABSOLUTELY NEED IT!***
15
+ *
16
+ * **Instead, use the `hash` property from the parent object. The `id` property should be used
17
+ * only for informational purposes, typically when having to present it on screen.**
18
+ *
19
+ * ***NEVER SEND THIS PROPERTY TO THE BACK END!***
20
+ */
21
+ get id(): string;
22
+ /**
23
+ * The `name` property from the `app.json` file.
24
+ */
25
+ get name(): string;
26
+ /**
27
+ * The `publisher` property from the `app.json` file.
28
+ */
29
+ get publisher(): string;
30
+ /**
31
+ * The `version` property from the `app.json` file.
32
+ */
33
+ get version(): string;
34
+ /**
35
+ * The `idRanges` property from the `app.json` file.
36
+ */
37
+ get idRanges(): ALRange[];
38
+ get preprocessorSymbols(): string[];
39
+ }
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ALAppManifest = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const comment_json_1 = require("comment-json");
39
+ class ALAppManifest {
40
+ _path;
41
+ _manifest;
42
+ constructor(path, manifest) {
43
+ this._path = path;
44
+ this._manifest = manifest;
45
+ }
46
+ static tryCreate(appJsonPath) {
47
+ try {
48
+ const contents = fs.readFileSync(appJsonPath).toString();
49
+ const appObj = (0, comment_json_1.parse)(contents.replace(/^\uFEFF/, ""));
50
+ const expectProperty = (property, type = "string") => appObj.hasOwnProperty(property) && typeof appObj[property] === type;
51
+ if (!expectProperty("id") || !expectProperty("name") || !expectProperty("version")) {
52
+ return;
53
+ }
54
+ if (!appObj.idRanges && appObj.idRange) {
55
+ appObj.idRanges = [appObj.idRange];
56
+ }
57
+ if (!expectProperty("idRanges", "object")) {
58
+ return;
59
+ }
60
+ return new ALAppManifest(appJsonPath, appObj);
61
+ }
62
+ catch {
63
+ return;
64
+ }
65
+ }
66
+ /**
67
+ * Path of the `app.json` file.
68
+ */
69
+ get path() {
70
+ return this._path;
71
+ }
72
+ /**
73
+ * The `id` property from the `app.json` file.
74
+ *
75
+ * ***DO NOT USE THIS PROPERTY UNLESS YOU ABSOLUTELY NEED IT!***
76
+ *
77
+ * **Instead, use the `hash` property from the parent object. The `id` property should be used
78
+ * only for informational purposes, typically when having to present it on screen.**
79
+ *
80
+ * ***NEVER SEND THIS PROPERTY TO THE BACK END!***
81
+ */
82
+ get id() {
83
+ return this._manifest.id || "";
84
+ }
85
+ /**
86
+ * The `name` property from the `app.json` file.
87
+ */
88
+ get name() {
89
+ return this._manifest.name || "";
90
+ }
91
+ /**
92
+ * The `publisher` property from the `app.json` file.
93
+ */
94
+ get publisher() {
95
+ return this._manifest.publisher || "";
96
+ }
97
+ /**
98
+ * The `version` property from the `app.json` file.
99
+ */
100
+ get version() {
101
+ return this._manifest.version || "";
102
+ }
103
+ /**
104
+ * The `idRanges` property from the `app.json` file.
105
+ */
106
+ get idRanges() {
107
+ return this._manifest.idRanges || [];
108
+ }
109
+ get preprocessorSymbols() {
110
+ return this._manifest.preprocessorSymbols || [];
111
+ }
112
+ }
113
+ exports.ALAppManifest = ALAppManifest;
114
+ //# sourceMappingURL=ALAppManifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ALAppManifest.js","sourceRoot":"","sources":["../../../src/al-app/ALAppManifest.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,+CAAqC;AAYrC,MAAa,aAAa;IACL,KAAK,CAAS;IACd,SAAS,CAAY;IAEtC,YAAoB,IAAY,EAAE,QAAmB;QACjD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAEM,MAAM,CAAC,SAAS,CAAC,WAAmB;QACvC,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;YACzD,MAAM,MAAM,GAAG,IAAA,oBAAK,EAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAQ,CAAC;YAE7D,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,IAAI,GAAG,QAAQ,EAAE,EAAE,CACzD,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;YACxE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjF,OAAO;YACX,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACrC,MAAM,CAAC,QAAQ,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvC,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACxC,OAAO;YACX,CAAC;YAED,OAAO,IAAI,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACL,OAAO;QACX,CAAC;IACL,CAAC;IAED;;OAEG;IACH,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED;;;;;;;;;OASG;IACH,IAAW,EAAE;QACT,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAW,SAAS;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,IAAW,OAAO;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC;IACzC,CAAC;IAED,IAAW,mBAAmB;QAC1B,OAAO,IAAI,CAAC,SAAS,CAAC,mBAAmB,IAAI,EAAE,CAAC;IACpD,CAAC;CACJ;AArFD,sCAqFC"}
@@ -0,0 +1,24 @@
1
+ import { ALApp } from "./ALApp";
2
+ /**
3
+ * Resolves file paths to ALApp instances.
4
+ * Walks up the directory tree to find app.json and caches resolved apps.
5
+ */
6
+ export declare class AppResolver {
7
+ private static _cache;
8
+ /**
9
+ * Resolves a file path to its containing AL app.
10
+ * @param filePath Path to a file within an AL app
11
+ * @returns ALApp instance or undefined if not within an AL app
12
+ */
13
+ static resolveFromPath(filePath: string): ALApp | undefined;
14
+ /**
15
+ * Walks up the directory tree to find the AL app root (folder containing app.json).
16
+ * @param startDir Directory to start searching from
17
+ * @returns Path to the app root or undefined if not found
18
+ */
19
+ private static findAppRoot;
20
+ /**
21
+ * Clears the app cache.
22
+ */
23
+ static clearCache(): void;
24
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AppResolver = void 0;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs"));
39
+ const ALApp_1 = require("./ALApp");
40
+ const APP_FILE_NAME = "app.json";
41
+ /**
42
+ * Resolves file paths to ALApp instances.
43
+ * Walks up the directory tree to find app.json and caches resolved apps.
44
+ */
45
+ class AppResolver {
46
+ static _cache = new Map();
47
+ /**
48
+ * Resolves a file path to its containing AL app.
49
+ * @param filePath Path to a file within an AL app
50
+ * @returns ALApp instance or undefined if not within an AL app
51
+ */
52
+ static resolveFromPath(filePath) {
53
+ // Normalize the path
54
+ const normalizedPath = path.resolve(filePath);
55
+ // Check cache for the directory
56
+ const dir = fs.statSync(normalizedPath).isDirectory() ? normalizedPath : path.dirname(normalizedPath);
57
+ const appRoot = this.findAppRoot(dir);
58
+ if (!appRoot) {
59
+ return undefined;
60
+ }
61
+ // Check if we already have this app cached
62
+ const cached = this._cache.get(appRoot);
63
+ if (cached !== undefined) {
64
+ return cached || undefined;
65
+ }
66
+ // Try to create the app
67
+ const app = ALApp_1.ALApp.tryCreate(appRoot);
68
+ this._cache.set(appRoot, app || null);
69
+ return app || undefined;
70
+ }
71
+ /**
72
+ * Walks up the directory tree to find the AL app root (folder containing app.json).
73
+ * @param startDir Directory to start searching from
74
+ * @returns Path to the app root or undefined if not found
75
+ */
76
+ static findAppRoot(startDir) {
77
+ let currentDir = startDir;
78
+ // eslint-disable-next-line no-constant-condition
79
+ while (true) {
80
+ const appJsonPath = path.join(currentDir, APP_FILE_NAME);
81
+ if (fs.existsSync(appJsonPath)) {
82
+ return currentDir;
83
+ }
84
+ const parentDir = path.dirname(currentDir);
85
+ if (parentDir === currentDir) {
86
+ // Reached filesystem root
87
+ return undefined;
88
+ }
89
+ currentDir = parentDir;
90
+ }
91
+ }
92
+ /**
93
+ * Clears the app cache.
94
+ */
95
+ static clearCache() {
96
+ this._cache.clear();
97
+ }
98
+ }
99
+ exports.AppResolver = AppResolver;
100
+ //# sourceMappingURL=AppResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppResolver.js","sourceRoot":"","sources":["../../../src/al-app/AppResolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAC7B,uCAAyB;AACzB,mCAAgC;AAEhC,MAAM,aAAa,GAAG,UAAU,CAAC;AAEjC;;;GAGG;AACH,MAAa,WAAW;IACZ,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAExD;;;;OAIG;IACI,MAAM,CAAC,eAAe,CAAC,QAAgB;QAC1C,qBAAqB;QACrB,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAE9C,gCAAgC;QAChC,MAAM,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACtG,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAEtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,2CAA2C;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,MAAM,IAAI,SAAS,CAAC;QAC/B,CAAC;QAED,wBAAwB;QACxB,MAAM,GAAG,GAAG,aAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;QACtC,OAAO,GAAG,IAAI,SAAS,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACK,MAAM,CAAC,WAAW,CAAC,QAAgB;QACvC,IAAI,UAAU,GAAG,QAAQ,CAAC;QAE1B,iDAAiD;QACjD,OAAO,IAAI,EAAE,CAAC;YACV,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;YACzD,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC7B,OAAO,UAAU,CAAC;YACtB,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC3C,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;gBAC3B,0BAA0B;gBAC1B,OAAO,SAAS,CAAC;YACrB,CAAC;YACD,UAAU,GAAG,SAAS,CAAC;QAC3B,CAAC;IACL,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,UAAU;QACpB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;;AA7DL,kCA8DC"}
@@ -0,0 +1,23 @@
1
+ import { PropertyBag } from "../types/PropertyBag";
2
+ import { NinjaALRange } from "../types/NinjaALRange";
3
+ /**
4
+ * Read-only representation of the .objidconfig file.
5
+ */
6
+ export declare class ObjIdConfig {
7
+ private readonly _path;
8
+ private readonly _config;
9
+ constructor(configPath: string);
10
+ private read;
11
+ get path(): string;
12
+ get authKey(): string;
13
+ get appPoolId(): string;
14
+ get idRanges(): NinjaALRange[];
15
+ get objectRanges(): PropertyBag<NinjaALRange[]>;
16
+ /**
17
+ * Gets ranges for the specified object type.
18
+ * Falls back to idRanges if no object-specific ranges are defined.
19
+ * @param objectType Object type for which to get ranges
20
+ * @returns Ranges for the specified object type
21
+ */
22
+ getObjectTypeRanges(objectType: string): NinjaALRange[];
23
+ }