Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/publish-sdk-angular.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ jobs:
cache: 'npm'
- name: Angular SDK - Install packages
run: yarn install --frozen-lockfile
- name: Copy Core to Angular
working-directory: ./packages/sdk-angular
run: yarn get-sdk-core
- name: Angular SDK - Test
run: yarn test:sdk-angular

Expand All @@ -35,6 +38,6 @@ jobs:
run: yarn build:sdk-angular
- name: Angular SDK - Publish
working-directory: ./packages/sdk-angular/dist/fusionauth-angular-sdk
run: npm publish
run: npm publish --dry-run
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN_ANGULAR_SDK }}
3 changes: 3 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ jobs:
cache: 'npm'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Copy Core to Angular
working-directory: ./packages/sdk-angular
run: yarn get-sdk-core
- name: Build Core
run: yarn build:core
- name: Run Tests
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules

dist
packages/sdk-angular/projects/fusionauth-angular-sdk/src/sdkcore

yarn-error.log

Expand Down
39 changes: 35 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Table of Contents

- [Development](#development)
- [Manual testing](#manual-testing)
- [Gotchas](#gotchas)
- [Architecture](#architecture)
- [Upgrade Policy](#upgrade-policy)

# FusionAuth Web SDKs

This is the FusionAuth Web SDKs monorepo. This repo manages FusionAuth [React](https://fusionauth.io/docs/sdks/react-sdk), [Angular](https://fusionauth.io/docs/sdks/angular-sdk), and [Vue](https://fusionauth.io/docs/sdks/vue-sdk) SDKs.
Expand All @@ -16,16 +24,39 @@ Install dependencies with `yarn install`.

The SDKs share a core package that contains framework agnostic functionality. This package should be built before the the SDK is built--a step included in the build script for each SDK (for example `build:sdk-react`).

### Manual testing

[yalc](https://github.com/wclr/yalc) is a way to test your changes locally.
## Manual testing

You may use the FusionAuth Quickstarts to consume the package and test changes. See [React Quickstart](https://fusionauth.io/docs/quickstarts/quickstart-javascript-react-web), [Angular Quickstart](https://fusionauth.io/docs/quickstarts/quickstart-javascript-angular-web), & [Vue Quickstart](https://fusionauth.io/docs/quickstarts/quickstart-javascript-vue-web)

Be aware of what node version you are using to publish and consume the package with yalc--mismatched versions can make the link not work.
There is more than one way to test your changes locally, but [yalc](https://github.com/wclr/yalc) has serves devs of this project well, as long as you pay attention to the [gotchas](#gotchas).

You may use the `yalc-pub:sdk` scripts in the root package.json. For example, `yarn yalc-pub:sdk-react`. These build the SDKs and publish to your yalc store so they may be consumed locally.

Here's a potential iteration:
- Make your changes in one of the SDKs. (Consider adding something like `console.log('Hello 👋')` where you know you’ll see it, to confirm your changes have been consumed.)
- Build the SDK and publish a local build of the package. You may use: `yarn yalc-pub:sdk-angular`
- cd into the app that will consume the local package.
- `yalc add @fusionauth/angular-sdk`
- Start the app and observe your changes.

### Gotchas

If your changes are not being consumed as you expected, consider the following:

- Delete `node_modules` and removing all previous yalc installations (`rm -rf node_modules && yalc remove --all`). Then reinstall dependencies and re-install from yalc. We've found this to provide consistent iterations, whereas `yalc push` has proved flakey for developers of this project.
- If your consuming application uses an application framework like Angular, Nuxt, or Next, consider deleting any cache directories (such as `.angular` or `.nuxt`) between iterations.
- Be aware of what node version you are using to publish and consume the package--mismatched node versions can cause yalc to flake with indication.

If you decide to use something like `yarn link` instead of `yalc`, be aware of how your dependencies are being consumed via the symlink. `yalc` copies your assets directly, so it's a more realistic representation of the production build than a symlink.

## Architecture

We use a monorepo because our SDKs share core functionality, which is contained in the @fusionauth-sdk/core package. This private module is bundled into the distributed SDK packages, allowing us to maintain core logic in a single place.

For React and Vue, our build tool is [`Vite`](https://vitejs.dev/guide/).

Angular differs slightly because [`@angular-devkit/build-angular:ng-packagr`](https://github.com/ng-packagr/ng-packagr), the builder for Angular libraries, doesn't support bundling dependencies from outside the Angular workspace. Our solution is to copy the core package's `src` directory into the Angular workspace without transpiling it, letting Angular's library builder handle it as if it were not an external dependency. This copied directory functions like a `dist`: it is git-ignored, and changes should be made in `packages/core`. The build process will then consume the updates. See [GitHub issue #84](https://github.com/FusionAuth/fusionauth-javascript-sdk/issues/84) for more details.

## Upgrade Policy

This library may periodically receive updates with bug fixes, security patches, tests, code samples, or documentation changes.
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@
"prepare": "husky",
"build:core": "yarn workspace @fusionauth-sdk/core build",
"build:lexicon": "yarn workspace @fusionauth-sdk/lexicon build",
"build:sdk-angular": "yarn build:lexicon && yarn build:core && yarn workspace sdk-angular-workspace build",
"build:sdk-angular": "yarn workspace sdk-angular-workspace build",
"build:sdk-react": "yarn build:lexicon && yarn build:core && yarn workspace @fusionauth/react-sdk build",
"build:sdk-vue": "yarn build:lexicon && yarn build:core && yarn workspace @fusionauth/vue-sdk build",
"yalc-pub:sdk-react": "yarn build:sdk-react && yalc publish packages/sdk-react",
"yalc-pub:sdk-vue": "yarn build:sdk-vue && yalc publish packages/sdk-vue",
"yalc-pub:sdk-angular": "yarn build:sdk-angular && yalc publish packages/sdk-angular/dist/fusionauth-angular-sdk",
"test": "yarn test:lexicon && yarn test:core && yarn test:sdk-react && yarn test:sdk-angular && yarn test:sdk-vue",
"test:core": "yarn workspace @fusionauth-sdk/core test",
"test:lexicon": "yarn workspace @fusionauth-sdk/lexicon test",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"dist"
],
"scripts": {
"build": "tsc && vite build",
"build": "vite build",
"dev:watch": "vite",
"test:watch": "vitest",
"test": "vitest --watch=false"
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/SDKCore/SDKCore.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { afterEach, describe, it, expect, vi } from 'vitest';

import { SDKConfig } from '#/SDKConfig';
import { SDKConfig } from '../SDKConfig';
import { SDKCore } from '.';

import { mockIsLoggedIn, removeAt_expCookie } from '..';
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/SDKCore/SDKCore.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { UrlHelper } from '#/UrlHelper';
import { SDKConfig } from '#/SDKConfig';
import { UserInfo } from '#/SDKContext';
import { RedirectHelper } from '#/RedirectHelper';
import { getAccessTokenExpirationMoment } from '#/CookieHelpers';
import { UrlHelper } from '../UrlHelper';
import { SDKConfig } from '../SDKConfig';
import { UserInfo } from '../SDKContext';
import { RedirectHelper } from '../RedirectHelper';
import { getAccessTokenExpirationMoment } from '../CookieHelpers';

/** A class containing framework-agnostic SDK methods */
export class SDKCore {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/UrlHelper/UrlHelperTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SDKConfig } from '#/SDKConfig';
import { SDKConfig } from '../SDKConfig';

/** A configuration object for the UrlHelper class. */
export type UrlHelperConfig = Pick<
Expand Down
6 changes: 1 addition & 5 deletions packages/core/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,

"paths": {
"#/*": ["./src/*"]
}
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
17 changes: 5 additions & 12 deletions packages/core/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,10 @@ export default defineConfig({
fileName: 'index',
formats: ['es'],
},
rollupOptions: {
external: ['**/*.test.*'],
},
},
plugins: [dts()],
server: {
port: 3001,
},
resolve: {
alias: {
'#': resolve(__dirname, './src'),
},
},
plugins: [
dts({
exclude: ['**/*.test.ts'],
}),
],
});
5 changes: 5 additions & 0 deletions packages/sdk-angular/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ An SDK for using FusionAuth in Angular applications.
- [FusionAuthService](#fusionauthservice)
- [Pre-built buttons](#pre-built-buttons)
- [State Parameter](#state-parameter)
- [SSR](#ssr)
- [Known issues](#known-issues)
- [Quickstart](#quickstart)
- [Documentation](#documentation)
Expand Down Expand Up @@ -174,6 +175,10 @@ pass any value you would like for the state parameter, it is often used to indic
which page the user was on before redirecting to login or registration, so that the
user can be returned to that location after a successful authentication.

#### SSR

The SDK supports Angular applications using SSR. No additional configuration is needed.

### Known Issues

None.
Expand Down
71 changes: 71 additions & 0 deletions packages/sdk-angular/getSDKCore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* This file is responsible for copying @fusionauth-sdk/core into this Angular package without transpiling it.
* This is to allow Angular's library builder to bundle the core code into dist.
* Further details here: https://github.com/FusionAuth/fusionauth-javascript-sdk/issues/84
*/

const fs = require('fs').promises;
const { existsSync } = require('fs');
const path = require('path');

async function copyDirectory(src, dest) {
await fs.mkdir(dest, { recursive: true });

const srcDirContents = await fs.readdir(src, { withFileTypes: true });

for (const item of srcDirContents) {
if (item.isFile() && item.name.endsWith('.test.ts')) {
continue;
}

const itemSrc = path.resolve(src, item.name);
const itemDest = path.resolve(dest, item.name);

if (item.isDirectory()) {
await copyDirectory(itemSrc, itemDest);
} else if (item.isFile()) {
await fs.copyFile(itemSrc, itemDest);
}
}
}

async function pruneDirectory(dir) {
if (!existsSync(dir)) {
// check if directory can be accessed before reading from it
return;
}

try {
const directoryContents = await fs.readdir(dir, {
withFileTypes: true,
});

await Promise.all(
directoryContents.map(async item => {
const itemPath = path.resolve(dir, item.name);

if (item.isDirectory()) {
await pruneDirectory(itemPath);
} else {
await fs.unlink(itemPath);
}
}),
);
} catch (err) {
throw err;
}
}

(async () => {
const coreSrc = '../core/src';
const coreDest = 'projects/fusionauth-angular-sdk/src/sdkcore';

await pruneDirectory(coreDest);
await copyDirectory(coreSrc, coreDest)
.then(() =>
console.log(`Successfully copied @fusionauth-sdk/core into ${coreDest}`),
)
.catch(err =>
console.error('Error copying core src directory for angular:', err),
);
})();
3 changes: 2 additions & 1 deletion packages/sdk-angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"version": "0.0.1",
"scripts": {
"ng": "ng",
"build": "ng build && cp README.md dist/fusionauth-angular-sdk/README.md",
"get-sdk-core": "node getSDKCore.js",
"build": "yarn get-sdk-core && ng build && cp README.md dist/fusionauth-angular-sdk/README.md",
"test": "ng test --watch=false --browsers=ChromeHeadless",
"test:watch": "ng test",
"docs": "typedoc --plugin typedoc-plugin-markdown"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// import { CookieAdapter } from '@fusionauth-sdk/core';
import { CookieAdapter } from '../sdkcore';

/** An adapter class that supports accessing cookies with SSR */
export class SSRCookieAdapter /* implements CookieAdapter */ {
export class SSRCookieAdapter implements CookieAdapter {
constructor(private isBrowser: boolean) {}

at_exp(cookieName: string = 'app.at_exp') {
Expand Down
Loading