Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

README

Effect App is a light-weight framework to build resilient and fully type-safe services and apps with Effect and FP-TS, in a statically typed functional style in the latest of Typescript. Compiler extensions through ts-plus are recommended, yet not required. It allows for a compiler/type driven development, where often, if it compiles, your program is probably quite correct :) Reducing the need for boilerplate testing and providing you a level of confidence out of the box.

We aim to provide defaults in the box which are useful to 80% of the apps you want to build.

Models and Resources

All data modeling is Schema based. It powers the strong domain modelling, RPC (client+api controllers), database schema, input/form schemas, providing a single source of truth for all models and refined primitives.

Your UI and services will never be out of sync, and even the fully type-safe api client (incl. runtime client side input and response validation) to use in your apps is automatically derived from your resource specifications, also guiding the implementation of your api controllers.

Data type architecture/hierarchy

Sketch..

alt text

Concepts

  • Applications
    • API - private business logic, endpoints with resources for UI
    • UI - views and public business logic, uses derived clients to talk to endpoints on the API
  • Messages - talk between API/Worker services
  • Resources - talk between UI and API - think REST resources, actions, view models.
  • Models - domain core types, many others are derived from these

Queries (read) & Commands/Mutations (write)

TBD

Messaging Queues

TBD

in the box are adapters for:

  • in memory (mem://): great for testing locally, no resilience, only works within a single process (but you can of course compose multiple service entrypoints into a single app).
  • Azure ServiceBus: (Endpoint=)
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Long Running Operations

TBD

UI Events

TBD

  • Published to UI via Server Sent Events

Configuration

Configuration is specified in API config.ts files, and leverages the built-in Effect Config.

Logging

Logging defaults to the logfmt format. It's recommended to use humanlog for improved formatting and highlighting, especially of embedded JSON payloads.

Database

The default storage adapters and setup is for document databases. There is the Persistence Model (how does the data look like within the data store), Encoded type (often the same as persistence model) and Model type (fully validated and strong domain types).

Adapters

In the box Store are adapters for

  • memory (mem://): good for local development, tests, single instance, no need for migrations
  • disk (disk://.data): good for local development, tests, single instance, migrations optional
  • redis (redis://...): good for dev instances, single instance, migrations optional
  • CosmosDB (AccountEndpoint=): production ready, multi instance support
  • Mongo (WIP) (mongo://...): production ready, multi instance support
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Transactions

While basic transaction support for ACID operations is possible, it is often limited to one collection and perhaps 100 records at a time, therefore it is recommended to design mutations in non corruptive ways, and consider reconciliation options.

e.g:

  • remove links before removing the actual record
  • design in a way where you can process batches

Migrations

Data migrations are manual and explicit. Empty values should be null, so omitted/undefined values in the data are usually considered suspicious and an error. So if you use a persistent database adapter like diskdb, cosmos, redis or mongo, you need to make sure you migrate your data, via:

  • just in time migration within the repository, when converting from Persistence Model, to Encoded type, before parsing
  • implementing a migration strategy that runs at start up or at specific command request
  • manually writin/executing migration queries for the particular database.

locally when the data is considered disposable, you could also increment the STORAGE_VERSION constant, which will ignore previous data, and store under a new namespace.

Concurrency

By default, optimistic concurrency is used via an _etag field. If the _etag on a record changed between reading the record, and updating the record, an OptimisticConcurrencyException is thrown. You will need to handle it as appropriate for your case.

Domain & Integration Events

During saving operations you can include events (domain or integration events), each repository decides what events to support and what to do with them. Often an Event needs to be published on a Queue or MessageBus, after the data has been successfuly saved. To make this even more durable, you can save the events within the same database transaction, so that if reaching a queue fails after saving or the process is terminated, you can reconsile this by replaying unprocessed events from the database.

The Pure type helps you to build logic that builds or updates state, and logs events to be picked up by the save and publish. It composes nicely. Which is inspired by ZPure

Links

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

README

Effect App is a light-weight framework to build resilient and fully type-safe services and apps with Effect and FP-TS, in a statically typed functional style in the latest of Typescript. Compiler extensions through ts-plus are recommended, yet not required. It allows for a compiler/type driven development, where often, if it compiles, your program is probably quite correct :) Reducing the need for boilerplate testing and providing you a level of confidence out of the box.

We aim to provide defaults in the box which are useful to 80% of the apps you want to build.

Models and Resources

All data modeling is Schema based. It powers the strong domain modelling, RPC (client+api controllers), database schema, input/form schemas, providing a single source of truth for all models and refined primitives.

Your UI and services will never be out of sync, and even the fully type-safe api client (incl. runtime client side input and response validation) to use in your apps is automatically derived from your resource specifications, also guiding the implementation of your api controllers.

Data type architecture/hierarchy

Sketch..

alt text

Concepts

  • Applications
    • API - private business logic, endpoints with resources for UI
    • UI - views and public business logic, uses derived clients to talk to endpoints on the API
  • Messages - talk between API/Worker services
  • Resources - talk between UI and API - think REST resources, actions, view models.
  • Models - domain core types, many others are derived from these

Queries (read) & Commands/Mutations (write)

TBD

Messaging Queues

TBD

in the box are adapters for:

  • in memory (mem://): great for testing locally, no resilience, only works within a single process (but you can of course compose multiple service entrypoints into a single app).
  • Azure ServiceBus: (Endpoint=)
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Long Running Operations

TBD

UI Events

TBD

  • Published to UI via Server Sent Events

Configuration

Configuration is specified in API config.ts files, and leverages the built-in Effect Config.

Logging

Logging defaults to the logfmt format. It's recommended to use humanlog for improved formatting and highlighting, especially of embedded JSON payloads.

Database

The default storage adapters and setup is for document databases. There is the Persistence Model (how does the data look like within the data store), Encoded type (often the same as persistence model) and Model type (fully validated and strong domain types).

Adapters

In the box Store are adapters for

  • memory (mem://): good for local development, tests, single instance, no need for migrations
  • disk (disk://.data): good for local development, tests, single instance, migrations optional
  • redis (redis://...): good for dev instances, single instance, migrations optional
  • CosmosDB (AccountEndpoint=): production ready, multi instance support
  • Mongo (WIP) (mongo://...): production ready, multi instance support
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Transactions

While basic transaction support for ACID operations is possible, it is often limited to one collection and perhaps 100 records at a time, therefore it is recommended to design mutations in non corruptive ways, and consider reconciliation options.

e.g:

  • remove links before removing the actual record
  • design in a way where you can process batches

Migrations

Data migrations are manual and explicit. Empty values should be null, so omitted/undefined values in the data are usually considered suspicious and an error. So if you use a persistent database adapter like diskdb, cosmos, redis or mongo, you need to make sure you migrate your data, via:

  • just in time migration within the repository, when converting from Persistence Model, to Encoded type, before parsing
  • implementing a migration strategy that runs at start up or at specific command request
  • manually writin/executing migration queries for the particular database.

locally when the data is considered disposable, you could also increment the STORAGE_VERSION constant, which will ignore previous data, and store under a new namespace.

Concurrency

By default, optimistic concurrency is used via an _etag field. If the _etag on a record changed between reading the record, and updating the record, an OptimisticConcurrencyException is thrown. You will need to handle it as appropriate for your case.

Domain & Integration Events

During saving operations you can include events (domain or integration events), each repository decides what events to support and what to do with them. Often an Event needs to be published on a Queue or MessageBus, after the data has been successfuly saved. To make this even more durable, you can save the events within the same database transaction, so that if reaching a queue fails after saving or the process is terminated, you can reconsile this by replaying unprocessed events from the database.

The Pure type helps you to build logic that builds or updates state, and logs events to be picked up by the save and publish. It composes nicely. Which is inspired by ZPure

Links

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

README

Effect App is a light-weight framework to build resilient and fully type-safe services and apps with Effect and FP-TS, in a statically typed functional style in the latest of Typescript. Compiler extensions through ts-plus are recommended, yet not required. It allows for a compiler/type driven development, where often, if it compiles, your program is probably quite correct :) Reducing the need for boilerplate testing and providing you a level of confidence out of the box.

We aim to provide defaults in the box which are useful to 80% of the apps you want to build.

Models and Resources

All data modeling is Schema based. It powers the strong domain modelling, RPC (client+api controllers), database schema, input/form schemas, providing a single source of truth for all models and refined primitives.

Your UI and services will never be out of sync, and even the fully type-safe api client (incl. runtime client side input and response validation) to use in your apps is automatically derived from your resource specifications, also guiding the implementation of your api controllers.

Data type architecture/hierarchy

Sketch..

alt text

Concepts

  • Applications
    • API - private business logic, endpoints with resources for UI
    • UI - views and public business logic, uses derived clients to talk to endpoints on the API
  • Messages - talk between API/Worker services
  • Resources - talk between UI and API - think REST resources, actions, view models.
  • Models - domain core types, many others are derived from these

Queries (read) & Commands/Mutations (write)

TBD

Messaging Queues

TBD

in the box are adapters for:

  • in memory (mem://): great for testing locally, no resilience, only works within a single process (but you can of course compose multiple service entrypoints into a single app).
  • Azure ServiceBus: (Endpoint=)
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Long Running Operations

TBD

UI Events

TBD

  • Published to UI via Server Sent Events

Configuration

Configuration is specified in API config.ts files, and leverages the built-in Effect Config.

Logging

Logging defaults to the logfmt format. It's recommended to use humanlog for improved formatting and highlighting, especially of embedded JSON payloads.

Database

The default storage adapters and setup is for document databases. There is the Persistence Model (how does the data look like within the data store), Encoded type (often the same as persistence model) and Model type (fully validated and strong domain types).

Adapters

In the box Store are adapters for

  • memory (mem://): good for local development, tests, single instance, no need for migrations
  • disk (disk://.data): good for local development, tests, single instance, migrations optional
  • redis (redis://...): good for dev instances, single instance, migrations optional
  • CosmosDB (AccountEndpoint=): production ready, multi instance support
  • Mongo (WIP) (mongo://...): production ready, multi instance support
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Transactions

While basic transaction support for ACID operations is possible, it is often limited to one collection and perhaps 100 records at a time, therefore it is recommended to design mutations in non corruptive ways, and consider reconciliation options.

e.g:

  • remove links before removing the actual record
  • design in a way where you can process batches

Migrations

Data migrations are manual and explicit. Empty values should be null, so omitted/undefined values in the data are usually considered suspicious and an error. So if you use a persistent database adapter like diskdb, cosmos, redis or mongo, you need to make sure you migrate your data, via:

  • just in time migration within the repository, when converting from Persistence Model, to Encoded type, before parsing
  • implementing a migration strategy that runs at start up or at specific command request
  • manually writin/executing migration queries for the particular database.

locally when the data is considered disposable, you could also increment the STORAGE_VERSION constant, which will ignore previous data, and store under a new namespace.

Concurrency

By default, optimistic concurrency is used via an _etag field. If the _etag on a record changed between reading the record, and updating the record, an OptimisticConcurrencyException is thrown. You will need to handle it as appropriate for your case.

Domain & Integration Events

During saving operations you can include events (domain or integration events), each repository decides what events to support and what to do with them. Often an Event needs to be published on a Queue or MessageBus, after the data has been successfuly saved. To make this even more durable, you can save the events within the same database transaction, so that if reaching a queue fails after saving or the process is terminated, you can reconsile this by replaying unprocessed events from the database.

The Pure type helps you to build logic that builds or updates state, and logs events to be picked up by the save and publish. It composes nicely. Which is inspired by ZPure

Links

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

README

Effect App is a light-weight framework to build resilient and fully type-safe services and apps with Effect and FP-TS, in a statically typed functional style in the latest of Typescript. Compiler extensions through ts-plus are recommended, yet not required. It allows for a compiler/type driven development, where often, if it compiles, your program is probably quite correct :) Reducing the need for boilerplate testing and providing you a level of confidence out of the box.

We aim to provide defaults in the box which are useful to 80% of the apps you want to build.

Models and Resources

All data modeling is Schema based. It powers the strong domain modelling, RPC (client+api controllers), database schema, input/form schemas, providing a single source of truth for all models and refined primitives.

Your UI and services will never be out of sync, and even the fully type-safe api client (incl. runtime client side input and response validation) to use in your apps is automatically derived from your resource specifications, also guiding the implementation of your api controllers.

Data type architecture/hierarchy

Sketch..

alt text

Concepts

  • Applications
    • API - private business logic, endpoints with resources for UI
    • UI - views and public business logic, uses derived clients to talk to endpoints on the API
  • Messages - talk between API/Worker services
  • Resources - talk between UI and API - think REST resources, actions, view models.
  • Models - domain core types, many others are derived from these

Queries (read) & Commands/Mutations (write)

TBD

Messaging Queues

TBD

in the box are adapters for:

  • in memory (mem://): great for testing locally, no resilience, only works within a single process (but you can of course compose multiple service entrypoints into a single app).
  • Azure ServiceBus: (Endpoint=)
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Long Running Operations

TBD

UI Events

TBD

  • Published to UI via Server Sent Events

Configuration

Configuration is specified in API config.ts files, and leverages the built-in Effect Config.

Logging

Logging defaults to the logfmt format. It's recommended to use humanlog for improved formatting and highlighting, especially of embedded JSON payloads.

Database

The default storage adapters and setup is for document databases. There is the Persistence Model (how does the data look like within the data store), Encoded type (often the same as persistence model) and Model type (fully validated and strong domain types).

Adapters

In the box Store are adapters for

  • memory (mem://): good for local development, tests, single instance, no need for migrations
  • disk (disk://.data): good for local development, tests, single instance, migrations optional
  • redis (redis://...): good for dev instances, single instance, migrations optional
  • CosmosDB (AccountEndpoint=): production ready, multi instance support
  • Mongo (WIP) (mongo://...): production ready, multi instance support
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Transactions

While basic transaction support for ACID operations is possible, it is often limited to one collection and perhaps 100 records at a time, therefore it is recommended to design mutations in non corruptive ways, and consider reconciliation options.

e.g:

  • remove links before removing the actual record
  • design in a way where you can process batches

Migrations

Data migrations are manual and explicit. Empty values should be null, so omitted/undefined values in the data are usually considered suspicious and an error. So if you use a persistent database adapter like diskdb, cosmos, redis or mongo, you need to make sure you migrate your data, via:

  • just in time migration within the repository, when converting from Persistence Model, to Encoded type, before parsing
  • implementing a migration strategy that runs at start up or at specific command request
  • manually writin/executing migration queries for the particular database.

locally when the data is considered disposable, you could also increment the STORAGE_VERSION constant, which will ignore previous data, and store under a new namespace.

Concurrency

By default, optimistic concurrency is used via an _etag field. If the _etag on a record changed between reading the record, and updating the record, an OptimisticConcurrencyException is thrown. You will need to handle it as appropriate for your case.

Domain & Integration Events

During saving operations you can include events (domain or integration events), each repository decides what events to support and what to do with them. Often an Event needs to be published on a Queue or MessageBus, after the data has been successfuly saved. To make this even more durable, you can save the events within the same database transaction, so that if reaching a queue fails after saving or the process is terminated, you can reconsile this by replaying unprocessed events from the database.

The Pure type helps you to build logic that builds or updates state, and logs events to be picked up by the save and publish. It composes nicely. Which is inspired by ZPure

Links

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

README

Effect App is a light-weight framework to build resilient and fully type-safe services and apps with Effect and FP-TS, in a statically typed functional style in the latest of Typescript. Compiler extensions through ts-plus are recommended, yet not required. It allows for a compiler/type driven development, where often, if it compiles, your program is probably quite correct :) Reducing the need for boilerplate testing and providing you a level of confidence out of the box.

We aim to provide defaults in the box which are useful to 80% of the apps you want to build.

Models and Resources

All data modeling is Schema based. It powers the strong domain modelling, RPC (client+api controllers), database schema, input/form schemas, providing a single source of truth for all models and refined primitives.

Your UI and services will never be out of sync, and even the fully type-safe api client (incl. runtime client side input and response validation) to use in your apps is automatically derived from your resource specifications, also guiding the implementation of your api controllers.

Data type architecture/hierarchy

Sketch..

alt text

Concepts

  • Applications
    • API - private business logic, endpoints with resources for UI
    • UI - views and public business logic, uses derived clients to talk to endpoints on the API
  • Messages - talk between API/Worker services
  • Resources - talk between UI and API - think REST resources, actions, view models.
  • Models - domain core types, many others are derived from these

Queries (read) & Commands/Mutations (write)

TBD

Messaging Queues

TBD

in the box are adapters for:

  • in memory (mem://): great for testing locally, no resilience, only works within a single process (but you can of course compose multiple service entrypoints into a single app).
  • Azure ServiceBus: (Endpoint=)
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Long Running Operations

TBD

UI Events

TBD

  • Published to UI via Server Sent Events

Configuration

Configuration is specified in API config.ts files, and leverages the built-in Effect Config.

Logging

Logging defaults to the logfmt format. It's recommended to use humanlog for improved formatting and highlighting, especially of embedded JSON payloads.

Database

The default storage adapters and setup is for document databases. There is the Persistence Model (how does the data look like within the data store), Encoded type (often the same as persistence model) and Model type (fully validated and strong domain types).

Adapters

In the box Store are adapters for

  • memory (mem://): good for local development, tests, single instance, no need for migrations
  • disk (disk://.data): good for local development, tests, single instance, migrations optional
  • redis (redis://...): good for dev instances, single instance, migrations optional
  • CosmosDB (AccountEndpoint=): production ready, multi instance support
  • Mongo (WIP) (mongo://...): production ready, multi instance support
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Transactions

While basic transaction support for ACID operations is possible, it is often limited to one collection and perhaps 100 records at a time, therefore it is recommended to design mutations in non corruptive ways, and consider reconciliation options.

e.g:

  • remove links before removing the actual record
  • design in a way where you can process batches

Migrations

Data migrations are manual and explicit. Empty values should be null, so omitted/undefined values in the data are usually considered suspicious and an error. So if you use a persistent database adapter like diskdb, cosmos, redis or mongo, you need to make sure you migrate your data, via:

  • just in time migration within the repository, when converting from Persistence Model, to Encoded type, before parsing
  • implementing a migration strategy that runs at start up or at specific command request
  • manually writin/executing migration queries for the particular database.

locally when the data is considered disposable, you could also increment the STORAGE_VERSION constant, which will ignore previous data, and store under a new namespace.

Concurrency

By default, optimistic concurrency is used via an _etag field. If the _etag on a record changed between reading the record, and updating the record, an OptimisticConcurrencyException is thrown. You will need to handle it as appropriate for your case.

Domain & Integration Events

During saving operations you can include events (domain or integration events), each repository decides what events to support and what to do with them. Often an Event needs to be published on a Queue or MessageBus, after the data has been successfuly saved. To make this even more durable, you can save the events within the same database transaction, so that if reaching a queue fails after saving or the process is terminated, you can reconsile this by replaying unprocessed events from the database.

The Pure type helps you to build logic that builds or updates state, and logs events to be picked up by the save and publish. It composes nicely. Which is inspired by ZPure

Links

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

README

Effect App is a light-weight framework to build resilient and fully type-safe services and apps with Effect and FP-TS, in a statically typed functional style in the latest of Typescript. Compiler extensions through ts-plus are recommended, yet not required. It allows for a compiler/type driven development, where often, if it compiles, your program is probably quite correct :) Reducing the need for boilerplate testing and providing you a level of confidence out of the box.

We aim to provide defaults in the box which are useful to 80% of the apps you want to build.

Models and Resources

All data modeling is Schema based. It powers the strong domain modelling, RPC (client+api controllers), database schema, input/form schemas, providing a single source of truth for all models and refined primitives.

Your UI and services will never be out of sync, and even the fully type-safe api client (incl. runtime client side input and response validation) to use in your apps is automatically derived from your resource specifications, also guiding the implementation of your api controllers.

Data type architecture/hierarchy

Sketch..

alt text

Concepts

  • Applications
    • API - private business logic, endpoints with resources for UI
    • UI - views and public business logic, uses derived clients to talk to endpoints on the API
  • Messages - talk between API/Worker services
  • Resources - talk between UI and API - think REST resources, actions, view models.
  • Models - domain core types, many others are derived from these

Queries (read) & Commands/Mutations (write)

TBD

Messaging Queues

TBD

in the box are adapters for:

  • in memory (mem://): great for testing locally, no resilience, only works within a single process (but you can of course compose multiple service entrypoints into a single app).
  • Azure ServiceBus: (Endpoint=)
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Long Running Operations

TBD

UI Events

TBD

  • Published to UI via Server Sent Events

Configuration

Configuration is specified in API config.ts files, and leverages the built-in Effect Config.

Logging

Logging defaults to the logfmt format. It's recommended to use humanlog for improved formatting and highlighting, especially of embedded JSON payloads.

Database

The default storage adapters and setup is for document databases. There is the Persistence Model (how does the data look like within the data store), Encoded type (often the same as persistence model) and Model type (fully validated and strong domain types).

Adapters

In the box Store are adapters for

  • memory (mem://): good for local development, tests, single instance, no need for migrations
  • disk (disk://.data): good for local development, tests, single instance, migrations optional
  • redis (redis://...): good for dev instances, single instance, migrations optional
  • CosmosDB (AccountEndpoint=): production ready, multi instance support
  • Mongo (WIP) (mongo://...): production ready, multi instance support
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Transactions

While basic transaction support for ACID operations is possible, it is often limited to one collection and perhaps 100 records at a time, therefore it is recommended to design mutations in non corruptive ways, and consider reconciliation options.

e.g:

  • remove links before removing the actual record
  • design in a way where you can process batches

Migrations

Data migrations are manual and explicit. Empty values should be null, so omitted/undefined values in the data are usually considered suspicious and an error. So if you use a persistent database adapter like diskdb, cosmos, redis or mongo, you need to make sure you migrate your data, via:

  • just in time migration within the repository, when converting from Persistence Model, to Encoded type, before parsing
  • implementing a migration strategy that runs at start up or at specific command request
  • manually writin/executing migration queries for the particular database.

locally when the data is considered disposable, you could also increment the STORAGE_VERSION constant, which will ignore previous data, and store under a new namespace.

Concurrency

By default, optimistic concurrency is used via an _etag field. If the _etag on a record changed between reading the record, and updating the record, an OptimisticConcurrencyException is thrown. You will need to handle it as appropriate for your case.

Domain & Integration Events

During saving operations you can include events (domain or integration events), each repository decides what events to support and what to do with them. Often an Event needs to be published on a Queue or MessageBus, after the data has been successfuly saved. To make this even more durable, you can save the events within the same database transaction, so that if reaching a queue fails after saving or the process is terminated, you can reconsile this by replaying unprocessed events from the database.

The Pure type helps you to build logic that builds or updates state, and logs events to be picked up by the save and publish. It composes nicely. Which is inspired by ZPure

Links

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

README

Effect App is a light-weight framework to build resilient and fully type-safe services and apps with Effect and FP-TS, in a statically typed functional style in the latest of Typescript. Compiler extensions through ts-plus are recommended, yet not required. It allows for a compiler/type driven development, where often, if it compiles, your program is probably quite correct :) Reducing the need for boilerplate testing and providing you a level of confidence out of the box.

We aim to provide defaults in the box which are useful to 80% of the apps you want to build.

Models and Resources

All data modeling is Schema based. It powers the strong domain modelling, RPC (client+api controllers), database schema, input/form schemas, providing a single source of truth for all models and refined primitives.

Your UI and services will never be out of sync, and even the fully type-safe api client (incl. runtime client side input and response validation) to use in your apps is automatically derived from your resource specifications, also guiding the implementation of your api controllers.

Data type architecture/hierarchy

Sketch..

alt text

Concepts

  • Applications
    • API - private business logic, endpoints with resources for UI
    • UI - views and public business logic, uses derived clients to talk to endpoints on the API
  • Messages - talk between API/Worker services
  • Resources - talk between UI and API - think REST resources, actions, view models.
  • Models - domain core types, many others are derived from these

Queries (read) & Commands/Mutations (write)

TBD

Messaging Queues

TBD

in the box are adapters for:

  • in memory (mem://): great for testing locally, no resilience, only works within a single process (but you can of course compose multiple service entrypoints into a single app).
  • Azure ServiceBus: (Endpoint=)
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Long Running Operations

TBD

UI Events

TBD

  • Published to UI via Server Sent Events

Configuration

Configuration is specified in API config.ts files, and leverages the built-in Effect Config.

Logging

Logging defaults to the logfmt format. It's recommended to use humanlog for improved formatting and highlighting, especially of embedded JSON payloads.

Database

The default storage adapters and setup is for document databases. There is the Persistence Model (how does the data look like within the data store), Encoded type (often the same as persistence model) and Model type (fully validated and strong domain types).

Adapters

In the box Store are adapters for

  • memory (mem://): good for local development, tests, single instance, no need for migrations
  • disk (disk://.data): good for local development, tests, single instance, migrations optional
  • redis (redis://...): good for dev instances, single instance, migrations optional
  • CosmosDB (AccountEndpoint=): production ready, multi instance support
  • Mongo (WIP) (mongo://...): production ready, multi instance support
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Transactions

While basic transaction support for ACID operations is possible, it is often limited to one collection and perhaps 100 records at a time, therefore it is recommended to design mutations in non corruptive ways, and consider reconciliation options.

e.g:

  • remove links before removing the actual record
  • design in a way where you can process batches

Migrations

Data migrations are manual and explicit. Empty values should be null, so omitted/undefined values in the data are usually considered suspicious and an error. So if you use a persistent database adapter like diskdb, cosmos, redis or mongo, you need to make sure you migrate your data, via:

  • just in time migration within the repository, when converting from Persistence Model, to Encoded type, before parsing
  • implementing a migration strategy that runs at start up or at specific command request
  • manually writin/executing migration queries for the particular database.

locally when the data is considered disposable, you could also increment the STORAGE_VERSION constant, which will ignore previous data, and store under a new namespace.

Concurrency

By default, optimistic concurrency is used via an _etag field. If the _etag on a record changed between reading the record, and updating the record, an OptimisticConcurrencyException is thrown. You will need to handle it as appropriate for your case.

Domain & Integration Events

During saving operations you can include events (domain or integration events), each repository decides what events to support and what to do with them. Often an Event needs to be published on a Queue or MessageBus, after the data has been successfuly saved. To make this even more durable, you can save the events within the same database transaction, so that if reaching a queue fails after saving or the process is terminated, you can reconsile this by replaying unprocessed events from the database.

The Pure type helps you to build logic that builds or updates state, and logs events to be picked up by the save and publish. It composes nicely. Which is inspired by ZPure

Links

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

README

Effect App is a light-weight framework to build resilient and fully type-safe services and apps with Effect and FP-TS, in a statically typed functional style in the latest of Typescript. Compiler extensions through ts-plus are recommended, yet not required. It allows for a compiler/type driven development, where often, if it compiles, your program is probably quite correct :) Reducing the need for boilerplate testing and providing you a level of confidence out of the box.

We aim to provide defaults in the box which are useful to 80% of the apps you want to build.

Models and Resources

All data modeling is Schema based. It powers the strong domain modelling, RPC (client+api controllers), database schema, input/form schemas, providing a single source of truth for all models and refined primitives.

Your UI and services will never be out of sync, and even the fully type-safe api client (incl. runtime client side input and response validation) to use in your apps is automatically derived from your resource specifications, also guiding the implementation of your api controllers.

Data type architecture/hierarchy

Sketch..

alt text

Concepts

  • Applications
    • API - private business logic, endpoints with resources for UI
    • UI - views and public business logic, uses derived clients to talk to endpoints on the API
  • Messages - talk between API/Worker services
  • Resources - talk between UI and API - think REST resources, actions, view models.
  • Models - domain core types, many others are derived from these

Queries (read) & Commands/Mutations (write)

TBD

Messaging Queues

TBD

in the box are adapters for:

  • in memory (mem://): great for testing locally, no resilience, only works within a single process (but you can of course compose multiple service entrypoints into a single app).
  • Azure ServiceBus: (Endpoint=)
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Long Running Operations

TBD

UI Events

TBD

  • Published to UI via Server Sent Events

Configuration

Configuration is specified in API config.ts files, and leverages the built-in Effect Config.

Logging

Logging defaults to the logfmt format. It's recommended to use humanlog for improved formatting and highlighting, especially of embedded JSON payloads.

Database

The default storage adapters and setup is for document databases. There is the Persistence Model (how does the data look like within the data store), Encoded type (often the same as persistence model) and Model type (fully validated and strong domain types).

Adapters

In the box Store are adapters for

  • memory (mem://): good for local development, tests, single instance, no need for migrations
  • disk (disk://.data): good for local development, tests, single instance, migrations optional
  • redis (redis://...): good for dev instances, single instance, migrations optional
  • CosmosDB (AccountEndpoint=): production ready, multi instance support
  • Mongo (WIP) (mongo://...): production ready, multi instance support
  • adding your own is a piece of cake

(All of these are based on established community or vendor libraries)

Transactions

While basic transaction support for ACID operations is possible, it is often limited to one collection and perhaps 100 records at a time, therefore it is recommended to design mutations in non corruptive ways, and consider reconciliation options.

e.g:

  • remove links before removing the actual record
  • design in a way where you can process batches

Migrations

Data migrations are manual and explicit. Empty values should be null, so omitted/undefined values in the data are usually considered suspicious and an error. So if you use a persistent database adapter like diskdb, cosmos, redis or mongo, you need to make sure you migrate your data, via:

  • just in time migration within the repository, when converting from Persistence Model, to Encoded type, before parsing
  • implementing a migration strategy that runs at start up or at specific command request
  • manually writin/executing migration queries for the particular database.

locally when the data is considered disposable, you could also increment the STORAGE_VERSION constant, which will ignore previous data, and store under a new namespace.

Concurrency

By default, optimistic concurrency is used via an _etag field. If the _etag on a record changed between reading the record, and updating the record, an OptimisticConcurrencyException is thrown. You will need to handle it as appropriate for your case.

Domain & Integration Events

During saving operations you can include events (domain or integration events), each repository decides what events to support and what to do with them. Often an Event needs to be published on a Queue or MessageBus, after the data has been successfuly saved. To make this even more durable, you can save the events within the same database transaction, so that if reaching a queue fails after saving or the process is terminated, you can reconsile this by replaying unprocessed events from the database.

The Pure type helps you to build logic that builds or updates state, and logs events to be picked up by the save and publish. It composes nicely. Which is inspired by ZPure

Links

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors