@quadient/skillshare 1.8.0 → 1.8.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/README.md CHANGED
@@ -41,6 +41,10 @@ skillshare teams access readOnly
41
41
  skillshare teams logout
42
42
  ```
43
43
 
44
+ Starting with 1.8.1, Teams uses the Microsoft account object id that Skillshare records at
45
+ web sign-in, not the Skillshare user id. If the server does not know it yet, `teams login`
46
+ opens one more Skillshare sign-in in the browser to link the account.
47
+
44
48
  Use `teams login local` for localhost or `--server <https-origin>` for another host.
45
49
  `login` accepts `--server` too. Browser options: `--browser chrome|msedge|chromium`,
46
50
  `--headless`, and `--browser-profile <dedicated-profile-directory>`.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { assertCredentialDestination, runTeamsCommand } from './teams.js';
1
+ import { assertCredentialDestination, resolveTeamsObjectId, runTeamsCommand } from './teams.js';
2
2
  import { formatUnknownCommand, parseCliArgs } from './cli-args.js';
3
3
  import { findCommand, readCliVersion, renderCommandHelp, renderUsage } from './help.js';
4
4
  import { inspectInstallTarget, installFilesAtomically } from './install-files.js';
@@ -122,7 +122,15 @@ async function main() {
122
122
  assertCredentialDestination(baseUrl);
123
123
  if (!options.token && !await loadSession(baseUrl))
124
124
  await login(baseUrl);
125
- await runTeamsCommand(await createClient(baseUrl, options.token), options.positionals, options.flags, APP_DIR);
125
+ const teamsClient = await createClient(baseUrl, options.token);
126
+ const action = options.positionals[0];
127
+ if (!options.token && (action === 'login' || action === 'watch')
128
+ && !resolveTeamsObjectId(await teamsClient.get('/api/auth/me'))) {
129
+ // A browser sign-in lets the server record the Entra object id for this account.
130
+ console.log('Linking your Microsoft account to Skillshare. Sign in once more in the browser.');
131
+ await login(baseUrl);
132
+ }
133
+ await runTeamsCommand(teamsClient, options.positionals, options.flags, APP_DIR);
126
134
  return;
127
135
  }
128
136
  case 'git': {
@@ -16,7 +16,7 @@ export function decodeTeamsJwt(value) {
16
16
  /** Select only credentials belonging to the Skillshare account. No full browser state leaves this machine. */
17
17
  export function extractTeamsSession(state, expectedObjectId, now = Date.now(), allowExpired = false) {
18
18
  if (!uuid.test(expectedObjectId))
19
- throw new Error('Skillshare must be signed in with a Microsoft account before connecting Teams.');
19
+ throw new Error('The Microsoft account object id is missing. Sign in to Skillshare in the browser, then run skillshare teams login again.');
20
20
  const stores = state.origins.filter(origin => origins.has(origin.origin));
21
21
  const entries = stores.flatMap(origin => origin.localStorage.flatMap(item => {
22
22
  try {
package/dist/teams.js CHANGED
@@ -7,6 +7,17 @@ import { pipeline } from 'node:stream/promises';
7
7
  import { captureTeamsLogin } from './teams-auth.js';
8
8
  import { watchTeamsConnection } from './teams-watch.js';
9
9
  const root = '/api/mcps/providers/teams';
10
+ const guid = /^[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}$/i;
11
+ /**
12
+ * Skillshare identifies users by the pairwise subject; Teams credentials carry the Entra
13
+ * object id, which the server records at web sign-in. Older servers only return a GUID id.
14
+ */
15
+ export function resolveTeamsObjectId(account) {
16
+ if (account.entraObjectId && guid.test(account.entraObjectId))
17
+ return account.entraObjectId;
18
+ return guid.test(account.id) ? account.id : null;
19
+ }
20
+ export const UNLINKED_ACCOUNT_MESSAGE = 'Skillshare does not know your Microsoft account yet. Run "skillshare login" (or open Skillshare in the browser and sign in), then run "skillshare teams login" again.';
10
21
  async function expectOk(response) {
11
22
  if (response.ok)
12
23
  return;
@@ -23,11 +34,15 @@ export async function runTeamsCommand(client, args, flags, appDirectory) {
23
34
  const action = args[0];
24
35
  if (action === 'login' || action === 'watch') {
25
36
  const user = await client.get('/api/auth/me');
37
+ const resolvedObjectId = resolveTeamsObjectId(user);
38
+ if (!resolvedObjectId)
39
+ throw new Error(UNLINKED_ACCOUNT_MESSAGE);
40
+ const objectId = resolvedObjectId;
26
41
  const key = createHash('sha256').update(client.baseUrl + '\0' + user.id).digest('hex').slice(0, 24);
27
42
  const profileDirectory = flags['browser-profile'] ? resolve(flags['browser-profile']) : join(appDirectory, 'teams', key, 'browser-profile');
28
43
  const abort = new AbortController();
29
44
  async function connect(connectionId) {
30
- const session = await captureTeamsLogin({ profileDirectory, objectId: user.id, browser: flags.browser,
45
+ const session = await captureTeamsLogin({ profileDirectory, objectId, browser: flags.browser,
31
46
  headless: action === 'watch' ? flags.headless !== 'false' : flags.headless === 'true', recover: action === 'watch',
32
47
  signal: abort.signal, timeoutMs: action === 'watch' ? 90_000 : undefined, onProgress: console.log });
33
48
  const headers = { 'Content-Type': 'application/json' };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quadient/skillshare",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Skillshare CLI for installing and publishing Quadient skills",
5
5
  "type": "module",
6
6
  "bin": {