### Starting Klerk Instance (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/intro.md Shows how to create and start a Klerk instance using the previously built configuration. The klerk.meta.start() call initializes the framework. ```kotlin val klerk = Klerk.create(config) klerk.meta.start() ``` -------------------------------- ### Reading Data with Klerk (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/intro.md Provides an example of how to use the Klerk instance to read data. This snippet shows a basic read operation to retrieve an item by its ID. ```kotlin val myBook = klerk.read(context) { get(myBookId) } ``` -------------------------------- ### Building Klerk Configuration (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/intro.md Demonstrates how to create a Klerk configuration object using ConfigBuilder, which is the first step in defining the rules and structure for the Klerk system. ```kotlin val config = ConfigBuilder(collections).build { // lots of stuff here } ``` -------------------------------- ### Start Local Development Server - Docusaurus Website - Shell Source: https://github.com/klerk-framework/website/blob/main/README.md Starts a local development server for the website. This command opens a browser window and provides live reloading for most changes. ```shell $ yarn start ``` -------------------------------- ### Install Dependencies - Docusaurus Website - Shell Source: https://github.com/klerk-framework/website/blob/main/README.md Installs the necessary project dependencies using the Yarn package manager. This command should be run after cloning the repository. ```shell $ yarn ``` -------------------------------- ### Adding Klerk Repository in settings.gradle.kts (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/intro.md Configures the dependency resolution management in settings.gradle.kts to include mavenCentral() and jitpack.io repositories, which are required to fetch the Klerk framework dependency. ```kotlin dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() maven ("https://jitpack.io") } } ``` -------------------------------- ### Adding Klerk Dependency in build.gradle.kts (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/intro.md Adds the Klerk framework as an implementation dependency in the build.gradle.kts file, specifying the artifact coordinates. Replace with the desired version. ```kotlin dependencies { implementation("com.github.klerk-framework:") } ``` -------------------------------- ### Configuring GraphQL Routes in Ktor (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/graphql.md Set up the standard GraphQL routes (POST, GET, GraphiQL, SDL) within your Ktor application's routing block to expose the GraphQL API. ```Kotlin routing { graphQLPostRoute() graphQLGetRoute() graphiQLRoute() graphQLSDLRoute() } ``` -------------------------------- ### Quick Start Defining Data Object and Klerk Config Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/collections.md Provides a minimal example for defining a 'Data' object with a 'ModelCollections' property for the 'Invoice' model and then using this object to configure Klerk via 'ConfigBuilder'. This is a recommended starting point. ```Kotlin object Data { val invoices = ModelCollections() // add one property like this for each model you have } val config = ConfigBuilder(Data).build { ... } ``` -------------------------------- ### Installing GraphQL Plugin in Ktor (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/graphql.md Install the GraphQL plugin within your Ktor application's module configuration, specifying the schema packages, queries, and mutations. ```Kotlin embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = { install(GraphQL) { schema { packages = listOf("dev.klerkframework.graphql") queries = listOf(GenericQuery(klerk, ::graphQlContextProvider)) mutations = listOf(EventMutationService(klerk, ::graphQlContextProvider)) } } // remaining configuration }).start(wait = true) ``` -------------------------------- ### Reading Data with Context in Klerk (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/context.md Shows a basic example of using the `klerk.read` function to fetch data, emphasizing the requirement to provide a context object for the operation. ```Kotlin val myReport = klerk.read(context) { get(myReportId) } ``` -------------------------------- ### Reading a single model with Klerk Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/usage/reading.md Demonstrates the simplest way to read a single model using the `klerk.read` block and the `get` method, which throws an exception if the item doesn't exist or is unauthorized. Requires a context and the model ID. ```Kotlin val myModel = klerk.read(context) { get(id) } ``` -------------------------------- ### Allowing All Actions Insecurely in Klerk Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/authorization.md This snippet provides a quick way to configure Klerk authorization to allow all actions. It uses the insecureAllowEverything() function within the authorization block. This is intended for initial setup or testing and should not be used in production environments as it disables security. ```Klerk DSL authorization { apply(insecureAllowEverything()) } ``` -------------------------------- ### Reading three models using Triple in Klerk Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/usage/reading.md Shows how to read three distinct models within a single `klerk.read` block by returning a `Triple`. The result can be destructured into individual variables. Uses the `get` method for each item, assuming they are expected to exist. ```Kotlin val (first, second, third) = klerk.read(context) { Triple(get(firstId), get(secondId), get(thirdId)) } ``` -------------------------------- ### Reading two models using Pair in Klerk Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/usage/reading.md Illustrates reading two distinct models within a single `klerk.read` block by returning a `Pair`. The result can be destructured into individual variables. Uses the `get` method for each item, assuming they are expected to exist. ```Kotlin val (first, second) = klerk.read(context) { Pair(get(firstId), get(secondId)) } ``` -------------------------------- ### Building Gradle Project via Command Line Source: https://github.com/klerk-framework/website/blob/main/docs/advanced-topics/troubleshooting.md Execute this command in the project's root directory to build the project using the Gradle wrapper from the command line. This helps determine if a build issue is specific to the IntelliJ IDE or a general problem with the Gradle configuration or dependencies. ```Shell ./gradlew build ``` -------------------------------- ### Build the form Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md Before calling `call.respondHtml` we need to build the form by initializing parameters and using a form template. ```kotlin val initialValues = CreateAuthorParams( firstName = FirstName("James"), lastName = LastName("Clavell") ) val createAuthorForm = klerk.read(context) { createAuthorFormTemplate.build(call, initialValues, this, translator = context.translator) } ``` -------------------------------- ### Build Static Website - Docusaurus Website - Shell Source: https://github.com/klerk-framework/website/blob/main/README.md Generates the static content for the website into the 'build' directory. The output can be served using any standard static file server. ```shell $ yarn build ``` -------------------------------- ### Deploy Website (GitHub Pages) - Docusaurus Website - Shell Source: https://github.com/klerk-framework/website/blob/main/README.md Deploys the built website content, typically to GitHub Pages. This command requires specifying the GitHub username via the GIT_USER environment variable. ```shell $ GIT_USER= yarn deploy ``` -------------------------------- ### Handling Command with Klerk (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/usage/commands.md This snippet demonstrates how to issue a command using the `klerk.handle` function. It shows the structure of a `Command` object, including the event (`CreateAuthor`), model (set to `null` as it's a creation command), and parameters (`CreateAuthorParams`). It also includes the required `context` and `ProcessingOptions` with a simple `CommandToken` for idempotence. ```Kotlin val result = klerk.handle( Command( event = CreateAuthor, model = null, params = CreateAuthorParams( firstName = FirstName("Astrid"), lastName = LastName("Lindgren"), ), ), context, ProcessingOptions(CommandToken.simple()), ) ``` -------------------------------- ### Deploy Website (SSH) - Docusaurus Website - Shell Source: https://github.com/klerk-framework/website/blob/main/README.md Deploys the built website content using Yarn, specifically configured to use SSH for the deployment process. ```shell $ USE_SSH=true yarn deploy ``` -------------------------------- ### Add Klerk-web Dependencies (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md Add the necessary Klerk and Klerk-web dependencies to your project's build configuration (e.g., build.gradle.kts or build.gradle) using Kotlin syntax. This makes the Klerk and Klerk-web libraries available for use in your Ktor application. ```kotlin implementation("com.github.klerk-framework:klerk:$klerk_version") implementation("com.github.klerk-framework:klerk-web:$klerk_web_version") ``` -------------------------------- ### Configure LowCodeConfig (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md Define the LowCodeConfig object required by Klerk-web. This configuration specifies the base path for the admin UI, provides functions to obtain the application context and control optional parameter visibility, and sets the CSS path. ```kotlin val lowCodeConfig = LowCodeConfig( basePath = "/admin", contextProvider = ::contextFromCall, showOptionalParameters = ::showOptionalParameters, cssPath = "https://unpkg.com/almond.css@latest/dist/almond.min.css", knownAlgorithms = setOf() ) suspend fun contextFromCall(call: ApplicationCall): Ctx { // as described in https://klerkframework.dev/docs/building-config/context a Context is always required when // interacting with Klerk. This function tells Klerk-web how to get this Context. } fun showOptionalParameters(event: EventReference) = false // this function will not required in the future ``` -------------------------------- ### Adding Klerk-graphql Dependencies (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/graphql.md Add the necessary dependencies for graphql-kotlin-ktor-server and klerk-graphql to your project's build file (e.g., build.gradle.kts or build.gradle). ```Kotlin implementation("com.expediagroup:graphql-kotlin-ktor-server:$graphql_version") implementation("com.github.klerk-framework:klerk-graphql:$klerk_graphql_version") ``` -------------------------------- ### Configuring Klerk Context Provider (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/context.md Shows how to configure a simple `contextProvider` within the Klerk `ConfigBuilder`. This provider is used by Klerk internally when it needs a context for system-initiated operations, such as those triggered by state machines or plugins. ```Kotlin val config = ConfigBuilder(collections).build { contextProvider { actor -> Ctx(actor) } ... } ``` -------------------------------- ### Configuring Klerk with SQLite Persistence (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/advanced-topics/persistence.md Creates an instance of SqlPersistence using the configured DataSource and then integrates it into the Klerk configuration using the ConfigBuilder. This tells Klerk to use the specified SQLite database for persistence. ```Kotlin val sqlitePersistence = SqlPersistence(ds) val config = ConfigBuilder(Data).build { persistence(sqlitePersistence) ... } ``` -------------------------------- ### Render Buttons for Instance Events (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md Show how to use Klerk-web's easy mode to render HTML buttons for events associated with a specific instance (e.g., a game instance identified by gameId). Clicking these buttons can trigger the associated events for that instance. ```kotlin call.respondHtml { body { h3 { +"Things you can do with this game" } getPossibleEvents(gameId).forEach { apply(LowCodeCreateEvent.renderButton(it, klerk, gameId, lowCodeConfig, buttonTargets, context)) } } } ``` -------------------------------- ### Register Admin UI Routes (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md Integrate the auto-generated admin UI into your Ktor application's routing. This code snippet applies the routes provided by LowCodeMain to the Ktor routing block, making the admin UI accessible at the configured basePath. ```kotlin routing { apply(LowCodeMain(klerk, lowCodeConfig).registerRoutes()) } ``` -------------------------------- ### Render the form Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md After building the form, it can be rendered within an HTML response using `call.respondHtml` and the form's render method. ```kotlin call.respondHtml { body { createAuthorForm.render(this) } } ``` -------------------------------- ### Reading a list of models with Klerk Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/usage/reading.md Shows how to read a list of models using the `klerk.read` block and the `list` method. The `list` method returns an empty list if no items are found but throws if the actor is unauthorized. Requires a context and a reference to the data collection. ```Kotlin val myTodos = klerk.read(context) { list(data.todos.all) } ``` -------------------------------- ### Defining Authorization Rule in Klerk DSL (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/pure-functions.md This snippet shows how to configure an authorization rule within the Klerk DSL using the ConfigBuilder. It demonstrates linking a specific authorization point (readModel, positive) to a pure function (::generalsCanReadSecretReports). ```kotlin val config = ConfigBuilder(collections).build { authentication { readModel { positive { rule(::generalsCanReadSecretReports) } } ... } } ``` -------------------------------- ### Creating Klerk Context from Ktor ApplicationCall (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/context.md Demonstrates how to create a `Ctx` object from a Ktor `ApplicationCall`. It retrieves user session information, uses `AuthenticationIdentity` to look up the user, and returns a context with `ModelIdentity` or `Unauthenticated`. ```Kotlin suspend fun ApplicationCall.context(): Ctx { val userSession = call.sessions.get() if (userSession == null) { return Ctx(Unauthenticated) } val user = klerk.read(Ctx(AuthenticationIdentity)) { getFirstWhere(collections.users.all) { it.props.sessionKey.string == userSession } } if (user == null) { return Ctx(Unauthenticated) } return Ctx(actor = ModelIdentity(user), user = user) } ``` -------------------------------- ### Creating SQLite DataSource (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/advanced-topics/persistence.md Initializes an SQLiteDataSource object and sets its connection URL. This DataSource object is used by Klerk's persistence layer to connect to the SQLite database file. ```Kotlin val ds = SQLiteDataSource() ds.url = "jdbc:sqlite:/path/to/database" ``` -------------------------------- ### Render Buttons for Void Events (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md Demonstrate how to use Klerk-web's easy mode to render HTML buttons for void events (events without parameters) of a specific class (e.g., Game). Clicking these buttons can trigger the associated events. ```kotlin val buttonTargets = ButtonTargets(back = "/", model = "/game/{id}", error = "/") // where to navigate after form call.respondHtml { body { h2 { +"Things you can do" } getPossibleVoidEvents(Game::class).forEach { apply(LowCodeCreateEvent.renderButton(it, klerk, null, lowCodeConfig, buttonTargets, context)) } } } ``` -------------------------------- ### Create Event Form Template (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md Illustrate how to create an EventFormTemplate for rendering forms in full control mode. This template defines which parameters of an event (e.g., CreateAuthorParams) should be included in the form and how they should be rendered (e.g., text input, number input). ```kotlin val createAuthorFormTemplate = EventFormTemplate( EventWithParameters( CreateAuthor.id, EventParameters(CreateAuthorParams::class) ), klerk, "/", ) { text(CreateAuthorParams::firstName) text(CreateAuthorParams::lastName) text(CreateAuthorParams::phone) number(CreateAuthorParams::age) populatedAfterSubmit(CreateAuthorParams::secretToken) } ``` -------------------------------- ### Configuring Klerk with Custom Data Object Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/collections.md Shows how to initialize the Klerk configuration using 'ConfigBuilder', passing a custom 'Data' object instance ('myData') to make model collections available within read/write operations. ```Kotlin val config = ConfigBuilder(myData).build { ... } ``` -------------------------------- ### Handling Event and Transitioning State - Klerk Framework (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/state-machines.md This snippet shows an `onEvent` block within a state definition. When the `Pay` event occurs in this state, the executable `transitionTo(Payed)` is triggered, moving the model to the `Payed` state. ```Kotlin onEvent(Pay) { transitionTo(Payed) } ``` -------------------------------- ### Creating GraphQL Context Provider (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/graphql.md Define a suspend function to provide the necessary Klerk Context (Ctx) for GraphQL operations, as required by the Klerk framework. ```Kotlin suspend fun graphQlContextProvider(graphQlContext: GraphQLContext): Ctx { // as described in https://klerkframework.dev/docs/building-config/context a Context is always required when // interacting with Klerk. This function tells Klerk-web how to get this Context. } ``` -------------------------------- ### Reading Data Using Ktor-Derived Context (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/context.md Shows how to use the `context()` extension function (defined in snippet 5) on a Ktor `ApplicationCall` to obtain the appropriate Klerk context for performing a read operation. ```Kotlin val myReport = klerk.read(call.context()) { get(myReportId) } ``` -------------------------------- ### Adding SQLite JDBC Dependency (Gradle/Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/advanced-topics/persistence.md Adds the necessary dependency for the SQLite JDBC driver to the project's build configuration using Gradle's Kotlin DSL. This is required to connect Klerk to an SQLite database. ```Gradle implementation("org.xerial:sqlite-jdbc:$sqliteJdbcVersion") ``` -------------------------------- ### Defining a MigrationStep to Rename a Property (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/advanced-topics/migration.md Defines a MigrationStep object that implements the MigrationStepV1toV1 interface. It provides a description, specifies the target version (2), and implements the migrateModel function to rename the 'coAuthors' key to 'changed' specifically for models of type 'Book'. Returning null from migrateModel indicates the model should be deleted. ```Kotlin object MyMigrationStep : MigrationStepV1toV1 { override val description = "My first migration" override val migratesToVersion = 2 override fun migrateModel(original: MigrationModelV1): MigrationModelV1? = if (original.type == "Book") renameKey(original, "coAuthors", "changed") else original } ``` -------------------------------- ### Defining an Authorization Rule Function (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/context.md Illustrates how to define a function for Klerk authorization rules. It takes `ArgContextReader` which provides access to the context (`args.context`) and the model being evaluated (`args.model`) to determine authorization. ```Kotlin fun generalsCanReadSecretReports(args: ArgContextReader): PositiveAuthorization { if (args.model !is Report || args.model.classification != Secret) { return NoOpinion } return if (args.context.user.rank == General) Allow else NoOpinion } ``` -------------------------------- ### Defining Invoice State Machine - Klerk Framework Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/state-machines.md This snippet shows the declaration of a state machine for an Invoice model using the Klerk framework. It defines external events, the void state for creation, and instance states like WaitingForApproval, Approved, and Payed, along with their event handlers and transitions. ```Kotlin stateMachine { externalEvents { event(CreateInvoice, CreateInvoiceParams::class) event(Delete) event(Aprove) event(Pay) } voidState { onEvent(CreateInvoice) { createModel(WaitingForApproval, ::newInvoice) } } state(WaitingForApproval) { onEnter { action(::sendEmailToApprover) } onEvent(Delete) { delete() } onEvent(Approve) { transitionTo(Approved) } } state(Approved) { onEvent(Pay) { transitionTo(Payed) } onEvent(Delete) { delete() } } state(Payed) { } } ``` -------------------------------- ### Reading All Invoices using Klerk Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/collections.md Demonstrates how to read all instances of the 'Invoice' model using the default 'all' collection available through the 'data' object within a Klerk 'read' operation. Requires a 'context' object and access to the 'data.invoices.all' collection. ```Kotlin klerk.read(context) { val invoices = list(data.invoices.all) } ``` -------------------------------- ### Minimal Custom Klerk Context Class (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/context.md Shows a basic implementation of a custom context class named `Ctx` that fulfills the `KlerkContext` interface requirements, including `actor`, `auditExtra`, `time`, and `translator`. ```Kotlin class Ctx( override val actor: ActorIdentity, override val auditExtra: String? = null, override val time: Instant = Clock.System.now(), override val translator: Translator = DefaultTranslator(), ) : KlerkContext ``` -------------------------------- ### Declaring External Event with Parameters - Klerk Framework (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/state-machines.md This Kotlin snippet demonstrates how to declare an external event (`CreateInvoice`) that takes parameters (`CreateInvoiceParams`) and is associated with a specific model (`Invoice`). It specifies that the event is external, allowing it to be triggered via a Command. ```Kotlin object CreateInvoice : VoidEventWithParameters( forModel = Invoice::class, isExternal = true, // true makes it possible to trigger the event using a Command parametersClass = CreateInvoiceParams::class) ``` -------------------------------- ### Reading multiple models using a data class in Klerk Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/usage/reading.md Demonstrates reading more than three distinct pieces of data (models or properties) within a `klerk.read` block by defining and returning a local data class. This allows structuring complex read operations and returning a single object. ```Kotlin val manyThings = klerk.read(context) { val todo = get(todoId) val owner = get(todo.props.owner) val someState = get(someId).state val numberOfTodos = list(data.todos.all).size data class ManyThings(val todo: Model, val user: Model, val someState: String, val numberOfTodos: Int) ManyThings(todo, owner, someState, numberOfTodos) } ``` -------------------------------- ### Defining Klerk Authorization Rules Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/authorization.md This snippet demonstrates how to define authorization rules within the Klerk framework configuration. It shows positive and negative rules for various actions like reading models, properties, triggering commands (events), and accessing the event log. Rules are defined using references to functions (e.g., ::usersCanReadInvoiceItemNames) that implement the actual logic. ```Klerk DSL authorization { readModels { positive { rule(::usersCanReadInvoiceItemNames) rule(::usersInTheFinancialDepartmentCanReadEverything) } negative { } } readProperties { positive { rule(::everybodyCanReadAllProperties) } negative { } } commands { positive { rule(::theCFOCanTriggerAnyEvent) } negative { rule(::mustBeAuthenticatedWithMultiFactor) } } eventLog { positive { rule(::superadminCanReadEventLog) } negative { } } } ``` -------------------------------- ### Parse the data Source: https://github.com/klerk-framework/website/blob/main/docs/plugins/web.md When the form is submitted, the data needs to be parsed into the parameter class. The form template assists with this process, handling different result states. ```kotlin when (val result = createAuthorFormTemplate.parse(call)) { is Invalid -> EventFormTemplate.respondInvalid(result, call) is DryRun -> // TODO: describe what to do here is Parsed -> // the parameters are now available in result.params } ``` -------------------------------- ### Registering External Events in State Machine - Klerk Framework (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/state-machines.md This snippet illustrates how to include previously declared external events, such as `CreateInvoice`, within the `externalEvents` block of a Klerk state machine definition, making them available for use in state transitions. ```Kotlin externalEvents { event(CreateInvoice, CreateInvoiceParams::class) } ``` -------------------------------- ### Adding Meaning and Alternative Representations to Klerk Containers (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/models-types.md This Kotlin snippet demonstrates how to enhance a Klerk `LongContainer` (`LastInvoiceTime`) by adding a constructor that accepts an `Instant` and a property that provides the value as an `Instant`. This allows interacting with the container using a more meaningful type (`Instant`) while Klerk internally handles it as a `Long`, preventing misinterpretations of the raw numerical value. ```Kotlin class LastInvoiceTime(value: Long) : LongContainer(value) { constructor(instant: Instant) : this(instant.toEpochMilliseconds()) val instant = Instant.fromEpochMilliseconds(value) } ``` -------------------------------- ### Defining Custom InvoiceCollections and Data Object Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/collections.md Shows how to create a custom 'ModelCollections' object ('InvoiceCollections') that extends the base functionality, defines a new collection ('approved') by filtering the 'all' collection, and registers it. It then shows how to use this custom object in the main 'Data' object. ```Kotlin object InvoiceCollections : ModelCollections() { val approved = all.filter { it.state == "approved" }.register("approved") } object Data { val invoices = InvoiceCollections } ``` -------------------------------- ### Custom Klerk Context with User Model (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/context.md Extends the basic `Ctx` class to include an optional `user` property of type `Model`. This is a common pattern to easily access the logged-in user's model within the context, although Klerk itself doesn't require it. ```Kotlin data class Ctx( override val actor: ActorIdentity, override val auditExtra: String? = null, override val time: Instant = Clock.System.now(), override val translator: Translator = DefaultTranslator(), val user: Model? = null // Klerk doesn't care about this ) : KlerkContext ``` -------------------------------- ### Defining Custom String Validation with Klerk and Apache Commons (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/models-types.md This Kotlin snippet defines a custom data container `WebsiteUrl` extending `StringContainer`. It enforces minimum and maximum length constraints and uses a custom validator function `validUrl` which leverages Apache Commons `UrlValidator` to check if the contained string is a valid URL. It returns `InvalidParametersProblem` on failure. ```Kotlin val urlValidator = UrlValidator() class WebsiteUrl(url: String) : StringContainer(url) { override val minLength = 5 override val maxLength = 100 override val validators = setOf(::validUrl) private fun validUrl(): InvalidParametersProblem? { return if (urlValidator.isValid(value)) null else InvalidParametersProblem() } } ``` -------------------------------- ### Implementing Authorization Logic in Klerk (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/pure-functions.md This pure Kotlin function implements the logic for the 'generalsCanReadSecretReports' authorization rule. It checks if the model is a 'Report' of 'Secret' classification and if the user's rank is 'General' to determine authorization. ```kotlin fun generalsCanReadSecretReports(args: ArgContextReader): PositiveAuthorization { if (args.model !is Report || args.model.classification != Secret) { return NoOpinion } return if (args.context.user.rank == General) Allow else NoOpinion } ``` -------------------------------- ### Preventing Type Errors with Specific Container Types in Klerk (Kotlin) Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/models-types.md These Kotlin snippets contrast two function signatures. The first uses a generic `String` for an email parameter, potentially allowing unverified emails. The second uses a specific Klerk container type `VerifiedEmail`, demonstrating how using distinct types for parameters prevents passing incorrect or unvalidated data, enhancing type safety and preventing logical errors. ```Kotlin fun sendSecretInformation(email: String) { ... } ``` ```Kotlin fun sendSecretInformation(email: VerifiedEmail) { ... } ``` -------------------------------- ### Reading Approved Invoices using Custom Collection Klerk Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/collections.md Demonstrates how to read invoices using a custom collection named 'approved', which is defined elsewhere. This simplifies the read operation by abstracting the filtering logic into the collection definition. ```Kotlin klerk.read(context) { val approvedInvoices = list(data.invoices.approved) } ``` -------------------------------- ### Performing suspending operations while holding read lock in Klerk Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/usage/reading.md Illustrates using `klerk.readSuspend` to perform suspending operations (like rendering HTML and responding to a call) while maintaining the read lock. This can simplify code but might impact performance if the suspending operation is long. Requires a suspending context. ```Kotlin suspend fun renderWebPage(call: ApplicationCall) { ... klerk.readSuspend(call.context()) { call.respondHtml { body { h1 { +"Hello ${get(userId).props.name}" } +"Your Todo for today is in state: ${get(todoId).state}" } } } } ``` -------------------------------- ### Filtering All Invoices by State in Klerk Read Kotlin Source: https://github.com/klerk-framework/website/blob/main/docs/building-config/collections.md Illustrates how to filter the default 'all' collection within a Klerk 'read' operation to retrieve only invoices that meet a specific condition (state is "approved"). This approach is shown before introducing custom collections for readability. ```Kotlin klerk.read(context) { val approvedInvoices = list(data.invoices.all) { it.state == "approved" } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.