@lambda-kata/licensing 0.1.6 → 0.1.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambda-kata/licensing",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Tamper-resistant native licensing validator for Lambda Kata Integration",
5
5
  "main": "out/dist/index.js",
6
6
  "types": "out/tsc/index.d.ts",
@@ -48,13 +48,16 @@
48
48
  "lint": "eslint src/ test/ --ext .ts",
49
49
  "lint:fix": "eslint src/ test/ --ext .ts --fix",
50
50
  "docs": "typedoc src/index.ts --out docs/",
51
- "_install": "node scripts/install.js",
52
- "_postinstall": "node scripts/postinstall.js || echo 'Postinstall script failed, using fallback mode'"
51
+ "install": "node scripts/install.js",
52
+ "postinstall": "node scripts/postinstall.js || echo 'Postinstall script failed, using fallback mode'"
53
53
  },
54
54
  "files": [
55
55
  "out/",
56
+ "prebuilt/",
56
57
  "build/amd64/",
57
58
  "build/arm64/",
59
+ "scripts/install.js",
60
+ "scripts/postinstall.js",
58
61
  "README.md",
59
62
  "LICENSE"
60
63
  ],
@@ -94,4 +97,4 @@
94
97
  9
95
98
  ]
96
99
  }
97
- }
100
+ }
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Elastic License 2.0
4
+ *
5
+ * Copyright (c) 2024 Lambda Kata Team, Raman Marozau raman@worktif.com
6
+ *
7
+ * npm install script for native licensing validator
8
+ * Handles prebuilt binary selection and fallback logic
9
+ *
10
+ * @remarks Validates: Requirements 5.6
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const os = require('os');
16
+
17
+ // Configuration
18
+ const PACKAGE_NAME = '@lambda-kata/licensing';
19
+ const ADDON_NAME = 'lambda_kata_licensing.node';
20
+
21
+ // Platform mapping
22
+ const PLATFORM_MAP = {
23
+ 'linux-x64': 'amd64',
24
+ 'linux-arm64': 'arm64'
25
+ };
26
+
27
+ // Colors for output
28
+ const colors = {
29
+ red: '\x1b[31m',
30
+ green: '\x1b[32m',
31
+ yellow: '\x1b[33m',
32
+ blue: '\x1b[34m',
33
+ reset: '\x1b[0m'
34
+ };
35
+
36
+ function log(level, message) {
37
+ const timestamp = new Date().toISOString();
38
+ const color = colors[level] || colors.reset;
39
+ console.log(`${color}[${level.toUpperCase()}]${colors.reset} ${timestamp} ${message}`);
40
+ }
41
+
42
+ function getPlatformKey() {
43
+ const platform = os.platform();
44
+ const arch = os.arch();
45
+
46
+ // Only support Linux for Lambda deployment
47
+ if (platform !== 'linux') {
48
+ return null;
49
+ }
50
+
51
+ // Map Node.js arch to our naming convention
52
+ const archMap = {
53
+ 'x64': 'x64',
54
+ 'arm64': 'arm64'
55
+ };
56
+
57
+ const mappedArch = archMap[arch];
58
+ if (!mappedArch) {
59
+ return null;
60
+ }
61
+
62
+ return `${platform}-${mappedArch}`;
63
+ }
64
+
65
+ function getPrebuiltPath() {
66
+ const platformKey = getPlatformKey();
67
+ if (!platformKey) {
68
+ return null;
69
+ }
70
+
71
+ const mappedArch = PLATFORM_MAP[platformKey];
72
+ if (!mappedArch) {
73
+ return null;
74
+ }
75
+
76
+ // Look for prebuilt binary in prebuilt directory (shipped with npm package)
77
+ const prebuiltDir = path.join(__dirname, '..', 'prebuilt');
78
+ const prebuiltPath = path.join(prebuiltDir, mappedArch, 'build', 'Release', ADDON_NAME);
79
+
80
+ if (fs.existsSync(prebuiltPath)) {
81
+ return prebuiltPath;
82
+ }
83
+
84
+ // Fallback: check if already in build directory (from previous install)
85
+ const buildDir = path.join(__dirname, '..', 'build');
86
+ const buildPath = path.join(buildDir, 'Release', ADDON_NAME);
87
+
88
+ if (fs.existsSync(buildPath)) {
89
+ log('blue', 'Using existing build from previous installation');
90
+ return null; // Already in place, no need to copy
91
+ }
92
+
93
+ return null;
94
+ }
95
+
96
+ function getTargetPath() {
97
+ const targetDir = path.join(__dirname, '..', 'build', 'Release');
98
+ return path.join(targetDir, ADDON_NAME);
99
+ }
100
+
101
+ function ensureDirectoryExists(dirPath) {
102
+ if (!fs.existsSync(dirPath)) {
103
+ fs.mkdirSync(dirPath, { recursive: true });
104
+ }
105
+ }
106
+
107
+ function copyPrebuiltBinary() {
108
+ const prebuiltPath = getPrebuiltPath();
109
+ if (!prebuiltPath) {
110
+ log('warn', 'No prebuilt binary available for this platform');
111
+ return false;
112
+ }
113
+
114
+ const targetPath = getTargetPath();
115
+ const targetDir = path.dirname(targetPath);
116
+
117
+ try {
118
+ // Ensure target directory exists
119
+ ensureDirectoryExists(targetDir);
120
+
121
+ // Copy prebuilt binary
122
+ fs.copyFileSync(prebuiltPath, targetPath);
123
+
124
+ // Set executable permissions
125
+ fs.chmodSync(targetPath, 0o755);
126
+
127
+ log('green', `Installed prebuilt binary: ${targetPath}`);
128
+ return true;
129
+ } catch (error) {
130
+ log('red', `Failed to copy prebuilt binary: ${error.message}`);
131
+ return false;
132
+ }
133
+ }
134
+
135
+ function tryNativeBuild() {
136
+ const { execSync } = require('child_process');
137
+
138
+ try {
139
+ log('blue', 'Attempting native build...');
140
+
141
+ // Check if we have build tools
142
+ execSync('node-gyp --version', { stdio: 'pipe' });
143
+
144
+ // Try to build
145
+ execSync('node-gyp rebuild', {
146
+ stdio: 'inherit',
147
+ cwd: path.join(__dirname, '..')
148
+ });
149
+
150
+ // Verify build output
151
+ const targetPath = getTargetPath();
152
+ if (fs.existsSync(targetPath)) {
153
+ log('green', 'Native build successful');
154
+ return true;
155
+ } else {
156
+ log('red', 'Native build completed but addon not found');
157
+ return false;
158
+ }
159
+ } catch (error) {
160
+ log('yellow', `Native build failed: ${error.message}`);
161
+ return false;
162
+ }
163
+ }
164
+
165
+ function createFallbackMarker() {
166
+ const markerPath = path.join(__dirname, '..', '.fallback-mode');
167
+ try {
168
+ fs.writeFileSync(markerPath, JSON.stringify({
169
+ reason: 'No native addon available',
170
+ platform: os.platform(),
171
+ arch: os.arch(),
172
+ timestamp: new Date().toISOString()
173
+ }, null, 2));
174
+ log('yellow', 'Created fallback mode marker');
175
+ } catch (error) {
176
+ log('red', `Failed to create fallback marker: ${error.message}`);
177
+ }
178
+ }
179
+
180
+ function main() {
181
+ log('blue', `Installing ${PACKAGE_NAME}...`);
182
+ log('blue', `Platform: ${os.platform()}-${os.arch()}`);
183
+
184
+ // Skip installation in CI environments unless explicitly requested
185
+ if (process.env.CI && !process.env.FORCE_NATIVE_BUILD) {
186
+ log('yellow', 'Skipping native addon installation in CI environment');
187
+ createFallbackMarker();
188
+ return;
189
+ }
190
+
191
+ // Skip installation during npm pack/publish
192
+ if (process.env.npm_lifecycle_event === 'prepack' ||
193
+ process.env.npm_lifecycle_event === 'prepublishOnly') {
194
+ log('yellow', 'Skipping native addon installation during packaging');
195
+ return;
196
+ }
197
+
198
+ // Try prebuilt binary first
199
+ if (copyPrebuiltBinary()) {
200
+ log('green', 'Installation completed using prebuilt binary');
201
+ return;
202
+ }
203
+
204
+ // Fall back to native build
205
+ if (tryNativeBuild()) {
206
+ log('green', 'Installation completed using native build');
207
+ return;
208
+ }
209
+
210
+ // Create fallback marker
211
+ createFallbackMarker();
212
+ log('yellow', 'Installation completed in fallback mode (JavaScript only)');
213
+ log('yellow', 'Native licensing validation will not be available');
214
+ }
215
+
216
+ // Only run if called directly
217
+ if (require.main === module) {
218
+ main();
219
+ }
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Elastic License 2.0
4
+ *
5
+ * Copyright (c) 2024 Lambda Kata Team, Raman Marozau raman@worktif.com
6
+ *
7
+ * npm postinstall script for native licensing validator
8
+ * Verifies installation and provides user feedback
9
+ *
10
+ * @remarks Validates: Requirements 5.6
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const os = require('os');
16
+
17
+ // Configuration
18
+ const ADDON_NAME = 'lambda_kata_licensing.node';
19
+
20
+ // Colors for output
21
+ const colors = {
22
+ red: '\x1b[31m',
23
+ green: '\x1b[32m',
24
+ yellow: '\x1b[33m',
25
+ blue: '\x1b[34m',
26
+ reset: '\x1b[0m'
27
+ };
28
+
29
+ function log(level, message) {
30
+ const color = colors[level] || colors.reset;
31
+ console.log(`${color}[${level.toUpperCase()}]${colors.reset} ${message}`);
32
+ }
33
+
34
+ function checkNativeAddon() {
35
+ const addonPath = path.join(__dirname, '..', 'build', 'Release', ADDON_NAME);
36
+
37
+ if (!fs.existsSync(addonPath)) {
38
+ return {available: false, reason: 'Addon file not found'};
39
+ }
40
+
41
+ try {
42
+ const stats = fs.statSync(addonPath);
43
+
44
+ // Check if file is executable
45
+ const isExecutable = (stats.mode & parseInt('111', 8)) !== 0;
46
+ if (!isExecutable) {
47
+ return {available: false, reason: 'Addon file not executable'};
48
+ }
49
+
50
+ // Try to load the addon
51
+ const addon = require(addonPath);
52
+ if (typeof addon.checkEntitlement === 'function') {
53
+ return {available: true, path: addonPath, size: stats.size};
54
+ } else {
55
+ return {available: false, reason: 'Addon missing required exports'};
56
+ }
57
+ } catch (error) {
58
+ return {available: false, reason: `Addon load failed: ${error.message}`};
59
+ }
60
+ }
61
+
62
+ function checkFallbackMode() {
63
+ const markerPath = path.join(__dirname, '..', '.fallback-mode');
64
+
65
+ if (fs.existsSync(markerPath)) {
66
+ try {
67
+ const marker = JSON.parse(fs.readFileSync(markerPath, 'utf8'));
68
+ return {fallback: true, marker};
69
+ } catch (error) {
70
+ return {fallback: true, marker: {reason: 'Unknown'}};
71
+ }
72
+ }
73
+
74
+ return {fallback: false};
75
+ }
76
+
77
+ function checkTypeScriptOutput() {
78
+ const jsPath = path.join(__dirname, '..', 'out', 'dist', 'index.js');
79
+ const dtsPath = path.join(__dirname, '..', 'out', 'tsc', 'index.d.ts');
80
+
81
+ return {
82
+ js: fs.existsSync(jsPath),
83
+ types: fs.existsSync(dtsPath)
84
+ };
85
+ }
86
+
87
+ function displayInstallationSummary() {
88
+ log('blue', '='.repeat(60));
89
+ log('blue', 'Native Licensing Validator - Installation Summary');
90
+ log('blue', '='.repeat(60));
91
+
92
+ // Platform info
93
+ log('blue', `Platform: ${os.platform()}-${os.arch()}`);
94
+ log('blue', `Node.js: ${process.version}`);
95
+
96
+ // Check native addon
97
+ const addonStatus = checkNativeAddon();
98
+ if (addonStatus.available) {
99
+ log('green', `✓ Native addon: Available (${Math.round(addonStatus.size / 1024)}KB)`);
100
+ log('green', ' Enhanced security features enabled');
101
+ } else {
102
+ log('yellow', `⚠ Native addon: Not available (${addonStatus.reason})`);
103
+ }
104
+
105
+ // Check fallback mode
106
+ const fallbackStatus = checkFallbackMode();
107
+ if (fallbackStatus.fallback) {
108
+ log('yellow', `⚠ Fallback mode: Active (${fallbackStatus.marker.reason})`);
109
+ log('yellow', ' Using JavaScript-only implementation');
110
+ }
111
+
112
+ // Check TypeScript output
113
+ const tsStatus = checkTypeScriptOutput();
114
+ if (tsStatus.js && tsStatus.types) {
115
+ log('green', '✓ TypeScript output: Available');
116
+ } else {
117
+ log('red', '✗ TypeScript output: Missing');
118
+ if (!tsStatus.js) log('red', ' - JavaScript bundle missing');
119
+ if (!tsStatus.types) log('red', ' - Type definitions missing');
120
+ }
121
+
122
+ // Usage recommendations
123
+ log('blue', '');
124
+ log('blue', 'Usage:');
125
+ log('blue', ' const { NativeLicensingService } = require("@lambda-kata/licensing");');
126
+ log('blue', ' const service = new NativeLicensingService();');
127
+
128
+ if (!addonStatus.available) {
129
+ log('yellow', '');
130
+ log('yellow', 'Note: Native addon not available. The service will use fallback mode.');
131
+ log('yellow', 'For production use, ensure native addon is built for your target platform.');
132
+ }
133
+
134
+ // Lambda deployment info
135
+ if (addonStatus.available) {
136
+ log('blue', '');
137
+ log('blue', 'Lambda Deployment:');
138
+ log('blue', ' Use the provided Lambda Layer packages for deployment');
139
+ log('blue', ' Run: npm run build:all to create deployment artifacts');
140
+ }
141
+
142
+ log('blue', '='.repeat(60));
143
+ }
144
+
145
+ function main() {
146
+ // Skip in CI unless explicitly requested
147
+ if (process.env.CI && !process.env.SHOW_INSTALL_SUMMARY) {
148
+ return;
149
+ }
150
+
151
+ // Skip during npm pack/publish
152
+ if (process.env.npm_lifecycle_event === 'prepack' ||
153
+ process.env.npm_lifecycle_event === 'prepublishOnly') {
154
+ return;
155
+ }
156
+
157
+ displayInstallationSummary();
158
+ }
159
+
160
+ // Only run if called directly
161
+ if (require.main === module) {
162
+ main();
163
+ }