myio-js-library 0.1.489 → 0.1.490

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.cjs CHANGED
@@ -711,6 +711,7 @@ __export(index_exports, {
711
711
  MenuShoppingView: () => MenuShoppingView,
712
712
  MenuView: () => MenuView,
713
713
  ModalHeader: () => ModalHeader,
714
+ MyIOAuthContext: () => MyIOAuthContext,
714
715
  MyIOChartModal: () => MyIOChartModal,
715
716
  MyIODraggableCard: () => MyIODraggableCard,
716
717
  MyIOSelectionStore: () => MyIOSelectionStore,
@@ -739,6 +740,7 @@ __export(index_exports, {
739
740
  OperationalGeneralListController: () => OperationalGeneralListController,
740
741
  OperationalGeneralListView: () => OperationalGeneralListView,
741
742
  OperationalHeaderDevicesGridView: () => OperationalHeaderDevicesGridView,
743
+ PERM: () => PERM,
742
744
  POWER_LIMITS_DEVICE_TYPES: () => DEVICE_TYPES,
743
745
  POWER_LIMITS_STATUS_CONFIG: () => STATUS_CONFIG,
744
746
  POWER_LIMITS_TELEMETRY_TYPES: () => TELEMETRY_TYPES2,
@@ -1007,6 +1009,7 @@ __export(index_exports, {
1007
1009
  groupByDay: () => groupByDay,
1008
1010
  handleDeviceType: () => handleDeviceType,
1009
1011
  hasSelectedDays: () => hasSelectedDays,
1012
+ initMyIOAuthContext: () => initMyIOAuthContext,
1010
1013
  initOnOffTimelineTooltips: () => initOnOffTimelineTooltips,
1011
1014
  injectActionButtonStyles: () => injectActionButtonStyles,
1012
1015
  injectAlarmsNotificationsPanelStyles: () => injectAlarmsNotificationsPanelStyles,
@@ -1159,7 +1162,7 @@ module.exports = __toCommonJS(index_exports);
1159
1162
  // package.json
1160
1163
  var package_default = {
1161
1164
  name: "myio-js-library",
1162
- version: "0.1.489",
1165
+ version: "0.1.490",
1163
1166
  description: "A clean, standalone JS SDK for MYIO projects",
1164
1167
  license: "MIT",
1165
1168
  repository: "github:gh-myio/myio-js-library",
@@ -58602,15 +58605,24 @@ var AlarmsTab = class {
58602
58605
  * Falls back to prefetchedAlarms prop when ASO is not available (e.g. standalone showcase).
58603
58606
  */
58604
58607
  readAlarmsFromASO() {
58605
- const aso = window.AlarmServiceOrchestrator;
58608
+ const win = window;
58609
+ const aso = win.AlarmServiceOrchestrator;
58610
+ const showOffline = win.MyIOOrchestrator?.showOfflineAlarms === true;
58611
+ const _OFFLINE_TYPES = ["DEVICE OFFLINE", "DISPOSITIVO OFFLINE"];
58612
+ const _isOffline = (a) => {
58613
+ const t = ((a.title ?? a.alarmType) || "").toUpperCase();
58614
+ return _OFFLINE_TYPES.some((ex) => t.startsWith(ex)) || a.alarmType === "connectivity";
58615
+ };
58616
+ let alarms = [];
58606
58617
  if (aso && this.config.gcdrDeviceId) {
58607
- return aso.getAlarmsForDevice(this.config.gcdrDeviceId);
58608
- }
58609
- const prefetched = this.config.prefetchedAlarms;
58610
- if (prefetched != null) {
58611
- return prefetched.filter((a) => a.deviceId === this.config.gcdrDeviceId);
58618
+ alarms = aso.getAlarmsForDevice(this.config.gcdrDeviceId);
58619
+ } else {
58620
+ const prefetched = this.config.prefetchedAlarms;
58621
+ if (prefetched != null) {
58622
+ alarms = prefetched.filter((a) => a.deviceId === this.config.gcdrDeviceId);
58623
+ }
58612
58624
  }
58613
- return [];
58625
+ return showOffline ? alarms : alarms.filter((a) => !_isOffline(a));
58614
58626
  }
58615
58627
  // ============================================================================
58616
58628
  // Card mapping — separado (Disp. + Tipo) view: one card per individual alarm
@@ -92182,6 +92194,272 @@ function openUserManagementModal(params) {
92182
92194
  controller.show();
92183
92195
  }
92184
92196
 
92197
+ // src/components/gcdr-auth/MyIOAuthContext.ts
92198
+ var MyIOAuthContext = class _MyIOAuthContext {
92199
+ allowedActions = /* @__PURE__ */ new Set();
92200
+ deniedActions = /* @__PURE__ */ new Set();
92201
+ snap;
92202
+ constructor(snap) {
92203
+ this.snap = snap;
92204
+ }
92205
+ // ── Public read-only state ────────────────────────────────────────────────
92206
+ get ready() {
92207
+ return this.snap.ready;
92208
+ }
92209
+ get gcdrUserId() {
92210
+ return this.snap.gcdrUserId;
92211
+ }
92212
+ get scope() {
92213
+ return this.snap.scope;
92214
+ }
92215
+ get error() {
92216
+ return this.snap.error;
92217
+ }
92218
+ get allowAll() {
92219
+ return this.snap.allowAll;
92220
+ }
92221
+ get assignments() {
92222
+ return this.snap.assignments;
92223
+ }
92224
+ // ── Permission checks ─────────────────────────────────────────────────────
92225
+ /**
92226
+ * Returns `true` if the current user is allowed to perform `action`.
92227
+ *
92228
+ * Evaluation order (deny-first):
92229
+ * 1. If allowAll (TENANT_ADMIN) → always true
92230
+ * 2. If action (or `*`) is in the deny set → false
92231
+ * 3. If action (or `*`) is in the allow set → true
92232
+ * 4. Otherwise → false (closed-by-default)
92233
+ *
92234
+ * Returns `false` while not yet ready.
92235
+ */
92236
+ can(action) {
92237
+ if (!this.snap.ready) return false;
92238
+ if (this.snap.allowAll) return true;
92239
+ if (this.deniedActions.has("*") || this.deniedActions.has(action)) return false;
92240
+ return this.allowedActions.has("*") || this.allowedActions.has(action);
92241
+ }
92242
+ /** True if the user can perform **at least one** of the given actions. */
92243
+ canAny(...actions) {
92244
+ return actions.some((a) => this.can(a));
92245
+ }
92246
+ /** True if the user can perform **all** of the given actions. */
92247
+ canAll(...actions) {
92248
+ return actions.every((a) => this.can(a));
92249
+ }
92250
+ // ── Factory ───────────────────────────────────────────────────────────────
92251
+ /**
92252
+ * Initialises the auth context.
92253
+ * Resolves immediately when `allowAll` is set or GCDR is not configured.
92254
+ * Always dispatches `myio:auth-ready` when done (success or error).
92255
+ */
92256
+ static async init(config) {
92257
+ const scope = config.scope ?? (config.customerId ? `customer:${config.customerId}` : "*");
92258
+ const ctx = new _MyIOAuthContext({
92259
+ ready: false,
92260
+ gcdrUserId: null,
92261
+ scope,
92262
+ allowAll: config.allowAll ?? false,
92263
+ error: null,
92264
+ assignments: []
92265
+ });
92266
+ if (config.allowAll) {
92267
+ ctx.snap.ready = true;
92268
+ ctx._dispatch();
92269
+ return ctx;
92270
+ }
92271
+ if (!config.gcdrApiBaseUrl) {
92272
+ ctx.snap.ready = true;
92273
+ ctx.snap.error = "GCDR not configured";
92274
+ ctx._dispatch();
92275
+ return ctx;
92276
+ }
92277
+ try {
92278
+ const hdrs = ctx._gcdrHeaders(config);
92279
+ const gcdrUserId = await ctx._resolveGcdrUserId(config, hdrs);
92280
+ if (!gcdrUserId) {
92281
+ ctx.snap.error = "GCDR user not found";
92282
+ ctx.snap.ready = true;
92283
+ ctx._dispatch();
92284
+ return ctx;
92285
+ }
92286
+ ctx.snap.gcdrUserId = gcdrUserId;
92287
+ const assignRes = await fetch(
92288
+ `${config.gcdrApiBaseUrl}/authorization/users/${gcdrUserId}/assignments`,
92289
+ { headers: hdrs }
92290
+ );
92291
+ let allAssignments = [];
92292
+ if (assignRes.ok) {
92293
+ const json = await assignRes.json();
92294
+ allAssignments = Array.isArray(json) ? json : json.assignments ?? [];
92295
+ }
92296
+ const relevant = allAssignments.filter(
92297
+ (a) => a.status === "active" && (a.scope === "*" || a.scope === scope)
92298
+ );
92299
+ ctx.snap.assignments = relevant;
92300
+ if (relevant.length === 0) {
92301
+ ctx.snap.ready = true;
92302
+ ctx._dispatch();
92303
+ return ctx;
92304
+ }
92305
+ const roleKeys = [...new Set(relevant.map((a) => a.roleKey))];
92306
+ const roles = await ctx._fetchRoles(config.gcdrApiBaseUrl, roleKeys, hdrs);
92307
+ const policyKeys = [...new Set(
92308
+ roles.flatMap((r) => [...r.policies ?? [], ...r.policyIds ?? []])
92309
+ )];
92310
+ if (policyKeys.length > 0) {
92311
+ const policies = await ctx._fetchPolicies(config.gcdrApiBaseUrl, policyKeys, hdrs);
92312
+ ctx._applyPolicies(policies);
92313
+ }
92314
+ } catch (err) {
92315
+ ctx.snap.error = err?.message ?? "Auth init failed";
92316
+ }
92317
+ ctx.snap.ready = true;
92318
+ ctx._dispatch();
92319
+ return ctx;
92320
+ }
92321
+ // ── Private helpers ───────────────────────────────────────────────────────
92322
+ _gcdrHeaders(config) {
92323
+ return {
92324
+ "Content-Type": "application/json",
92325
+ "X-API-Key": config.gcdrApiKey || "",
92326
+ "X-Tenant-ID": config.gcdrTenantId || ""
92327
+ };
92328
+ }
92329
+ /**
92330
+ * Two-step GCDR user lookup:
92331
+ * 1. Read `gcdrUserConfigs` from TB SERVER_SCOPE attribute (fast path if previously synced)
92332
+ * 2. Email search via GCDR API
92333
+ */
92334
+ async _resolveGcdrUserId(config, gcdrHeaders) {
92335
+ if (config.currentUserTbId && config.tbBaseUrl && config.jwtToken) {
92336
+ try {
92337
+ const res = await fetch(
92338
+ `${config.tbBaseUrl}/api/plugins/telemetry/USER/${config.currentUserTbId}/values/attributes/SERVER_SCOPE?keys=gcdrUserConfigs`,
92339
+ { headers: { "X-Authorization": `Bearer ${config.jwtToken}` } }
92340
+ );
92341
+ if (res.ok) {
92342
+ const attrs = await res.json();
92343
+ const gcdrId = attrs.find((a) => a.key === "gcdrUserConfigs")?.value?.gcdrUserId;
92344
+ if (gcdrId) return gcdrId;
92345
+ }
92346
+ } catch {
92347
+ }
92348
+ }
92349
+ if (!config.currentUserEmail) return null;
92350
+ try {
92351
+ const q = encodeURIComponent(config.currentUserEmail);
92352
+ const cid = config.customerId ? `&customerId=${encodeURIComponent(config.customerId)}` : "";
92353
+ const res = await fetch(
92354
+ `${config.gcdrApiBaseUrl}/api/v1/users?search=${q}${cid}&limit=10`,
92355
+ { headers: gcdrHeaders }
92356
+ );
92357
+ if (res.ok) {
92358
+ const data = await res.json();
92359
+ const items = Array.isArray(data) ? data : data?.data?.items ?? data?.items ?? [];
92360
+ const found = items.find(
92361
+ (u) => u.email?.toLowerCase() === config.currentUserEmail.toLowerCase()
92362
+ );
92363
+ if (found) return found.id;
92364
+ }
92365
+ } catch {
92366
+ }
92367
+ return null;
92368
+ }
92369
+ /**
92370
+ * Fetches roles — tries GET /roles bulk endpoint first, falls back to per-key.
92371
+ */
92372
+ async _fetchRoles(base, roleKeys, headers) {
92373
+ try {
92374
+ const res = await fetch(`${base}/roles`, { headers });
92375
+ if (res.ok) {
92376
+ const json = await res.json();
92377
+ const all = Array.isArray(json) ? json : json?.data?.items ?? json?.items ?? json?.data ?? [];
92378
+ return all.filter((r) => roleKeys.includes(r.key ?? r.id));
92379
+ }
92380
+ } catch {
92381
+ }
92382
+ const settled = await Promise.allSettled(
92383
+ roleKeys.map(
92384
+ (key) => fetch(`${base}/roles/${key}`, { headers }).then((r) => r.ok ? r.json() : null)
92385
+ )
92386
+ );
92387
+ return settled.filter((r) => r.status === "fulfilled" && r.value != null).map((r) => r.value);
92388
+ }
92389
+ /**
92390
+ * Fetches policies — tries GET /policies bulk endpoint first, falls back to per-key.
92391
+ */
92392
+ async _fetchPolicies(base, policyKeys, headers) {
92393
+ try {
92394
+ const res = await fetch(`${base}/policies`, { headers });
92395
+ if (res.ok) {
92396
+ const json = await res.json();
92397
+ const all = Array.isArray(json) ? json : json?.data?.items ?? json?.items ?? json?.data ?? [];
92398
+ return all.filter((p) => policyKeys.includes(p.key ?? p.id));
92399
+ }
92400
+ } catch {
92401
+ }
92402
+ const settled = await Promise.allSettled(
92403
+ policyKeys.map(
92404
+ (key) => fetch(`${base}/policies/${key}`, { headers }).then((r) => r.ok ? r.json() : null)
92405
+ )
92406
+ );
92407
+ return settled.filter((r) => r.status === "fulfilled" && r.value != null).map((r) => r.value);
92408
+ }
92409
+ /**
92410
+ * Merges all policy allow/deny lists into the context's permission sets.
92411
+ * Deny always wins over allow (deny-first strategy).
92412
+ */
92413
+ _applyPolicies(policies) {
92414
+ for (const policy of policies) {
92415
+ for (const action of policy.allow ?? []) this.allowedActions.add(action);
92416
+ for (const action of policy.deny ?? []) this.deniedActions.add(action);
92417
+ }
92418
+ }
92419
+ /** Dispatches `myio:auth-ready` so widgets can react without polling. */
92420
+ _dispatch() {
92421
+ window.dispatchEvent(
92422
+ new CustomEvent("myio:auth-ready", {
92423
+ detail: {
92424
+ ready: this.snap.ready,
92425
+ scope: this.snap.scope,
92426
+ allowAll: this.snap.allowAll,
92427
+ error: this.snap.error
92428
+ }
92429
+ })
92430
+ );
92431
+ }
92432
+ };
92433
+ async function initMyIOAuthContext(config) {
92434
+ return MyIOAuthContext.init(config);
92435
+ }
92436
+
92437
+ // src/components/gcdr-auth/permissions.ts
92438
+ var PERM = {
92439
+ // ── Alarm actions ────────────────────────────────────────────────────────
92440
+ ALARM_VIEW: "alarm:view",
92441
+ ALARM_ACK: "alarm:ack",
92442
+ ALARM_ESCALATE: "alarm:escalate",
92443
+ ALARM_SNOOZE: "alarm:snooze",
92444
+ ALARM_CLOSE: "alarm:close",
92445
+ // ── Reports ──────────────────────────────────────────────────────────────
92446
+ REPORT_VIEW: "report:view",
92447
+ REPORT_EXPORT: "report:export",
92448
+ // ── Settings modal ───────────────────────────────────────────────────────
92449
+ SETTINGS_VIEW: "settings:view",
92450
+ SETTINGS_EDIT: "settings:edit",
92451
+ // ── User management (GCDR) ───────────────────────────────────────────────
92452
+ USER_VIEW: "user:view",
92453
+ USER_MANAGE: "user:manage",
92454
+ // ── Integration config ───────────────────────────────────────────────────
92455
+ INTEGRATION_VIEW: "integration:view",
92456
+ INTEGRATION_EDIT: "integration:edit",
92457
+ // ── Dashboard config ─────────────────────────────────────────────────────
92458
+ DASHBOARD_CONFIG: "dashboard:configure",
92459
+ // ── Shopping / customer selector ─────────────────────────────────────────
92460
+ SHOPPING_SELECT: "shopping:select"
92461
+ };
92462
+
92185
92463
  // src/components/menu/types.ts
92186
92464
  var DEFAULT_LIGHT_THEME3 = {
92187
92465
  // Tabs
@@ -139604,6 +139882,7 @@ var version = package_default.version || "0.0.0";
139604
139882
  MenuShoppingView,
139605
139883
  MenuView,
139606
139884
  ModalHeader,
139885
+ MyIOAuthContext,
139607
139886
  MyIOChartModal,
139608
139887
  MyIODraggableCard,
139609
139888
  MyIOSelectionStore,
@@ -139632,6 +139911,7 @@ var version = package_default.version || "0.0.0";
139632
139911
  OperationalGeneralListController,
139633
139912
  OperationalGeneralListView,
139634
139913
  OperationalHeaderDevicesGridView,
139914
+ PERM,
139635
139915
  POWER_LIMITS_DEVICE_TYPES,
139636
139916
  POWER_LIMITS_STATUS_CONFIG,
139637
139917
  POWER_LIMITS_TELEMETRY_TYPES,
@@ -139900,6 +140180,7 @@ var version = package_default.version || "0.0.0";
139900
140180
  groupByDay,
139901
140181
  handleDeviceType,
139902
140182
  hasSelectedDays,
140183
+ initMyIOAuthContext,
139903
140184
  initOnOffTimelineTooltips,
139904
140185
  injectActionButtonStyles,
139905
140186
  injectAlarmsNotificationsPanelStyles,