@phystack/device-phyos 4.5.64-dev → 5.0.1

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/bin/index.js CHANGED
@@ -1,23 +1,27 @@
1
1
  #!/usr/bin/env node
2
- const { spawnSync } = require('child_process');
3
- const path = require('path');
2
+ const { spawnSync } = require("child_process");
3
+ const path = require("path");
4
4
 
5
- const BINARY = 'phydevice';
5
+ const BINARY = "phydevice";
6
6
  const key = `${process.platform}-${process.arch}`;
7
7
  const pkg = `@phystack/${BINARY}-${key}`;
8
8
 
9
9
  let binPath;
10
10
  try {
11
- binPath = path.join(path.dirname(require.resolve(`${pkg}/package.json`)), 'bin', BINARY);
11
+ binPath = path.join(
12
+ path.dirname(require.resolve(`${pkg}/package.json`)),
13
+ "bin",
14
+ BINARY,
15
+ );
12
16
  } catch {
13
17
  console.error(
14
18
  `Unsupported or missing platform package: ${pkg}\n` +
15
- `Platform: ${key}\n\n` +
16
- `Install manually: npm install ${pkg}\n` +
17
- `Or download: npx ${pkg}`
19
+ `Platform: ${key}\n\n` +
20
+ `Install manually: npm install ${pkg}\n` +
21
+ `Or download: bunx ${pkg}`,
18
22
  );
19
23
  process.exit(1);
20
24
  }
21
25
 
22
- const result = spawnSync(binPath, process.argv.slice(2), { stdio: 'inherit' });
26
+ const result = spawnSync(binPath, process.argv.slice(2), { stdio: "inherit" });
23
27
  process.exit(result.status ?? 1);
package/dist/index.js ADDED
@@ -0,0 +1,491 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = __importDefault(require("fs"));
7
+ const child_process_1 = require("child_process");
8
+ const hub_device_1 = __importDefault(require("@phystack/hub-device"));
9
+ const phy_logger_1 = require("@phystack/phy-logger");
10
+ const edge_hub_1 = require("./edge-hub");
11
+ const instances_1 = require("./utilities/instances");
12
+ const methods_1 = require("./methods");
13
+ const scheduler_service_1 = require("./services/scheduler.service");
14
+ const time_sync_1 = __importDefault(require("./time-sync"));
15
+ const environment_1 = require("./methods/environment");
16
+ const ca_1 = require("./methods/network/ca");
17
+ const twin_manager_1 = require("./utilities/twin-manager");
18
+ const { connectToPhyHub } = hub_device_1.default;
19
+ const phyosEnvPath = '/etc/phyos.env';
20
+ const phyosVersionPath = '/etc/phyos.version';
21
+ const credentialsMigrationPath = '/data/migration.json';
22
+ const environmentFilePath = '/etc/environment';
23
+ const regionFilePath = '/data/settings/phyhub/region.json';
24
+ const customProxyFilePath = '/data/environment-custom-proxy';
25
+ const logger = new phy_logger_1.PhyLogger({
26
+ logToFile: false,
27
+ logToConsole: true,
28
+ includeTrace: true,
29
+ namespace: 'device-phyos',
30
+ });
31
+ function sourceEnvironment() {
32
+ let gridEnv = 'PROD';
33
+ try {
34
+ const symlinkFixed = (0, environment_1.ensureEnvironmentSymlink)();
35
+ try {
36
+ if (fs_1.default.existsSync(phyosEnvPath)) {
37
+ const envContent = fs_1.default.readFileSync(phyosEnvPath, 'utf8').trim().toUpperCase();
38
+ if (envContent === 'DEV' || envContent === 'QA') {
39
+ gridEnv = envContent;
40
+ }
41
+ }
42
+ }
43
+ catch (error) {
44
+ logger.warn('Error reading grid environment, defaulting to prod:', error);
45
+ }
46
+ if (symlinkFixed || !fs_1.default.existsSync(environmentFilePath)) {
47
+ (0, environment_1.setDefaultEnvironmentConfiguration)(gridEnv);
48
+ }
49
+ const envContent = fs_1.default.readFileSync(environmentFilePath, 'utf8');
50
+ const envLines = envContent.split('\n');
51
+ for (const line of envLines) {
52
+ if (line.trim() && !line.startsWith('#')) {
53
+ const [key, value] = line.split('=');
54
+ if (key && value) {
55
+ process.env[key.trim()] = value.trim().replace(/["']/g, '');
56
+ }
57
+ }
58
+ }
59
+ }
60
+ catch (error) {
61
+ logger.error('Failed to read /etc/environment:', error);
62
+ try {
63
+ (0, environment_1.setDefaultEnvironmentConfiguration)(gridEnv);
64
+ }
65
+ catch (innerError) {
66
+ logger.error('Failed to set default proxy configuration:', innerError);
67
+ }
68
+ }
69
+ }
70
+ function getSystemdJournalGid() {
71
+ try {
72
+ const groupFile = fs_1.default.readFileSync('/etc/group', 'utf8');
73
+ const groups = groupFile.split('\n');
74
+ const journalGroup = groups.find(line => line.startsWith('systemd-journal:'));
75
+ if (!journalGroup) {
76
+ throw new Error('systemd-journal group not found');
77
+ }
78
+ const gid = parseInt(journalGroup.split(':')[2]);
79
+ if (isNaN(gid)) {
80
+ throw new Error('Invalid GID for systemd-journal');
81
+ }
82
+ return gid;
83
+ }
84
+ catch (error) {
85
+ logger.error('Failed to get systemd-journal GID:', error);
86
+ return 0;
87
+ }
88
+ }
89
+ function initializeFiles() {
90
+ const PROVISIONING_CODE_PATH = '/tmp/provisioning_code';
91
+ const LOG_PATH = '/data/log';
92
+ try {
93
+ if (!fs_1.default.existsSync(PROVISIONING_CODE_PATH)) {
94
+ fs_1.default.writeFileSync(PROVISIONING_CODE_PATH, '');
95
+ }
96
+ fs_1.default.chmodSync(PROVISIONING_CODE_PATH, 0o666);
97
+ if (!fs_1.default.existsSync(LOG_PATH)) {
98
+ fs_1.default.mkdirSync(LOG_PATH, { recursive: true });
99
+ }
100
+ try {
101
+ const journalGid = getSystemdJournalGid();
102
+ fs_1.default.chownSync(LOG_PATH, 0, journalGid);
103
+ fs_1.default.chmodSync(LOG_PATH, 0o2775);
104
+ }
105
+ catch (error) {
106
+ logger.error('Failed to set log directory permissions:', error);
107
+ setTimeout(() => process.exit(1), 1000);
108
+ }
109
+ }
110
+ catch (error) {
111
+ logger.error('Failed to initialize required files:', error);
112
+ setTimeout(() => process.exit(1), 1000);
113
+ }
114
+ }
115
+ function initializeProxy() {
116
+ try {
117
+ let needsDefaultConfig = true;
118
+ if (fs_1.default.existsSync(environmentFilePath)) {
119
+ const envContent = fs_1.default.readFileSync(environmentFilePath, 'utf8');
120
+ const hasHttpProxy = envContent.includes('http_proxy=');
121
+ const hasHttpsProxy = envContent.includes('https_proxy=');
122
+ needsDefaultConfig = !hasHttpProxy && !hasHttpsProxy;
123
+ }
124
+ let gridEnv = 'PROD';
125
+ try {
126
+ if (fs_1.default.existsSync(phyosEnvPath)) {
127
+ const envContent = fs_1.default.readFileSync(phyosEnvPath, 'utf8').trim().toUpperCase();
128
+ if (envContent === 'DEV' || envContent === 'QA') {
129
+ gridEnv = envContent;
130
+ }
131
+ }
132
+ }
133
+ catch (error) {
134
+ logger.warn('initializeProxy(): Error reading grid environment, defaulting to prod:', error);
135
+ }
136
+ if (needsDefaultConfig) {
137
+ logger.info('Proxy settings not found, setting default configuration for environment:', gridEnv);
138
+ (0, environment_1.setDefaultEnvironmentConfiguration)(gridEnv);
139
+ }
140
+ else {
141
+ logger.info('Proxy settings already exist, skipping default configuration');
142
+ }
143
+ }
144
+ catch (error) {
145
+ logger.error('Failed to check proxy settings:', error);
146
+ try {
147
+ (0, environment_1.setDefaultEnvironmentConfiguration)('PROD');
148
+ }
149
+ catch (innerError) {
150
+ logger.error('Failed to set default proxy configuration:', innerError);
151
+ setTimeout(() => process.exit(1), 1000);
152
+ }
153
+ }
154
+ }
155
+ try {
156
+ initializeFiles();
157
+ initializeProxy();
158
+ sourceEnvironment();
159
+ (0, environment_1.checkProxySettings)();
160
+ }
161
+ catch (error) {
162
+ logger.error('Failed to initialize environment:', error);
163
+ setTimeout(() => process.exit(1), 1000);
164
+ }
165
+ class DevicePhyos {
166
+ GRID_ENV;
167
+ PHYOS_VERSION;
168
+ firstConnect;
169
+ phyHubInterval;
170
+ logger;
171
+ scheduler = new scheduler_service_1.Scheduler();
172
+ twinManager;
173
+ constructor() {
174
+ this.GRID_ENV = 'PROD';
175
+ this.PHYOS_VERSION = 'N/A';
176
+ this.firstConnect = false;
177
+ this.phyHubInterval = null;
178
+ this.logger = new phy_logger_1.PhyLogger({
179
+ logToFile: false,
180
+ logToConsole: true,
181
+ includeTrace: true,
182
+ namespace: 'device-phyos',
183
+ });
184
+ }
185
+ async initialize() {
186
+ await this.initializeEnvironment();
187
+ await this.initializeTimeSync();
188
+ this.logger.info(`Starting device phyos service 🟢-⚪-⚪-⚪-⚪`, {
189
+ GRID_ENV: this.GRID_ENV,
190
+ PHYOS_VERSION: this.PHYOS_VERSION
191
+ });
192
+ }
193
+ async initializeEnvironment() {
194
+ try {
195
+ this.GRID_ENV = await fs_1.default.promises.readFile(phyosEnvPath, 'utf8').then(data => data.trim() || 'LOCAL');
196
+ this.logger.info('initializeEnvironment(): Setting grid environment', {
197
+ GRID_ENV: this.GRID_ENV,
198
+ });
199
+ }
200
+ catch (error) {
201
+ this.logger.error('initializeEnvironment(): Error reading grid environment', error);
202
+ this.GRID_ENV = 'PROD';
203
+ }
204
+ try {
205
+ this.PHYOS_VERSION = await fs_1.default.promises.readFile(phyosVersionPath, 'utf8').then(data => data.trim());
206
+ this.logger.info('initializeEnvironment(): Setting PhyOS version', {
207
+ PHYOS_VERSION: this.PHYOS_VERSION
208
+ });
209
+ }
210
+ catch (error) {
211
+ this.logger.error('initializeEnvironment(): Error reading PhyOS version', error);
212
+ this.PHYOS_VERSION = 'N/A';
213
+ }
214
+ }
215
+ async initializeTimeSync() {
216
+ try {
217
+ this.logger.info('initializeTimeSync(): Performing initial time sync');
218
+ await (0, time_sync_1.default)();
219
+ }
220
+ catch (error) {
221
+ this.logger.error('initializeTimeSync(): Initial time sync failed:', error);
222
+ }
223
+ }
224
+ async initializeCachedInstances(twinManager) {
225
+ const twinsInfoCache = await twinManager.getCachedTwins();
226
+ console.log('initializeCachedInstances(): twinsInfoCache', twinsInfoCache);
227
+ if (!twinsInfoCache || typeof twinsInfoCache !== 'object') {
228
+ this.logger.info('initializeCachedInstances(): No cached twins found');
229
+ return;
230
+ }
231
+ const allTwins = [];
232
+ for (const type of Object.keys(twinsInfoCache)) {
233
+ const twinIds = twinsInfoCache[type];
234
+ if (!Array.isArray(twinIds))
235
+ continue;
236
+ const twins = await Promise.all(twinIds.map(async (twinId) => {
237
+ const twin = await twinManager.getCachedTwins(twinId);
238
+ return twin;
239
+ }));
240
+ allTwins.push(...twins.filter(Boolean));
241
+ }
242
+ if (allTwins.length > 0) {
243
+ this.logger.info(`initializeCachedInstances(): Found ${allTwins.length} cached twin(s), initializing...`);
244
+ await (0, instances_1.initInstances)(this.twinManager, allTwins);
245
+ }
246
+ else {
247
+ this.logger.info('initializeCachedInstances(): No valid twins to initialize');
248
+ }
249
+ }
250
+ async connectPhyHub(hubDevice) {
251
+ this.twinManager = await (0, twin_manager_1.getTwinManagerInstance)();
252
+ this.twinManager.setHubDevice(hubDevice);
253
+ this.scheduler.setHubDevice(hubDevice);
254
+ hubDevice.setScheduler(this.scheduler);
255
+ hubDevice.onAuthReconnect(async () => {
256
+ this.logger.info('connectPhyHub(): Device authenticated, resubscribing twins...');
257
+ await edge_hub_1.EdgeHubServer.getInstance().resubscribeAllTwins();
258
+ try {
259
+ const cachedTwinsInfo = await this.twinManager.getCachedTwins();
260
+ if (cachedTwinsInfo && typeof cachedTwinsInfo === 'object' && 'Device' in cachedTwinsInfo && Array.isArray(cachedTwinsInfo.Device) && cachedTwinsInfo.Device.length > 0) {
261
+ const deviceTwinId = cachedTwinsInfo.Device[0];
262
+ const deviceTwin = await this.twinManager.getCachedTwins(deviceTwinId);
263
+ if (deviceTwin && deviceTwin.type === 'Device' && 'properties' in deviceTwin && deviceTwin.properties) {
264
+ const deviceProps = deviceTwin.properties;
265
+ const jobs = deviceProps.reported?.jobs || [];
266
+ const timezone = deviceProps.desired?.timezone || 'UTC';
267
+ this.logger.info(`connectPhyHub(): Re-processing ${jobs.length} jobs after reconnection`);
268
+ this.scheduler.processJobs(jobs, timezone, deviceTwinId);
269
+ }
270
+ }
271
+ }
272
+ catch (error) {
273
+ this.logger.error('connectPhyHub(): Failed to re-process scheduler jobs after reconnection', error);
274
+ }
275
+ });
276
+ await hubDevice.connect();
277
+ this.logger.info('connectPhyHub(): Connected to PhyHub');
278
+ hubDevice.connectDevice(async (response) => {
279
+ const { twins } = response;
280
+ console.log('connectPhyHub(): response', response);
281
+ const deviceTwin = twins?.find((twin) => twin.type === 'Device');
282
+ const deviceId = deviceTwin?.deviceId;
283
+ if (!deviceId) {
284
+ this.logger.warn('connectPhyHub(): Missing required device ID in response');
285
+ return;
286
+ }
287
+ this.logger.info(`connectPhyHub(): Device connected with details:`, { deviceId });
288
+ if (deviceId) {
289
+ let shouldUpdateEnvironment = false;
290
+ try {
291
+ if (fs_1.default.existsSync(environmentFilePath)) {
292
+ const envContent = fs_1.default.readFileSync(environmentFilePath, 'utf8');
293
+ shouldUpdateEnvironment = envContent.includes('unprovisioned:device@');
294
+ }
295
+ else {
296
+ shouldUpdateEnvironment = true;
297
+ }
298
+ }
299
+ catch (error) {
300
+ this.logger.warn('connectPhyHub(): Failed to read environment file:', error);
301
+ shouldUpdateEnvironment = true;
302
+ }
303
+ if (shouldUpdateEnvironment) {
304
+ try {
305
+ const proxyConfig = {
306
+ region: hubDevice.region,
307
+ port: 443,
308
+ username: deviceId,
309
+ password: 'device',
310
+ timezone: deviceTwin?.properties?.desired?.timezone || 'Etc/UTC'
311
+ };
312
+ this.logger.info('connectPhyHub(): Environment contains unprovisioned username, configuring with device credentials:', proxyConfig);
313
+ await (0, environment_1.setEnvironmentConfiguration)(proxyConfig);
314
+ this.logger.info('connectPhyHub(): Environment configuration completed successfully');
315
+ }
316
+ catch (error) {
317
+ this.logger.error('connectPhyHub(): Failed to configure provisioned environment, continuing with unprovisioned environment:', error);
318
+ }
319
+ }
320
+ else {
321
+ this.logger.info('connectPhyHub(): Environment already provisioned with device credentials, skipping configuration');
322
+ }
323
+ }
324
+ if (!this.firstConnect) {
325
+ this.firstConnect = true;
326
+ }
327
+ if (twins?.length) {
328
+ this.logger.info('connectPhyHub(): Caching twins from server response...');
329
+ await Promise.all(twins.map((twin) => this.twinManager.cacheHubTwin(twin)));
330
+ this.logger.info(`connectPhyHub(): Cached ${twins.length} twins from hub`);
331
+ const twinsByType = await this.twinManager.getCachedTwins();
332
+ const allTwinIds = Object.values(twinsByType).flat();
333
+ this.logger.info(`connectPhyHub(): Found ${allTwinIds.length} total twins after caching`);
334
+ const allTwins = await Promise.all(allTwinIds.map(id => this.twinManager.getCachedTwins(id)));
335
+ console.log(`connectPhyHub(): allTwins ${allTwins.length}`);
336
+ await (0, instances_1.initInstances)(this.twinManager, allTwins);
337
+ await (0, methods_1.initMethods)(hubDevice);
338
+ }
339
+ });
340
+ await this.initializeCachedInstances(this.twinManager);
341
+ hubDevice.setTwinUpdateHandler(async (twin) => {
342
+ this.logger.info('connectPhyHub() on setTwinUpdateHandler(): Twin update received, updating instance...');
343
+ await this.twinManager.cacheHubTwin(twin);
344
+ if (twin.type === 'Device' && twin.properties?.desired?.timezone) {
345
+ try {
346
+ const region = JSON.parse(fs_1.default.readFileSync(regionFilePath, 'utf8'));
347
+ const proxyConfig = {
348
+ region,
349
+ port: 443,
350
+ username: twin.deviceId,
351
+ password: 'device',
352
+ timezone: twin.properties.desired.timezone
353
+ };
354
+ this.logger.info('connectPhyHub(): Updating environment with:', proxyConfig);
355
+ await (0, environment_1.setTZinEnvFile)(twin.properties.desired.timezone);
356
+ }
357
+ catch (error) {
358
+ this.logger.error('connectPhyHub(): Failed to update environment with new timezone:', error);
359
+ }
360
+ }
361
+ await (0, instances_1.updateInstances)(this.twinManager, [
362
+ (await this.twinManager.getCachedTwins(twin.id)),
363
+ ]);
364
+ });
365
+ hubDevice.setTwinRemoveHandler(async (twin) => {
366
+ this.logger.info('connectPhyHub() on setTwinRemoveHandler(): Twin remove event received, removing instance twin...', twin);
367
+ await (0, instances_1.removeInstances)(this.twinManager, [twin]);
368
+ });
369
+ hubDevice.on('setCACertificate', async (payload, callback) => {
370
+ try {
371
+ const config = payload.data;
372
+ const result = await (0, ca_1.configureCACertificate)(config);
373
+ callback && callback(null, { status: result ? 'success' : 'error' });
374
+ }
375
+ catch (error) {
376
+ console.error('Error configuring CA certificate:', error);
377
+ callback && callback(error);
378
+ }
379
+ });
380
+ hubDevice.on('twinMessage', async (payload, callback) => {
381
+ await edge_hub_1.EdgeHubServer.getInstance().handleTwinMessage(payload, callback, true);
382
+ });
383
+ hubDevice.on('twinUpdated', async (payload, callback) => {
384
+ this.logger.info('connectPhyHub() on twinUpdated(): Twin update received, forwarding to edge-hub...');
385
+ await edge_hub_1.EdgeHubServer.getInstance().handleTwinUpdated(payload, callback, true);
386
+ });
387
+ }
388
+ migrateDeviceCredentialsToPhyOS() {
389
+ this.logger.info('migrateDeviceCredentialsToPhyOS(): Checking if legacy GridOS/PhyOS device');
390
+ try {
391
+ if (fs_1.default.existsSync(customProxyFilePath)) {
392
+ this.logger.info('migrateDeviceCredentialsToPhyOS(): Custom proxy file found, migrating proxy settings');
393
+ (0, child_process_1.execSync)('sudo mv /data/environment-custom-proxy /data/settings/environment');
394
+ (0, child_process_1.execSync)('sudo rm /etc/environment');
395
+ (0, child_process_1.execSync)('sudo ln -sf /data/settings/environment /etc/environment');
396
+ process.exit(0);
397
+ }
398
+ if (fs_1.default.existsSync(credentialsMigrationPath)) {
399
+ const data = fs_1.default.readFileSync(credentialsMigrationPath, 'utf-8');
400
+ const credentials = JSON.parse(data);
401
+ if (credentials.deviceId && credentials.accessKey && credentials.deviceSerial && credentials.region) {
402
+ fs_1.default.unlinkSync(credentialsMigrationPath);
403
+ return credentials;
404
+ }
405
+ }
406
+ }
407
+ catch (error) {
408
+ this.logger.error(`migrateDeviceCredentialsToPhyOS(): Error reading file: ${error}`);
409
+ }
410
+ return undefined;
411
+ }
412
+ async getPhyHub() {
413
+ this.logger.info('getPhyHub(): Attempting to connect to PhyHub');
414
+ let credentials = undefined;
415
+ this.logger.info('getPhyHub(): Checking if migrating legacy device');
416
+ credentials = this.migrateDeviceCredentialsToPhyOS();
417
+ if (credentials && credentials.deviceId && credentials.accessKey && credentials.deviceSerial) {
418
+ this.logger.info('getPhyHub(): Migrating credentials for legacy device');
419
+ }
420
+ else {
421
+ this.logger.info('getPhyHub(): Not a legacy device, attempting to provision device');
422
+ }
423
+ const connectionStatus = await connectToPhyHub(this.GRID_ENV, this.PHYOS_VERSION, credentials);
424
+ if (!connectionStatus) {
425
+ this.logger.warn('getPhyHub(): No connection status received from PhyHub');
426
+ return;
427
+ }
428
+ this.logger.info('getPhyHub(): PhyHub connection details', { connectionStatus });
429
+ const { phyHub: phyHubInstance } = connectionStatus;
430
+ if (phyHubInstance) {
431
+ console.log('found phyHubInstance', { phyHubInstance });
432
+ if (this.phyHubInterval) {
433
+ clearInterval(this.phyHubInterval);
434
+ }
435
+ phyHubInstance.setScheduler(this.scheduler);
436
+ await this.connectPhyHub(phyHubInstance);
437
+ }
438
+ }
439
+ async start() {
440
+ try {
441
+ await this.initialize();
442
+ this.logger.info('start(): Verifying scheduler initialization');
443
+ if (!this.scheduler) {
444
+ this.scheduler = new scheduler_service_1.Scheduler();
445
+ this.logger.info('start(): Created new scheduler instance');
446
+ }
447
+ (0, edge_hub_1.startEdgeHub)().catch(error => {
448
+ this.logger.error('start(): Error starting edgeHub messaging', error);
449
+ });
450
+ this.phyHubInterval = setInterval(() => this.getPhyHub(), 30000);
451
+ await this.getPhyHub();
452
+ }
453
+ catch (error) {
454
+ this.logger.error('start(): Initialization failed:', error);
455
+ process.exit(1);
456
+ }
457
+ }
458
+ stop() {
459
+ if (this.phyHubInterval) {
460
+ clearInterval(this.phyHubInterval);
461
+ this.phyHubInterval = null;
462
+ }
463
+ }
464
+ }
465
+ exports.default = DevicePhyos;
466
+ const initializeDevicePhyos = async () => {
467
+ try {
468
+ const devicePhyos = new DevicePhyos();
469
+ await devicePhyos.start();
470
+ }
471
+ catch (error) {
472
+ console.error('initializeDevicePhyos(): Failed to initialize device phyos', error);
473
+ process.exit(1);
474
+ }
475
+ };
476
+ const HEARTBEAT_PATH = '/tmp/phydevice-heartbeat';
477
+ setInterval(() => {
478
+ fs_1.default.writeFileSync(HEARTBEAT_PATH, new Date().toISOString());
479
+ }, 1000);
480
+ process.on('SIGTERM', async () => {
481
+ console.log('Received SIGTERM, exiting');
482
+ try {
483
+ fs_1.default.unlinkSync(HEARTBEAT_PATH);
484
+ }
485
+ catch (e) {
486
+ console.error(e.toString());
487
+ }
488
+ process.exit(1);
489
+ });
490
+ initializeDevicePhyos();
491
+ //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,19 +1,12 @@
1
1
  {
2
2
  "name": "@phystack/device-phyos",
3
- "version": "4.5.64-dev",
4
- "main": "index.js",
3
+ "version": "5.0.1",
4
+ "description": "PhyOS device agent",
5
+ "main": "dist/index.js",
6
+ "license": "UNLICENSED",
5
7
  "publishConfig": {
6
8
  "access": "public"
7
9
  },
8
- "scripts": {
9
- "test": "echo \"Error: no test specified\" && exit 1",
10
- "build": "rimraf dist && tsc",
11
- "build:binary": "VERSION=$(node -p \"require('./package.json').version\") && npx bun build --compile --minify --define \"__PKG_VERSION__=\\\"$VERSION\\\"\" ./src/index.ts --outfile phydevice",
12
- "start": "yarn build && node --inspect --enable-source-maps dist/index",
13
- "dev": "NODE_ENV=development npx nodemon",
14
- "format": "prettier --write \"src/**/*.{ts,js,json,md}\"",
15
- "format:check": "prettier --check \"src/**/*.{ts,js,json,md}\""
16
- },
17
10
  "bin": {
18
11
  "phydevice": "./bin/index.js"
19
12
  },
@@ -23,14 +16,18 @@
23
16
  "engines": {
24
17
  "node": ">=20.0.0"
25
18
  },
26
- "author": "PhyStack.com",
27
- "license": "MIT",
28
- "description": "",
29
- "optionalDependencies": {
30
- "@phystack/phydevice-darwin-arm64": "4.5.64-dev",
31
- "@phystack/phydevice-darwin-x64": "4.5.64-dev",
32
- "@phystack/phydevice-linux-arm64": "4.5.64-dev",
33
- "@phystack/phydevice-linux-x64": "4.5.64-dev"
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "build:binary": "VERSION=$(bun -e \"console.log(require('./package.json').version)\") && bun build --compile --minify --external cpu-features --define \"__PKG_VERSION__=\\\"$VERSION\\\"\" ./src/index.ts --outfile phydevice",
22
+ "dev": "bun --watch src/index.ts",
23
+ "lint": "tsc --noEmit",
24
+ "test:ci": "echo 'no tests' && exit 0",
25
+ "format": "prettier --write \"src/**/*.{ts,js,json,md}\""
34
26
  },
35
- "gitHead": "e29cb3adee4f709ac3f5f2b3de62fe7f14a7a7b3"
27
+ "optionalDependencies": {
28
+ "@phystack/phydevice-darwin-arm64": "5.0.1",
29
+ "@phystack/phydevice-darwin-x64": "5.0.1",
30
+ "@phystack/phydevice-linux-arm64": "5.0.1",
31
+ "@phystack/phydevice-linux-x64": "5.0.1"
32
+ }
36
33
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 PhyStack.com
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,71 +0,0 @@
1
- # phydevice
2
-
3
- PhyStack device agent for PhyOS. Compiled as a standalone Bun binary.
4
-
5
- ## Installation
6
-
7
- ### Via npm (recommended)
8
-
9
- ```bash
10
- npm install -g @phystack/device-phyos
11
- ```
12
-
13
- npm automatically downloads the correct binary for your platform.
14
-
15
- ### Direct binary download (no npm required)
16
-
17
- ```bash
18
- VERSION=4.5.62-dev # replace with desired version
19
-
20
- # Linux ARM64
21
- sudo curl -sL "https://registry.npmjs.org/@phystack/phydevice-linux-arm64/-/phydevice-linux-arm64-${VERSION}.tgz" | sudo tar xz --strip-components=2 -C /usr/bin package/bin/phydevice
22
-
23
- # Linux x86_64
24
- sudo curl -sL "https://registry.npmjs.org/@phystack/phydevice-linux-x64/-/phydevice-linux-x64-${VERSION}.tgz" | sudo tar xz --strip-components=2 -C /usr/bin package/bin/phydevice
25
-
26
- # macOS Apple Silicon
27
- curl -sL "https://registry.npmjs.org/@phystack/phydevice-darwin-arm64/-/phydevice-darwin-arm64-${VERSION}.tgz" | tar xz --strip-components=2 -C /usr/local/bin package/bin/phydevice
28
-
29
- # macOS Intel
30
- curl -sL "https://registry.npmjs.org/@phystack/phydevice-darwin-x64/-/phydevice-darwin-x64-${VERSION}.tgz" | tar xz --strip-components=2 -C /usr/local/bin package/bin/phydevice
31
- ```
32
-
33
- To check available versions:
34
-
35
- ```bash
36
- npm view @phystack/phydevice-linux-arm64 versions --json
37
- ```
38
-
39
- ## Supported platforms
40
-
41
- | Platform | Architecture | npm package |
42
- |----------|-------------|-------------|
43
- | Linux | ARM64 | `@phystack/phydevice-linux-arm64` |
44
- | Linux | x86_64 | `@phystack/phydevice-linux-x64` |
45
- | macOS | ARM64 | `@phystack/phydevice-darwin-arm64` |
46
- | macOS | x86_64 | `@phystack/phydevice-darwin-x64` |
47
-
48
- ## Building from source
49
-
50
- ```bash
51
- yarn build:binary # compile for current platform
52
- ```
53
-
54
- Or use the central build script for cross-compilation:
55
-
56
- ```bash
57
- # from repo root
58
- yarn build:binaries # current platform
59
- yarn build:binaries:cross # all platforms
60
- ```
61
-
62
- Output: `dist-binaries/<platform>/phydevice`
63
-
64
- ## Local development
65
-
66
- Ensure the process can write to `/etc/phyos.env`. On macOS:
67
-
68
- ```bash
69
- sudo sh -c 'echo LOCAL > /etc/phyos.env'
70
- sudo chmod 666 /etc/phyos.env
71
- ```