- From GitHub Issues
- Configure
prettier
- Set up
.editorconfig
- Set up
husky
+lint-staged
to runeslint
/prettier
- Conventional Commits, Conventional Changelog, Semantic Release,
release.yml
,semantic.yml
, Commitlint, Commitizen, etc - Implement Next Auth
refresh_token
rotation - Implement Next Auth Federated Logout (eg. OpenID Connect Federated Logout)
- Implement 'copy on write' drafts
- Monaco - Save/restore undo history
- Explore/embody the best practices described in Stripe's 'Designing APIs for Humans' blog series and similar
- Explore methods for prefixing generated database record IDs by type
- Consider JSON:API best practices (eg. error formats, etc)
- Explore best methods for unit/integration tests
- Set up
.devcontainer/devcontainer.json
for Copilot Workspace / etc
- Configure
- See Also
This is an issue to remind me to review our current prettier configuration, and ensure it matches how I like things to work.
Set up
.editorconfig
and ensure it aligns with our prettier config:
- https://editorconfig.org/
What is EditorConfig? EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.
- https://typicode.github.io/husky/
Husky enhances your commits and more 🐶 woof!
Automatically lint your commit messages, code, and run tests upon committing or pushing.
- https://github.com/typicode/husky
- https://github.com/lint-staged/lint-staged
🚫💩 — Run linters on git staged files
Run linters against staged git files and don't let 💩 slip into your code base!
- https://eslint.org/
- https://github.com/eslint/eslint
Find and fix problems in your JavaScript code.
- https://prettier.io/
- https://github.com/prettier/prettier
Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.
Conventional Commits, Conventional Changelog, Semantic Release, release.yml
, semantic.yml
, Commitlint, Commitizen, etc
See:
- continuedev/continue#5300
-
Improve GitHub release notes by grouping changes under logical subheadings
- Lots of different tools/GitHub actions/etc in here.. need to figure out what my favourite choice/combo is; then can document it more specifically here.
-
- https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuring-automatically-generated-release-notes
release.yml
- etc
- https://authjs.dev/guides/refresh-token-rotation
Refresh Token Rotation As of today, there is no built-in solution for automatic Refresh Token rotation. This guide will help you to achieve this in your application. Our goal is to add zero-config support for built-in providers eventually.
There is an inherent limitation of the following guides that comes from the fact, that - for security reasons - refresh_tokens are usually only usable once. Meaning that after a successful refresh, the refresh_token will be invalidated and cannot be used again. Therefore, in some cases, a race-condition might occur if multiple requests will try to refresh the token at the same time. The Auth.js team is aware of this and would like to provide a solution in the future. This might include some “lock” mechanism to prevent multiple requests from trying to refresh the token at the same time, but that comes with the drawback of potentially creating a bottleneck in the application. Another possible solution is background token refresh, to prevent the token from expiring during an authenticated request.
- https://authjs.dev/guides/refresh-token-rotation#database-strategy
Database strategy Using the database session strategy is similar, but instead we will save the
access_token
,expires_at
andrefresh_token
on the account for the given provider.- https://github.com/nextauthjs/next-auth-refresh-token-example
- nextauthjs/next-auth#4229
- https://stackoverflow.com/questions/75164721/nextauth-refresh-token-with-azure-ad
- https://next-auth.js.org/getting-started/client#updating-the-session
X Also asked about whether Next Auth has a logout callback URI, which from some quick googling, sounds like it might relate to OpenID Connect federated logout; which isn't built in to Next Auth:
- https://stackoverflow.com/questions/74557856/next-auth-azure-ad-b2c-signout-problem-session-kills-on-app-but-not-on-azure-ad
Next Auth Azure Ad B2C signout problem session kills on app but not on azure AD
I am integrating Next Auth with Azure AD B2C i am able to create a login session when i login or signup on azure AD but when i signout using next Auth i am not signing out of azure AD and it automatically signins me in till the azure AD session expires that is 1 day after a day i will get option again to sign in.
You can either..
- Force users to re-enter their credentials on each login
signIn("azure-ad-b2c", null, { prompt: "login" })
- Reference: Next-Auth "Additional parameters" documentation
- Defer calling
signOut()
until after you redirect to B2C, as B2C handles clearing its session
- Reference: Benjamin Fox Blog, Azure B2C with Next-Auth
- https://next-auth.js.org/configuration/events#signout
- nextauthjs/next-auth#3938
- https://kinderas.com/technology/implementing-federated-sign-out-when-using-next-auth-in-you-next-js-app
Implementing federated sign out when using next-auth in you Next.js app
When using federated auth, such a Google or a custom oAuth & OpenId Connect setup, a user will in some cases expect to be signed out from the original provider as well as your Next application. In this post I'll go into detail on how this can be achieved using next-auth v4.
Next-auth will as writing this (v4.10) not automatically handle federated sign out defined by the OpenId standard, so we have to manually implement this.
This post is based on this Github discussion over at the next-auth repo. See sources below.
- https://learn.microsoft.com/en-us/azure/active-directory-b2c/session-behavior?pivots=b2c-user-flow#sign-out
Sign out When you want to sign the user out of the application, it isn't enough to clear the application's cookies or otherwise end the session with the user. You must redirect the user to Azure AD B2C to sign out. Otherwise, the user might be able to reauthenticate to your applications without entering their credentials again.
Upon a sign-out request, Azure AD B2C:
- Invalidates the Azure AD B2C cookie-based session.
- Attempts to sign out from federated identity providers.
The sign-out clears the user's single sign-on state with Azure AD B2C, but it might not sign the user out of their social identity provider session. If the user selects the same identity provider during a subsequent sign-in, they might reauthenticate without entering their credentials. If a user wants to sign out of the application, it doesn't necessarily mean they want to sign out of their Facebook account. However, if local accounts are used, the user's session ends properly.
- https://learn.microsoft.com/en-us/azure/active-directory-b2c/session-behavior#secure-your-logout-redirect
Secure your logout redirect After logout, the user is redirected to the URI specified in the post_logout_redirect_uri parameter, regardless of the reply URLs that you specify for the application. However, if a valid id_token_hint is passed and the Require ID Token in logout requests is turned on, Azure AD B2C verifies that the value of post_logout_redirect_uri matches one of the application's configured redirect URIs before performing the redirect. If no matching reply URL was configured for the application, an error message is displayed and the user isn't redirected.
To require an ID Token in logout requests: ..snip..
To configure your application Logout URL: ..snip..
- https://dev.to/aryaman_/implementing-federated-sign-out-with-authjs-in-nextjs-14-app-router-44jj
Implementing Federated Sign-Out with Auth.js in Next.js 14 App Router
The Challenge Auth.js doesn't provide built-in support for federated sign-out as defined by the OpenID Connect standard. This means we need to implement it manually to ensure our users are properly signed out from both the client application and the identity provider.
See also:
- https://gist.github.com/0xdevalias/20cfaaeb33698440b58b00ab97dd3bbc#copy-on-write--event-sourcing-for-edit-history
-
Copy on Write + Event Sourcing for Edit History
-
Some random thoughts/notes from Messenger the other day:
Random article about copy on write: https://softwarepatternslexicon.com/103/4/5/
The article itself doesn’t matter hugely, but the ‘related patterns’ at the end reminded me of this:
Event Sourcing: Used to record changes as a sequence of events, which enables reconstructing states from these events, similar to CoW’s rollback and history features.
Which coincides with something that was floating in my mind recently RE: how we could store ‘in progress drafts’ of responses in case the user’s browser crashes or similar.
Obviously wouldn’t want to pollute the main response table with this as it would get too big too quickly; so probably would be a new table with a single ‘in progress draft’ per user at most.
Could also just store this in browser local storage if we didn’t want to persist it in the DB.
But anyways; then I was thinking about undo history, or being able to see more fine grained changes on a version; and that’s where the event sourcing pattern could fit in.
Whether it’s on an in progress draft, or on a saved response version itself; there could be an additional field (probably JSON field) that stores the ‘edit history’ events since the last ‘snapshot’ (for a saved model, that would basically be the edits made since the last saved model)
That would allow seeing finer grained edits as a sort of metadata; while having a single ‘snapshot’ of the main content as a single block of text still.
See also:
- https://gist.github.com/0xdevalias/20cfaaeb33698440b58b00ab97dd3bbc#copy-on-write--event-sourcing-for-edit-history
-
Copy on Write + Event Sourcing for Edit History
-
- https://gist.github.com/0xdevalias/2fc3d66875dcc76d5408ce324824deab#editor-frameworks-and-collaborative-editingconflict-resolution-tech
-
Editor Frameworks and Collaborative Editing/Conflict Resolution Tech
-
Further reading RE: 'edit history':
- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.ITextModel.html#applyEdits
applyEdits
Edit the model without adding the edits to the undo stack. This can have dire consequences on the undo stack!- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.ITextModel.html#pushEditOperations
pushEditOperations
Push edit operations, basically editing the model. This is the preferred way of editing the model. The edit operations will land on the undo stack.- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.ITextModel.html#popStackElement
popStackElement
Open the current undo-redo element. This offers a way to remove the current undo/redo stop point.- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.ITextModel.html#pushStackElement
pushStackElement
Close the current undo-redo element. This offers a way to create an undo/redo stop point.- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.ITextModel.html#getVersionId
getVersionId
Get the current version id of the model. Anytime a change happens to the model (even undo/redo), the version id is incremented.- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.ITextModel.html#getAlternativeVersionId
Get the alternative version id of the model. This alternative version id is not always incremented, it will return the same values in the case of undo-redo.
- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IIdentifiedSingleEditOperation.html
Interface
IIdentifiedSingleEditOperation
A single edit operation, that has an identifier.- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.ITextModel.html#onDidChangeContent
onDidChangeContent
An event emitted when the contents of the model have changed.- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IModelContentChangedEvent.html
Interface
IModelContentChangedEvent
An event describing a change in the text of a model.- https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IModelContentChange.html
Interface
IModelContentChange
- microsoft/monaco-editor#977
I'm trying to implement tabs for editor and I'm storing viewState of prev file before switch to new tab
prevFile.historyData = editorInstance.saveViewState();
so, when user switches back to this tab, Im restoring viewstate of this file thru:newEditorInstance.restoreViewState(curFile.historyData);
It works perfectly for scroll position, selection e.t.c, but undo/redo history is gone and user is not able to get his undo/redo history, that was before switching tabs.try this #604
- microsoft/monaco-editor#604 (comment)
To implement tabs, the recommended way is:
create a single editor instance via
monaco.editor.create({ ... , model: null })
create N model instances via
monaco.editor.createModel(...)
.switch tabs by calling
editorInstance.setModel(modelInstance)
for each model, you can save its view state (cursor, scroll position, etc) via
editorInstance.saveViewState()
and restore it viaeditorInstance.restoreViewState()
.e.g. the code of the playground -- https://github.com/Microsoft/monaco-editor/blob/bad3c34056624dca34ac8be5028ae3454172125c/website/playground/playground.js#L108
- microsoft/monaco-editor#686
Get/Restore Monaco editor Undo&Redo stack
I want to create a system to store the Undo&Redo stack of the Monaco editor.
UPDATE: The model records edits in its own structure. However, we don't have a direct access through its API. The next example seems to work but it keeps everything in memory. I would like to have a way where I could serialize it.
var model = editorInstance.getModel(); var viewState = editorInstance.saveViewState(); //Destroy your instance for whatever reason editorInstance.dispose(); //When you create the new instance load the model that you saved var newInstance = monaco.editor.create(elem, options); newInstance.setModel(model); newInstance.restoreViewState(viewState);- microsoft/monaco-editor#686 (comment)
I've figured out how. first, you have redefine the
EditStackElement
class because it's not exported. ..snip..then backup like this
{ history: JSON.stringify({ past: model['_commandManager'].past, future: model['_commandManager'].future, }) }and restore like this
if (history){ if (history.past && history.past.length) { editor['_commandManager'].past.push(...history.past.map(data => new EditStackElement(data))); } if (history.future && history.future.length) { editor['_commandManager'].future.push(...history.future.map(data => new EditStackElement(data))); } }- microsoft/monaco-editor#686 (comment)
It looks like the internal interface behind undo stack serialization changed, has anybody got any ideas on how to work with the new one?
Undo stacks seem to have "createSnapshot" and "restoreSnapshot" methods now, but I'm not sure where the actual data is stored, without that disposing of models breaks restoration.
- microsoft/monaco-editor#686 (comment)
The data is now held inside
UndoRedoService._editStacks
(https://github.com/microsoft/vscode/blob/e451364da155c9d59229d0d6a973a66e46592308/src/vs/platform/undoRedo/common/undoRedoService.ts#L434)- microsoft/monaco-editor#686 (comment)
It looks like using
model._commandManager._undoRedoService.getElements(model.uri)
, you can get an object with past and future elements, but they're filled withSingleModelEditStackElements
, which are created byeditStack.js
here:_getOrCreateEditStackElement
- microsoft/monaco-editor#686 (comment)
Be warned that this is quite difficult. Here's what we do in vscode to keep undo/redo state between closing an reopening a file. Please note that we don't yet support in vscode keeping undo/redo state across window reloads:
- when the model is about to be disposed, if its undo/redo state is resonably sized (e.g. to exclude files where someone pasted 200MB etc.), we compute its sha1 and we invalidate the undo/redo elements stored in the
IUndoRedoService
. We remember the model's URI, its sha1, and more inDisposedModelInfo
- when a model is about to be created, we check if we have some previous state stored for it, we validate it if the sha matches, and then revive the stack elements and mark them as valid.
- there are a lot of vscode specific complications, such as having undo-redo elements for models which are not really text edits (like for example when dragging & dropping cells in a notebook)
- this is probably also vscode specific, but we have a participant in the undo-redo elements which reopens closed files in case an undo would want to execute across files (e.g. you rename a variable across 4 files and close 3 of them and then undo). You will encounter this as
SingleModelEditStackElement
orMultiModelEditStackElement
.- microsoft/monaco-editor#686 (comment)
For anyone who comes from new version (0.26.1), here is a workaround:
switchModelToNewUri
- microsoft/monaco-editor#686 (comment)
This code works. Obviously, it's all private APIs, so YMMV and is only valid as of
[email protected]
, although it may work in other versions too.- microsoft/monaco-editor#686 (comment)
Does anyone know a workaround to achieve this that works at the moment? I tried with
@lukeautry
‘s solution and it doesn‘t restore the undo/redo stack.- microsoft/monaco-editor#239
Hi, is there any way to serialize the editing session? I want to have the capability to save the code, selection range, cursor, undo manager etc. on the server side. I've found
saveViewState
method, but i can't find the way to serialize the editor model.- microsoft/monaco-editor#239 (comment)
At this time there's no API to serialize the undo/redo stack, so that would be lost, the view state contains the cursor state (selection state) and scroll state, you can save the model text via
model.getValue()
. We plan to add serializable undo/redo stack soon, but it is problematic w.r.t. what should be its limit (number of edits vs size of the edits) -- today the undo stack is unbounded which is okaysh given it sits in memory, when serializing it, we need to introduce some cut-off heuristics.- https://stackoverflow.com/questions/78444302/monaco-editor-possible-to-check-redo-stack
Monaco editor - possible to check redo stack?
what I am looking to do is to disable the "redo" button if there isnt anything to redo. Is there a way to query the redo stack to see if there is anything in there?
- https://stackoverflow.com/questions/78444302/monaco-editor-possible-to-check-redo-stack/78777814#78777814
Yes, you can. Short answer is:
editor.getModel().canUndo();
See
undoRedoService
. It hascanUndo
andcanRedo
methods: https://github.com/microsoft/vscode/blob/cba3b821977fbd1d45eacf0add96cbf9e3865c1e/src/vs/platform/undoRedo/common/undoRedoService.ts#L697Unfortunately, these two methods are marked as
@internal
on theITextModel
interface, so TypeScript users would need to cast to any: https://github.com/microsoft/vscode/blob/d64d40ad01d0d3a0230b93231332536ec1884b8a/src/vs/editor/common/model.ts#L1197
Explore/embody the best practices described in Stripe's 'Designing APIs for Humans' blog series and similar
Explore/embody the best practices described in Stripe's 'Designing APIs for Humans' blog series and similar:
- https://dev.to/paulasjes/series/19794
Designing APIs for humans Series' Articles
- https://dev.to/stripe/designing-apis-for-humans-object-ids-3o5a
Designing APIs for humans: Object IDs
- See also:
- https://dev.to/stripe/designing-apis-for-humans-error-messages-94p
Designing APIs for humans: Error messages
- https://dev.to/stripe/designing-apis-for-humans-design-patterns-5847
Designing APIs for humans: Design patterns
- https://dev.to/stripe/common-design-patterns-at-stripe-1hb4
Common design patterns at Stripe
- https://stripe.com/blog/engineering
- https://stripe.com/blog/markdoc
How Stripe builds interactive docs with Markdoc
- https://markdoc.dev/
Use Markdoc to create interactive documentation experiences, static content sites, authoring tooling, and more.
Stripe created Markdoc to power its largest and most detailed content site. Since then, we have adopted it across the company, writing hundreds of thousands of lines of Markdoc to create thousands of pages of expressive, custom documentation.
- https://github.com/markdoc/markdoc
Markdoc
A powerful, flexible, Markdown-based authoring framework.
Markdoc is a Markdown-based syntax and toolchain for creating custom documentation sites and experiences. We designed Markdoc to power Stripe's public docs, our largest and most complex content site.
- https://stripe.com/blog/accessible-color-systems
Designing accessible color systems
- https://stripe.com/blog/api-versioning
APIs as infrastructure: future-proofing Stripe with versioning
- https://stripe.com/blog/rate-limiters
Scaling your API with rate limiters
- https://stripe.com/blog/idempotency
Designing robust and predictable APIs with idempotency
- https://stripe.com/blog/online-migrations
Online migrations at scale
See also:
It can be useful for DB record IDs to include a prefix that represents their type. This is used by companies such as Stripe/etc, and improves developer experience, as well as providing other tangible benefits:
- https://dev.to/stripe/designing-apis-for-humans-object-ids-3o5a
Designing APIs for humans: Object IDs
Currently Prisma doesn't support generating IDs with prefixes natively in their schema definitions:
- prisma/prisma#3391
Support adding prefix to an
@id
field- Possible workaround from July 10 20222: prisma/prisma#3391 (comment)
- Possible workaround from February 6 2024: prisma/prisma#3391 (comment)
- Possible workaround from May 24 2024: prisma/prisma#3391 (comment)
- https://github.com/jetify-com/typeid-js
Official TypeID-JS Package
TypeScript implementation of TypeIDs: type-safe, K-sortable, and globally unique identifiers inspired by Stripe IDs
TypeIDs are a modern, type-safe, globally unique identifier based on the upcoming UUIDv7 standard. They provide a ton of nice properties that make them a great choice as the primary identifiers for your data in a database, APIs, and distributed systems. Read more about TypeIDs in their spec.
- https://github.com/jetify-com/typeid
TypeID A type-safe, K-sortable, globally unique identifier inspired by Stripe IDs
TypeIDs are a modern, type-safe extension of UUIDv7. Inspired by a similar use of prefixes in Stripe's APIs.
TypeIDs are canonically encoded as lowercase strings consisting of three parts:
- A type prefix (at most 63 characters in all lowercase snake_case ASCII [a-z_]).
- An underscore '_' separator
- A 128-bit UUIDv7 encoded as a 26-character string using a modified base32 encoding.
- Possible workaround from September 29 2024: prisma/prisma#3391 (comment)
- prisma/prisma#6719
Support custom user defined ID patterns (on model and global basis)
- Possible workaround from July 8 2022: prisma/prisma#6719 (comment)
- Possible workaround from July 8 2022: prisma/prisma#6719 (comment) + amendment to it prisma/prisma#6719 (comment)
- Postgres workaround from October 21 2022: prisma/prisma#6719 (comment) + variation on it prisma/prisma#6719 (comment)
- Nanoid workaround from Jan 6 2023: prisma/prisma#6719 (comment)
- prisma/prisma#6930
Want to build a Prisma extension for
@default(<fn>)
, could you hint where I should look?@default(dbgenerated("gen_random_uuid()"))
: prisma/prisma#6930 (reply in thread)- Prisma client extension workaround from June 23 2023: prisma/prisma#6930 (reply in thread)
- prisma/prisma#12243
Prisma + PostgreSQL: Prefixing uuid-primary keys with
dbgenerated()
@default(dbgenerated("(concat('usr_', gen_random_uuid()))::TEXT"))
- prisma/prisma#12243 (comment)
It can be even shorter after ignoring type inference.
@default(dbgenerated("'user-' || gen_random_uuid()"))
- prisma/prisma#2396
Prefixed default values for model fields within the schema
- prisma/prisma#3580
Allow prefixing a cuid similar to Stripe and Slack does
- https://jsonapi.org/
JSON API
A specification for building APIs in JSON
JSON:API v1.1 was finalized September 30, 2022!
If you’ve ever argued with your team about the way your JSON responses should be formatted, JSON:API can help you stop the bikeshedding and focus on what matters: your application.
By following shared conventions, you can increase productivity, take advantage of generalized tooling and best practices.
- https://jsonapi.org/format/
Latest Specification (v1.1)
- https://jsonapi.org/format/#document-structure
7 - Document Structure
- https://jsonapi.org/format/#document-top-level
7.1 - Top Level
- https://jsonapi.org/format/#document-resource-objects
7.2 - Resource Objects
- https://jsonapi.org/format/#document-resource-identifier-objects
7.3 - Resource Identifier Objects
- https://jsonapi.org/format/#document-compound-documents
7.4 - Compound Documents
- https://jsonapi.org/format/#document-meta
7.5 - Meta Information
- https://jsonapi.org/format/#document-links
7.6 - Links
- https://jsonapi.org/format/#fetching
8 - Fetching Data
- https://jsonapi.org/format/#fetching-sorting
8.5 - Sorting
- https://jsonapi.org/format/#fetching-pagination
8.6 - Pagination
- https://jsonapi.org/format/#fetching-filtering
8.7 - Filtering
- https://jsonapi.org/format/#errors
11 - Errors
- https://jsonapi.org/format/#error-objects
11.2 - Error Objects
- https://jsonapi.org/extensions/
Extensions and Profiles The JSON:API specification provides a way to define new functionality not provided by the base specification using extensions. Additionally, it provides a means to share a particular usage of the specification among implementations using profiles.
Extensions
Atomic Operations URI: https://jsonapi.org/ext/atomic Namespace: atomic Description: This extension provides a means to perform multiple “operations” in a linear and atomic manner.
Profiles Cursor Pagination URI: https://jsonapi.org/profiles/ethanresnick/cursor-pagination Description: Cursor-based pagination (aka keyset pagination) is a common pagination strategy that avoids many of the pitfalls of “offset–limit” pagination.
- https://jsonapi.org/profiles/ethanresnick/cursor-pagination/
“Cursor Pagination” Profile
My default answer for unit tests used to be Jest:
- https://jestjs.io/
Jest is a delightful JavaScript Testing Framework with a focus on simplicity.
It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!
- https://github.com/jestjs/jest
Jest Delightful JavaScript Testing.
But these days I think a better option might actually be Vitest:
- https://vitest.dev/
Vitest Next Generation Testing Framework
A Vite-native testing framework. It's fast!
- https://github.com/vitest-dev/vitest
Vitest
Next generation testing framework powered by Vite.
Possibly also combined with something like
testing-library
:
- https://testing-library.com/
Testing Library Simple and complete testing utilities that encourage good testing practices
- https://github.com/testing-library/react-testing-library
React Testing Library
Simple and complete React DOM testing utilities that encourage good testing practices.
For integration tests (eg. browser tests) I don't have as deep knowledge, but I believe Playwright is probably a good place to start from memory:
- https://playwright.dev/
Playwright enables reliable end-to-end testing for modern web apps
- https://github.com/microsoft/playwright
Playwright
Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
There are no doubt more options/considerations here.. but that is a quick 'top of mind' context dump.
Some other random things vaguely in this space:
- https://storybook.js.org/
Build UIs without the grunt work Storybook is a frontend workshop for building UI components and pages in isolation. Thousands of teams use it for UI development, testing, and documentation. It's open source and free.
- https://github.com/storybookjs/storybook
Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
- https://mswjs.io/
Industry standard API mocking for JavaScript. Mock Service Worker is an API mocking library that allows you to write client-agnostic mocks and reuse them across any frameworks, tools, and environments.
- https://github.com/mswjs/msw
Mock Service Worker Mock Service Worker (MSW) is a seamless REST/GraphQL API mocking library for browser and Node.js.
- https://docs.github.com/en/copilot/using-github-copilot/using-github-copilot-for-pull-requests/using-copilot-to-help-you-work-on-a-pull-request#verifying-your-changes
Verifying your changes Workspace includes a built-in terminal and a quick way to build, run, and test your code.
- https://docs.github.com/en/copilot/using-github-copilot/using-github-copilot-for-pull-requests/using-copilot-to-help-you-work-on-a-pull-request#configuring-quick-commands-for-your-repository
Configuring quick commands for your repository You can set default Build, Run, and Test commands for everyone who uses Copilot Workspace to work on pull requests for your repository.
Note: The
.devcontainer/devcontainer.json
file is a configuration file for codespaces created for a repository. For more information, see Introduction to dev containers.
- https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers
Introduction to dev containers When you work in a codespace, the environment you are working in is created using a development container, or dev container, hosted on a virtual machine.
- https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/setting-up-your-nodejs-project-for-codespaces
Setting up a Node.js project for GitHub Codespaces Get started with a Node.js, JavaScript, or TypeScript project in GitHub Codespaces by creating a custom dev container configuration.
- https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/configuring-dev-containers/adding-features-to-a-devcontainer-file
Adding features to a
devcontainer.json
file With features, you can quickly add tools, runtimes, or libraries to your dev container configuration.
- https://containers.dev/implementors/features/
Specification Dev Container Features reference Development Container Features are self-contained, shareable units of installation code and development container configuration. The name comes from the idea that referencing one of them allows you to quickly and easily add more tooling, runtime, or library “features” into your development container for you or your collaborators to use.
- https://containers.dev/features
Available Dev Container Features
PostgreSQL | John Chlark Sumatra | ghcr.io/itsmechlark/features/postgresql:1 | 1.5.0
- https://gist.github.com/0xdevalias
- https://github.com/0xdevalias
- CLI App Tech Stack Things (0xdevalias' gist)
- Design Systems (0xdevalias' gist)
- Web Extensions / Browser Extensions / Chrome Extensions / etc (0xdevalias' gist)
- Azure serverless functions and related features/patterns/etc (0xdevalias' gist)
- Explore methods for prefixing Prisma generated database record IDs by type (0xdevalias' gist)
- Editor Frameworks and Collaborative Editing/Conflict Resolution Tech (0xdevalias' gist)
- Copy on Write + Event Sourcing for Edit History (0xdevalias' gist)
- My Typesafe/Etc Stack(0xdevalias' gist)