Skip to content

feat: add ex-register-box component and Account API endpoint#66

Merged
Ross-s merged 4 commits intomainfrom
feature/ex-register-box
Apr 27, 2026
Merged

feat: add ex-register-box component and Account API endpoint#66
Ross-s merged 4 commits intomainfrom
feature/ex-register-box

Conversation

@Ross-s
Copy link
Copy Markdown
Member

@Ross-s Ross-s commented Apr 27, 2026

Summary

Adds a registration flow end-to-end: a new Stencil ex-register-box UI component, an AccountController API endpoint, and dev CORS configuration to wire them together.

Changes

packages/uiex-register-box Stencil component

  • New EXRegisterBox component (ex-register-box tag) with email, password, and confirm-password fields
  • Password visibility toggles for both password inputs
  • Client-side password match validation with inline error message
  • Fires exSubmit event with { email, password } on successful submission
  • Fires exSignIn event when the "Sign in" link is clicked
  • Calls POST /api/account via the generated @expressthat-auth/api-client
  • Extends ThemeBase for consistent theming
  • Exported from packages/ui/src/index.ts

apps/apiAccountController

  • New POST /api/account endpoint (Register action)
  • Accepts { email, password }, returns { id, email } (stub implementation)
  • No authorization required

apps/api – Dev CORS

  • Added CORS policy in Program.cs to allow requests from the local Vite/Next dev servers during development

apps/web

  • Minor update to page.tsx to render ex-register-box for local testing

Testing

  • Build the API (pnpm --filter api build) and regenerate the client if needed
  • Start both apps/api and apps/web via pnpm dev and verify the register box renders and submits

Ross-s and others added 3 commits April 27, 2026 05:21
Introduces a new Stencil web component, `ExRegisterBox`, which provides a complete UI for user registration.

This component includes:
- Email, password, and confirm password input fields.
- Password visibility toggling.
- Password confirmation validation.
- An event for form submission (`exSubmit`).
- An event for navigating to the sign-in page (`exSignIn`).
- A slot for integrating social login buttons.
- Full integration with the existing theming system.

The component is exposed in the `@expressthat-auth/ui-react` package and demonstrated in the example `apps/web` application. The `@expressthat-auth/api-client` is added as a dev dependency to the `ui` package, anticipating its use in future component logic.
The confirm password input's `onExChange` handler was not correctly
capturing its value, preventing it from updating the component's state.
This commit adds the necessary handler to bind the input's value
and removes a redundant `onExRightButtonClick` definition.
- Add AccountController with register endpoint
- Add ex-register-box Stencil component wired to API
- Fix ex-register-box submit button (shadow DOM form workaround)
- Allow all CORS in development environment
- Add main entry to packages/ui/package.json for Stencil dist
- Update stencil.config.ts and web page

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Ross-s Ross-s requested review from a team and Copilot April 27, 2026 05:10
@huly-for-github
Copy link
Copy Markdown

Connected to Huly®: AUTH-64

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an end-to-end registration path across the Stencil UI library, ASP.NET API, and the Next.js web app for local testing.

Changes:

  • Introduces a new ex-register-box Stencil component and exports it from @expressthat-auth/ui.
  • Adds a new POST /api/account registration endpoint (stub) and enables dev CORS.
  • Updates the web home page to render the new register box for manual verification.

Reviewed changes

Copilot reviewed 11 out of 13 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds workspace dependency on @expressthat-auth/api-client and esbuild for packages/ui.
packages/ui/stencil.config.ts Adds a Rollup plugin (esbuild-based) to transpile external TS workspace imports.
packages/ui/src/index.ts Exports the new EXRegisterBox.
packages/ui/src/components/ex-register-box/readme.md Auto-generated docs for the new component.
packages/ui/src/components/ex-register-box/ex-register-box.tsx Implements the registration UI, validation, events, and API call.
packages/ui/src/components/ex-register-box/ex-register-box.css Base host styling for the new component.
packages/ui/src/components/ex-input/readme.md Updates component usage graph to include ex-register-box.
packages/ui/src/components/ex-button/readme.md Updates component usage graph to include ex-register-box.
packages/ui/src/components.d.ts Updates generated Stencil typings for the new component/events.
packages/ui/package.json Adds api-client + esbuild dev deps and sets a main entry.
apps/web/src/app/page.tsx Renders ExRegisterBox for local testing and switches to @expressthat-auth/ui-react/next.
apps/api/Program.cs Adds a dev-only default CORS policy and enables it in development.
apps/api/Controllers/AccountController.cs Adds AccountController with Register action (stub response).
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines +42 to +50
this.client.account.register({
email: this.email,
password: this.password,
}) .then((response) => {
console.log(`Registration successful: Email: ${response.email}, User ID: ${response.id}`);
})
.catch((error) => {
console.error("Registration failed:", error);
});
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The promise chain formatting has a stray space before .then (}) .then(...)) and inconsistent indentation, which will likely fail Biome formatting checks. Please run the formatter (or adjust spacing/line breaks) so the chain is consistently formatted.

Suggested change
this.client.account.register({
email: this.email,
password: this.password,
}) .then((response) => {
console.log(`Registration successful: Email: ${response.email}, User ID: ${response.id}`);
})
.catch((error) => {
console.error("Registration failed:", error);
});
this.client.account
.register({
email: this.email,
password: this.password,
})
.then((response) => {
console.log(`Registration successful: Email: ${response.email}, User ID: ${response.id}`);
})
.catch((error) => {
console.error("Registration failed:", error);
});

Copilot uses AI. Check for mistakes.
Comment thread packages/ui/package.json
Comment on lines 6 to 9
"type": "module",
"main": "dist/index.cjs.js",
"module": "dist/components/index.js",
"collection": "dist/collection/collection-manifest.json",
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main points to dist/index.cjs.js, but this package is "type": "module" and your exports["."] doesn’t provide a require condition. If dist/index.cjs.js is actually CommonJS output, Node/tooling may treat it as ESM (because the extension is still .js) and/or ignore it due to exports, leading to confusing resolution behavior. Consider either removing main, renaming the CJS entry to a real .cjs file, and/or adding an explicit exports["."].require/default mapping to the correct artifact.

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +35
console.log("Submitting registration form with email:", this.email);
e?.preventDefault();
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid logging user identifiers from auth flows in a shared component library. console.log here will leak email addresses into browser logs (and could end up in remote log collectors). Please remove these logs or gate them behind an explicit debug flag.

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +53
this.client.account.register({
email: this.email,
password: this.password,
}) .then((response) => {
console.log(`Registration successful: Email: ${response.email}, User ID: ${response.id}`);
})
.catch((error) => {
console.error("Registration failed:", error);
});

this.exSubmit.emit({ email: this.email, password: this.password });
};
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exSubmit is emitted immediately after starting the API request, even if the request fails. This conflicts with the docstring (“on successful submission”) and can lead to consumers treating registration as successful when it isn’t. Emit the event only after the request resolves successfully (or emit a separate exError/exSubmitting state), and consider surfacing the server response (e.g. id, email) instead of re-emitting the password.

Copilot uses AI. Check for mistakes.
</div>

<div style={{ marginTop: "0.5rem" }}>
<ex-button label="Create account" type="button" variant="primary" {...theme} onExClick={this.handleSubmit} />
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The submit button is rendered as type="button" and manually calls handleSubmit. This differs from ex-login-box (which uses type="submit") and hurts keyboard behavior (Enter key submission) and form semantics. Prefer type="submit" on the <ex-button> and rely on the form’s onSubmit handler instead of wiring onExClick.

Suggested change
<ex-button label="Create account" type="button" variant="primary" {...theme} onExClick={this.handleSubmit} />
<ex-button label="Create account" type="submit" variant="primary" {...theme} />

Copilot uses AI. Check for mistakes.
Comment thread apps/api/Program.cs
Comment on lines +16 to +20
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
});
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says CORS is added “to allow requests from the local Vite/Next dev servers”, but the implementation uses AllowAnyOrigin() which allows any origin in development. If the intent is to only allow local dev UIs, configure explicit WithOrigins(...) entries (and add AllowCredentials() if you expect cookie-based auth).

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Authorization;
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using Microsoft.AspNetCore.Authorization; is unused in this controller (there’s no [Authorize]/[AllowAnonymous] usage). Please remove the unused using to keep the file clean, or add the intended attribute if authorization behavior was meant to be explicit.

Suggested change
using Microsoft.AspNetCore.Authorization;

Copilot uses AI. Check for mistakes.
const externalTsPlugin: Plugin = {
name: "external-ts",
async transform(code, id) {
if (id.endsWith(".ts") && !id.includes("/ui/src/")) {
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Rollup plugin excludes internal sources via !id.includes("/ui/src/"), which is path-separator dependent and will fail on Windows (paths use \\). That can cause the plugin to transpile this package’s own .ts modules unexpectedly. Use a separator-agnostic check (e.g., normalize the path, or check id.includes(path.join("packages","ui","src") + path.sep)), and consider narrowing the match to only the workspace packages you actually need to transpile.

Suggested change
if (id.endsWith(".ts") && !id.includes("/ui/src/")) {
const normalizedId = id.replace(/\\/g, "/");
if (id.endsWith(".ts") && !normalizedId.includes("/ui/src/")) {

Copilot uses AI. Check for mistakes.
@State() private showConfirmPassword: boolean = false;
@State() private confirmError: string = "";

private client = createExpressThatAuthClient("http://localhost:3001");
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createExpressThatAuthClient("http://localhost:3001") hardcodes a dev-only base URL inside a reusable UI component. This will break in non-local environments and makes SSR builds environment-dependent. Consider taking the base URL as a prop (or reading from a global config) and defaulting to same-origin (e.g. new URL("/", window.location.origin) on the client) where appropriate.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Ross-s Ross-s merged commit 163b057 into main Apr 27, 2026
21 checks passed
@Ross-s Ross-s deleted the feature/ex-register-box branch April 27, 2026 05:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants