@camstack/addon-import-alexa 0.2.150 → 0.2.152

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/_stub.js CHANGED
@@ -10,7 +10,7 @@ import "./trash-2-DCHugLVt.mjs";
10
10
  import { t as Fe } from "./_virtual_mf___mfe_internal__addon_import_alexa_page__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.js-B3qxfxBT.mjs";
11
11
  import "./_virtual_mf___mfe_internal__addon_import_alexa_page__loadShare__react_mf_2_dom__loadShare__.js-CIPmAyPi.mjs";
12
12
  import "./_virtual_mf___mfe_internal__addon_import_alexa_page__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-Bct5qZia.mjs";
13
- import "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_import_alexa_page__remoteEntry_js-DMdgQOgz.mjs";
13
+ import "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_import_alexa_page__remoteEntry_js-BHSk6VHO.mjs";
14
14
  import "./_virtual_mf___mfe_internal__addon_import_alexa_page__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-tXm1x5EZ.mjs";
15
15
  import "./_virtual_mf___mfe_internal__addon_import_alexa_page__loadShare___mf_0_trpc_mf_1_client__loadShare__.js-BHqOw8oh.mjs";
16
16
  import "./_virtual_mf___mfe_internal__addon_import_alexa_page__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.js-BmoaT3cr.mjs";
@@ -1,4 +1,4 @@
1
- import "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_import_alexa_page__remoteEntry_js-DMdgQOgz.mjs";
1
+ import "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_import_alexa_page__remoteEntry_js-BHSk6VHO.mjs";
2
2
  //#region \0virtual:mf-localSharedImportMap:__mfe_internal__addon_import_alexa_page
3
3
  var e = {
4
4
  "@camstack/sdk": {
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.424",
21
+ version: "1.2.425",
22
22
  scope: ["default"],
23
23
  loaded: !1,
24
24
  from: "addon_import_alexa_page",
package/dist/addon.js CHANGED
@@ -17611,7 +17611,22 @@ var BrokerProviderInfoSchema = object({
17611
17611
  */
17612
17612
  interactiveConnectPath: string().min(1).optional(),
17613
17613
  /** Relative hub path to disconnect the linked account (same popup pattern). */
17614
- interactiveDisconnectPath: string().min(1).optional()
17614
+ interactiveDisconnectPath: string().min(1).optional(),
17615
+ /**
17616
+ * The kind signs in through a server-held interactive session instead of
17617
+ * (or before) typed credentials. `basePath` is a hub-relative route set
17618
+ * served by the owning addon (`/addon/<id>/...`) speaking the sign-in
17619
+ * contract: `POST {basePath}/start` (body: the form's settings) answers
17620
+ * `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
17621
+ * `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
17622
+ * 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
17623
+ * (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
17624
+ * existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
17625
+ * (`{ sessionId }`) drops the session. The dialog that edits a broker
17626
+ * offers it as the default path; the fields the session fills are
17627
+ * marked `filledBySignIn` in the kind's settings schema.
17628
+ */
17629
+ signIn: object({ basePath: string().min(1) }).optional()
17615
17630
  }))
17616
17631
  });
17617
17632
  var ListInputSchema = object({
@@ -90090,37 +90105,78 @@ function toRecord(value) {
90090
90105
  function settingsToAlexaConnection(settings) {
90091
90106
  return alexaConnectionSchema.parse(toRecord(settings));
90092
90107
  }
90108
+ /**
90109
+ * Allowlist of real Amazon regional domains that alexa-remote2 is known to
90110
+ * support. An enum (not a free-form string) keeps the value from ever naming an
90111
+ * arbitrary host: alexa-remote2 uses it as a raw domain suffix.
90112
+ */
90113
+ var AMAZON_DOMAINS = [
90114
+ "amazon.com",
90115
+ "amazon.it",
90116
+ "amazon.de",
90117
+ "amazon.co.uk",
90118
+ "amazon.fr",
90119
+ "amazon.es",
90120
+ "amazon.ca",
90121
+ "amazon.com.au",
90122
+ "amazon.co.jp",
90123
+ "amazon.in",
90124
+ "amazon.com.br",
90125
+ "amazon.com.mx"
90126
+ ];
90127
+ /** The country each domain serves; the first match for a country prefills the form. */
90128
+ var AMAZON_DOMAIN_BY_COUNTRY = {
90129
+ US: "amazon.com",
90130
+ IT: "amazon.it",
90131
+ DE: "amazon.de",
90132
+ AT: "amazon.de",
90133
+ GB: "amazon.co.uk",
90134
+ FR: "amazon.fr",
90135
+ ES: "amazon.es",
90136
+ CA: "amazon.ca",
90137
+ AU: "amazon.com.au",
90138
+ JP: "amazon.co.jp",
90139
+ IN: "amazon.in",
90140
+ BR: "amazon.com.br",
90141
+ MX: "amazon.com.mx"
90142
+ };
90093
90143
  /** Hand-written connection form for the broker/integration creation UI. */
90094
90144
  function buildConnectionFormSchema() {
90095
90145
  return { sections: [{
90096
90146
  id: "alexa-account",
90097
90147
  title: "Amazon Alexa account",
90098
90148
  titleKey: "import-alexa:connection.s_alexa-account.title",
90099
- description: "Link an Amazon account via the unofficial Alexa client. Supply a captured cookie OR a refresh token. NOTE: this is an unofficial integration — Amazon can change or break it without notice, and it may violate Amazon ToS. State is polled, not pushed.",
90149
+ description: "Sign in with your Amazon account to link it. This is an unofficial integration: Amazon can change or break it without notice, and it may violate Amazon ToS. State is polled, not pushed.",
90100
90150
  descriptionKey: "import-alexa:connection.s_alexa-account.description",
90101
90151
  columns: 1,
90102
90152
  fields: [
90103
90153
  {
90104
- type: "text",
90154
+ type: "select",
90105
90155
  key: "amazonDomain",
90106
90156
  label: "Amazon domain (region)",
90107
90157
  labelKey: "import-alexa:connection.s_alexa-account.amazonDomain.label",
90108
- placeholder: "amazon.com",
90109
- default: "amazon.com"
90158
+ options: AMAZON_DOMAINS.map((value) => ({
90159
+ value,
90160
+ label: value
90161
+ })),
90162
+ default: "amazon.com",
90163
+ defaultByCountry: AMAZON_DOMAIN_BY_COUNTRY
90110
90164
  },
90111
90165
  {
90112
90166
  type: "password",
90113
90167
  key: "cookie",
90114
- label: "Cookie blob (from proxy login)",
90168
+ label: "Cookie blob (filled by the sign-in)",
90115
90169
  labelKey: "import-alexa:connection.s_alexa-account.cookie.label",
90116
- showToggle: true
90170
+ showToggle: true,
90171
+ filledBySignIn: true
90117
90172
  },
90118
90173
  {
90119
90174
  type: "password",
90120
90175
  key: "refreshToken",
90121
- label: "Refresh token (alternative to cookie)",
90176
+ label: "Refresh token (alternative to the sign-in)",
90122
90177
  labelKey: "import-alexa:connection.s_alexa-account.refreshToken.label",
90123
- showToggle: true
90178
+ showToggle: true,
90179
+ filledBySignIn: true
90124
90180
  },
90125
90181
  {
90126
90182
  type: "number",
@@ -131611,20 +131667,25 @@ function capturedToCookieString(captured) {
131611
131667
  }
131612
131668
  //#endregion
131613
131669
  //#region src/alexa-login-routes.ts
131614
- var StartBodySchema = object({ amazonDomain: _enum([
131615
- "amazon.com",
131616
- "amazon.it",
131617
- "amazon.de",
131618
- "amazon.co.uk",
131619
- "amazon.fr",
131620
- "amazon.es",
131621
- "amazon.ca",
131622
- "amazon.com.au",
131623
- "amazon.co.jp",
131624
- "amazon.in",
131625
- "amazon.com.br",
131626
- "amazon.com.mx"
131627
- ]).default("amazon.com") });
131670
+ /**
131671
+ * `addon-routes` control plane that drives the INTERACTIVE Amazon login from the
131672
+ * broker dialog (the kind's `signIn` contract). All routes are `admin` — they start a proxy server and
131673
+ * mutate broker credentials, so they require an admin session/scoped token (the
131674
+ * hub enforces this BEFORE the handler runs; see `main.ts` `/addon/:addonId/*`).
131675
+ *
131676
+ * Public URLs (hub reachable as `https://<hub>`):
131677
+ * POST /addon/import-alexa/login/start { amazonDomain } → { sessionId, loginUrl }
131678
+ * GET /addon/import-alexa/login/status?sessionId=… → AlexaProxyLoginStatus (no secrets)
131679
+ * POST /addon/import-alexa/login/commit { sessionId, name, brokerId? } → { brokerId }
131680
+ * POST /addon/import-alexa/login/cancel { sessionId } → { ok: true }
131681
+ *
131682
+ * The wizard flow: POST /login/start → render a "Login to Amazon" button linking
131683
+ * to `loginUrl` (opened in a new tab) → poll /login/status until
131684
+ * `phase === 'captured'` → POST /login/commit to persist the cookie onto a new
131685
+ * or existing broker → proceed to device discovery/adoption.
131686
+ */
131687
+ /** The broker dialog posts the whole form; only the region matters here (other keys are ignored). */
131688
+ var StartBodySchema = object({ amazonDomain: _enum(AMAZON_DOMAINS).default("amazon.com") });
131628
131689
  var StatusQuerySchema = object({ sessionId: string().min(1) });
131629
131690
  var CommitBodySchema = object({
131630
131691
  sessionId: string().min(1),
@@ -132728,7 +132789,8 @@ function buildAlexaBrokerProvider(deps) {
132728
132789
  addonId: ownerAddonId,
132729
132790
  kinds: [{
132730
132791
  kind: ALEXA_KIND,
132731
- label: "Alexa Import"
132792
+ label: "Alexa Import",
132793
+ signIn: { basePath: "/addon/import-alexa/login" }
132732
132794
  }]
132733
132795
  }],
132734
132796
  add: async ({ kind, name, settings }) => {
@@ -133515,6 +133577,11 @@ var alexaSpeakSessionsEntryKind = defineEntryKind("speak-sessions", {
133515
133577
  schema: entryBody({ session: string().default("").meta({ secret: true }) }),
133516
133578
  writeTrigger: "an Echo worker signs in as an Alexa account broker"
133517
133579
  });
133580
+ /** Every kind this addon declares, keyed by its name: `records.declare` refuses any other key. */
133581
+ var alexaRecordKinds = {
133582
+ brokers: alexaBrokersEntryKind,
133583
+ "speak-sessions": alexaSpeakSessionsEntryKind
133584
+ };
133518
133585
  //#endregion
133519
133586
  //#region src/alexa-broker-store.ts
133520
133587
  function rowToEntry(id, data) {
@@ -135242,10 +135309,7 @@ var AlexaImportAddon = class extends BaseDeviceProvider {
135242
135309
  const regs = this.providerRegistrationsFromSuper(await super.onInitialize());
135243
135310
  const records = this.ctx.records;
135244
135311
  if (records === void 0) throw new Error("import-alexa: ctx.records is required (hub-only addon)");
135245
- await records.declare({
135246
- brokers: alexaBrokersEntryKind,
135247
- speakSessions: alexaSpeakSessionsEntryKind
135248
- });
135312
+ await records.declare(alexaRecordKinds);
135249
135313
  this.brokerStore = AlexaBrokerStore.of(records);
135250
135314
  this.activeBrokers = await this.loadPersistedBrokers();
135251
135315
  this.registry = new AlexaBrokerRegistry(this.ctx.logger, {
package/dist/addon.mjs CHANGED
@@ -17610,7 +17610,22 @@ var BrokerProviderInfoSchema = object({
17610
17610
  */
17611
17611
  interactiveConnectPath: string().min(1).optional(),
17612
17612
  /** Relative hub path to disconnect the linked account (same popup pattern). */
17613
- interactiveDisconnectPath: string().min(1).optional()
17613
+ interactiveDisconnectPath: string().min(1).optional(),
17614
+ /**
17615
+ * The kind signs in through a server-held interactive session instead of
17616
+ * (or before) typed credentials. `basePath` is a hub-relative route set
17617
+ * served by the owning addon (`/addon/<id>/...`) speaking the sign-in
17618
+ * contract: `POST {basePath}/start` (body: the form's settings) answers
17619
+ * `{ sessionId, loginUrl }`; `GET {basePath}/status?sessionId=` answers
17620
+ * `{ phase: 'starting' | 'awaiting-login' | 'captured' | 'error' |
17621
+ * 'cancelled', loginUrl, error }`; `POST {basePath}/commit`
17622
+ * (`{ sessionId, name, brokerId? }`) stores the credentials on a new or
17623
+ * existing broker and answers `{ brokerId }`; `POST {basePath}/cancel`
17624
+ * (`{ sessionId }`) drops the session. The dialog that edits a broker
17625
+ * offers it as the default path; the fields the session fills are
17626
+ * marked `filledBySignIn` in the kind's settings schema.
17627
+ */
17628
+ signIn: object({ basePath: string().min(1) }).optional()
17614
17629
  }))
17615
17630
  });
17616
17631
  var ListInputSchema = object({
@@ -90089,37 +90104,78 @@ function toRecord(value) {
90089
90104
  function settingsToAlexaConnection(settings) {
90090
90105
  return alexaConnectionSchema.parse(toRecord(settings));
90091
90106
  }
90107
+ /**
90108
+ * Allowlist of real Amazon regional domains that alexa-remote2 is known to
90109
+ * support. An enum (not a free-form string) keeps the value from ever naming an
90110
+ * arbitrary host: alexa-remote2 uses it as a raw domain suffix.
90111
+ */
90112
+ var AMAZON_DOMAINS = [
90113
+ "amazon.com",
90114
+ "amazon.it",
90115
+ "amazon.de",
90116
+ "amazon.co.uk",
90117
+ "amazon.fr",
90118
+ "amazon.es",
90119
+ "amazon.ca",
90120
+ "amazon.com.au",
90121
+ "amazon.co.jp",
90122
+ "amazon.in",
90123
+ "amazon.com.br",
90124
+ "amazon.com.mx"
90125
+ ];
90126
+ /** The country each domain serves; the first match for a country prefills the form. */
90127
+ var AMAZON_DOMAIN_BY_COUNTRY = {
90128
+ US: "amazon.com",
90129
+ IT: "amazon.it",
90130
+ DE: "amazon.de",
90131
+ AT: "amazon.de",
90132
+ GB: "amazon.co.uk",
90133
+ FR: "amazon.fr",
90134
+ ES: "amazon.es",
90135
+ CA: "amazon.ca",
90136
+ AU: "amazon.com.au",
90137
+ JP: "amazon.co.jp",
90138
+ IN: "amazon.in",
90139
+ BR: "amazon.com.br",
90140
+ MX: "amazon.com.mx"
90141
+ };
90092
90142
  /** Hand-written connection form for the broker/integration creation UI. */
90093
90143
  function buildConnectionFormSchema() {
90094
90144
  return { sections: [{
90095
90145
  id: "alexa-account",
90096
90146
  title: "Amazon Alexa account",
90097
90147
  titleKey: "import-alexa:connection.s_alexa-account.title",
90098
- description: "Link an Amazon account via the unofficial Alexa client. Supply a captured cookie OR a refresh token. NOTE: this is an unofficial integration — Amazon can change or break it without notice, and it may violate Amazon ToS. State is polled, not pushed.",
90148
+ description: "Sign in with your Amazon account to link it. This is an unofficial integration: Amazon can change or break it without notice, and it may violate Amazon ToS. State is polled, not pushed.",
90099
90149
  descriptionKey: "import-alexa:connection.s_alexa-account.description",
90100
90150
  columns: 1,
90101
90151
  fields: [
90102
90152
  {
90103
- type: "text",
90153
+ type: "select",
90104
90154
  key: "amazonDomain",
90105
90155
  label: "Amazon domain (region)",
90106
90156
  labelKey: "import-alexa:connection.s_alexa-account.amazonDomain.label",
90107
- placeholder: "amazon.com",
90108
- default: "amazon.com"
90157
+ options: AMAZON_DOMAINS.map((value) => ({
90158
+ value,
90159
+ label: value
90160
+ })),
90161
+ default: "amazon.com",
90162
+ defaultByCountry: AMAZON_DOMAIN_BY_COUNTRY
90109
90163
  },
90110
90164
  {
90111
90165
  type: "password",
90112
90166
  key: "cookie",
90113
- label: "Cookie blob (from proxy login)",
90167
+ label: "Cookie blob (filled by the sign-in)",
90114
90168
  labelKey: "import-alexa:connection.s_alexa-account.cookie.label",
90115
- showToggle: true
90169
+ showToggle: true,
90170
+ filledBySignIn: true
90116
90171
  },
90117
90172
  {
90118
90173
  type: "password",
90119
90174
  key: "refreshToken",
90120
- label: "Refresh token (alternative to cookie)",
90175
+ label: "Refresh token (alternative to the sign-in)",
90121
90176
  labelKey: "import-alexa:connection.s_alexa-account.refreshToken.label",
90122
- showToggle: true
90177
+ showToggle: true,
90178
+ filledBySignIn: true
90123
90179
  },
90124
90180
  {
90125
90181
  type: "number",
@@ -131610,20 +131666,25 @@ function capturedToCookieString(captured) {
131610
131666
  }
131611
131667
  //#endregion
131612
131668
  //#region src/alexa-login-routes.ts
131613
- var StartBodySchema = object({ amazonDomain: _enum([
131614
- "amazon.com",
131615
- "amazon.it",
131616
- "amazon.de",
131617
- "amazon.co.uk",
131618
- "amazon.fr",
131619
- "amazon.es",
131620
- "amazon.ca",
131621
- "amazon.com.au",
131622
- "amazon.co.jp",
131623
- "amazon.in",
131624
- "amazon.com.br",
131625
- "amazon.com.mx"
131626
- ]).default("amazon.com") });
131669
+ /**
131670
+ * `addon-routes` control plane that drives the INTERACTIVE Amazon login from the
131671
+ * broker dialog (the kind's `signIn` contract). All routes are `admin` — they start a proxy server and
131672
+ * mutate broker credentials, so they require an admin session/scoped token (the
131673
+ * hub enforces this BEFORE the handler runs; see `main.ts` `/addon/:addonId/*`).
131674
+ *
131675
+ * Public URLs (hub reachable as `https://<hub>`):
131676
+ * POST /addon/import-alexa/login/start { amazonDomain } → { sessionId, loginUrl }
131677
+ * GET /addon/import-alexa/login/status?sessionId=… → AlexaProxyLoginStatus (no secrets)
131678
+ * POST /addon/import-alexa/login/commit { sessionId, name, brokerId? } → { brokerId }
131679
+ * POST /addon/import-alexa/login/cancel { sessionId } → { ok: true }
131680
+ *
131681
+ * The wizard flow: POST /login/start → render a "Login to Amazon" button linking
131682
+ * to `loginUrl` (opened in a new tab) → poll /login/status until
131683
+ * `phase === 'captured'` → POST /login/commit to persist the cookie onto a new
131684
+ * or existing broker → proceed to device discovery/adoption.
131685
+ */
131686
+ /** The broker dialog posts the whole form; only the region matters here (other keys are ignored). */
131687
+ var StartBodySchema = object({ amazonDomain: _enum(AMAZON_DOMAINS).default("amazon.com") });
131627
131688
  var StatusQuerySchema = object({ sessionId: string().min(1) });
131628
131689
  var CommitBodySchema = object({
131629
131690
  sessionId: string().min(1),
@@ -132727,7 +132788,8 @@ function buildAlexaBrokerProvider(deps) {
132727
132788
  addonId: ownerAddonId,
132728
132789
  kinds: [{
132729
132790
  kind: ALEXA_KIND,
132730
- label: "Alexa Import"
132791
+ label: "Alexa Import",
132792
+ signIn: { basePath: "/addon/import-alexa/login" }
132731
132793
  }]
132732
132794
  }],
132733
132795
  add: async ({ kind, name, settings }) => {
@@ -133514,6 +133576,11 @@ var alexaSpeakSessionsEntryKind = defineEntryKind("speak-sessions", {
133514
133576
  schema: entryBody({ session: string().default("").meta({ secret: true }) }),
133515
133577
  writeTrigger: "an Echo worker signs in as an Alexa account broker"
133516
133578
  });
133579
+ /** Every kind this addon declares, keyed by its name: `records.declare` refuses any other key. */
133580
+ var alexaRecordKinds = {
133581
+ brokers: alexaBrokersEntryKind,
133582
+ "speak-sessions": alexaSpeakSessionsEntryKind
133583
+ };
133517
133584
  //#endregion
133518
133585
  //#region src/alexa-broker-store.ts
133519
133586
  function rowToEntry(id, data) {
@@ -135241,10 +135308,7 @@ var AlexaImportAddon = class extends BaseDeviceProvider {
135241
135308
  const regs = this.providerRegistrationsFromSuper(await super.onInitialize());
135242
135309
  const records = this.ctx.records;
135243
135310
  if (records === void 0) throw new Error("import-alexa: ctx.records is required (hub-only addon)");
135244
- await records.declare({
135245
- brokers: alexaBrokersEntryKind,
135246
- speakSessions: alexaSpeakSessionsEntryKind
135247
- });
135311
+ await records.declare(alexaRecordKinds);
135248
135312
  this.brokerStore = AlexaBrokerStore.of(records);
135249
135313
  this.activeBrokers = await this.loadPersistedBrokers();
135250
135314
  this.registry = new AlexaBrokerRegistry(this.ctx.logger, {
@@ -36,7 +36,7 @@ async function r() {
36
36
  }
37
37
  },
38
38
  "@camstack/types": {
39
- version: "1.2.424",
39
+ version: "1.2.425",
40
40
  scope: "default",
41
41
  shareConfig: {
42
42
  singleton: !0,
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_import_alexa_page__remoteEntry_js-DMdgQOgz.mjs";
1
+ import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_import_alexa_page__remoteEntry_js-BHSk6VHO.mjs";
2
2
  export { t as get, e as init };
@@ -2753,7 +2753,7 @@ async function rr(e) {
2753
2753
  }
2754
2754
  }
2755
2755
  async function ir() {
2756
- return tr ||= rr(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_import_alexa_page-CcQjQJmj.mjs")).catch((e) => {
2756
+ return tr ||= rr(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_import_alexa_page-DZkNpxsX.mjs")).catch((e) => {
2757
2757
  throw tr = void 0, e;
2758
2758
  }), tr;
2759
2759
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-import-alexa",
3
- "version": "0.2.150",
3
+ "version": "0.2.152",
4
4
  "description": "Alexa device-import provider for CamStack — imports the smart-home devices in a user's Alexa account via the unofficial alexa-remote2 cookie/token client (the inverse of the Alexa exporter)",
5
5
  "keywords": [
6
6
  "camstack",