@openmdm/core 0.7.0 → 0.8.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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { WebhookConfig, MDMEvent, WebhookEndpoint, EventType, DatabaseAdapter, TenantManager, AuthorizationManager, AuditConfig, AuditManager, ScheduleManager, MessageQueueManager, DashboardManager, PluginStorageAdapter, MDMConfig, MDMInstance, EnrollmentRequest } from './types.js';
2
- export { AppInstallationSummary, AppRollback, AppVersion, Application, ApplicationManager, ApplicationNotFoundError, AuditAction, AuditLog, AuditLogFilter, AuditLogListResult, AuditSummary, AuthConfig, AuthenticationError, AuthorizationError, Command, CommandFilter, CommandManager, CommandNotFoundError, CommandResult, CommandStatus, CommandSuccessRates, CommandType, CreateAppRollbackInput, CreateApplicationInput, CreateAuditLogInput, CreateDeviceInput, CreateGroupInput, CreatePolicyInput, CreateRoleInput, CreateScheduledTaskInput, CreateTenantInput, CreateUserInput, DashboardStats, DeployTarget, Device, DeviceFilter, DeviceListResult, DeviceLocation, DeviceManager, DeviceNotFoundError, DeviceStatus, DeviceStatusBreakdown, EnqueueMessageInput, EnrollmentConfig, EnrollmentError, EnrollmentMethod, EnrollmentResponse, EnrollmentTrendPoint, EventFilter, EventHandler, EventPayloadMap, Group, GroupHierarchyStats, GroupManager, GroupNotFoundError, GroupTreeNode, HardwareControl, Heartbeat, InstalledApp, MDMError, MDMPlugin, MaintenanceWindow, PasswordPolicy, Permission, PermissionAction, PermissionResource, PluginMiddleware, PluginRoute, PluginStorageEntry, Policy, PolicyApplication, PolicyManager, PolicyNotFoundError, PolicySettings, PushAdapter, PushBatchResult, PushConfig, PushMessage, PushProviderConfig, PushResult, PushToken, QueueMessageStatus, QueueStats, QueuedMessage, RegisterPushTokenInput, Role, RoleNotFoundError, ScheduledTask, ScheduledTaskFilter, ScheduledTaskListResult, ScheduledTaskStatus, SendCommandInput, StorageConfig, SystemUpdatePolicy, TaskExecution, TaskSchedule, TaskType, Tenant, TenantFilter, TenantListResult, TenantNotFoundError, TenantSettings, TenantStats, TenantStatus, TimeWindow, UpdateApplicationInput, UpdateDeviceInput, UpdateGroupInput, UpdatePolicyInput, UpdateRoleInput, UpdateScheduledTaskInput, UpdateTenantInput, UpdateUserInput, User, UserFilter, UserListResult, UserNotFoundError, UserWithRoles, ValidationError, VpnConfig, WebhookDeliveryResult, WebhookManager, WifiConfig } from './types.js';
1
+ import { WebhookConfig, Logger, MDMEvent, WebhookEndpoint, EventType, DatabaseAdapter, TenantManager, AuthorizationManager, AuditConfig, AuditManager, ScheduleManager, MessageQueueManager, DashboardManager, PluginStorageAdapter, MDMConfig, MDMInstance, EnrollmentRequest } from './types.js';
2
+ export { AppInstallationSummary, AppRollback, AppVersion, Application, ApplicationManager, ApplicationNotFoundError, AuditAction, AuditLog, AuditLogFilter, AuditLogListResult, AuditSummary, AuthConfig, AuthenticationError, AuthorizationError, Command, CommandFilter, CommandManager, CommandNotFoundError, CommandResult, CommandStatus, CommandSuccessRates, CommandType, CreateAppRollbackInput, CreateApplicationInput, CreateAuditLogInput, CreateDeviceInput, CreateGroupInput, CreatePolicyInput, CreateRoleInput, CreateScheduledTaskInput, CreateTenantInput, CreateUserInput, DashboardStats, DeployTarget, Device, DeviceFilter, DeviceListResult, DeviceLocation, DeviceManager, DeviceNotFoundError, DeviceStatus, DeviceStatusBreakdown, EnqueueMessageInput, EnrollmentConfig, EnrollmentError, EnrollmentMethod, EnrollmentResponse, EnrollmentTrendPoint, EventFilter, EventHandler, EventPayloadMap, Group, GroupHierarchyStats, GroupManager, GroupNotFoundError, GroupTreeNode, HardwareControl, Heartbeat, InstalledApp, LogContext, MDMError, MDMPlugin, MaintenanceWindow, PasswordPolicy, Permission, PermissionAction, PermissionResource, PluginMiddleware, PluginRoute, PluginStorageEntry, Policy, PolicyApplication, PolicyManager, PolicyNotFoundError, PolicySettings, PushAdapter, PushBatchResult, PushConfig, PushMessage, PushProviderConfig, PushResult, PushToken, QueueMessageStatus, QueueStats, QueuedMessage, RegisterPushTokenInput, Role, RoleNotFoundError, ScheduledTask, ScheduledTaskFilter, ScheduledTaskListResult, ScheduledTaskStatus, SendCommandInput, StorageConfig, SystemUpdatePolicy, TaskExecution, TaskSchedule, TaskType, Tenant, TenantFilter, TenantListResult, TenantNotFoundError, TenantSettings, TenantStats, TenantStatus, TimeWindow, UpdateApplicationInput, UpdateDeviceInput, UpdateGroupInput, UpdatePolicyInput, UpdateRoleInput, UpdateScheduledTaskInput, UpdateTenantInput, UpdateUserInput, User, UserFilter, UserListResult, UserNotFoundError, UserWithRoles, ValidationError, VpnConfig, WebhookDeliveryResult, WebhookManager, WifiConfig } from './types.js';
3
3
  export { ColumnDefinition, ColumnType, IndexDefinition, SchemaDefinition, TableDefinition, camelToSnake, getColumnNames, getPrimaryKey, getTableNames, mdmSchema, snakeToCamel, transformToCamelCase, transformToSnakeCase } from './schema.js';
4
4
 
5
5
  /**
@@ -164,13 +164,37 @@ interface WebhookManager {
164
164
  /**
165
165
  * Create a webhook manager instance
166
166
  */
167
- declare function createWebhookManager(config: WebhookConfig): WebhookManager;
167
+ declare function createWebhookManager(config: WebhookConfig, logger?: Logger): WebhookManager;
168
168
  /**
169
169
  * Verify a webhook signature from incoming requests
170
170
  * (Utility for consumers to verify our webhooks)
171
171
  */
172
172
  declare function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean;
173
173
 
174
+ /**
175
+ * OpenMDM Logger
176
+ *
177
+ * Default logger implementations and helpers. Production users are
178
+ * expected to pass their own pino/winston/bunyan instance via
179
+ * `createMDM({ logger })`; these defaults are for development and
180
+ * for the zero-config path.
181
+ */
182
+
183
+ /**
184
+ * Console-backed logger. Writes JSON-ish lines to stdout/stderr with
185
+ * an `[openmdm]` prefix so they stand out in a mixed-log stream.
186
+ *
187
+ * This is the zero-config default — it intentionally does the
188
+ * minimum viable thing. Hosts running in production should replace
189
+ * it with a real structured logger.
190
+ */
191
+ declare function createConsoleLogger(scope?: string[]): Logger;
192
+ /**
193
+ * No-op logger. Use to silence OpenMDM entirely — e.g. in tests or in
194
+ * environments where log noise is inappropriate.
195
+ */
196
+ declare function createSilentLogger(): Logger;
197
+
174
198
  /**
175
199
  * OpenMDM Tenant Manager
176
200
  *
@@ -303,4 +327,4 @@ declare function parsePluginKey(key: string): {
303
327
  declare function createMDM(config: MDMConfig): MDMInstance;
304
328
  declare function verifyEnrollmentSignature(request: EnrollmentRequest, secret: string): boolean;
305
329
 
306
- export { AGENT_PROTOCOL_HEADER, AGENT_PROTOCOL_V2, type AgentAction, type AgentResponse, AuditConfig, AuditManager, AuthorizationManager, DashboardManager, DatabaseAdapter, EnrollmentRequest, EventType, MDMConfig, MDMEvent, MDMInstance, MessageQueueManager, PluginStorageAdapter, ScheduleManager, TenantManager, WebhookConfig, WebhookEndpoint, type WebhookPayload, agentFail, agentOk, createAuditManager, createAuthorizationManager, createDashboardManager, createMDM, createMemoryPluginStorageAdapter, createMessageQueueManager, createPluginKey, createPluginStorageAdapter, createScheduleManager, createTenantManager, createWebhookManager, parsePluginKey, verifyEnrollmentSignature, verifyWebhookSignature, wantsAgentProtocolV2 };
330
+ export { AGENT_PROTOCOL_HEADER, AGENT_PROTOCOL_V2, type AgentAction, type AgentResponse, AuditConfig, AuditManager, AuthorizationManager, DashboardManager, DatabaseAdapter, EnrollmentRequest, EventType, Logger, MDMConfig, MDMEvent, MDMInstance, MessageQueueManager, PluginStorageAdapter, ScheduleManager, TenantManager, WebhookConfig, WebhookEndpoint, type WebhookPayload, agentFail, agentOk, createAuditManager, createAuthorizationManager, createConsoleLogger, createDashboardManager, createMDM, createMemoryPluginStorageAdapter, createMessageQueueManager, createPluginKey, createPluginStorageAdapter, createScheduleManager, createSilentLogger, createTenantManager, createWebhookManager, parsePluginKey, verifyEnrollmentSignature, verifyWebhookSignature, wantsAgentProtocolV2 };
package/dist/index.js CHANGED
@@ -72,14 +72,69 @@ var ValidationError = class extends MDMError {
72
72
  super(message, "VALIDATION_ERROR", 400, details);
73
73
  }
74
74
  };
75
+
76
+ // src/logger.ts
77
+ function normalize(...args) {
78
+ if (args.length === 1) {
79
+ return { context: void 0, message: args[0] };
80
+ }
81
+ return { context: args[0], message: args[1] };
82
+ }
83
+ function createConsoleLogger(scope = []) {
84
+ const prefix = scope.length > 0 ? `[openmdm:${scope.join(":")}]` : "[openmdm]";
85
+ const render = (context) => {
86
+ if (!context || Object.keys(context).length === 0) return "";
87
+ try {
88
+ return " " + JSON.stringify(context);
89
+ } catch {
90
+ return " " + String(context);
91
+ }
92
+ };
93
+ return {
94
+ debug: (...args) => {
95
+ const { context, message } = normalize(...args);
96
+ if (!process.env.DEBUG) return;
97
+ console.debug(`${prefix} ${message}${render(context)}`);
98
+ },
99
+ info: (...args) => {
100
+ const { context, message } = normalize(...args);
101
+ console.log(`${prefix} ${message}${render(context)}`);
102
+ },
103
+ warn: (...args) => {
104
+ const { context, message } = normalize(...args);
105
+ console.warn(`${prefix} ${message}${render(context)}`);
106
+ },
107
+ error: (...args) => {
108
+ const { context, message } = normalize(...args);
109
+ console.error(`${prefix} ${message}${render(context)}`);
110
+ },
111
+ child: (bindings) => {
112
+ const componentPart = typeof bindings.component === "string" ? [bindings.component] : [];
113
+ return createConsoleLogger([...scope, ...componentPart]);
114
+ }
115
+ };
116
+ }
117
+ function createSilentLogger() {
118
+ const silent = {
119
+ debug: () => void 0,
120
+ info: () => void 0,
121
+ warn: () => void 0,
122
+ error: () => void 0,
123
+ child: () => silent
124
+ };
125
+ return silent;
126
+ }
127
+
128
+ // src/webhooks.ts
75
129
  var DEFAULT_RETRY_CONFIG = {
76
130
  maxRetries: 3,
77
131
  initialDelay: 1e3,
78
132
  maxDelay: 3e4
79
133
  };
80
- function createWebhookManager(config) {
134
+ function createWebhookManager(config, logger = createSilentLogger()) {
81
135
  const endpoints = /* @__PURE__ */ new Map();
82
136
  const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...config.retry };
137
+ const log = logger.child({ component: "webhooks" });
83
138
  if (config.endpoints) {
84
139
  for (const endpoint of config.endpoints) {
85
140
  endpoints.set(endpoint.id, endpoint);
@@ -181,9 +236,14 @@ function createWebhookManager(config) {
181
236
  const results = await Promise.all(deliveryPromises);
182
237
  for (const result of results) {
183
238
  if (!result.success) {
184
- console.error(
185
- `[OpenMDM] Webhook delivery failed to endpoint ${result.endpointId}:`,
186
- result.error
239
+ log.error(
240
+ {
241
+ endpointId: result.endpointId,
242
+ statusCode: result.statusCode,
243
+ retryCount: result.retryCount,
244
+ err: result.error
245
+ },
246
+ "Webhook delivery failed"
187
247
  );
188
248
  }
189
249
  }
@@ -1277,7 +1337,6 @@ function createPluginStorageAdapter(db) {
1277
1337
  const value = await db.getPluginValue(pluginName, key);
1278
1338
  return value;
1279
1339
  }
1280
- console.warn("Plugin storage not supported by database adapter");
1281
1340
  return null;
1282
1341
  },
1283
1342
  async set(pluginName, key, value) {
@@ -1285,20 +1344,17 @@ function createPluginStorageAdapter(db) {
1285
1344
  await db.setPluginValue(pluginName, key, value);
1286
1345
  return;
1287
1346
  }
1288
- console.warn("Plugin storage not supported by database adapter");
1289
1347
  },
1290
1348
  async delete(pluginName, key) {
1291
1349
  if (db.deletePluginValue) {
1292
1350
  await db.deletePluginValue(pluginName, key);
1293
1351
  return;
1294
1352
  }
1295
- console.warn("Plugin storage not supported by database adapter");
1296
1353
  },
1297
1354
  async list(pluginName, prefix) {
1298
1355
  if (db.listPluginKeys) {
1299
1356
  return db.listPluginKeys(pluginName, prefix);
1300
1357
  }
1301
- console.warn("Plugin storage not supported by database adapter");
1302
1358
  return [];
1303
1359
  },
1304
1360
  async clear(pluginName) {
@@ -1306,7 +1362,6 @@ function createPluginStorageAdapter(db) {
1306
1362
  await db.clearPluginData(pluginName);
1307
1363
  return;
1308
1364
  }
1309
- console.warn("Plugin storage not supported by database adapter");
1310
1365
  }
1311
1366
  };
1312
1367
  }
@@ -2042,9 +2097,19 @@ function wantsAgentProtocolV2(headerValue) {
2042
2097
  // src/index.ts
2043
2098
  function createMDM(config) {
2044
2099
  const { database, push, enrollment, webhooks: webhooksConfig, plugins = [] } = config;
2100
+ const logger = config.logger ?? createConsoleLogger();
2101
+ const errorMessage = (err) => {
2102
+ if (err instanceof Error) return err.message;
2103
+ if (typeof err === "string") return err;
2104
+ try {
2105
+ return JSON.stringify(err);
2106
+ } catch {
2107
+ return String(err);
2108
+ }
2109
+ };
2045
2110
  const eventHandlers = /* @__PURE__ */ new Map();
2046
- const pushAdapter = push ? createPushAdapter(push, database) : createStubPushAdapter();
2047
- const webhookManager = webhooksConfig ? createWebhookManager(webhooksConfig) : void 0;
2111
+ const pushAdapter = push ? createPushAdapter(push, database, logger) : createStubPushAdapter(logger);
2112
+ const webhookManager = webhooksConfig ? createWebhookManager(webhooksConfig, logger) : void 0;
2048
2113
  const tenantManager = config.multiTenancy?.enabled ? createTenantManager(database) : void 0;
2049
2114
  const authorizationManager = config.authorization?.enabled ? createAuthorizationManager(database) : void 0;
2050
2115
  const auditManager = config.audit?.enabled ? createAuditManager(database) : void 0;
@@ -2078,11 +2143,14 @@ function createMDM(config) {
2078
2143
  payload: eventRecord.payload
2079
2144
  });
2080
2145
  } catch (error) {
2081
- console.error("[OpenMDM] Failed to persist event:", error);
2146
+ logger.error({ err: errorMessage(error), event }, "Failed to persist event");
2082
2147
  }
2083
2148
  if (webhookManager) {
2084
2149
  webhookManager.deliver(eventRecord).catch((error) => {
2085
- console.error("[OpenMDM] Webhook delivery error:", error);
2150
+ logger.error(
2151
+ { err: errorMessage(error), event },
2152
+ "Webhook delivery error"
2153
+ );
2086
2154
  });
2087
2155
  }
2088
2156
  if (handlers) {
@@ -2090,7 +2158,10 @@ function createMDM(config) {
2090
2158
  try {
2091
2159
  await handler(eventRecord);
2092
2160
  } catch (error) {
2093
- console.error(`[OpenMDM] Event handler error for ${event}:`, error);
2161
+ logger.error(
2162
+ { err: errorMessage(error), event },
2163
+ "Event handler threw"
2164
+ );
2094
2165
  }
2095
2166
  }
2096
2167
  }
@@ -2098,7 +2169,7 @@ function createMDM(config) {
2098
2169
  try {
2099
2170
  await config.onEvent(eventRecord);
2100
2171
  } catch (error) {
2101
- console.error("[OpenMDM] onEvent hook error:", error);
2172
+ logger.error({ err: errorMessage(error) }, "onEvent hook threw");
2102
2173
  }
2103
2174
  }
2104
2175
  };
@@ -2775,6 +2846,7 @@ function createMDM(config) {
2775
2846
  push: pushAdapter,
2776
2847
  webhooks: webhookManager,
2777
2848
  db: database,
2849
+ logger,
2778
2850
  config,
2779
2851
  on,
2780
2852
  emit,
@@ -2797,11 +2869,11 @@ function createMDM(config) {
2797
2869
  if (plugin.onInit) {
2798
2870
  try {
2799
2871
  await plugin.onInit(instance);
2800
- console.log(`[OpenMDM] Plugin initialized: ${plugin.name}`);
2872
+ logger.info({ plugin: plugin.name }, "Plugin initialized");
2801
2873
  } catch (error) {
2802
- console.error(
2803
- `[OpenMDM] Failed to initialize plugin ${plugin.name}:`,
2804
- error
2874
+ logger.error(
2875
+ { plugin: plugin.name, err: errorMessage(error) },
2876
+ "Failed to initialize plugin"
2805
2877
  );
2806
2878
  }
2807
2879
  }
@@ -2809,21 +2881,23 @@ function createMDM(config) {
2809
2881
  })();
2810
2882
  return instance;
2811
2883
  }
2812
- function createPushAdapter(config, database) {
2884
+ function createPushAdapter(config, database, logger) {
2813
2885
  if (!config) {
2814
- return createStubPushAdapter();
2886
+ return createStubPushAdapter(logger);
2815
2887
  }
2888
+ const pushLogger = logger.child({ component: "push" });
2816
2889
  return {
2817
2890
  async send(deviceId, message) {
2818
- console.log(
2819
- `[OpenMDM] Push to ${deviceId}: ${message.type}`,
2820
- message.payload
2891
+ pushLogger.debug(
2892
+ { deviceId, type: message.type, payload: message.payload },
2893
+ "send"
2821
2894
  );
2822
2895
  return { success: true, messageId: randomUUID() };
2823
2896
  },
2824
2897
  async sendBatch(deviceIds, message) {
2825
- console.log(
2826
- `[OpenMDM] Push to ${deviceIds.length} devices: ${message.type}`
2898
+ pushLogger.debug(
2899
+ { count: deviceIds.length, type: message.type },
2900
+ "sendBatch"
2827
2901
  );
2828
2902
  const results = deviceIds.map((deviceId) => ({
2829
2903
  deviceId,
@@ -2853,15 +2927,17 @@ function createPushAdapter(config, database) {
2853
2927
  }
2854
2928
  };
2855
2929
  }
2856
- function createStubPushAdapter() {
2930
+ function createStubPushAdapter(logger) {
2931
+ const stubLogger = logger.child({ component: "push-stub" });
2857
2932
  return {
2858
2933
  async send(deviceId, message) {
2859
- console.log(`[OpenMDM] Push (stub): ${deviceId} <- ${message.type}`);
2934
+ stubLogger.debug({ deviceId, type: message.type }, "send (stub)");
2860
2935
  return { success: true, messageId: "stub" };
2861
2936
  },
2862
2937
  async sendBatch(deviceIds, message) {
2863
- console.log(
2864
- `[OpenMDM] Push (stub): ${deviceIds.length} devices <- ${message.type}`
2938
+ stubLogger.debug(
2939
+ { count: deviceIds.length, type: message.type },
2940
+ "sendBatch (stub)"
2865
2941
  );
2866
2942
  return {
2867
2943
  successCount: deviceIds.length,
@@ -2917,6 +2993,6 @@ function generateDeviceToken(deviceId, secret, expirationSeconds) {
2917
2993
  return `${header}.${payload}.${signature}`;
2918
2994
  }
2919
2995
 
2920
- export { AGENT_PROTOCOL_HEADER, AGENT_PROTOCOL_V2, ApplicationNotFoundError, AuthenticationError, AuthorizationError, CommandNotFoundError, DeviceNotFoundError, EnrollmentError, GroupNotFoundError, MDMError, PolicyNotFoundError, RoleNotFoundError, TenantNotFoundError, UserNotFoundError, ValidationError, agentFail, agentOk, camelToSnake, createAuditManager, createAuthorizationManager, createDashboardManager, createMDM, createMemoryPluginStorageAdapter, createMessageQueueManager, createPluginKey, createPluginStorageAdapter, createScheduleManager, createTenantManager, createWebhookManager, getColumnNames, getPrimaryKey, getTableNames, mdmSchema, parsePluginKey, snakeToCamel, transformToCamelCase, transformToSnakeCase, verifyEnrollmentSignature, verifyWebhookSignature, wantsAgentProtocolV2 };
2996
+ export { AGENT_PROTOCOL_HEADER, AGENT_PROTOCOL_V2, ApplicationNotFoundError, AuthenticationError, AuthorizationError, CommandNotFoundError, DeviceNotFoundError, EnrollmentError, GroupNotFoundError, MDMError, PolicyNotFoundError, RoleNotFoundError, TenantNotFoundError, UserNotFoundError, ValidationError, agentFail, agentOk, camelToSnake, createAuditManager, createAuthorizationManager, createConsoleLogger, createDashboardManager, createMDM, createMemoryPluginStorageAdapter, createMessageQueueManager, createPluginKey, createPluginStorageAdapter, createScheduleManager, createSilentLogger, createTenantManager, createWebhookManager, getColumnNames, getPrimaryKey, getTableNames, mdmSchema, parsePluginKey, snakeToCamel, transformToCamelCase, transformToSnakeCase, verifyEnrollmentSignature, verifyWebhookSignature, wantsAgentProtocolV2 };
2921
2997
  //# sourceMappingURL=index.js.map
2922
2998
  //# sourceMappingURL=index.js.map