From 62c8fb4dd6e7a4ec1be47e1c277e4bb878c27aea Mon Sep 17 00:00:00 2001 From: bobrimperator Date: Mon, 23 Dec 2024 16:36:57 +0100 Subject: [PATCH 1/3] chore(typescript): ember-simple-auth initial setup --- pnpm-lock.yaml | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0d5ae354..86074b48e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13713,26 +13713,6 @@ snapshots: dependencies: '@types/ms': 0.7.34 - '@types/ember@4.0.11': - dependencies: - '@types/ember__application': 4.0.11(@babel/core@7.26.0) - '@types/ember__array': 4.0.10(@babel/core@7.26.0) - '@types/ember__component': 4.0.22(@babel/core@7.26.0) - '@types/ember__controller': 4.0.12(@babel/core@7.26.0) - '@types/ember__debug': 4.0.8 - '@types/ember__engine': 4.0.11 - '@types/ember__error': 4.0.6 - '@types/ember__object': 4.0.12(@babel/core@7.26.0) - '@types/ember__polyfills': 4.0.6 - '@types/ember__routing': 4.0.22(@babel/core@7.26.0) - '@types/ember__runloop': 4.0.10(@babel/core@7.26.0) - '@types/ember__service': 4.0.9(@babel/core@7.26.0) - '@types/ember__string': 3.0.15 - '@types/ember__template': 4.0.7 - '@types/ember__test': 4.0.6(@babel/core@7.26.0) - '@types/ember__utils': 4.0.7 - '@types/rsvp': 4.0.9 - '@types/ember@4.0.11(@babel/core@7.26.0)': dependencies: '@types/ember__application': 4.0.11(@babel/core@7.26.0) @@ -13759,7 +13739,7 @@ snapshots: '@types/ember__application@4.0.11(@babel/core@7.26.0)': dependencies: '@glimmer/component': 1.1.2(@babel/core@7.26.0) - '@types/ember': 4.0.11 + '@types/ember': 4.0.11(@babel/core@7.26.0) '@types/ember__engine': 4.0.11 '@types/ember__object': 4.0.12(@babel/core@7.26.0) '@types/ember__owner': 4.0.9 @@ -13850,10 +13830,6 @@ snapshots: - '@babel/core' - supports-color - '@types/ember__utils@4.0.7': - dependencies: - '@types/ember': 4.0.11 - '@types/ember__utils@4.0.7(@babel/core@7.26.0)': dependencies: '@types/ember': 4.0.11(@babel/core@7.26.0) From d448cc9b5adaecf5c636dd32d5db7c31231b63cd Mon Sep 17 00:00:00 2001 From: bobrimperator Date: Mon, 23 Dec 2024 22:45:16 +0100 Subject: [PATCH 2/3] chore(typescript): migrate services/session --- packages/ember-simple-auth/babel.config.json | 2 +- packages/ember-simple-auth/package.json | 4 + .../src/services/{session.js => session.ts} | 123 +++++++++++------- packages/ember-simple-auth/tsconfig.json | 3 +- pnpm-lock.yaml | 28 +++- 5 files changed, 102 insertions(+), 58 deletions(-) rename packages/ember-simple-auth/src/services/{session.js => session.ts} (80%) diff --git a/packages/ember-simple-auth/babel.config.json b/packages/ember-simple-auth/babel.config.json index d3ea846f6..1f2d1d527 100644 --- a/packages/ember-simple-auth/babel.config.json +++ b/packages/ember-simple-auth/babel.config.json @@ -2,7 +2,7 @@ "plugins": [ [ "@babel/plugin-transform-typescript", - { "allExtensions": true, "onlyRemoveTypeImports": true } + { "allExtensions": true, "onlyRemoveTypeImports": true, "allowDeclareFields": true } ], "@embroider/addon-dev/template-colocation-plugin", ["@babel/plugin-proposal-decorators", { "legacy": true }], diff --git a/packages/ember-simple-auth/package.json b/packages/ember-simple-auth/package.json index 4418b49a6..55037b7b5 100644 --- a/packages/ember-simple-auth/package.json +++ b/packages/ember-simple-auth/package.json @@ -49,6 +49,10 @@ "@rollup/plugin-babel": "6.0.4", "@rollup/plugin-node-resolve": "15.3.1", "@tsconfig/ember": "^3.0.8", + "@types/ember__application": "^4.0.11", + "@types/ember__debug": "^4.0.8", + "@types/ember__object": "^4.0.12", + "@types/ember__routing": "^4.0.22", "@types/ember__service": "^4.0.9", "@typescript-eslint/eslint-plugin": "^8.18.1", "@typescript-eslint/parser": "^8.18.1", diff --git a/packages/ember-simple-auth/src/services/session.js b/packages/ember-simple-auth/src/services/session.ts similarity index 80% rename from packages/ember-simple-auth/src/services/session.js rename to packages/ember-simple-auth/src/services/session.ts index ce2cab167..5bbf20add 100644 --- a/packages/ember-simple-auth/src/services/session.js +++ b/packages/ember-simple-auth/src/services/session.ts @@ -1,4 +1,3 @@ -import { alias, readOnly } from '@ember/object/computed'; import Service from '@ember/service'; import { getOwner } from '@ember/application'; import { assert } from '@ember/debug'; @@ -11,10 +10,11 @@ import { handleSessionAuthenticated, handleSessionInvalidated, } from '../-internals/routing'; +import type Transition from '@ember/routing/transition'; const SESSION_DATA_KEY_PREFIX = /^data\./; -function assertSetupHasBeenCalled(isSetupCalled) { +function assertSetupHasBeenCalled(isSetupCalled: boolean) { if (!isSetupCalled) { assert( "Ember Simple Auth: session#setup wasn't called. Make sure to call session#setup in your application route's beforeModel hook.", @@ -23,6 +23,21 @@ function assertSetupHasBeenCalled(isSetupCalled) { } } +type RouteOrCallback = string | (() => void); + +type InternalSessionMock = { + isAuthenticated: boolean; + content: { authenticated: Record }; + store: unknown; + attemptedTransition: null; + on: (event: 'authenticationSucceeded' | 'invalidationSucceeded', cb: () => void) => void; + authenticate: (authenticator: string, ...args: any[]) => void; + invalidate: (...args: any[]) => void; + requireAuthentication: (transition: Transition, routeOrCallback: RouteOrCallback) => boolean; + prohibitAuthentication: (routeOrCallback: RouteOrCallback) => boolean; + restore: () => Promise; +}; + /** __The session service provides access to the current session as well as methods to authenticate it, invalidate it, etc.__ It is the main interface for @@ -42,7 +57,23 @@ function assertSetupHasBeenCalled(isSetupCalled) { @extends Service @public */ -export default Service.extend({ +export default class EmberSimpleAuthSessionService extends Service { + declare session: InternalSessionMock; + + constructor() { + super(...arguments); + + const owner = getOwner(this); + if (owner) { + this.session = owner.lookup('session:main') as InternalSessionMock; + } + } + + /** + * Says whether the service was correctly initialized by the {#linkplain SessionService.setup} + */ + _setupIsCalled = false; + /** Returns whether the session is currently authenticated. @@ -53,7 +84,9 @@ export default Service.extend({ @default false @public */ - isAuthenticated: readOnly('session.isAuthenticated'), + get isAuthenticated() { + return this.session.isAuthenticated; + } /** The current session data as a plain object. The @@ -70,7 +103,9 @@ export default Service.extend({ @default { authenticated: {} } @public */ - data: readOnly('session.content'), + get data() { + return this.session.content; + } /** The session store. @@ -82,7 +117,9 @@ export default Service.extend({ @default null @public */ - store: readOnly('session.store'), + get store() { + return this.session.store; + } /** A previously attempted but intercepted transition (e.g. by the @@ -95,17 +132,11 @@ export default Service.extend({ @default null @public */ - attemptedTransition: alias('session.attemptedTransition'), - - session: null, - - init() { - this._super(...arguments); - - this.set('session', getOwner(this).lookup('session:main')); - }, + get attemptedTransition() { + return this.session.attemptedTransition; + } - set(key, value) { + set(key: any, value: any) { const setsSessionData = SESSION_DATA_KEY_PREFIX.test(key); if (setsSessionData) { const sessionDataKey = `session.${key.replace(SESSION_DATA_KEY_PREFIX, '')}`; @@ -113,16 +144,14 @@ export default Service.extend({ } else { return this._super(...arguments); } - }, + } _setupHandlers() { - this.get('session').on('authenticationSucceeded', () => + this.session.on('authenticationSucceeded', () => this.handleAuthentication(Configuration.routeAfterAuthentication) ); - this.get('session').on('invalidationSucceeded', () => - this.handleInvalidation(Configuration.rootURL) - ); - }, + this.session.on('invalidationSucceeded', () => this.handleInvalidation(Configuration.rootURL)); + } /** __Authenticates the session with an `authenticator`__ and appropriate @@ -153,11 +182,9 @@ export default Service.extend({ @return {Promise} A promise that resolves when the session was authenticated successfully and rejects otherwise @public */ - authenticate() { - const session = this.get('session'); - - return session.authenticate(...arguments); - }, + authenticate(authenticator: string, ...args: any[]) { + return this.session.authenticate(authenticator, ...args); + } /** __Invalidates the session with the authenticator it is currently @@ -187,11 +214,9 @@ export default Service.extend({ @return {Promise} A promise that resolves when the session was invalidated successfully and rejects otherwise @public */ - invalidate() { - const session = this.get('session'); - - return session.invalidate(...arguments); - }, + invalidate(...args: any[]) { + return this.session.invalidate(...args); + } /** Checks whether the session is authenticated and if it is not, transitions @@ -212,24 +237,23 @@ export default Service.extend({ @return {Boolean} true when the session is authenticated, false otherwise @public */ - requireAuthentication(transition, routeOrCallback) { + requireAuthentication(transition: Transition, routeOrCallback: RouteOrCallback) { assertSetupHasBeenCalled(this._setupIsCalled); let isAuthenticated = requireAuthentication(getOwner(this), transition); if (!isAuthenticated) { - let argType = typeof routeOrCallback; - if (argType === 'string') { + if (typeof routeOrCallback === 'string') { triggerAuthentication(getOwner(this), routeOrCallback); - } else if (argType === 'function') { + } else if (typeof routeOrCallback === 'function') { routeOrCallback(); } else { assert( - `The second argument to requireAuthentication must be a String or Function, got "${argType}"!`, + `The second argument to requireAuthentication must be a String or Function, got "${typeof routeOrCallback}"!`, false ); } } return isAuthenticated; - }, + } /** Checks whether the session is authenticated and if it is, transitions @@ -241,24 +265,23 @@ export default Service.extend({ @return {Boolean} true when the session is not authenticated, false otherwise @public */ - prohibitAuthentication(routeOrCallback) { + prohibitAuthentication(routeOrCallback: RouteOrCallback) { assertSetupHasBeenCalled(this._setupIsCalled); let isAuthenticated = this.get('isAuthenticated'); if (isAuthenticated) { - let argType = typeof routeOrCallback; - if (argType === 'string') { + if (typeof routeOrCallback === 'string') { prohibitAuthentication(getOwner(this), routeOrCallback); - } else if (argType === 'function') { + } else if (typeof routeOrCallback === 'function') { routeOrCallback(); } else { assert( - `The first argument to prohibitAuthentication must be a String or Function, got "${argType}"!`, + `The first argument to prohibitAuthentication must be a String or Function, got "${typeof routeOrCallback}"!`, false ); } } return !isAuthenticated; - }, + } /** This method is called whenever the session goes from being unauthenticated @@ -276,9 +299,9 @@ export default Service.extend({ @param {String} routeAfterAuthentication The route to transition to @public */ - handleAuthentication(routeAfterAuthentication) { + handleAuthentication(routeAfterAuthentication: string) { handleSessionAuthenticated(getOwner(this), routeAfterAuthentication); - }, + } /** This method is called whenever the session goes from being authenticated to @@ -296,9 +319,9 @@ export default Service.extend({ @param {String} routeAfterInvalidation The route to transition to @public */ - handleInvalidation(routeAfterInvalidation) { + handleInvalidation(routeAfterInvalidation: string) { handleSessionInvalidated(getOwner(this), routeAfterInvalidation); - }, + } /** Sets up the session service. @@ -318,5 +341,5 @@ export default Service.extend({ return this.session.restore().catch(() => { // If it raises an error then it means that restore didn't find any restorable state. }); - }, -}); + } +} diff --git a/packages/ember-simple-auth/tsconfig.json b/packages/ember-simple-auth/tsconfig.json index f01c8c73d..5a308e6bf 100644 --- a/packages/ember-simple-auth/tsconfig.json +++ b/packages/ember-simple-auth/tsconfig.json @@ -42,7 +42,6 @@ can do the proper transformations on those files. */ "allowImportingTsExtensions": true, - - "types": ["ember-source/types"] + "types": ["ember-source/types", "types"] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86074b48e..48b6daa65 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -280,6 +280,18 @@ importers: '@tsconfig/ember': specifier: ^3.0.8 version: 3.0.8 + '@types/ember__application': + specifier: ^4.0.11 + version: 4.0.11(@babel/core@7.26.0) + '@types/ember__debug': + specifier: ^4.0.8 + version: 4.0.8(@babel/core@7.26.0) + '@types/ember__object': + specifier: ^4.0.12 + version: 4.0.12(@babel/core@7.26.0) + '@types/ember__routing': + specifier: ^4.0.22 + version: 4.0.22(@babel/core@7.26.0) '@types/ember__service': specifier: ^4.0.9 version: 4.0.9(@babel/core@7.26.0) @@ -13719,8 +13731,8 @@ snapshots: '@types/ember__array': 4.0.10(@babel/core@7.26.0) '@types/ember__component': 4.0.22(@babel/core@7.26.0) '@types/ember__controller': 4.0.12(@babel/core@7.26.0) - '@types/ember__debug': 4.0.8 - '@types/ember__engine': 4.0.11 + '@types/ember__debug': 4.0.8(@babel/core@7.26.0) + '@types/ember__engine': 4.0.11(@babel/core@7.26.0) '@types/ember__error': 4.0.6 '@types/ember__object': 4.0.12(@babel/core@7.26.0) '@types/ember__polyfills': 4.0.6 @@ -13740,7 +13752,7 @@ snapshots: dependencies: '@glimmer/component': 1.1.2(@babel/core@7.26.0) '@types/ember': 4.0.11(@babel/core@7.26.0) - '@types/ember__engine': 4.0.11 + '@types/ember__engine': 4.0.11(@babel/core@7.26.0) '@types/ember__object': 4.0.12(@babel/core@7.26.0) '@types/ember__owner': 4.0.9 '@types/ember__routing': 4.0.22(@babel/core@7.26.0) @@ -13771,15 +13783,21 @@ snapshots: - '@babel/core' - supports-color - '@types/ember__debug@4.0.8': + '@types/ember__debug@4.0.8(@babel/core@7.26.0)': dependencies: '@types/ember__object': 4.0.12(@babel/core@7.26.0) '@types/ember__owner': 4.0.9 + transitivePeerDependencies: + - '@babel/core' + - supports-color - '@types/ember__engine@4.0.11': + '@types/ember__engine@4.0.11(@babel/core@7.26.0)': dependencies: '@types/ember__object': 4.0.12(@babel/core@7.26.0) '@types/ember__owner': 4.0.9 + transitivePeerDependencies: + - '@babel/core' + - supports-color '@types/ember__error@4.0.6': {} From 551491c51bb16390641220751fd332df678170a5 Mon Sep 17 00:00:00 2001 From: bobrimperator Date: Thu, 26 Dec 2024 18:50:38 +0100 Subject: [PATCH 3/3] fix(ember-simple-auth): session must alias attemptedTransition --- packages/ember-simple-auth/babel.config.json | 2 +- .../ember-simple-auth/src/services/session.ts | 22 +++++++------- .../tests/unit/services/session-test.js | 30 ------------------- 3 files changed, 11 insertions(+), 43 deletions(-) diff --git a/packages/ember-simple-auth/babel.config.json b/packages/ember-simple-auth/babel.config.json index 1f2d1d527..d3ea846f6 100644 --- a/packages/ember-simple-auth/babel.config.json +++ b/packages/ember-simple-auth/babel.config.json @@ -2,7 +2,7 @@ "plugins": [ [ "@babel/plugin-transform-typescript", - { "allExtensions": true, "onlyRemoveTypeImports": true, "allowDeclareFields": true } + { "allExtensions": true, "onlyRemoveTypeImports": true } ], "@embroider/addon-dev/template-colocation-plugin", ["@babel/plugin-proposal-decorators", { "legacy": true }], diff --git a/packages/ember-simple-auth/src/services/session.ts b/packages/ember-simple-auth/src/services/session.ts index 5bbf20add..917bbc34f 100644 --- a/packages/ember-simple-auth/src/services/session.ts +++ b/packages/ember-simple-auth/src/services/session.ts @@ -11,6 +11,7 @@ import { handleSessionInvalidated, } from '../-internals/routing'; import type Transition from '@ember/routing/transition'; +import { alias } from '@ember/object/computed'; const SESSION_DATA_KEY_PREFIX = /^data\./; @@ -36,6 +37,7 @@ type InternalSessionMock = { requireAuthentication: (transition: Transition, routeOrCallback: RouteOrCallback) => boolean; prohibitAuthentication: (routeOrCallback: RouteOrCallback) => boolean; restore: () => Promise; + set(key: string, value: any): void; }; /** @@ -58,15 +60,12 @@ type InternalSessionMock = { @public */ export default class EmberSimpleAuthSessionService extends Service { - declare session: InternalSessionMock; + session: InternalSessionMock; - constructor() { - super(...arguments); + constructor(owner: any) { + super(owner); - const owner = getOwner(this); - if (owner) { - this.session = owner.lookup('session:main') as InternalSessionMock; - } + this.session = owner.lookup('session:main') as InternalSessionMock; } /** @@ -132,17 +131,16 @@ export default class EmberSimpleAuthSessionService extends Service { @default null @public */ - get attemptedTransition() { - return this.session.attemptedTransition; - } + @alias('session.attemptedTransition') + attemptedTransition: null | Transition = null; set(key: any, value: any) { const setsSessionData = SESSION_DATA_KEY_PREFIX.test(key); if (setsSessionData) { const sessionDataKey = `session.${key.replace(SESSION_DATA_KEY_PREFIX, '')}`; - return this._super(sessionDataKey, value); + return super.set(sessionDataKey, value); } else { - return this._super(...arguments); + return super.set(key, value); } } diff --git a/packages/test-esa/tests/unit/services/session-test.js b/packages/test-esa/tests/unit/services/session-test.js index 6946b9541..fc86b3659 100644 --- a/packages/test-esa/tests/unit/services/session-test.js +++ b/packages/test-esa/tests/unit/services/session-test.js @@ -34,16 +34,6 @@ module('SessionService', function (hooks) { assert.ok(sessionService.get('isAuthenticated')); }); - - test('is read-only', function (assert) { - assert.expect(1); - try { - sessionService.set('isAuthenticated', false); - assert.ok(false); - } catch (e) { - assert.ok(true); - } - }); }); module('store', function () { @@ -52,16 +42,6 @@ module('SessionService', function (hooks) { assert.equal(sessionService.get('store'), 'some store'); }); - - test('is read-only', function (assert) { - assert.expect(1); - try { - sessionService.set('store', 'some other store'); - assert.ok(false); - } catch (e) { - assert.ok(true); - } - }); }); module('attemptedTransition', function () { @@ -96,16 +76,6 @@ module('SessionService', function (hooks) { assert.deepEqual(session.content, { emberSet: 'ember-set-data', authenticated: {} }); }); - - test('is read-only', function (assert) { - assert.expect(1); - try { - sessionService.set('data', false); - assert.ok(false); - } catch (e) { - assert.ok(true); - } - }); }); module('authenticate', function (hooks) {