@camstack/addon-google-services 0.1.1 → 0.1.2

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.
@@ -35164,6 +35164,7 @@ var OsdNamedTemplateSchema = object({
35164
35164
  });
35165
35165
  /** Where a slot's value comes from. */
35166
35166
  var OsdSourceSchema = discriminatedUnion("kind", [
35167
+ object({ kind: literal("none") }),
35167
35168
  object({
35168
35169
  kind: literal("static"),
35169
35170
  text: string().max(64)
@@ -39524,7 +39525,43 @@ var TrainingProviderDescriptorSchema = object({
39524
39525
  dataResidencyNote: string(),
39525
39526
  /** Credentials are present — never the values. */
39526
39527
  configured: boolean(),
39527
- defaults: TrainingProviderDefaultsSchema
39528
+ defaults: TrainingProviderDefaultsSchema,
39529
+ /**
39530
+ * Non-secret account fields for the Providers form (e.g. Modal token id).
39531
+ * The secret itself never appears — only a keychain {@link SecretFieldView}
39532
+ * (or `hasTokenSecret` for older clients).
39533
+ */
39534
+ tokenId: string().optional(),
39535
+ environment: string().optional(),
39536
+ hasTokenSecret: boolean().optional(),
39537
+ /**
39538
+ * Keychain view for the entry's token secret — for `SecretFieldControl` on
39539
+ * edit. Create has no view (`null` / omitted); the form uses a plain
39540
+ * `PasswordInput` instead.
39541
+ */
39542
+ tokenSecretView: object({
39543
+ $secret: string().nullable(),
39544
+ v: literal(1),
39545
+ set: literal(true),
39546
+ inline: literal(true).optional()
39547
+ }).nullable().optional()
39548
+ });
39549
+ /**
39550
+ * Patch one entry's name, credentials and defaults. Pin with owning `{ addonId }`.
39551
+ * An omitted or empty `tokenSecret` means KEEP the stored secret (D787).
39552
+ * `{ $secretClear: true }` clears it.
39553
+ */
39554
+ var TrainingProviderUpdateEntryInputSchema = object({
39555
+ entryId: string().min(1),
39556
+ name: string().min(1),
39557
+ tokenId: string().optional(),
39558
+ tokenSecret: union([string(), object({ $secretClear: literal(true) })]).optional(),
39559
+ environment: string().optional(),
39560
+ gpuType: string().optional(),
39561
+ region: string().optional(),
39562
+ costCapUsd: number().nonnegative().optional(),
39563
+ maxRuntimeSec: number().int().positive().optional(),
39564
+ failedDatasetGraceHours: number().nonnegative().optional()
39528
39565
  });
39529
39566
  var TrainingCredentialCheckSchema = object({
39530
39567
  ok: boolean(),
@@ -39594,6 +39631,9 @@ method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "
39594
39631
  }), method(object({ entryId: string().min(1) }), object({ ok: literal(true) }), {
39595
39632
  kind: "mutation",
39596
39633
  auth: "admin"
39634
+ }), method(TrainingProviderUpdateEntryInputSchema, object({ ok: literal(true) }), {
39635
+ kind: "mutation",
39636
+ auth: "admin"
39597
39637
  }), method(object({ entryId: string().min(1) }), TrainingCredentialCheckSchema, {
39598
39638
  kind: "mutation",
39599
39639
  auth: "admin",
@@ -47155,6 +47195,12 @@ Object.freeze({
47155
47195
  addonId: null,
47156
47196
  access: "create"
47157
47197
  },
47198
+ "trainingProvider.updateEntry": {
47199
+ capName: "training-provider",
47200
+ capScope: "system",
47201
+ addonId: null,
47202
+ access: "create"
47203
+ },
47158
47204
  "trainingProvider.uploadDataset": {
47159
47205
  capName: "training-provider",
47160
47206
  capScope: "system",
@@ -52926,6 +52972,16 @@ function needsRefresh(state, nowMs = Date.now()) {
52926
52972
  return state.accessExpiresAt <= nowMs;
52927
52973
  }
52928
52974
  //#endregion
52975
+ //#region src/oauth-redirect-origin.ts
52976
+ /**
52977
+ * Google OAuth redirect origin — same role as hub OAuth2 / sign-in
52978
+ * (`local-network` cap: `roles.publicEndpoint`), never `internal` (LAN / agents).
52979
+ * Google rejects non-localhost `http://` redirect URIs for Web clients.
52980
+ */
52981
+ function pickOauthRedirectOrigin(book) {
52982
+ return book.roles.publicEndpoint.resolved ?? book.roles.internal.resolved ?? null;
52983
+ }
52984
+ //#endregion
52929
52985
  //#region src/google-services.addon.ts
52930
52986
  /**
52931
52987
  * Google Services — hub-only calendar-source over Google Calendar API (OAuth2).
@@ -53066,16 +53122,15 @@ var GoogleServicesAddon = class extends BaseAddon {
53066
53122
  return new Set(raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0));
53067
53123
  }
53068
53124
  async resolveRedirectUri() {
53069
- const book = await this.ctx.api.localNetwork.getAddresses.query({});
53070
- const origin = book.roles.internal.resolved ?? book.roles.publicEndpoint.resolved ?? null;
53071
- if (!origin) throw new Error("No hub address available from local-network — set an Internal address on the Network page.");
53125
+ const origin = pickOauthRedirectOrigin(await this.ctx.api.localNetwork.getAddresses.query({}));
53126
+ if (!origin) throw new Error("No hub public address available from local-network — set a Public endpoint on the Network page (OAuth2 redirects use that role, not Internal).");
53072
53127
  return `${origin.replace(/\/$/, "")}/addon/${ADDON_ID}${CALLBACK_PATH}`;
53073
53128
  }
53074
53129
  globalSettingsSchema() {
53075
53130
  return this.schema({ sections: [{
53076
53131
  id: "google-oauth",
53077
53132
  title: "Google Calendar OAuth",
53078
- description: "Create an OAuth client (Web application) in Google Cloud Console with the Calendar API enabled. Register the redirect URI `<hub>/addon/google-services/oauth/callback` (hub = Internal address from Network).",
53133
+ description: "Create an OAuth client (Web application) in Google Cloud Console with the Calendar API enabled. Register the redirect URI `<public-hub>/addon/google-services/oauth/callback` — hub = Public endpoint from Network (same role as sign-in / OAuth2; Google rejects plain LAN http).",
53079
53134
  columns: 1,
53080
53135
  fields: [
53081
53136
  {
@@ -53100,7 +53155,7 @@ var GoogleServicesAddon = class extends BaseAddon {
53100
53155
  key: "_connectInfo",
53101
53156
  label: "Connect",
53102
53157
  format: "html",
53103
- content: `After saving client id/secret, open <a href="/addon/${ADDON_ID}${START_PATH}">Connect Google Calendar</a> while signed in as admin.`
53158
+ content: `After saving client id/secret, open <a href="/addon/${ADDON_ID}${START_PATH}">Connect Google Calendar</a> while signed in as admin. Redirect URI uses the Network <b>Public endpoint</b> (today typically <code>https://…/addon/google-services/oauth/callback</code>).`
53104
53159
  }
53105
53160
  ]
53106
53161
  }] });
@@ -35160,6 +35160,7 @@ var OsdNamedTemplateSchema = object({
35160
35160
  });
35161
35161
  /** Where a slot's value comes from. */
35162
35162
  var OsdSourceSchema = discriminatedUnion("kind", [
35163
+ object({ kind: literal("none") }),
35163
35164
  object({
35164
35165
  kind: literal("static"),
35165
35166
  text: string().max(64)
@@ -39520,7 +39521,43 @@ var TrainingProviderDescriptorSchema = object({
39520
39521
  dataResidencyNote: string(),
39521
39522
  /** Credentials are present — never the values. */
39522
39523
  configured: boolean(),
39523
- defaults: TrainingProviderDefaultsSchema
39524
+ defaults: TrainingProviderDefaultsSchema,
39525
+ /**
39526
+ * Non-secret account fields for the Providers form (e.g. Modal token id).
39527
+ * The secret itself never appears — only a keychain {@link SecretFieldView}
39528
+ * (or `hasTokenSecret` for older clients).
39529
+ */
39530
+ tokenId: string().optional(),
39531
+ environment: string().optional(),
39532
+ hasTokenSecret: boolean().optional(),
39533
+ /**
39534
+ * Keychain view for the entry's token secret — for `SecretFieldControl` on
39535
+ * edit. Create has no view (`null` / omitted); the form uses a plain
39536
+ * `PasswordInput` instead.
39537
+ */
39538
+ tokenSecretView: object({
39539
+ $secret: string().nullable(),
39540
+ v: literal(1),
39541
+ set: literal(true),
39542
+ inline: literal(true).optional()
39543
+ }).nullable().optional()
39544
+ });
39545
+ /**
39546
+ * Patch one entry's name, credentials and defaults. Pin with owning `{ addonId }`.
39547
+ * An omitted or empty `tokenSecret` means KEEP the stored secret (D787).
39548
+ * `{ $secretClear: true }` clears it.
39549
+ */
39550
+ var TrainingProviderUpdateEntryInputSchema = object({
39551
+ entryId: string().min(1),
39552
+ name: string().min(1),
39553
+ tokenId: string().optional(),
39554
+ tokenSecret: union([string(), object({ $secretClear: literal(true) })]).optional(),
39555
+ environment: string().optional(),
39556
+ gpuType: string().optional(),
39557
+ region: string().optional(),
39558
+ costCapUsd: number().nonnegative().optional(),
39559
+ maxRuntimeSec: number().int().positive().optional(),
39560
+ failedDatasetGraceHours: number().nonnegative().optional()
39524
39561
  });
39525
39562
  var TrainingCredentialCheckSchema = object({
39526
39563
  ok: boolean(),
@@ -39590,6 +39627,9 @@ method(object({}), array(TrainingProviderDescriptorSchema).readonly(), { auth: "
39590
39627
  }), method(object({ entryId: string().min(1) }), object({ ok: literal(true) }), {
39591
39628
  kind: "mutation",
39592
39629
  auth: "admin"
39630
+ }), method(TrainingProviderUpdateEntryInputSchema, object({ ok: literal(true) }), {
39631
+ kind: "mutation",
39632
+ auth: "admin"
39593
39633
  }), method(object({ entryId: string().min(1) }), TrainingCredentialCheckSchema, {
39594
39634
  kind: "mutation",
39595
39635
  auth: "admin",
@@ -47151,6 +47191,12 @@ Object.freeze({
47151
47191
  addonId: null,
47152
47192
  access: "create"
47153
47193
  },
47194
+ "trainingProvider.updateEntry": {
47195
+ capName: "training-provider",
47196
+ capScope: "system",
47197
+ addonId: null,
47198
+ access: "create"
47199
+ },
47154
47200
  "trainingProvider.uploadDataset": {
47155
47201
  capName: "training-provider",
47156
47202
  capScope: "system",
@@ -52922,6 +52968,16 @@ function needsRefresh(state, nowMs = Date.now()) {
52922
52968
  return state.accessExpiresAt <= nowMs;
52923
52969
  }
52924
52970
  //#endregion
52971
+ //#region src/oauth-redirect-origin.ts
52972
+ /**
52973
+ * Google OAuth redirect origin — same role as hub OAuth2 / sign-in
52974
+ * (`local-network` cap: `roles.publicEndpoint`), never `internal` (LAN / agents).
52975
+ * Google rejects non-localhost `http://` redirect URIs for Web clients.
52976
+ */
52977
+ function pickOauthRedirectOrigin(book) {
52978
+ return book.roles.publicEndpoint.resolved ?? book.roles.internal.resolved ?? null;
52979
+ }
52980
+ //#endregion
52925
52981
  //#region src/google-services.addon.ts
52926
52982
  /**
52927
52983
  * Google Services — hub-only calendar-source over Google Calendar API (OAuth2).
@@ -53062,16 +53118,15 @@ var GoogleServicesAddon = class extends BaseAddon {
53062
53118
  return new Set(raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0));
53063
53119
  }
53064
53120
  async resolveRedirectUri() {
53065
- const book = await this.ctx.api.localNetwork.getAddresses.query({});
53066
- const origin = book.roles.internal.resolved ?? book.roles.publicEndpoint.resolved ?? null;
53067
- if (!origin) throw new Error("No hub address available from local-network — set an Internal address on the Network page.");
53121
+ const origin = pickOauthRedirectOrigin(await this.ctx.api.localNetwork.getAddresses.query({}));
53122
+ if (!origin) throw new Error("No hub public address available from local-network — set a Public endpoint on the Network page (OAuth2 redirects use that role, not Internal).");
53068
53123
  return `${origin.replace(/\/$/, "")}/addon/${ADDON_ID}${CALLBACK_PATH}`;
53069
53124
  }
53070
53125
  globalSettingsSchema() {
53071
53126
  return this.schema({ sections: [{
53072
53127
  id: "google-oauth",
53073
53128
  title: "Google Calendar OAuth",
53074
- description: "Create an OAuth client (Web application) in Google Cloud Console with the Calendar API enabled. Register the redirect URI `<hub>/addon/google-services/oauth/callback` (hub = Internal address from Network).",
53129
+ description: "Create an OAuth client (Web application) in Google Cloud Console with the Calendar API enabled. Register the redirect URI `<public-hub>/addon/google-services/oauth/callback` — hub = Public endpoint from Network (same role as sign-in / OAuth2; Google rejects plain LAN http).",
53075
53130
  columns: 1,
53076
53131
  fields: [
53077
53132
  {
@@ -53096,7 +53151,7 @@ var GoogleServicesAddon = class extends BaseAddon {
53096
53151
  key: "_connectInfo",
53097
53152
  label: "Connect",
53098
53153
  format: "html",
53099
- content: `After saving client id/secret, open <a href="/addon/${ADDON_ID}${START_PATH}">Connect Google Calendar</a> while signed in as admin.`
53154
+ content: `After saving client id/secret, open <a href="/addon/${ADDON_ID}${START_PATH}">Connect Google Calendar</a> while signed in as admin. Redirect URI uses the Network <b>Public endpoint</b> (today typically <code>https://…/addon/google-services/oauth/callback</code>).`
53100
53155
  }
53101
53156
  ]
53102
53157
  }] });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-google-services",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Google Services — Google Calendar as a CamStack calendar-source via OAuth2.",
5
5
  "keywords": [
6
6
  "camstack",