@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.
- package/README.md +115 -0
- package/dist/src/al-app/ALApp.d.ts +52 -0
- package/dist/src/al-app/ALApp.js +130 -0
- package/dist/src/al-app/ALApp.js.map +1 -0
- package/dist/src/al-app/ALAppManifest.d.ts +39 -0
- package/dist/src/al-app/ALAppManifest.js +114 -0
- package/dist/src/al-app/ALAppManifest.js.map +1 -0
- package/dist/src/al-app/AppResolver.d.ts +24 -0
- package/dist/src/al-app/AppResolver.js +100 -0
- package/dist/src/al-app/AppResolver.js.map +1 -0
- package/dist/src/al-app/ObjIdConfig.d.ts +23 -0
- package/dist/src/al-app/ObjIdConfig.js +84 -0
- package/dist/src/al-app/ObjIdConfig.js.map +1 -0
- package/dist/src/al-app/index.d.ts +4 -0
- package/dist/src/al-app/index.js +12 -0
- package/dist/src/al-app/index.js.map +1 -0
- package/dist/src/backend/BackendClient.d.ts +35 -0
- package/dist/src/backend/BackendClient.js +129 -0
- package/dist/src/backend/BackendClient.js.map +1 -0
- package/dist/src/backend/index.d.ts +1 -0
- package/dist/src/backend/index.js +6 -0
- package/dist/src/backend/index.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/server.d.ts +3 -0
- package/dist/src/server.js +108 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/tools/AssignObjectIdTool.d.ts +16 -0
- package/dist/src/tools/AssignObjectIdTool.js +83 -0
- package/dist/src/tools/AssignObjectIdTool.js.map +1 -0
- package/dist/src/tools/UnassignObjectIdTool.d.ts +16 -0
- package/dist/src/tools/UnassignObjectIdTool.js +50 -0
- package/dist/src/tools/UnassignObjectIdTool.js.map +1 -0
- package/dist/src/tools/index.d.ts +3 -0
- package/dist/src/tools/index.js +8 -0
- package/dist/src/tools/index.js.map +1 -0
- package/dist/src/types/ALObjectType.d.ts +15 -0
- package/dist/src/types/ALObjectType.js +20 -0
- package/dist/src/types/ALObjectType.js.map +1 -0
- package/dist/src/types/ALRange.d.ts +7 -0
- package/dist/src/types/ALRange.js +3 -0
- package/dist/src/types/ALRange.js.map +1 -0
- package/dist/src/types/NextObjectIdInfo.d.ts +9 -0
- package/dist/src/types/NextObjectIdInfo.js +3 -0
- package/dist/src/types/NextObjectIdInfo.js.map +1 -0
- package/dist/src/types/NinjaALRange.d.ts +4 -0
- package/dist/src/types/NinjaALRange.js +3 -0
- package/dist/src/types/NinjaALRange.js.map +1 -0
- package/dist/src/types/PropertyBag.d.ts +3 -0
- package/dist/src/types/PropertyBag.js +3 -0
- package/dist/src/types/PropertyBag.js.map +1 -0
- package/dist/src/types/index.d.ts +5 -0
- package/dist/src/types/index.js +6 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/utils/getSha256.d.ts +1 -0
- package/dist/src/utils/getSha256.js +43 -0
- package/dist/src/utils/getSha256.js.map +1 -0
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/src/utils/index.js +9 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/validation.d.ts +2 -0
- package/dist/src/utils/validation.js +20 -0
- package/dist/src/utils/validation.js.map +1 -0
- 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
|
+
}
|