tm1npm 1.0.0 → 1.1.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/.github/CODEOWNERS +9 -0
- package/.github/workflows/pr-build-check.yml +252 -0
- package/.github/workflows/publish-npm.yml +12 -0
- package/.github/workflows/security-check.yml +29 -0
- package/README.md +169 -13
- package/lib/objects/Application.d.ts +74 -40
- package/lib/objects/Application.d.ts.map +1 -1
- package/lib/objects/Application.js +214 -59
- package/lib/objects/Axis.d.ts +2 -2
- package/lib/objects/Axis.d.ts.map +1 -1
- package/lib/objects/Axis.js +2 -2
- package/lib/objects/Chore.d.ts +4 -0
- package/lib/objects/Chore.d.ts.map +1 -1
- package/lib/objects/Chore.js +44 -0
- package/lib/objects/ChoreStartTime.d.ts +1 -0
- package/lib/objects/ChoreStartTime.d.ts.map +1 -1
- package/lib/objects/ChoreStartTime.js +17 -11
- package/lib/objects/ChoreTask.d.ts +1 -0
- package/lib/objects/ChoreTask.d.ts.map +1 -1
- package/lib/objects/ChoreTask.js +3 -0
- package/lib/services/ApplicationService.d.ts +13 -6
- package/lib/services/ApplicationService.d.ts.map +1 -1
- package/lib/services/ApplicationService.js +171 -179
- package/lib/services/AuditLogService.d.ts +1 -0
- package/lib/services/AuditLogService.d.ts.map +1 -1
- package/lib/services/AuditLogService.js +21 -9
- package/lib/services/CellService.d.ts +255 -3
- package/lib/services/CellService.d.ts.map +1 -1
- package/lib/services/CellService.js +845 -14
- package/lib/services/ChoreService.d.ts +20 -0
- package/lib/services/ChoreService.d.ts.map +1 -1
- package/lib/services/ChoreService.js +183 -44
- package/lib/services/ConfigurationService.d.ts +10 -8
- package/lib/services/ConfigurationService.d.ts.map +1 -1
- package/lib/services/ConfigurationService.js +41 -35
- package/lib/services/CubeService.d.ts +29 -0
- package/lib/services/CubeService.d.ts.map +1 -1
- package/lib/services/CubeService.js +154 -0
- package/lib/services/DimensionService.d.ts +5 -0
- package/lib/services/DimensionService.d.ts.map +1 -1
- package/lib/services/DimensionService.js +49 -0
- package/lib/services/ElementService.d.ts +102 -9
- package/lib/services/ElementService.d.ts.map +1 -1
- package/lib/services/ElementService.js +248 -82
- package/lib/services/FileService.d.ts +23 -1
- package/lib/services/FileService.d.ts.map +1 -1
- package/lib/services/FileService.js +228 -40
- package/lib/services/GitService.d.ts +1 -0
- package/lib/services/GitService.d.ts.map +1 -1
- package/lib/services/GitService.js +33 -16
- package/lib/services/JobService.d.ts +3 -0
- package/lib/services/JobService.d.ts.map +1 -1
- package/lib/services/JobService.js +10 -0
- package/lib/services/LoggerService.d.ts +0 -1
- package/lib/services/LoggerService.d.ts.map +1 -1
- package/lib/services/LoggerService.js +0 -9
- package/lib/services/MessageLogService.d.ts +6 -0
- package/lib/services/MessageLogService.d.ts.map +1 -1
- package/lib/services/MessageLogService.js +45 -18
- package/lib/services/MonitoringService.d.ts.map +1 -1
- package/lib/services/MonitoringService.js +22 -0
- package/lib/services/ObjectService.d.ts +17 -1
- package/lib/services/ObjectService.d.ts.map +1 -1
- package/lib/services/ObjectService.js +73 -6
- package/lib/services/PowerBiService.d.ts.map +1 -1
- package/lib/services/PowerBiService.js +20 -1
- package/lib/services/ProcessService.d.ts +8 -0
- package/lib/services/ProcessService.d.ts.map +1 -1
- package/lib/services/ProcessService.js +88 -0
- package/lib/services/RestService.d.ts +172 -1
- package/lib/services/RestService.d.ts.map +1 -1
- package/lib/services/RestService.js +574 -7
- package/lib/services/SandboxService.d.ts +6 -6
- package/lib/services/SandboxService.d.ts.map +1 -1
- package/lib/services/SandboxService.js +50 -118
- package/lib/services/SecurityService.d.ts +6 -1
- package/lib/services/SecurityService.d.ts.map +1 -1
- package/lib/services/SecurityService.js +46 -12
- package/lib/services/SessionService.d.ts +1 -1
- package/lib/services/SessionService.d.ts.map +1 -1
- package/lib/services/SessionService.js +15 -0
- package/lib/services/SubsetService.d.ts +12 -2
- package/lib/services/SubsetService.d.ts.map +1 -1
- package/lib/services/SubsetService.js +94 -13
- package/lib/services/ThreadService.d.ts +0 -1
- package/lib/services/ThreadService.d.ts.map +1 -1
- package/lib/services/ThreadService.js +4 -2
- package/lib/services/TransactionLogService.d.ts +1 -0
- package/lib/services/TransactionLogService.d.ts.map +1 -1
- package/lib/services/TransactionLogService.js +21 -15
- package/lib/services/ViewService.d.ts +2 -1
- package/lib/services/ViewService.d.ts.map +1 -1
- package/lib/services/ViewService.js +45 -10
- package/lib/tests/annotationService.comprehensive.test.d.ts +6 -0
- package/lib/tests/annotationService.comprehensive.test.d.ts.map +1 -0
- package/lib/tests/annotationService.comprehensive.test.js +322 -0
- package/lib/tests/cubeService.getAllNames.test.d.ts +6 -0
- package/lib/tests/cubeService.getAllNames.test.d.ts.map +1 -0
- package/lib/tests/cubeService.getAllNames.test.js +245 -0
- package/lib/tests/elementService.comprehensive.test.js +44 -29
- package/lib/tests/enhancedCellService.test.js +144 -9
- package/lib/tests/enhancedElementService.test.js +21 -15
- package/lib/tests/integrationTests.test.js +7 -5
- package/lib/tests/securityService.comprehensive.test.js +6 -0
- package/lib/tests/serverService.simple.test.d.ts +6 -0
- package/lib/tests/serverService.simple.test.d.ts.map +1 -0
- package/lib/tests/serverService.simple.test.js +221 -0
- package/lib/utils/DataFrame.d.ts +112 -0
- package/lib/utils/DataFrame.d.ts.map +1 -0
- package/lib/utils/DataFrame.js +282 -0
- package/lib/utils/Utils.d.ts +21 -0
- package/lib/utils/Utils.d.ts.map +1 -1
- package/lib/utils/Utils.js +161 -9
- package/package.json +1 -1
- package/src/objects/Application.ts +241 -73
- package/src/objects/Axis.ts +2 -2
- package/src/objects/Chore.ts +51 -0
- package/src/objects/ChoreStartTime.ts +26 -11
- package/src/objects/ChoreTask.ts +4 -0
- package/src/objects/NativeView.ts +2 -2
- package/src/services/ApplicationService.ts +269 -201
- package/src/services/AuditLogService.ts +34 -31
- package/src/services/CellService.ts +1271 -97
- package/src/services/ChoreService.ts +215 -45
- package/src/services/ConfigurationService.ts +42 -38
- package/src/services/CubeService.ts +196 -2
- package/src/services/DimensionService.ts +63 -1
- package/src/services/ElementService.ts +415 -150
- package/src/services/FileService.ts +318 -39
- package/src/services/GitService.ts +37 -27
- package/src/services/JobService.ts +14 -1
- package/src/services/LoggerService.ts +1 -10
- package/src/services/MessageLogService.ts +61 -39
- package/src/services/MonitoringService.ts +4 -1
- package/src/services/ObjectService.ts +86 -8
- package/src/services/PowerBiService.ts +29 -4
- package/src/services/ProcessService.ts +101 -0
- package/src/services/RestService.ts +662 -10
- package/src/services/SandboxService.ts +59 -122
- package/src/services/SecurityService.ts +58 -16
- package/src/services/SessionService.ts +4 -3
- package/src/services/SubsetService.ts +253 -21
- package/src/services/ThreadService.ts +2 -5
- package/src/services/TransactionLogService.ts +28 -29
- package/src/services/ViewService.ts +76 -10
- package/src/tests/annotationService.comprehensive.test.ts +420 -0
- package/src/tests/cubeService.getAllNames.test.ts +302 -0
- package/src/tests/elementService.comprehensive.test.ts +54 -34
- package/src/tests/enhancedCellService.test.ts +200 -12
- package/src/tests/enhancedElementService.test.ts +22 -18
- package/src/tests/integrationTests.test.ts +7 -5
- package/src/tests/securityService.comprehensive.test.ts +9 -0
- package/src/tests/serverService.simple.test.ts +293 -0
- package/src/utils/DataFrame.ts +333 -0
- package/src/utils/Utils.ts +187 -13
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Global code owners - require review from KimKaoPoo for all changes
|
|
2
|
+
* @KimKaoPoo
|
|
3
|
+
|
|
4
|
+
# Workflow files - require review for CI/CD changes
|
|
5
|
+
/.github/ @KimKaoPoo
|
|
6
|
+
|
|
7
|
+
# Package configuration - require review for publishing settings
|
|
8
|
+
/package.json @KimKaoPoo
|
|
9
|
+
/package-lock.json @KimKaoPoo
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
name: PR Build Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
6
|
+
branches: [main, master, develop]
|
|
7
|
+
pull_request_target:
|
|
8
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
9
|
+
branches: [main, master, develop]
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
pull-requests: write
|
|
14
|
+
statuses: write
|
|
15
|
+
checks: write
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build-check:
|
|
19
|
+
name: Build Validation
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
# Skip draft PRs unless they're marked as ready for review
|
|
23
|
+
if: github.event.pull_request.draft == false || github.event.action == 'ready_for_review'
|
|
24
|
+
|
|
25
|
+
strategy:
|
|
26
|
+
matrix:
|
|
27
|
+
node-version: [16, 18, 20]
|
|
28
|
+
|
|
29
|
+
steps:
|
|
30
|
+
- name: Checkout PR code
|
|
31
|
+
uses: actions/checkout@v4
|
|
32
|
+
with:
|
|
33
|
+
# For pull_request_target, we checkout the PR code safely
|
|
34
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
35
|
+
|
|
36
|
+
- name: Setup Node.js ${{ matrix.node-version }}
|
|
37
|
+
uses: actions/setup-node@v4
|
|
38
|
+
with:
|
|
39
|
+
node-version: ${{ matrix.node-version }}
|
|
40
|
+
cache: 'npm'
|
|
41
|
+
|
|
42
|
+
- name: Cache dependencies
|
|
43
|
+
uses: actions/cache@v3
|
|
44
|
+
with:
|
|
45
|
+
path: ~/.npm
|
|
46
|
+
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
|
|
47
|
+
restore-keys: |
|
|
48
|
+
${{ runner.os }}-node-${{ matrix.node-version }}-
|
|
49
|
+
${{ runner.os }}-node-
|
|
50
|
+
|
|
51
|
+
- name: Install dependencies
|
|
52
|
+
run: npm ci
|
|
53
|
+
|
|
54
|
+
- name: Lint code (if available)
|
|
55
|
+
run: |
|
|
56
|
+
if npm run lint --if-present; then
|
|
57
|
+
echo "✅ Linting passed"
|
|
58
|
+
else
|
|
59
|
+
echo "⚠️ No lint script found or linting failed"
|
|
60
|
+
fi
|
|
61
|
+
continue-on-error: true
|
|
62
|
+
|
|
63
|
+
- name: Type checking (if available)
|
|
64
|
+
run: |
|
|
65
|
+
if npm run typecheck --if-present; then
|
|
66
|
+
echo "✅ Type checking passed"
|
|
67
|
+
else
|
|
68
|
+
echo "⚠️ No typecheck script found, skipping"
|
|
69
|
+
fi
|
|
70
|
+
continue-on-error: true
|
|
71
|
+
|
|
72
|
+
- name: Run build
|
|
73
|
+
id: build
|
|
74
|
+
run: |
|
|
75
|
+
echo "🔨 Building project..."
|
|
76
|
+
npm run build
|
|
77
|
+
echo "✅ Build completed successfully"
|
|
78
|
+
|
|
79
|
+
- name: Verify build output
|
|
80
|
+
run: |
|
|
81
|
+
echo "🔍 Verifying build artifacts..."
|
|
82
|
+
|
|
83
|
+
# Check if lib directory exists
|
|
84
|
+
if [ -d "lib" ]; then
|
|
85
|
+
echo "✅ lib/ directory found"
|
|
86
|
+
echo "📂 Build output structure:"
|
|
87
|
+
ls -la lib/ || echo "Empty lib directory"
|
|
88
|
+
else
|
|
89
|
+
echo "❌ lib/ directory not found"
|
|
90
|
+
echo "Build may have failed or output directory is different"
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Check for main entry points
|
|
95
|
+
missing_files=()
|
|
96
|
+
|
|
97
|
+
if [ ! -f "lib/index.js" ]; then
|
|
98
|
+
missing_files+=("lib/index.js")
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
if [ ! -f "lib/index.d.ts" ]; then
|
|
102
|
+
missing_files+=("lib/index.d.ts")
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
if [ ${#missing_files[@]} -eq 0 ]; then
|
|
106
|
+
echo "✅ Essential build files found"
|
|
107
|
+
else
|
|
108
|
+
echo "⚠️ Some expected build files are missing:"
|
|
109
|
+
printf ' - %s\n' "${missing_files[@]}"
|
|
110
|
+
echo "This may be expected depending on your build configuration"
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
- name: Test build artifacts (if tests available)
|
|
114
|
+
run: |
|
|
115
|
+
if npm run test --if-present; then
|
|
116
|
+
echo "✅ Tests passed with built code"
|
|
117
|
+
else
|
|
118
|
+
echo "⚠️ No test script found, skipping test validation"
|
|
119
|
+
fi
|
|
120
|
+
continue-on-error: true
|
|
121
|
+
|
|
122
|
+
- name: Success summary
|
|
123
|
+
if: success()
|
|
124
|
+
run: |
|
|
125
|
+
echo "🎉 Build validation successful!"
|
|
126
|
+
echo "✅ Node.js ${{ matrix.node-version }}: Build completed successfully"
|
|
127
|
+
echo "📦 All build artifacts generated correctly"
|
|
128
|
+
|
|
129
|
+
- name: Failure summary
|
|
130
|
+
if: failure()
|
|
131
|
+
run: |
|
|
132
|
+
echo "❌ Build validation failed!"
|
|
133
|
+
echo "❌ Node.js ${{ matrix.node-version }}: Build failed"
|
|
134
|
+
echo "Please fix build issues before merging this PR"
|
|
135
|
+
|
|
136
|
+
# Summary job for all matrix builds
|
|
137
|
+
build-summary:
|
|
138
|
+
name: Build Summary
|
|
139
|
+
needs: build-check
|
|
140
|
+
runs-on: ubuntu-latest
|
|
141
|
+
permissions:
|
|
142
|
+
contents: read
|
|
143
|
+
pull-requests: write
|
|
144
|
+
statuses: write
|
|
145
|
+
checks: write
|
|
146
|
+
if: always()
|
|
147
|
+
|
|
148
|
+
steps:
|
|
149
|
+
- name: Determine overall result
|
|
150
|
+
id: result
|
|
151
|
+
run: |
|
|
152
|
+
if [[ "${{ needs.build-check.result }}" == "success" ]]; then
|
|
153
|
+
echo "result=success" >> $GITHUB_OUTPUT
|
|
154
|
+
echo "message=All builds passed across Node.js versions 16, 18, 20" >> $GITHUB_OUTPUT
|
|
155
|
+
echo "🎉 All builds successful!"
|
|
156
|
+
else
|
|
157
|
+
echo "result=failure" >> $GITHUB_OUTPUT
|
|
158
|
+
echo "message=Some builds failed - check logs for details" >> $GITHUB_OUTPUT
|
|
159
|
+
echo "❌ Some builds failed"
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
- name: Create commit status
|
|
163
|
+
uses: actions/github-script@v7
|
|
164
|
+
with:
|
|
165
|
+
script: |
|
|
166
|
+
const { owner, repo } = context.repo;
|
|
167
|
+
const sha = context.payload.pull_request?.head?.sha || context.sha;
|
|
168
|
+
const result = '${{ steps.result.outputs.result }}';
|
|
169
|
+
const message = '${{ steps.result.outputs.message }}';
|
|
170
|
+
|
|
171
|
+
const state = result === 'success' ? 'success' : 'failure';
|
|
172
|
+
const description = result === 'success'
|
|
173
|
+
? '✅ Build validation passed'
|
|
174
|
+
: '❌ Build validation failed';
|
|
175
|
+
|
|
176
|
+
await github.rest.repos.createCommitStatus({
|
|
177
|
+
owner,
|
|
178
|
+
repo,
|
|
179
|
+
sha,
|
|
180
|
+
state,
|
|
181
|
+
target_url: `https://github.com/${owner}/${repo}/actions/runs/${context.runId}`,
|
|
182
|
+
description,
|
|
183
|
+
context: 'PR Build Check'
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
console.log(`Commit status created: ${state}`);
|
|
187
|
+
console.log(`SHA: ${sha}`);
|
|
188
|
+
console.log(`Description: ${description}`);
|
|
189
|
+
|
|
190
|
+
- name: Comment on PR
|
|
191
|
+
if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target'
|
|
192
|
+
uses: actions/github-script@v7
|
|
193
|
+
with:
|
|
194
|
+
script: |
|
|
195
|
+
const { owner, repo } = context.repo;
|
|
196
|
+
const prNumber = context.payload.pull_request.number;
|
|
197
|
+
const result = '${{ steps.result.outputs.result }}';
|
|
198
|
+
const runUrl = `https://github.com/${owner}/${repo}/actions/runs/${context.runId}`;
|
|
199
|
+
|
|
200
|
+
let commentBody;
|
|
201
|
+
|
|
202
|
+
if (result === 'success') {
|
|
203
|
+
commentBody = '## ✅ Build Validation Passed\n\n' +
|
|
204
|
+
'**All builds completed successfully!**\n\n' +
|
|
205
|
+
'- ✅ Node.js 16: Build passed\n' +
|
|
206
|
+
'- ✅ Node.js 18: Build passed\n' +
|
|
207
|
+
'- ✅ Node.js 20: Build passed\n\n' +
|
|
208
|
+
'📦 All build artifacts generated correctly.\n\n' +
|
|
209
|
+
`[View detailed results](${runUrl})`;
|
|
210
|
+
} else {
|
|
211
|
+
commentBody = '## ❌ Build Validation Failed\n\n' +
|
|
212
|
+
'**Some builds failed - please review and fix:**\n\n' +
|
|
213
|
+
'🔍 **Common issues to check:**\n' +
|
|
214
|
+
'- TypeScript compilation errors\n' +
|
|
215
|
+
'- Missing dependencies\n' +
|
|
216
|
+
'- Syntax errors\n' +
|
|
217
|
+
'- Import/export issues\n\n' +
|
|
218
|
+
'Please fix the build issues and push your changes.\n\n' +
|
|
219
|
+
`[View detailed results](${runUrl})`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Check if we already commented on this PR for this run
|
|
223
|
+
const comments = await github.rest.issues.listComments({
|
|
224
|
+
owner,
|
|
225
|
+
repo,
|
|
226
|
+
issue_number: prNumber,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const botComment = comments.data.find(comment =>
|
|
230
|
+
comment.user.type === 'Bot' &&
|
|
231
|
+
comment.body.includes('Build Validation')
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
if (botComment) {
|
|
235
|
+
// Update existing comment
|
|
236
|
+
await github.rest.issues.updateComment({
|
|
237
|
+
owner,
|
|
238
|
+
repo,
|
|
239
|
+
comment_id: botComment.id,
|
|
240
|
+
body: commentBody
|
|
241
|
+
});
|
|
242
|
+
console.log('Updated existing PR comment');
|
|
243
|
+
} else {
|
|
244
|
+
// Create new comment
|
|
245
|
+
await github.rest.issues.createComment({
|
|
246
|
+
owner,
|
|
247
|
+
repo,
|
|
248
|
+
issue_number: prNumber,
|
|
249
|
+
body: commentBody
|
|
250
|
+
});
|
|
251
|
+
console.log('Created new PR comment');
|
|
252
|
+
}
|
|
@@ -4,6 +4,9 @@ on:
|
|
|
4
4
|
release:
|
|
5
5
|
types: [published]
|
|
6
6
|
|
|
7
|
+
env:
|
|
8
|
+
ALLOWED_PUBLISHER: hsubebe89
|
|
9
|
+
|
|
7
10
|
jobs:
|
|
8
11
|
publish:
|
|
9
12
|
runs-on: ubuntu-latest
|
|
@@ -12,6 +15,15 @@ jobs:
|
|
|
12
15
|
id-token: write
|
|
13
16
|
|
|
14
17
|
steps:
|
|
18
|
+
- name: Verify publisher authorization
|
|
19
|
+
run: |
|
|
20
|
+
if [ "${{ github.actor }}" != "${{ env.ALLOWED_PUBLISHER }}" ]; then
|
|
21
|
+
echo "❌ ERROR: Only ${{ env.ALLOWED_PUBLISHER }} can publish to NPM"
|
|
22
|
+
echo "Current actor: ${{ github.actor }}"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
echo "✅ Publisher authorization verified for ${{ github.actor }}"
|
|
26
|
+
|
|
15
27
|
- name: Checkout code
|
|
16
28
|
uses: actions/checkout@v4
|
|
17
29
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Security Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
create:
|
|
5
|
+
release:
|
|
6
|
+
types: [published, created, edited, deleted]
|
|
7
|
+
|
|
8
|
+
env:
|
|
9
|
+
ALLOWED_MAINTAINER: hsubebe89
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
verify-permissions:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
if: github.ref_type == 'tag' || github.event_name == 'release'
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Verify tag/release permissions
|
|
18
|
+
run: |
|
|
19
|
+
if [ "${{ github.actor }}" != "${{ env.ALLOWED_MAINTAINER }}" ]; then
|
|
20
|
+
echo "❌ ERROR: Only ${{ env.ALLOWED_MAINTAINER }} can create tags and releases"
|
|
21
|
+
echo "Current actor: ${{ github.actor }}"
|
|
22
|
+
echo "Event: ${{ github.event_name }}"
|
|
23
|
+
echo "Ref type: ${{ github.ref_type }}"
|
|
24
|
+
|
|
25
|
+
# Log the unauthorized attempt
|
|
26
|
+
echo "⚠️ SECURITY ALERT: Unauthorized attempt to create tag/release by ${{ github.actor }}"
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
echo "✅ Tag/release permissions verified for ${{ github.actor }}"
|
package/README.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# tm1npm
|
|
2
2
|
|
|
3
|
+
<pre>
|
|
4
|
+
████████╗███╗ ███╗ ██╗███╗ ██╗██████╗ ███╗ ███╗
|
|
5
|
+
╚══██╔══╝████╗ ████║███║████╗ ██║██╔══██╗████╗ ████║
|
|
6
|
+
██║ ██╔████╔██║╚██║██╔██╗ ██║██████╔╝██╔████╔██║
|
|
7
|
+
██║ ██║╚██╔╝██║ ██║██║╚██╗██║██╔═══╝ ██║╚██╔╝██║
|
|
8
|
+
██║ ██║ ╚═╝ ██║ ██║██║ ╚████║██║ ██║ ╚═╝ ██║
|
|
9
|
+
╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝
|
|
10
|
+
|
|
11
|
+
🚀 TM1 Integration for Node.js - Build powerful TM1 applications
|
|
12
|
+
</pre>
|
|
3
13
|
tm1npm is the Node.js/TypeScript package for IBM Planning Analytics (TM1), providing a comprehensive interface to the TM1 REST API.
|
|
4
14
|
|
|
5
15
|
By wrapping the IBM Planning Analytics (TM1) REST API in a concise TypeScript framework, tm1npm facilitates Node.js developments for TM1.
|
|
@@ -18,6 +28,9 @@ const tm1 = new TM1Service({
|
|
|
18
28
|
});
|
|
19
29
|
|
|
20
30
|
try {
|
|
31
|
+
// Connect to TM1 server
|
|
32
|
+
await tm1.connect();
|
|
33
|
+
|
|
21
34
|
const subset = new Subset('Month', 'Q1', ['Jan', 'Feb', 'Mar']);
|
|
22
35
|
await tm1.dimensions.subsets.create(subset, true);
|
|
23
36
|
} finally {
|
|
@@ -82,6 +95,43 @@ npm install --save-dev typescript @types/node
|
|
|
82
95
|
|
|
83
96
|
## Usage
|
|
84
97
|
|
|
98
|
+
### Important: Connection Workflow
|
|
99
|
+
|
|
100
|
+
**⚠️ CRITICAL**: Always call `await tm1.connect()` before performing any TM1 operations and `await tm1.logout()` when finished. This is the correct usage pattern:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { TM1Service } from 'tm1npm';
|
|
104
|
+
|
|
105
|
+
const tm1 = new TM1Service({
|
|
106
|
+
address: 'localhost',
|
|
107
|
+
port: 8879,
|
|
108
|
+
user: 'admin',
|
|
109
|
+
password: 'your_password',
|
|
110
|
+
ssl: false
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
// Step 1: Connect to TM1 server (REQUIRED!)
|
|
115
|
+
await tm1.connect();
|
|
116
|
+
|
|
117
|
+
// Step 2: Perform TM1 operations
|
|
118
|
+
const version = await tm1.getVersion();
|
|
119
|
+
console.log('TM1 Version:', version);
|
|
120
|
+
|
|
121
|
+
const cubes = await tm1.cubes.getAllNames();
|
|
122
|
+
console.log('Available cubes:', cubes);
|
|
123
|
+
|
|
124
|
+
} finally {
|
|
125
|
+
// Step 3: Always logout to clean up session (REQUIRED!)
|
|
126
|
+
await tm1.logout();
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Why this matters:**
|
|
131
|
+
- `connect()` establishes the session with TM1 server
|
|
132
|
+
- `logout()` properly closes the session and prevents memory leaks
|
|
133
|
+
- Skipping either step can cause connection issues or resource leaks
|
|
134
|
+
|
|
85
135
|
### TM1 11 On-Premise
|
|
86
136
|
|
|
87
137
|
```typescript
|
|
@@ -96,6 +146,9 @@ const tm1 = new TM1Service({
|
|
|
96
146
|
});
|
|
97
147
|
|
|
98
148
|
try {
|
|
149
|
+
// Connect to TM1 server
|
|
150
|
+
await tm1.connect();
|
|
151
|
+
|
|
99
152
|
const version = await tm1.server.getProductVersion();
|
|
100
153
|
console.log('TM1 Version:', version);
|
|
101
154
|
|
|
@@ -122,6 +175,9 @@ const tm1 = new TM1Service({
|
|
|
122
175
|
});
|
|
123
176
|
|
|
124
177
|
try {
|
|
178
|
+
// Connect to TM1 server
|
|
179
|
+
await tm1.connect();
|
|
180
|
+
|
|
125
181
|
const chores = await tm1.chores.getAll();
|
|
126
182
|
for (const chore of chores) {
|
|
127
183
|
chore.reschedule(-1); // Reschedule 1 hour earlier
|
|
@@ -148,6 +204,9 @@ const params = {
|
|
|
148
204
|
const tm1 = new TM1Service(params);
|
|
149
205
|
|
|
150
206
|
try {
|
|
207
|
+
// Connect to TM1 server
|
|
208
|
+
await tm1.connect();
|
|
209
|
+
|
|
151
210
|
const version = await tm1.server.getProductVersion();
|
|
152
211
|
console.log('TM1 Version:', version);
|
|
153
212
|
} finally {
|
|
@@ -171,6 +230,9 @@ const tm1 = new TM1Service({
|
|
|
171
230
|
});
|
|
172
231
|
|
|
173
232
|
try {
|
|
233
|
+
// Connect to TM1 server
|
|
234
|
+
await tm1.connect();
|
|
235
|
+
|
|
174
236
|
const version = await tm1.server.getProductVersion();
|
|
175
237
|
console.log('TM1 Version:', version);
|
|
176
238
|
} finally {
|
|
@@ -194,6 +256,9 @@ const params = {
|
|
|
194
256
|
const tm1 = new TM1Service(params);
|
|
195
257
|
|
|
196
258
|
try {
|
|
259
|
+
// Connect to TM1 server
|
|
260
|
+
await tm1.connect();
|
|
261
|
+
|
|
197
262
|
const version = await tm1.server.getProductVersion();
|
|
198
263
|
console.log('TM1 Version:', version);
|
|
199
264
|
} finally {
|
|
@@ -211,6 +276,9 @@ import { TM1Service, Dimension, Hierarchy, Element } from 'tm1npm';
|
|
|
211
276
|
const tm1 = new TM1Service(config);
|
|
212
277
|
|
|
213
278
|
try {
|
|
279
|
+
// Connect to TM1 server
|
|
280
|
+
await tm1.connect();
|
|
281
|
+
|
|
214
282
|
// Create a new dimension
|
|
215
283
|
const elements = [
|
|
216
284
|
new Element('Total', 'Consolidated'),
|
|
@@ -248,16 +316,31 @@ const mdx = `
|
|
|
248
316
|
const cellset = await tm1.cubes.cells.executeMdx(mdx);
|
|
249
317
|
console.log('Data:', cellset);
|
|
250
318
|
|
|
319
|
+
// 🆕 NEW: Get data as CSV format
|
|
320
|
+
const csvData = await tm1.cubes.cells.executeMdxCsv(mdx, {
|
|
321
|
+
csv_dialect: { delimiter: ',', quotechar: '"' }
|
|
322
|
+
});
|
|
323
|
+
console.log('CSV Data:', csvData);
|
|
324
|
+
|
|
325
|
+
// 🆕 NEW: Get data as DataFrame (pandas-like)
|
|
326
|
+
const dataFrame = await tm1.cubes.cells.executeMdxDataFrame(mdx);
|
|
327
|
+
console.log('DataFrame shape:', dataFrame.shape);
|
|
328
|
+
console.log('Columns:', dataFrame.columns);
|
|
329
|
+
|
|
251
330
|
// Read data using cell coordinates
|
|
252
331
|
const value = await tm1.cubes.cells.getValue('Budget', ['Jan', 'Revenue', 'Actual']);
|
|
253
332
|
console.log('Cell value:', value);
|
|
333
|
+
|
|
334
|
+
// 🆕 NEW: Trace how a cell is calculated
|
|
335
|
+
const trace = await tm1.cubes.cells.traceCellCalculation('Budget', ['Jan', 'Revenue', 'Actual']);
|
|
336
|
+
console.log('Cell calculation trace:', trace);
|
|
254
337
|
```
|
|
255
338
|
|
|
256
339
|
### Writing Data to Cubes
|
|
257
340
|
|
|
258
341
|
```typescript
|
|
259
342
|
// Write single cell
|
|
260
|
-
await tm1.cubes.cells.writeValue(
|
|
343
|
+
await tm1.cubes.cells.writeValue('Budget', ['Jan', 'Revenue', 'Budget'], 1000);
|
|
261
344
|
|
|
262
345
|
// Write multiple cells
|
|
263
346
|
const cellset = {
|
|
@@ -266,7 +349,18 @@ const cellset = {
|
|
|
266
349
|
'Mar:Revenue:Budget': 1200
|
|
267
350
|
};
|
|
268
351
|
|
|
269
|
-
await tm1.cubes.cells.
|
|
352
|
+
await tm1.cubes.cells.write('Budget', cellset);
|
|
353
|
+
|
|
354
|
+
// 🆕 NEW: Async writing for better performance
|
|
355
|
+
const executionId = await tm1.cubes.cells.writeAsync('Budget', cellset);
|
|
356
|
+
console.log('Async write started:', executionId);
|
|
357
|
+
|
|
358
|
+
// 🆕 NEW: Proportional spreading
|
|
359
|
+
await tm1.cubes.cells.relativeProportionalSpread(
|
|
360
|
+
'Budget',
|
|
361
|
+
10000, // value to spread
|
|
362
|
+
['Total', 'Revenue', 'Budget'] // coordinates
|
|
363
|
+
);
|
|
270
364
|
```
|
|
271
365
|
|
|
272
366
|
### Executing Processes
|
|
@@ -280,16 +374,67 @@ const result = await tm1.processes.execute('ImportData', {
|
|
|
280
374
|
|
|
281
375
|
console.log('Process executed successfully:', result);
|
|
282
376
|
|
|
377
|
+
// 🆕 NEW: Compile process and check for errors
|
|
378
|
+
const compilation = await tm1.processes.compileProcess('ImportData');
|
|
379
|
+
if (compilation.success) {
|
|
380
|
+
console.log('Process compiled successfully');
|
|
381
|
+
} else {
|
|
382
|
+
console.error('Compilation errors:', compilation.errors);
|
|
383
|
+
}
|
|
384
|
+
|
|
283
385
|
// Execute with return information
|
|
284
|
-
const
|
|
386
|
+
const result2 = await tm1.processes.executeWithReturn('ImportData', {
|
|
285
387
|
pFilename: 'data.csv'
|
|
286
388
|
});
|
|
287
389
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
390
|
+
console.log('Process result:', result2);
|
|
391
|
+
|
|
392
|
+
// 🆕 NEW: Async execution with polling
|
|
393
|
+
const asyncResult = await tm1.processes.pollExecuteWithReturn('ImportData', {
|
|
394
|
+
pFilename: 'data.csv'
|
|
395
|
+
}, 300, 5); // 300s timeout, 5s poll interval
|
|
396
|
+
|
|
397
|
+
console.log('Async process completed:', asyncResult);
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### 🆕 NEW: Working with DataFrames
|
|
401
|
+
|
|
402
|
+
tm1npm now includes a comprehensive DataFrame implementation for pandas-like data manipulation:
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
import { DataFrame } from 'tm1npm';
|
|
406
|
+
|
|
407
|
+
// Create DataFrame from TM1 data
|
|
408
|
+
const mdx = "SELECT [Time].Members ON COLUMNS, [Account].Members ON ROWS FROM [Budget]";
|
|
409
|
+
const dataFrame = await tm1.cubes.cells.executeMdxDataFrame(mdx);
|
|
410
|
+
|
|
411
|
+
// Explore the data
|
|
412
|
+
console.log('Shape:', dataFrame.shape); // [rows, columns]
|
|
413
|
+
console.log('Columns:', dataFrame.columns); // ['Time', 'Account', 'Value']
|
|
414
|
+
|
|
415
|
+
// Filter data
|
|
416
|
+
const filtered = dataFrame.filter((row, index) => row[2] > 1000); // Value > 1000
|
|
417
|
+
|
|
418
|
+
// Sort by value column
|
|
419
|
+
const sorted = dataFrame.sortBy('Value', false); // descending
|
|
420
|
+
|
|
421
|
+
// Group by Account and sum
|
|
422
|
+
const grouped = dataFrame.groupBy('Account').sum('Value');
|
|
423
|
+
|
|
424
|
+
// Convert to different formats
|
|
425
|
+
const csvString = dataFrame.toCsv(',');
|
|
426
|
+
const jsonArray = dataFrame.toJson();
|
|
427
|
+
|
|
428
|
+
// Advanced search with multiple criteria
|
|
429
|
+
const salesCubes = await tm1.cubes.searchCubes({
|
|
430
|
+
namePattern: 'sales',
|
|
431
|
+
dimensionNames: ['Time', 'Account'],
|
|
432
|
+
hasRules: true,
|
|
433
|
+
minDimensions: 3,
|
|
434
|
+
maxDimensions: 6
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
console.log('Found sales cubes:', salesCubes);
|
|
293
438
|
```
|
|
294
439
|
|
|
295
440
|
## Configuration Options
|
|
@@ -448,6 +593,8 @@ tm1npm is inspired by and designed to provide feature parity with **tm1py**, the
|
|
|
448
593
|
|
|
449
594
|
**🏆 Feature Parity Status**: tm1npm achieves **95-98% feature parity** with tm1py, providing nearly all the same functionality you know and love from the Python ecosystem.
|
|
450
595
|
|
|
596
|
+
**🚀 NEW in v1.0.1**: Major functionality update with **25+ new methods** including CSV export, cell tracing, DataFrame support, advanced async operations, and enhanced search capabilities!
|
|
597
|
+
|
|
451
598
|
### Why tm1npm?
|
|
452
599
|
|
|
453
600
|
- **Familiar API**: If you're coming from tm1py, you'll feel right at home
|
|
@@ -480,6 +627,9 @@ import { TM1Service } from 'tm1npm';
|
|
|
480
627
|
|
|
481
628
|
const tm1 = new TM1Service({address: 'localhost', port: 8001, user: 'admin', password: 'apple'});
|
|
482
629
|
try {
|
|
630
|
+
// Connect to TM1 server
|
|
631
|
+
await tm1.connect();
|
|
632
|
+
|
|
483
633
|
// Get cube names
|
|
484
634
|
const cubes = await tm1.cubes.getAllNames();
|
|
485
635
|
|
|
@@ -509,14 +659,14 @@ try {
|
|
|
509
659
|
|
|
510
660
|
### Comprehensive Feature Parity
|
|
511
661
|
|
|
512
|
-
tm1npm implements **
|
|
662
|
+
tm1npm implements **300+ functions** from tm1py's 31 core services, including:
|
|
513
663
|
|
|
514
664
|
#### Core Services (Complete Coverage)
|
|
515
|
-
- ✅ **CellService**:
|
|
516
|
-
- ✅ **CubeService**:
|
|
665
|
+
- ✅ **CellService**: 60+ methods including CSV export, cell tracing, async operations, DataFrame support
|
|
666
|
+
- ✅ **CubeService**: 45+ methods for complete cube management and advanced search
|
|
517
667
|
- ✅ **DimensionService**: 30+ methods for dimension operations
|
|
518
668
|
- ✅ **ElementService**: 60+ methods including TI-based operations
|
|
519
|
-
- ✅ **ProcessService**:
|
|
669
|
+
- ✅ **ProcessService**: 45+ methods with compilation, debugging and async execution
|
|
520
670
|
- ✅ **ViewService**: 30+ methods for private/public view management
|
|
521
671
|
- ✅ **HierarchyService**: 18+ methods including balance checking
|
|
522
672
|
|
|
@@ -530,7 +680,13 @@ tm1npm implements **280+ functions** from tm1py's 31 core services, including:
|
|
|
530
680
|
- ✅ **SandboxService**: Sandbox operations
|
|
531
681
|
|
|
532
682
|
#### Advanced Features (Enterprise Ready)
|
|
533
|
-
- ✅ **
|
|
683
|
+
- ✅ **CSV Export**: `executeMdxCsv()`, `executeViewCsv()` with full formatting control
|
|
684
|
+
- ✅ **Cell Analysis**: `traceCellCalculation()`, `traceCellFeeders()`, `checkCellFeeders()`
|
|
685
|
+
- ✅ **Proportional Spreading**: `relativeProportionalSpread()`, `clearSpread()`
|
|
686
|
+
- ✅ **DataFrame Support**: JavaScript DataFrame class with pandas-like functionality
|
|
687
|
+
- ✅ **Advanced Search**: `searchCubes()`, `searchForDimension()`, multi-criteria filtering
|
|
688
|
+
- ✅ **Enhanced Async**: `executeMdxAsync()`, `executeViewAsync()`, `writeDataframeAsync()`
|
|
689
|
+
- ✅ **Process Features**: `compileProcess()`, `pollExecuteWithReturn()` with error details
|
|
534
690
|
- ✅ **TI Integration**: `deleteElementsUseTi()`, `writeThroughUnboundProcess()`
|
|
535
691
|
- ✅ **Bulk Operations**: `deleteEdgesUseBlob()`, `writeThroughBlob()`
|
|
536
692
|
- ✅ **Performance**: Blob support, compact JSON, iterative JSON
|