text:
Verge

A performant state management library for iOS App - SwiftUI / UIKit

## Overview - focusing on faster performance

The concept of Verge Store is inspired by [Redux](https://redux.js.org/), [Vuex](https://vuex.vuejs.org/) and [ReSwift](https://github.com/ReSwift/ReSwift).

Recenlty, [facebookexperimental/Recoil](https://github.com/facebookexperimental/Recoil) has been opened.
Atoms and Selectors similar to `Derived`.

Plus, releasing from so many definition of the actions.

To be more Swift's Style on the writing code.

`store.myOperation()` instead of `store.dispatch(.myOperation)`

The characteristics are

* Method based dispatching action
* Separating the code in a large app
* Emits any events that isolated from State It's for SwiftUI's onReceive\(:\)
* Logging \(Commit, Performance monitoring\)
* Binding with Combine and RxSwift
* Normalizing the state with ORM
* Multi-threading

🌟 Differences between other Flux libraries in iOS

Firstly, Verge provides the functions to keep excellent performance in using Store-Pattern.

Verge focuses on using in the real-world.

For example, the application must have many features depends on its business.

Such as the application might be getting complicated.

To solve this issue, we can choose Store-Pattern such as flux.

At a glance, Flux architecture is amazing.

However, we have to follow the disadvantages behind it.

They are coming from the application runs with Data-Driven (Mostly).

Data-Driven will cause some expensive calculations in the application that depends on the complexity of the application.

Sometimes, we may face some performance issues we can't overlook it.

Redux and Vuex are already following that.

- Redux
  - reselect
  - ORM
- Vuex
  - Getters
  - ORM

Verge is trying to do that in iOS application with Swift.

Specifically:
- Derived (Similar to [facebookexperimental/Recoil](https://github.com/facebookexperimental/Recoil)'s Atom and Selector)
- ORM

🌟 Example code

```swift
struct State: StateType {
  var name: String = ""
  var age: Int = 0
}

enum Activity {
  case somethingHappen
}

// 🌟with UIKit
class ViewController: UIViewController {

  ...

  let store = Store<State, Activity>(initialState: .init(), logger: nil)

  ...

  func update(changes: Changes<State>) {

    changes.ifChanged(\.name) { (name) in
      nameLabel.text = name
    }

    changes.ifChanged(\.age) { (age) in
      ageLabel.text = age.description
    }

  }
}

// 🌟with SwiftUI
struct MyView: View {

  @EnvironmentObject var store: Store<State, Activity>

  var body: some View {
    Group {
      Text(store.state.name)
      Text(store.state.age)
    }
  }
}
```

## 🍐 Basic Usage

To start to use Verge in our app, we use these domains:

* **State**
  * A type of state-tree that describes the data our feature needs.
* **Activity**
  * A type that describes an activity that happens during performs the action.
  * This instance won't be stored in anywhere. It would help us to perform something by event-driven.
  * Consider to use this depends on that if can be represented as a state.
  * For example, to present alert or notifcitaions by the action.
* **Action**
  * Just a method that a store or dispatcher defines.
* **Store**
  * A storage object to manage a state and emit activities by the action.
  * Store can dispatch actions to itself.
* **Dispatcher (Optional)**
  * A type to dispatch an action to specific store.
  * For a large application, to separate the logics each domain.

**Setup a Store**

Define a state

```swift
struct MyState {
  var count = 0
}
```

Define an activity

```swift
enum MyActivity {
  case countWasIncremented
}
```

Define a store that uses defined state and activity

```swift
class MyStore: Store<MyState, MyActivity> {

  init(dependency: Dependency) {
    super.init(initialState: .init(), logger: nil)
  }

}
```

We can create an instance from `Store` but we can put some dependencies (e.g. API client) with creating a sub-class of `Store`.

(If you don't need Activity, you can set `Never` there.)

And then, add an action in the store

```swift
class MyStore: Store<MyState, MyActivity> {

  init(dependency: Dependency) {
    super.init(initialState: .init(), logger: nil)
  }

  func incrementCount() {
    commit {
      $0.count += 1
    }
  }
}
```

Yes, this point is most different with Redux. it's close to Vuex.

Store knows what the application's needs.

For example, call that action.

```swift
let store = MyStore(...)
store.incrementCount()
```

There are some advantages:

- **Better Performance**
  - Swift can perform this action with Swift's method dispatching instead switch-case computing.
- **Returns anything we need**
  - the action can return anything from that action (e.g. state or result)
  - If that action dispatch async operation, it can return `Future` object. (such as Vuex action)

Perform a commit asynchronously

```swift
func incrementCount() {
  DispatchQueue.main.async {
    commit {
      $0.count += 1
    }
  }
}
```

Send an activity from the action

```swift
func incrementCount() {
  commit {
    $0.count += 1
  }
  send(.countWasIncremented)
}
```

**Use the store in SwiftUI**

(Currently, Verge's development is focusing on UIKit.)

```swift
struct MyView: View {

  @EnvironmentObject var store: MyStore

  var body: some View {
    Group {
      Text(store.state.name)
      Text(store.state.age)
    }
    .onReceive(session.store.activityPublisher) { (activity) in
      ...
    }
  }
}
```

**Use the store in UIKit**

In UIKit, UIKit doesn't work with differentiating.

To keep better performance, we need to set a value if it's changed.

Verge publishes an object that contains previous state and latest state, Changes object would be so helpful to check if a value changed.

```swift
class ViewController: UIViewController {

  let store: MyStore

  var cancellable: VergeAnyCancellable?

  init(store: MyStore) {
    ...

    self.cancellable = store.sinkChanges { [weak self] changes in
      self?.update(changes: changes)
    }

  }

  private func update(changes: Changes<MyStore.State>) {

    changes.ifChanged(\.name) { (name) in
      nameLabel.text = name
    }

    changes.ifChanged(\.age) { (age) in
      ageLabel.text = age.description
    }

  }
}
```

## ☂ Advanced Usage - to keep performance and scalability

**Adding a cachable computed property in a State**

We can add a computed property in a state to get a derived value with stored property,

and that computed property works fine as well other stored property.

```swift
struct MyState {
  var items: [Item] = [] {

  var itemsCount: Int {
    items.count
  }
}
```

However, this patterns might cause an expensive cost of operation depends on how they computes.

To solve it, Verge arrows us to define the computed property with another approach.

```swift
struct MyState: ExtendedStateType {

  var name: String = ...
  var items: [Int] = []

  struct Extended: ExtendedType {
    let filteredArray = Field.Computed<[Int]> {
      $0.items.filter { $0 > 300 }
    }
    .ifChanged(selector: \.largeArray)
  }
}
```

```swift
let store: MyStore

store.changes.computed.filteredArray
```

This defined computed array calculates only if changed specified value.

That condition to re-calculate is defined with `.ifChanged` method in the example code.

And finally, it caches the result by first-time access and it returns cached value until if the source value changed.

**Making a slice of the state (Selector)**

We can create a slice object that derives a data from the state.

```swift
let derived: Derived<Int> = store.derived(.map(\.count))

// take a value
derived.value

// subscribe a value changes
derived.sinkChanges { (changes: Changes<Int>) in
}
```

[Details here](https://muukii-app.gitbook.io/verge/docs-vergestore/derived-bindingderived)

**Creating a Dispatcher**

Store arrows us to define an action in itself, that might cause gain complexity in supporting a large application.

To solve this, Verge offers us to create an object that dispatches an action to the store.

We can separate the code of actions to keep maintainability.

that also help us to manage a different type of dependencies.

For example, the case of those dependencies different between logged-in and logged-out.

```swift
class MyDispatcher: MyStore.Dispatcher {
  func moreOperation() {
    commit {
      ...
    }
  }
}

let store: MyStore
let dispatcher = MyDispatcher(target: store)
```

Additionally, We can create a dispatcher that focuses the specified sub-tree of the state.

You can check the detail of this from [our documentation](https://muukii-app.gitbook.io/verge/docs-vergestore/dispatcher).

## Modules overview

### 📦 VergeStore

It provides core functions of Store-pattern.

- State supports computed property with caching (like [Vuex's Getters](https://vuex.vuejs.org/guide/getters.html))
- Derived object to create derived data from state-tree with performant (like [redux/reselect](https://github.com/reduxjs/reselect))

🌑 Store

**Store**
-   a reference type object
-   manages the state object that contains the application state
-   commits **Mutation** to update the state

## Defines Store

```swift
struct State: StateType {
  var count: Int = 0
}

enum Activity {
  case happen
}

final class MyStore: StoreBase<State, Activity> {

  init() {
    super.init(
      initialState: .init(),
      logger: DefaultStoreLogger.shared
    )
  }

}
```

## Adds Mutation

```swift
final class MyStore: StoreBase<State, Activity> {

  func increment() {
    commit {
      $0.count += 0
    }
  }

}
```

## Commit mutation

```swift
let store = MyStore()
store.increment()
```

☄ Mutation

## What Mutation is
The only way to actually change state in a Store is by committing a mutation.
Define a function that returns Mutation object.
That expresses that function is Mutation

> Mutation does **NOT** allow to run asynchronous operation.

## To define mutations in the Store

```swift
class MyDispatcher: MyStore.Dispatcher {

  func addNewTodo(title: String) {
    commit { (state: inout RootState) in
      state.todos.append(Todo(title: title, hasCompleted: false))
    }
  }

}
```

## To run Mutation

```swift
let store = MyStore()
let dispatcher = MyDispatcher(target: store)

dispatcher.addNewTodo(title: "Create SwiftUI App")

print(store.state.todos)
// store.state.todos => [Todo(title: "Create SwiftUI App", hasCompleted: false)]
```

⚡ Activity

## What activity does
VergeStore supports send some events that won't be stored on state.
Even if an application runs with Data-Driven, it might have some issues that not easy to something with Data-Driven.
For example, something that would happen with the timer's trigger. This case is not easy with expressing state.
Activity helps that can do easily.
This means VergeStore can use Event-Driven from Data-Driven partially.
We think it's not so special concept. SwiftUI supports these use cases as well that using Combine's Publisher.

```swift
func onReceive<P>(_ publisher: P, perform action: @escaping (P.Output) -> Void) -> some View where P : Publisher, P.Failure == Never
```

[Apple's SwiftUI Ref]([https://developer.apple.com/documentation/swiftui/view/3365935-onreceive](https://developer.apple.com/documentation/swiftui/view/3365935-onreceive))

## Sends Activity

In sample code following this

```swift
final class MyStore: StoreBase<State, Never>
```

`Never` means no activity.
To send activity to subscriber, starting from defining the Activity.

```swift
struct State {

}

enum Activity {
  case didSendMessage
}

final class Store: StoreBase<State, Activity>, DispatcherType {

  var target: StoreBase<State, Activity> { self }

  init() {
    super.init(initialState: .init(), logger: DefaultLogger.shared)
  }

  func sendMessage() {
    send(.didSendMessage)
  }
}
```

> In this sample, Store has DispatcherType. If you create the application not so much complicated, you don't need separate Store and Dispatcher.

```swift
let store = Store()

store
  .activityPublisher
  .sink { event in
    // do something
  }
  .store(in: &subscriptions)
```

🪐 State and shape

## Using single state tree (Not enforced)

VergeStore uses a **single state-tree. (Recommended)** That means an object contains all of the application's state. With this, we can get to achieve **"single source of truth"**

That state is managed by **Store**. It process updating the state and notify updated events to the subscribers.

> 💡 VergeStore does support multiple state-tree as well. Depending on the case, we can create another Store instance.

## Add computed property

```swift
struct State: StateType {

  var count: Int = 0

  var countText: String {
    return count.description
  }

}
```

Although in some of cases, the cost of computing might be higher which depends on how it create the value from stored properties.

## StateType protocol helps to modify

VergeStore provides `StateType` protocol as a helper.

It will be used in State struct that Store uses. `StateType` protocol is just providing the extensions to mutate easily in the nested state.

```swift
public protocol StateType {
}

extension StateType {

  public mutating func update<T>(target keyPath: WritableKeyPath<Self, T>, update: (inout T.Wrapped) throws -> Void) rethrows where T : VergeStore._VergeStore_OptionalProtocol

  public mutating func update<T>(target keyPath: WritableKeyPath<Self, T>, update: (inout T) throws -> Void) rethrows

  public mutating func update(update: (inout Self) throws -> Void) rethrows
}
```

## Normalization

**If you put the data that has relation-ship or complicated structure into state tree, it would be needed normalization to keep performance. Please check VergeORM module**

[About more Normalization and why we need to do this]([https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape/](https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape/))

🌟 Changes from State

## Update UI from State

In subscribing the state and binding UI, it's most important to reduce the meaningless time to update UI.

What things are the meaningless? that is the update UI which contains no updates.

Basically, we can do this like followings

```swift
func updateUI(newState: State) {
  if self.label.text != newState.name {
    self.label.text = newState.name
  }
}
```

Although, this approach make the code a little bit complicated by increasing the code to update UI.

## Update UI when only the state changed

Store provides Changes<State> object.
It provides some functions to get the value from state with condition.

```swift
let store: Store<MyState, Never>

let changes: Changes<MyState> = store.changes

changes.ifChanged(\.name) { name in
  // called only name changed
}
```

## Subscribing the state

```swift
class ViewController: UIViewController {

  var subscriptions = Set<UntilDeinitCancellable>()

  let store: MyStore<MyState, MyActivity>

  override func viewDidLoad() {

    super.viewDidLoad()

    store.sinkChanges { [weak self] (changes) in
      // it will be called on the thread which committed
      self?.update(changes: changes)
    }
    .store(in: &subscriptions)
  }

  private func update(changes: Changes<MyState> {
    changes.ifChanged(\.name) { name in
      // called only name changed
    }
    ...
  }

}
```

🛸 Computed property on State

## Overview
A declaration to add a computed-property into the state. It helps to add a property that does not need to be stored-property. It's like Swift's computed property like following:

```swift
struct State {
 var items: [Item] = [] {

 var itemsCount: Int {
   items.count
 }
}
```

However, this Swift's computed-property will compute the value every state changed. It might become a serious issue on performance.

Compared with Swift's computed property and this, this does not compute the value every state changes, It does compute depend on specified rules.
That rules mainly come from the concept of Memoization.

Example code:

```swift
struct State: ExtendedStateType {

 var name: String = ...
 var items: [Int] = []

 struct Extended: ExtendedType {

   static let instance = Extended()

   let filteredArray = Field.Computed<[Int]> {
     $0.items.filter { $0 > 300 }
   }
   .dropsInput {
     $0.noChanges(\.items)
   }
 }
}
```

```swift
let store: MyStore<State, Never> = ...

let state = store.state

let result: [Int] = state.computed.filteredArray
```

## Instruction

### Computed Property on State

States may have a property that actually does not need to be stored property. In that case, we can use computed property.

Although, we should take care of the cost of the computing to return value in that. What is that case? Followings explains that.

> Computed concept is inspired from Vuex Getters. [https://vuex.vuejs.org/guide/getters.html](https://vuex.vuejs.org/guide/getters.html)

For example, there is itemsCount.

```swift
struct State {
  var items: [Item] = []

  var itemsCount: Int = 0
}
```

In order to become itemsCount dynamic value, it needs to be updated with updating items like this.

```swift
struct State {
  var items: [Item] = [] {
    didSet {
      itemsCount = items.count
    }
  }

  var itemsCount: Int = 0
}
```

We got it, but we don't think it's pretty simple. Actually we can do this like this.

```swift
struct State {
  var items: [Item] = [] {

  var itemsCount: Int {
    items.count
  }
}
```

With this, it did get to be more simple.

```swift
struct State {
  var items: [Item] = []

  var processedItems: [ProcessedItem] {
    items.map { $0.doSomeExpensiveProcessing() }
  }
}
```

As an example, Item can be processed with the something operation that takes expensive cost. We can replace this example with filter function.

This code looks is very simple and it has got data from source of truth. Every time we can get correct data. However we can look this takes a lot of the computing resources. In this case, it would be better to use didSet and update data.

```swift
struct State {
  var items: [Item] = [] {
    didSet {
      processedItems = items.map { $0.doSomeExpensiveProcessing() }
    }
  }

  var processedItems: [ProcessedItem] = []
}
```

However, as we said, this approach is not simple. And this can not handle easily a case that combining from multiple stored property. Next introduces one of the solutions.

## Computed Properties

VergeStore has a way of providing computed property with caching to reduce taking computing resource.

Keywords are:
-   ExtendedStateType
-   ExtendedType
-   Field.Computed<T>

Above State code can be improved like following.

```swift
struct State: ExtendedStateType {

  var name: String = ...
  var items: [Int] = []

  struct Extended: ExtendedType {

    static let instance = Extended()

    let filteredArray = Field.Computed<[Int]> {
      $0.items.filter { $0 > 300 }
    }
    .dropsInput {
      $0.noChanges(\.items)
    }
  }
}
```

To access that computed property, we can do the followings:

```swift
let store: MyStore<State, Never> = ...

let state = store.state

let result: [Int] = state.computed.filteredArray
```

`store.computed.filteredArray` will be updated only when items updated. Since the results are stored as a cache, we can take value without computing.

Followings are the steps describes when it computes while paying the cost.

```swift
let store: MyStore<State, Never> = ...

// It computes
store.state.computed.filteredArray

// no computes because results cached with first-time access
store.state.computed.filteredArray

// State will change but no affects items
store.commit {
  $0.name = "Muukii"
}

// no computes because results cached with first-time access
store.state.computed.filteredArray

// State will change with it affects items
store.commit {
  $0.items.append(...)
}

// It computes new value
store.state.computed.filteredArray
```

🌙 Derived - BindingDerived

> **Derived** is inspired by [redux/reselect](https://github.com/reduxjs/reselect).

Derived's functions are:
-   Computes the derived data from the state tree
-   Emit the updated data with updating Store
-   Supports subscribe the data
-   Supports Memoization

## Overview
### Setting up the Store

```swift
struct State {
  var title: String = ""
  var count: Int = 0
}

let store = StoreBase<State, Never>(initialState: .init(), logger: nil)
```

### Create a Derived object

```swift
let derived: Derived<Int> = store.derived(.map(\.count))

// we can write also this.
// However, we recommend do above way as possible
// because it enables cache.
let derived: Derived<Int> = store.derived(.map { $0.count })
```

Derived is an object (reference type). It provides a latest value from a store.
This supports getting the value ad-hoc or subscribing the value updating.

## Take a value
Derived allows us to take the latest value at the time.

```swift
let value: Int = derived.value
```

## Subscribe the latest value Derived provides

Derived allows us to subscribe to the updated value.

```swift
let cancellable = derived.sinkValue { (changes: Changes<Int>) in
}
```

> ✅
> Please, carefully handle a cancellable object. A concealable object that returns that subscribe method is similar to AnyCancellable of Combine.framework. We need to retain that until we don't need to get the update event.

## Supports other Reactive Frameworks
We might need to use some Reactive framework to integrate other sequence. Derived allows us to make to a sequence from itself. Currently, it supports Combine.framework and RxSwift.framework.

### + Combine

```swift
derived
  .valuePublisher()
  .sink { (changes: Changes<Int>) in

  }
```

### + RxSwift

> 💡You need to install VergeRx module to use this.

```swift
derived.rx
  .changesObservable()
  .subscribe(onNext: { (changes: Changes<Int>) in

  })
```

## Memoization to keep good performance

Mostly Derived is used for projecting the specified shape from the source object.
And some cases may contain an expensive operation. In that case, we can consider to tune Memoization up.
We can see the detail of Memoization from below link.

[Wiki - Memoization]([https://en.wikipedia.org/wiki/Memoization](https://en.wikipedia.org/wiki/Memoization))

## Suppress the map operation that projects no changes

In create Derived method, we can get the detail that how we suppress the no need updating and updated event.

```swift
extension StoreType {

  public func derived<NewState>(
    _ memoizeMap: MemoizeMap<Changes<State>, NewState>,
    dropsOutput: @escaping (Changes<NewState>) -> Bool = { _ in false }
  ) -> Derived<NewState>

}
```

🚀 Dispatcher - perform Mutation

# What Dispatcher does

Dispatcher's needs is **to update the state that Store manages** and to **manage dependencies to create Mutation and Action.**

**Dispatcher does not have own state. Dispatcher runs with Store.**

**Example**

```swift
class MyDispatcher: MyStore.Dispatcher {

}

let store = MyStore()
let dispatcher = MyDispatcher(target: store)
```

> 💡
> Actual type of MyStore.Dispatcher is DispatcherBase<State, Never> It is a typealias to write shortly.

Managing dependencies code

```swift
class MyDispatcher: MyStore.Dispatcher {

  let apiClient: APIClient

  init(apiClient: APIClient, target store: StoreBase<RootState>) {
    self.apiClient = apiClient
    super.init(target: store)
  }
}

let store = MyStore()
let apiClient = APIClient()
let dispatcher = MyDispatcher(apiClient: apiClient, target: store)
```

## Create multiple Dispatcher

![image](https://user-images.githubusercontent.com/1888355/82821486-28586a00-9edf-11ea-8c98-062eafcc4f16.png)

We can create multiple Dispatcher each use-cases.

For example, In case the timing of getting dependencies that to be needed by run Action or Mutation is different, it will not be easy to define in the one dispatcher. We will have the optional properties in there.

In this case, creating multiple dispatchers will help us. Define the dispatcher each the timing of getting dependencies.

```swift
class LoggedInDispatcher: MyStore.Dispatcher {

  let apiClientNeedsAuthToken = ...
  ...
}

class LoggedOutDispatcher: DispatcherBase<RootState> {

  let apiClientWithoutAuthToken = ...
  ...
}

let store = MyStore()
let loggedInDispatcher = LoggedInDispatcher(...)
let loggedOutDispatcher = LoggedOutDispatcher(...)
```

🔭 Logging

## Start logging from DefaultStoreLogger
DefaultStoreLogger is the pre-implemented logger that send the logs to OSLog.
To enable logging, set the logger instance to Store's initializer.

```swift
Store<MyState, MyActivity>.init(
  initialState: ...,
  logger: DefaultStoreLogger.shared // 🤩
)
```

Mainly, we can monitor log about commit in Xcode's console and Terminal.app

```
2020-05-25 23:47:06.884304+0900 VergeStoreDemoSwiftUI[84086:2813713] [Commit] {
  "store" : "VergeStore.Store<VergeStoreDemoSwiftUI.SessionState, Swift.Never>()",
  "tookMilliseconds" : 0.19299983978271484,
  "trace" : {
    "createdAt" : "2020-05-25T14:47:06Z",
    "file" : "\/Users\/muukii\/.ghq\/github.com\/muukii\/Verge\/worktree\/space1\/Sources\/VergeStoreDemoSwiftUI\/Session.swift",
    "function" : "submitNewPost(title:from:)",
    "line" : 129,
    "name" : ""
  },
  "type" : "commit"
}
```

## Creating a customized logger

If you need a customized logger, you can create that with `StoreLogger` protocol.

```swift
public protocol StoreLogger {

  func didCommit(log: CommitLog)

  func didCreateDispatcher(log: DidCreateDispatcherLog)
  func didDestroyDispatcher(log: DidDestroyDispatcherLog)
}
```

Utilities

## Fragment\<State>

## Fragment helps compare if state was updated without Equatable

In a single state tree, comparing for reducing the number of updates would be most important for keep performance. However, implementing Equatable is not easy basically. Instead, adding a like flag that indicates updated itself, it would be easy

## Actually, we need to get to flag that means different, it no need to be equal

Actually, we need to get to flag that means **different**, it no need to be **equal**.

## Fragment does embed state with flag

Now we can use Fragment struct that is a container for wrapping inside state up. With dynamicMemberLookup, we can access the properties without new property. Fragment has `UpdatedMarker`, we can compare if the state was updated with this.

```swift
struct YourState {
  var name: String = ...
}

struct AppState {

  @Fragment var yourState YourState = .init()
}

appState.yourState.name

// get unique value that indicates updated to compare with previous value.
// this value would be updated on every mutation of this tree.
appState.$yourState.counter.value
```

### 📦 VergeORM

It provides the function that manages performant many entity objects.

Technically, using Normalization.

In the application that uses many entity objects, we sure highly recommend using such as ORM using Normalization.

About more detail,
https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape

VergeORM Core Concepts

VergeORM is a library to manage Object-Relational Mapping in the value-type struct.

It provides to store with Normalization and accessing easier way.
Basically, If we do Normalization without any tool, accessing would be complicated.

The datastore can be stored anywhere because it's built by struct type.
It allows that to adapt to state-shape already exists.

```swift
struct YourAppState: StateType {

  // VergeORM's datastore
  struct Database: DatabaseType {

    ...
    // We will explain this later.
  }

  // Put Database anywhere you'd like
  var db: Database = .init()

  ... other states
}
```

## Stores data with normalization

Many applications manage a lot of entities. Single state-tree requires work similar to creating database schema. The state shape is most important, otherwise performance issue will appear when your application grows.

To avoid this, we should do **Normalize** the State Shape. About Normalizing state shape, [Redux documentation](https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape) explains it so good. VergeORM provides several helper methods to normalize state shape.

-   Supports find, insert, delete with easy plain implementations.
-   Supports batch update with context, anywhere it can abort and revert to current state.

Getting Started

## Create Database struct

**Database struct** contains the tables for each Entity. As a struct object, that allows to manage history and it can be embedded on the state that application uses.

-   Database struct
    -   Book entity
    -   Author entity

## Add DatabaseType protocol to your database struct

```swift
struct Database: DatabaseType {
}
```

`DatabaseType` protocol has several constraints and provides functions with that. To satisfy those constraints, make it like following

```swift
struct Database: DatabaseType {

  struct Schema: EntitySchemaType {

  }

  struct Indexes: IndexesType {

  }

  var _backingStorage: BackingStorage = .init()
}
```

## Register EntityTable

As an example, suppose we have Book and Author entities.

```swift
struct Book: EntityType {

  typealias IdentifierType = String

  var entityID: EntityID {
    .init(rawID)
  }

  let rawID: String
}

struct Author: EntityType {

  typealias IdentifierType = String

  var entityID: EntityID {
    .init(rawID)
  }

  let rawID: String
}
```

By conforming to `EntityType` protocol, it can be used by Database as Entity. It needs `rawID` and you can set whatever type your Entity needs.

And then, add these entities to Schema object.

```swift
struct Database: DatabaseType {

  struct Schema: EntitySchemaType {
    let book = Book.EntityTableKey()
    let author = Book.EntityTableKey()
  }

  struct Indexes: IndexesType {
    // In this time, we don't touch here.
  }

  var _backingStorage: BackingStorage = .init()
}
```

Finally, you can use Database object like this.

```swift
let db = RootState.Database()

let bookEntityTable: EntityTable<Book, Read> = db.entities.book
```

You can get aEntityTable object for Book.
And then you can use these methods.

```swift
bookEntityTable.all()
bookEntityTable.find(by: <#T##VergeTypedIdentifier<Book>#>)
bookEntityTable.find(in: <#T##Sequence#>)
```

> 💡
> These syntax are realized by Swift's dynamicMemberLookup. If you have curiosity, please check out the source-code.

## Update Database

To update Database object(Insert, Update, Delete), use `performbatchUpdates` method.

```swift
db.performBatchUpdates { (context) in
  // Put the updating code here
}
```

Example:
```swift
db.performBatchUpdates { (context) in
  let book = Book(rawID: "some")
  context.book.insert(book)
}

// db.entities.book.count == 1
```

Index

## To find the entity faster, Index.

As shown in the Getting Started section, we can get entities by the following code.

```swift
let db =  RootState.Database()

db.bookEntityTable.all()

db.bookEntityTable.find(by: <#T##VergeTypedIdentifier<Book>#>)

db.bookEntityTable.find(in: <#T##Sequence#>)
```

To do this, we need to manage the Identifier of the entity and additionally, to get an array of entities, we need to manage the order of Identifier.

To do this, VergeORM provides Index feature. Index manages the set of identifiers in several structures.

> 💡
> Meaning of Index might be a bit different than RDB's Index. At least, Index manages identifiers to find the entity faster than linear search.

Currently, we have the following types,
-   **OrderedIDIndex**
    -   [EntityID]
    -   Manages identifiers in an ordered collection
-   **GroupByEntityIndex**
    -   [EntityID : [EntityID]]
    -   Manages identifiers that are grouped by another identifier
-   **HashIndex**
	-  [Key : EntityID]
	-  Manages identifiers with hashable keys
-   **SetIndex**
    -   Set<EntityID>
-   **GroupByKeyIndex**
    -   [Key : [EntityID]]

## Register Index

Let's take a look at how to register Index. The whole index is here.

```swift
struct Database: DatabaseType {

  struct Schema: EntitySchemaType {
    let book = Book.EntityTableKey()
    let author = Book.EntityTableKey()
  }

  struct Indexes: IndexesType {
    // 👋 Here!
  }

  var _backingStorage: BackingStorage = .init()
}
```

Indexes struct describes the set of indexes. All of the indexes managed by VergeORM would be here.

For now, we add a simple ordered index just like this.

```swift
struct Indexes: IndexesType {
  let allBooks = IndexKey<OrderedIDIndex<Schema, Book>>()
  // or OrderedIDIndex<Schema, Book>.Key()
}
```

With this, now we have index property on DatabaseType.indexes.

```swift
let allBooks = state.db.indexes.allBooks
// allBooks: OrderedIDIndex<Database.Schema, Book>
```

## Read Index

**Accessing indexes**

```swift
// Get the number of ids
allBooks.count

// Take all ids
allBooks.forEach { id in ... }

// Get the id with location
let id: Book.ID = allBooks[0]
```

Fetch the entities from index

```swift
let books: [Book] = state.db.entities.book.find(in: state.db.indexes.allBooks)
// This syntax looks is a bit verbose.
// We will take shorter syntax.
```

## Write Index

To write index is similar with updating entities. Using `performBatchUpdates` , add or delete index through the `context` .

```swift
state.db.performBatchUpdates { (context) -> Book in

  let book = Book(rawID: id.raw, authorID: Author.anonymous.id)
  context.insertsOrUpdates.book.insert(book)

  // Here 👋
  context.indexes.allBooks.append(book.id)

}
```

Since Index is updated manually here, you might want to manage it automatically.
Using **Middleware**, it's possible.

Middleware
## Perform any operation for each of all updates

Using Middleware, you can perform any operation for each of all updates.

For example,
-   Manage Index according to updated entities, for each of all updates

## Register Middleware

In DatabaseType protocol, we can return the set of middlewares. This property would be called for each update.

```swift
struct Database: DatabaseType {

  ...

  var middlewares: [AnyMiddleware<RootState.Database>] {
    [
      // Here
    ]
  }
}
```

We can return `MiddlewareType` object here. However since it's a generic protocol, it needs to wrap up with AnyMiddleware object to return as an array.

**struct AnyMiddleware**

```swift
public struct AnyMiddleware<Database> : MiddlewareType where Database : VergeORM.DatabaseType {

    public init<Base>(_ base: Base) where Database == Base.Database, Base : VergeORM.MiddlewareType

    public init(performAfterUpdates: @escaping (DatabaseBatchUpdateContext<Database>) -> ())

    public func performAfterUpdates(context: DatabaseBatchUpdateContext<Database>)
}
```

**To wrap your middleware up with AnyMiddleware**

```swift
public struct MyMiddleware<Database: DatabaseType>: MiddlewareType {
  ...
}

let middleware = MyMiddleware()
AnyMiddleware<Database>(middleware)
```

To create anonymous middleware using AnyMiddleware

```swift
AnyMiddleware<Database>(performAfterUpdates: { (context) in

  // ... any operation

})
```

## What middleware handles

-   performs any operation with context after updating of batch-updates completed.
    -   `MiddlewareType.performAfterUpdates`

## Create Middleware

```swift
let autoIndex = AnyMiddleware<RootState.Database>(performAfterUpdates: { (context) in

  let ids = context.insertsOrUpdates.author.all().map { $0.id }
  context.indexes.bookMiddleware.append(contentsOf: ids)

})
```

This sample code adds identifier of Author that added on batch-updates.
This means it manages Index automatically.
Finally, returns this object on middlewares property.

```swift
let autoIndex = ...

struct Database: DatabaseType {

  ...

  var middlewares: [AnyMiddleware<RootState.Database>] {
    [
      autoIndex
    ]
  }
}
```

Makes a Derived for a entity

## To create getter, Add DatabaseEmbedding protocol to your state-tree.

```swift
struct RootState: DatabaseEmbedding {

  static let getterToDatabase: (RootState) -> RootState.Database = { $0.db }

  struct Database: DatabaseType {
    ...
  }

  var db = Database()
}
```

## Create getter from entity id

```swift
let id = Book.EntityID.init("some")

let derived: Book.Derived = storage.derived(from: id)
```

## Get entity from Getter

```swift
let entity: Book = getter.value.wrapped
```

VergeORM supports create MemoizeSelector from Storage or Store.

Tips

## Access to DB partially

We may want to create common accessing code with using protocol if we have multiple database object.

```swift
protocol Partial {
  var author: Author.EntityTableKey { get }
}

struct Database: DatabaseType {

  struct Schema: EntitySchemaType, Partial {
    let book = Book.EntityTableKey()
    let author = Author.EntityTableKey()
  }

  struct Indexes: IndexesType {
  }

  var _backingStorage: BackingStorage = .init()
}
```

```swift
func access<DB: DatabaseType>(db: DB) -> Int where DB.Schema : Partial {
  db.entities.author.all().count
}
```

Inside of access function, it supports only accessing to entity Partial protocol has.

### 📦 VergeRx

It provides several observable that compatible with RxSwift.

## More Documentations

[**🔗 You can see more detail of Verge on Documentation**](https://muukii-app.gitbook.io/verge/)

## Prepare moving to SwiftUI from now with Verge

SwiftUI's concept is similar to the concept of React, Vue, and Elm.

Therefore, the concept of state management will become to be similar as well.

That is Redux or Vuex and more.

Now, almost of iOS Applications are developed on top of UIKit.

And We can't say SwiftUI is ready for top production.

However, it would change.

It's better to use the state management that fits SwiftUI from now. It's not only for that, current UIKit based applications can get more productivity as well.

## Installation

With Cocoapods,

VergeStore

```ruby
pod 'Verge/Store'
```

VergeORM

```ruby
pod 'Verge/ORM'
```

VergeRx

```ruby
pod 'Verge/Rx'
```

These are separated with subspecs in Podspec.

After installed, these are merged into single module as `Verge`.

To use Verge in your code, define import decralation following.

```swift
import Verge
```

## Author

[muukii](https://github.com/muukii)

## License

Verge is released under the MIT license.


text:
---
title: Remember
author: Jeremy
tags: [presentations]
imagelink: Remember
permalink: /730
date: 2023-04-03
---

![On the left, there's a large circle with the label "What you say in a presentation". On the left is a much smaller circle with the label "What people remember".](https://res.cloudinary.com/dh3hm8pb7/image/upload/q_auto:best/v1535842782/Handwaving/Published/{{ page.imagelink }}.png){: .centre-image }

The fun part is that you often can't control what that memorable part will be.

license: MIT

branch_name: refs/heads/master

extension: md

license_type: permissive


text:
# Cro::UnhandledErrorReporter

The unhandled error reporting mechanism is used when an exception occurs and
there is nothing in place to handle it, and so it propagates to the sink of a
pipeline. In HTTP applications these errors occur at a connection or request
level, rather than affecting the service as a whole.

The default erorr reporter dumps the exception and backtrace to the standard
error stream. You may provide your own unhandled error reporter if you wish
to, for example, output the error using some kind of logging framework.

## Setting an unhandled error reporter

A `set-unhandled-error-reporter` sub is exported by the module. Call it with a
block, which will be passed an `Exception` as an argument.

```
use Cro::UnhandledErrorReporter;
set-unhandled-error-reporter -> $exception {
    note "OH NO!!!\n" ~ $exception.gist();
}
```

## Reporting an unhandled error

**Note**: This mechanism is only intended for those implementing Cro pipeline
components, and for situations where the error cannot be better communicated.

Call the `report-unhandled-error` sub, passing an `Exception`, in order to
report it using the registered handler.

repository: croservices/cro

gha_language: JavaScript

repo_name: croservices/cro


text:
# @g2a/request-id

[![npm][npm-image]][npm-url]

Library providing utility functions for manipulating and generating [Hierarchical Request IDs][hierarchical_request_id_standard].

## Installation

```shell
$ npm i @g2a/request-id
```

## Basic methods

The following methods are useful in everyday applications.

### `generateIncomingId()`

```ts
(baseId?: string) => string;
```

Generates an [incoming ID][incoming_id_description] based on a provided base ID.
If base ID is not provided or is invalid, generates it from scratch.

Use this function to generate a new ID based on one received in
the request from an external service. ID generated by this function should be
attached to all related log entries and should be used to create Outgoing IDs
assigned to all subsequential outgoing requests.

Example of use with Express.js:

```ts
const logger = new Logger();

// Generate new incoming id for each incoming request
app.use((req, res, next) => {
  res.locals.requestId = generateIncomingId(req.get("request-id"));
  next();
});

app.get("/some-endpoint", (req, res) => {
  // Attach previously generated id to log entries
  logger.trace({
    message: "Some very interesting message",
    requestId: res.locals.requestId
  });

  res.sendStatus(204);
});
```

### `generateOutgoingId()`

```ts
(id: string) => string;
```

Generates an [outgoing ID][outgoing_id_description] based on a provided base ID.
If base ID is not provided or is invalid, generates ID from scratch.

Use this function to generate unique ID each time you make a request to
any external service.

Example of use with:

```ts
app.post("/do-something", (req, res) => {
  // See how it's generated in the example to  the`generateIncomingId()` method
  const currentRequestId = res.locals.requestId;

  request.post({
    url: "http://some-external-service/api",
    headers: {
      "Request-Id": generateOutgoingId(currentRequestId)
    }
  });
});
```

## Advanced methods

Using the following methods requires a better understanding of the Hierarchical
Request Id format. These methods could be useful if you need to do some more
advanced manipulations on request IDs.

### `isValid()`

```ts
(id: string) => boolean;
```

Checks if the provided ID conforms to [Hierarchical Request ID
standard][hierarchical_request_id_standard].

### `isIncoming()`

```ts
(id: string) => boolean;
```

Checks if the provided ID is an [Incoming ID][incoming_id_description].

### `isOutgoing()`

```ts
(id: string) => boolean;
```

Checks if the provided ID is an [Outgoing ID][outgoing_id_description] (but not
a bare Root ID).

### `isRoot()`

```ts
(id: string) => boolean;
```

Checks if the provided ID is a [Root ID][root_id_description].

### `generateRootId()`

```ts
() => string;
```

Generates a new root ID.

### `generateOverflowedId()`

```ts
(id: string) => string;
```

Generates an [overflowed ID][overflowed_id_description] based on provided one.
If provided id is invalid, generates it from scratch.

### `extractRootId()`

```ts
(id: string) => string | null;
```

Extracts root ID from the provided hierarchical request ID. If root ID cannot be
extracted (ID is invalid) returns null instead.

[npm-image]<EMAIL_ADDRESS>[npm-url]: https://www.npmjs.com/package/@g2a/request-id
[hierarchical_request_id_standard]:
  https://github.com/dotnet/corefx/blob/40b9d2226636d9234f755e01f5e36811a55d7cd2/src/System.Diagnostics.DiagnosticSource/src/HierarchicalRequestId.md
[root_id_description]:
  https://github.com/dotnet/corefx/blob/40b9d2226636d9234f755e01f5e36811a55d7cd2/src/System.Diagnostics.DiagnosticSource/src/HierarchicalRequestId.md#root-request-id-generation
[incoming_id_description]:
  https://github.com/dotnet/corefx/blob/40b9d2226636d9234f755e01f5e36811a55d7cd2/src/System.Diagnostics.DiagnosticSource/src/HierarchicalRequestId.md#incoming-request
[outgoing_id_description]:
  https://github.com/dotnet/corefx/blob/40b9d2226636d9234f755e01f5e36811a55d7cd2/src/System.Diagnostics.DiagnosticSource/src/HierarchicalRequestId.md#outgoing-request
[overflowed_id_description]:
  https://github.com/dotnet/corefx/blob/40b9d2226636d9234f755e01f5e36811a55d7cd2/src/System.Diagnostics.DiagnosticSource/src/HierarchicalRequestId.md#request-id-overflow

gha_language: TypeScript

gha_license_id: MIT


text:
# Octopus Deploy - NuGet Deployment Feed
A NuGet feed for Octopus Deploy which creates NuGet packages used to chain deployments of different Octopus projects together.

# Install
1. Use the **[Octopus - Create Chain Deployment NuGet Feed micro service](https://github.com/OctopusDeploy/Library/pull/582)** community step template to provision & deploy the NuGet feed micro service. The following parameters do not have a default value and must be provided:
- API Key
- Octopus Azure Account
- Existing Virtual Network Resource Group Name
- Existing Virtual Network Name
- Existing Subnet Name
[Note : This template will not create a Virtual Network/Subnet]

Once deployed all chain functionality is provided by the NuGet feed & the built-in **Deploy a package** step.

2. Add a **Deploy a package** step to the deployment process of an Octopus project with the package id containing the name of the Octopus project you wish to trigger the deployment of.

![Octopus - D eployment Process - Add Deploy Package Step](/Images/package-step.png)

3. Create a release. The Octopus projects being deployed follow the same behaviour as regular package steps, so the release version being deployed is set when the parent release is made & channel version rules can be used to select stable or development channel releases appropriately.

![Octopus - Create Release](/Images/create-release.png)

![Octopus - View Release](/Images/release-page.png)

4. Deploy!
![Octopus - Deployment](/Images/deploy.png)

![Octopus - Deployed](/Images/deployed.png)

## Manual Install

**It is recommended to use the step template install described in the previous section, the following steps are only needed if manually deploying the service**

1. Deploy the NuGet feed from this repository, the following ARM template takes less than 10 minutes to run and if deployed onto a virtual network that has two way connectivity with Octopus Deploy is fully functional once the template finishes.

2. Create a new 'External Feed' in Octopus Deploy. The feed should be configured as follows:
  * **Feed Type** NuGet Feed
  * **URL** Address where the feed has been deployed, for example if the VM has the IP <IP_ADDRESS> enter http://<IP_ADDRESS>/nuget/
  * **Username** Base URL of the Octopus Server which the NuGet feed should connect to, for example https://my-octopus-server.com/
  * **Password** A valid Octopus Deploy API key to authenticate with
![Octopus - Library - External Feed](/Images/external-feed.png)

repository: paulmarsy/OctopusNuGetDeploymentFeed

gha_language: C#

repo_name: paulmarsy/OctopusNuGetDeploymentFeed


text:
# Embedded Rust

So I like [Rust](https://www.rust-lang.org/), and I'm curious about how it works embedded into microcontrollers.  But, the documentation is scattered and some of it is outdated.

This is my attempt to organize some of it for what I have found that works and is usefull.

## General
* [The Embedded Rust Book](https://docs.rust-embedded.org/book/intro/index.html)

## ESP32
* [Rust on ESP Book](https://esp-rs.github.io/book/introduction.html)
* [Embedded Rust on Espressif](https://espressif-trainings.ferrous-systems.com/01_intro.html)
* [Awesome ESP Rust](https://github.com/esp-rs/awesome-esp-rust)
* [Rust on ESP32 STD demo app](https://github.com/ivmarkov/rust-esp32-std-demo)
* [An embedded-hal implementation for ESP32[-XX] + ESP-IDF](https://github.com/esp-rs/esp-idf-hal)
* [Embedded Rust Trainings for Espressif](https://github.com/ferrous-systems/espressif-trainings)

## ESP8266
* [esp8266-hal](https://github.com/esp-rs/esp8266-hal)

branch_name: refs/heads/main


text:
# K8S-JCasC-Management (Go version)

# Build status #

| | Develop | Master |
| --- | --- | --- |
| Build | [![GoReportCard](https://github.com/Ragin-LundF/k8s-jcasc-management-go/workflows/Go/badge.svg?branch=develop)](https://github.com/Ragin-LundF/k8s-jcasc-management-go/actions) | [![GoReportCard](https://github.com/Ragin-LundF/k8s-jcasc-management-go/workflows/Go/badge.svg?branch=master)](https://github.com/Ragin-LundF/k8s-jcasc-management-go/actions) |
| GoReportCard | | [![GoReportCard](https://goreportcard.com/badge/github.com/Ragin-LundF/k8s-jcasc-management-go)](https://goreportcard.com/report/github.com/Ragin-LundF/k8s-jcasc-management-go) |
| Coveralls | [![Coverage Status](https://coveralls.io/repos/github/Ragin-LundF/k8s-jcasc-management-go/badge.svg?branch=develop)](https://coveralls.io/github/Ragin-LundF/k8s-jcasc-management-go?branch=develop) | [![Coverage Status](https://coveralls.io/repos/github/Ragin-LundF/k8s-jcasc-management-go/badge.svg?branch=master)](https://coveralls.io/github/Ragin-LundF/k8s-jcasc-management-go?branch=master) |

# Table of content #

* [Kubernetes Jenkins as Code management](#kubernetes-jenkins-as-code-management)
  * [Prerequisites](#prerequisites)
* [Basic concept](#basic-concept)
  * [Advantages](#advantages)
* [Build worker](#build-worker)
* [Configuration](#configuration)
  * [Configure alternative configuration with overlays](#configure-alternative-configuration-with-overlays)
  * [Setup with multiple secret files](#setup-with-multiple-secret-files)
* [How to use](#how-to-use)
  * [Server only usage / CLI](#server-only-usage--cli)
  * [Build hints](#build-hints)
  * [Dry-Run and Logging](#dry-run-and-logging)
  * [Debugging](#debugging)
  * [Templates](#templates)
    * [Deployment-only Namespaces](#deployment-only-namespaces)
    * [Sub-Templates (cloud-templates)](#sub-templates-cloud-templates)
* [Execution of Scripts](#execution-of-scripts)
* [IP Management](#ip-management)
* [Screenshots](#screenshots)
  * [Deployment](#deployment)
  * [Create Project](#create-project)
* [Additional tools](#additional-tools)
  * [k8sfullconfigexport](#k8sfullconfigexport)
* [Helpful links](#helpful-links)

# Kubernetes Jenkins as Code management #

This project offers a template for managing Jenkins instances on Kubernetes with a JobDSL and Jenkins Configuration as Code (JcasC).

To simplify the installation and the project settings, it has a small helper tool `k8s-jcasc-mgmt.go`, which can be used in wizard mode or via arguments to
* create new projects for Jenkins administration
* manage secrets
    * encrypt/decrypt secrets for secure commit to a VCS (version control system)
    * apply secrets to Kubernetes
        * for each project while installation or as an update (`applySecrets`)
        * for all known namespaces, that are configured in the `ip_config.cnf` file (applySecretsToAll)
    * store secrets globally for easy administration
    * store secrets per project for more security
* manage the Jenkins instances for a namespace with the project configuration
    * install
        * create namespace if it does not exist
        * install Jenkins
        * install nginx-ingress-controller per namespace (if configured)
        * install loadbalancer and ingress for Jenkins
    * uninstall
        * uninstall Jenkins installation
        * uninstall nginx-ingress-controller per namespace (if configured)
        * uninstall loadbalancer and ingress for Jenkins (other ingress routes will not be changed)
    * upgrade
* version check to see a message in the console if a new version is available

*If you want to use existing persistent volume claims, then you have to create a persistent volume before you install the application.*

*The password for the preconfigured secrets file is `admin`. There is no valid data inside this file! Please change it for your own project!*

As default the system uses encrypted passwords instead of using the password from the `jenkins_helm_values.yaml`.
The default users and passwords are:

- administrator
  - User: admin
  - Pass: admin
  - permissions: all
- project user
  - User: project-user
  - Pass: project
  - permissions: read all and execute build

This can be changed on the `jcasc_config.yaml` file under the `jenkins.securityRealm` section.

To learn more about the internal processes see [here](docs/processes/README.md).

## Prerequisites ##

To use this tool, you need to have the following tools installed:

* golang >= 1.14
* shell (sh/bash for scripts support)
* for encryption:
    * gpg
* [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
* [helm 3](https://helm.sh/)

# Basic concept #

![alt text](docs/images/k8s-mgmt-workflow.png "K8S Workflow")

* A namespace contains one Jenkins instance.
* The namespace is more or less equal to a k8s-mgmt project
    * Projects are stored in a separate repository in a VCS
    * The project contains
        * the Jenkins Helm Chart values.yaml overwrites
        * one JCasC file
* The Jenkins for each namespace will be deployed via k8s-mgmt from the cloned Git repository
* Jenkins loads its main configuration from the project repository (and only from this, which means you can play around and reload configuration directly from the remote URL)
* This main configuration also contains a very simple `seed-job`, which does a scm checkout of a Groovy script to manage jobs and a repository, which contains the job definition.
    * you can use the [jenkins-jobdsl-remote](https://github.com/Ragin-LundF/jenkins-jobdsl-remote) script as such an seed-job manager.

## Advantages ##
By having all things stored in VCS repositories, which are normally backed up, it is possible to recreate every instance in no-time.
It is impossible to misconfigure a Jenkins instance, because the configuration can be reloaded from this remote repository and all configurations are completely versioned.

 statement.

If the K8S cluster or server crashes, it is possible to redeploy everything as it was in minutes, because also the job definition is stored in a VCS repository.

# Build worker #
The pre-defined worker-containers will not work directly.
Every build worker container needs to set up the jenkins home work directory and jenkins user/group with `uid`/`gid` `1000`.

Also, the build worker did not need to have any jenkins agent or something else. Only the user/group and the workdir is needed.

To resolve the problem, that build containers directly shut down, simply add an entrypoint with a `tail -f /dev/null`.

You can also create a Jenkins build worker base container and build your own build tools container on top of it.

Example of a jenkins-build-worker-base-image:

```Dockerfile
ARG UBI_CORE_VERSION=ubi8
ARG UBI_TAG_VERSION=latest

FROM registry.access.redhat.com/${UBI_CORE_VERSION}/ubi-minimal:${UBI_TAG_VERSION}

ARG VERSION=1.0.0
LABEL Description="Jenkins Node Base Container" Vendor="K8S_MGMT" Version="${VERSION}"

# Jenkins user settings
ARG user=jenkins
ARG group=jenkins
ARG uid=1000
ARG gid=1000
ARG AGENT_WORKDIR=/home/${user}/agent

# GLIBC-ENVIRONMENT
ENV GLIBC_LANG=en_US
ENV LANG=${GLIBC_LANG}.UTF-8
ENV LANGUAGE=${GLIBC_LANG}.UTF-8

# install base packages
RUN microdnf update -y && \
    microdnf install -y shadow-utils xz tar zip unzip sudo curl wget bash git procps ca-certificates glibc glibc-langpack-en &&  \
    microdnf clean all

# create jenkins user
RUN groupadd -g ${gid} ${group} && useradd -d /home/${user} -u ${uid} -g ${group} ${user}

# setup jenkins directories and permissions
RUN mkdir /home/${user}/.jenkins && mkdir -p ${AGENT_WORKDIR}

VOLUME /home/${user}/.jenkins
VOLUME ${AGENT_WORKDIR}

WORKDIR /home/${user}

ENTRYPOINT ["tail", "-f", "/dev/null"]
```

A build-worker image for nodejs can look then like this:

```Dockerfile
FROM jenkins-worker-base
ARG VERSION=1.0.0
LABEL Description="Jenkins Worker image for NodeJS" Vendor="K8S_MGMT" Version="${VERSION}"

# install base packages
RUN microdnf update -y && \
    microdnf install -y nodejs && \
    microdnf clean all
```

# Configuration #

The system has a basic configuration file to pre-configure some global settings.
This file is located under [config/k8s_jcasc_mgmt.yaml](config/k8s_jcasc_mgmt.yaml).

It is recommended to change the project base directory to a directory outside of this project.
The `createproject` command will create new projects as subfolders of this directory.
All files and directories under this directory should be passed to a git repository which is backed up.

Then your existing Jenkins projects can be fully recovered from this repository.

## Configure alternative configuration with overlays ##

To use this repository "as-it-is", it is possible to create a `config/k8s_jcasc_custom.yaml` file.

This file can contain the following configuration:

```yaml
k8sManagement:
  # Configuration file for project specific overrides. This file must be relative to the `basePath`.
  configFile: "./config/k8s_jcasc_mgmt_custom.yaml"
  # Base path for all projects. The path can be specified absolutely.
  basePath: "/deployments/k8s-jcasc-manaagement"
```

The script checks, if this file exists.
If this is the case, it loads this configuration and checks the argument for the path of the alternative config file.

This means, that the `k8sManagement.configFile` key can define, where the alternative of the `k8s_jcasc_mgmt.cnf` is located.
In the `.gitignore` file, this file is set to ignore, to prevent a commit.

For base paths like templates, the system searches first for the configured base path and if the directory does not exist, it tries to find the directory in the local (`./`) directory.
With this mechanism it is not required to copy for example also the templates into the project directory if they are ok.

## Setup with multiple secret files

To set up multiple secret files, simply add new files in the same directory where the `secrets.sh(.gpg)` is located.
These files need the prefix `secrets_`.

# How to use #

The simplest way is to call the script without arguments. Everything else will be asked by the script.

*Hint: Before you install the Jenkins, you have to commit the files of your project directory and to ensure, that the `jasc_config.yaml` file is readable for Jenkins (public)*

```bash
go run k8s-jcasc-mgmt.go
```

You can also add one of the following flags:

| Flag | Description | Example |
| --- | --- | --- |
| -basepath=<basepath> | Set the basepath where the config and templates can be found. The default is the current directory. This can be used to re-use the configuration from the `bash` version. | `-basepath="/project/k8s-management/"` |
| -logfile=<path/to/logfile> | Set the path/name to a logfile. If this flag was set, the system logs into this file. | `-logfile="/var/log/k8smgmt.log"` |
| -logencoding=<encoding> | Set log encoding of the logger (`zap`). Default is `json`. Possible values are: `json` or `console` | `-logencoding=console` |
| -server=<true|false> | *Experimental*. Starts the system as a server. Currently it has not enough functions to talk about... | `-server=true` |

## Server only usage / CLI
To use the CLI interface only (e.g. on a server) the tag `cli` deactivates the GUI completely:
```bash
go run -tags cli k8s-jcasc-mgmt.go
```
With this tag the flag `-cli` is not necessary.
In this case Go uses the `app_cli.go` file instead of `app_gui.go` to compile.

## Build hints ##

This was realized with the [fyne](https://fyne.io/) framework.
If you have trouble to compile the project, please visit the [fyne developer](https://developer.fyne.io/started/) site first to check the prerequisites.
On Windows, it is recommended to install [TDM-GCC - tdm-gcc.tdragon.net](https://tdm-gcc.tdragon.net).

## Dry-Run and Logging ##

For dry-run with logging it is highly recommended, to use the following option:

```bash
go run k8s-jcasc-mgmt.go -logfile=debug.log -logencoding=console -dry-run
```
This logs the output in console format, which makes it much more readable. With the `-dry-run` option it renders only the Helm Charts and outputs them into the logfile.

It is also a good idea to use the `-logfile=<file>` and `-logencoding=console` arguments if there are problems.

## Debugging ##

To debug this application in JetBrains GoLand (will maybe work also in IntelliJ, but was not tested), you have to open the `Actions` and to choose `Registry...`.
There is a point called `go.run.processes.with.tty`, which should be activated. This is relevant because of the UI elements.

`Actions` can be found with:
- Mac: `Command` + `Shift` + `A`
- Windows: `Ctrl` + `Shift` + `A`

## Templates ##

At the `templates` directory contains the following:
- `cloud-templates` -> support for subsets for Jenkins Cloud templates
- `jcasc_config.yaml` -> Jenkins Configuration as Code template
- `jenkins_helm_values.yaml` -> Basic Jenkins configuration of the Helm Charts template
- `nginx_ingress_helm_values.yaml` -> Nginx Ingress Controller Helm Chart values template
- `pvc_claim.yaml` -> Template for Persistent Volume Claim
- `secrets.sh` -> Example of secrets.sh script

To find out more about available placeholders in the template files see [docs/TemplatePlaceholder.md](docs/TemplatePlaceholder.md).

### Deployment-only Namespaces ###

`jenkins_helm_values.yaml` offers the possibility to add other namespaces for a Jenkins instance, that should deploy.
The default for this section is empty:

```yaml
[...]
k8smanagement:
  rbac:
    # list of additional namespaces that should be deployable (adds RBAC roles to those namespaces)
    additionalNamespaces: {}
```

To let the Jenkins install applications into other namespaces, these namespaces can be added here.
It is not required to add the namespace in which the Jenkins instance is running.
The Helm Chart will then add additional `Roles` and `RoleBindings` to these namespaces for this instance.

*This is currently a manual process after creating a new project!*

**Example:**
In this example we add the namespaces `myapplication-qa`, `myapplication-preview` and `myapplication-production` to this Jenkins instance.
After this was deployed, Jenkins can now deploy the application into them.

```yaml
[...]
k8smanagement:
  rbac:
    # list of additional namespaces that should be deployable (adds RBAC roles to those namespaces)
    additionalNamespaces:
      - myapplication-qa
      - myapplication-preview
      - myapplication-production
```

### Sub-Templates (cloud-templates) ###

`k8s-jcasc-management` supports additional sub-templates to create projects with dynamic container configuration.
These templates are located in the `./templates/cloud-templates/` directory.
If this directory does not exist, the `create project` wizard will not ask for other sub-templates.

All files stored there can be selected with the process/menu `create project` and will added to the `jcasc_config.yaml`.

The file `jcasc_config.yaml` should now have a `{{ .JCasc.Clouds.Kubernetes.Templates.AdditionalCloudTemplates }}` placeholder:

```yaml
  clouds:
    - kubernetes:
        name: "jenkins-build-worker"
        serverUrl: ""
        serverCertificate: {{ .JCasc.Clouds.Kubernetes.ServerCertificate }}
        directConnection: false
        skipTlsVerify: true
        namespace: "{{ .Base.Namespace }}"
        jenkinsUrl: "http://{{ .Base.DeploymentName }}:8080"
        maxRequestsPerHostStr: 64
        retentionTimeout: 5
        connectTimeout: 10
        readTimeout: 20
        templates:
{{ .JCasc.Clouds.Kubernetes.Templates.AdditionalCloudTemplates }}
```

**It is important, that the placeholder is at the beginning of the line.**

If files are inside of this directory, the user can then select which (none or multiple) sub-templates should be added to the main template.

These sub-templates must also start on the beginning of the line.
For an example have a look here: [templates/cloud-templates/node.yaml](./templates/cloud-templates/node.yaml)

# Execution of Scripts #

It is also possible to create shell scripts for namespaces/directories. This can be helpful, if you want to install other tools besides Jenkins.
The `k8s-jcasc-mgmt.go` tool first tries to install the secrets, PVC and Jenkins. After this was done it checks, if a directory called `scripts` is inside of the project directory and if it contains `*.sh` files.

These files have to follow these rules and naming conventions:
- `i_*.sh` -> Files that should be executed for installation
- `d_*.sh` -> Files that should be executed for deinstallation

The deinstallation scripts can only be executed if the project directory matches the namespace name. This is necessary because normally only the namespace and no directory selection is required for deinstallation.

# IP Management #

For greater installations and after a recovery case too, it is helpful to know which Jenkins instance is running behind which loadbalancer IP on which namespace.

To provide a simple solution, the system stores this information (namespace and IP) into a configuration file, which can also be backed up.
For every deployment of Jenkins, the system looks into this file and configures the loadbalancer with the IP. This also allows static DNS records.

If you create a new project via the wizard, the system also checks, if a IP address already exists to avoid IP conflicts.

# Screenshots #

## GUI

### Welcome
![alt text](docs/images/screenshot_gui_welcome_win.png "K8S-JCasC-Mgmt GUI Welcome")
_Windows screenshot, dark theme_

### Deployment
![alt text](docs/images/screenshot_gui_deployment.png "K8S-JCasC-Mgmt GUI Deployment (Dark Theme)")
_Mac OSX Screenshot, dark theme_
![alt text](docs/images/screenshot_gui_deployment_light.png "K8S-JCasC-Mgmt GUI Deployment (Light Theme)")
_Mac OSX Screenshot, light theme_

### Create Project
![alt text](docs/images/screenshot_gui_createprj.png "K8S-JCasC-Mgmt GUI Project Create (Dark Theme)")
_Mac OSX Screenshot, dark theme_
![alt text](docs/images/screenshot_gui_createprj_light.png "K8S-JCasC-Mgmt GUI Project Create (Light Theme)")
_Mac OSX Screenshot, light theme_

## CLI
### Main Menu
![alt text](docs/images/screenshot_cli_mainmenu.png "K8S-JCasC-Mgmt CLI Main Menu")
_Main menu in CLI mode_

### Namespace selection
![alt text](docs/images/screenshot_cli_namespace-select.png "K8S-JCasC-Mgmt CLI Namespace Selection")
_Namespace selection in CLI mode_

# Additional tools #
## k8sfullconfigexport ##

You can use this tool to export the complete Kubernetes configuration to a local `k8s-manifests` directory.
This can help to figure out differences between clusters.

# Helpful links #

- K8S JCasC Management internal Processes: [Processes overview](docs/processes/README.md)
- Kubernetes DNS-Based Service Discovery: https://github.com/kubernetes/dns/blob/master/docs/specification.md
- JCasC Examples: https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos
- Jenkins Seed Job script to create jobs from a JSON in a GIT repository: https://github.com/Ragin-LundF/jenkins-jobdsl-remote
- Medium article about the background: https://medium.com/@ragin/jenkins-jenkins-configuration-as-code-jcasc-together-with-jobdsl-on-kubernetes-2f5a173491ab
- Medium article about a concept how to work with Jenkins and Kubernetes: https://ragin.medium.com/kubernetes-and-ci-cd-how-to-integrate-in-your-development-process-9b483b194975


text:
stripe
========
[![Hackage](https://img.shields.io/hackage/v/stripe-haskell.svg)](https://hackage.haskell.org/package/stripe-haskell)
[![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)](https://haskell.org)
[![MIT LICENSE](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/dmjio/stripe/blob/master/stripe-haskell/LICENSE)
[![Join the chat at https://gitter.im/dmjio/stripe](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dmjio/stripe?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/dmjio/stripe.svg?branch=master)](https://travis-ci.org/dmjio/stripe)

## Stripe API coverage for Haskell ([Stripe API](http://stripe.com/docs/api))

All Stripe commands are supported, including but not limited to:
  - Charges
  - Refunds
  - Customers
  - Cards
  - Subscriptions
  - Plans
  - Coupons
  - Discounts
  - Invoices
  - Invoice Items
  - Disputes
  - Transfers
  - Recipients ([Deprecated](https://stripe.com/docs/connect/migrating))
  - Bitcoin
  - Application Fees
  - Application Fee Refunds
  - Account
  - Balance
  - Events and Tokens

## Haddock Coverage
  All code written for this library is documented to completion with the haddock documentation tool

## [100+ Hspec Tests](https://github.com/dmjio/stripe-haskell/blob/master/COVERAGE.md)
 Thoroughly unit-tested with hspec.
    All API commands are unit-tested before inclusion into the API (see the tests directory).
    To run the tests, perform the following:
```bash
cabal clean
cabal configure --enable-tests
cabal build tests
dist/build/tests/tests # You will be prompted to enter your *TEST* key
```

## [Pagination](https://stripe.com/docs/api#pagination)
  Pagination is possible on all API calls that return a JSON array.
  Any API call that returns a `StripeList` is eligible for pagination.
  To use in practice do the following:

```haskell
import Web.Stripe
import Web.Stripe.Customer

main :: IO ()
main = do
  let config = StripeConfig (StripeKey "secret key") Nothing
  result <- stripe config $ getCustomers
				(Just 30 :: Maybe Limit) -- Defaults to 10 if Nothing, 100 is Max
				(StartingAfter $ CustomerId "customer_id0")
				(EndingBefore $ CustomerId "customer_id30")
  case result of
    Right stripelist -> print (list stripelist :: [Customer])
    Left stripeError -> print stripeError
```

## [Optional Parameters](https://alexeyzabelin.com/haskell-api-wrapper)
   Stripe API calls can take multiple optional parameters.
  `stripe-haskell` supports optional parameters through the use of type-families and typeclasses.
   In practice, the function to use is `(-&-)` to specify optional parameters on a request.
   For a deeper dive into how this works, please see this [blog post](https://alexeyzabelin.com/haskell-api-wrapper).

```haskell
chargeCardByToken :: TokenId -> Currency -> Amount -> IO (Either StripeError Charge)
chargeCardByToken tokenId currency amount =
  stripe config $ createCharge amount currency
     -&- tokenId
```

## [Versioning](https://stripe.com/docs/api#versioning)
  All versioning is hard-coded (for safety) to version `2014-10-07`.
  Stripe API versions specified in the HTTP headers of Stripe requests take precedence
  over the API version specified in your Stripe Dashboard. In an attempt to ensure
  API consistency and correct parsing of returned JSON, all Stripe versions are hard-coded, and are
  inaccessible to the end-users of this library. When a new Stripe API version is released
  this library will increment the hard-coded API version.

## [Expansion](https://stripe.com/docs/api#expansion)
  Object expansion is supported on Stripe objects eligible for expansion though the `ExpandParams` type.
  Object expansion allows normal Stripe API calls to return expanded objects inside of other objects.
  For example, a `Customer` object contains a Card ID hash on the default_card field.
  This default_card hash can be expanded into a full `Card` object inside a `Customer` object.
  As an example:

```haskell
import Web.Stripe
import Web.Stripe.Customer

main :: IO ()
main = do
  let config = StripeConfig (StripeKey "secret key") Nothing
  result <- stripe config $ getCustomerExpandable
				   (CustomerId "customerid")
				   (["default_card"] :: ExpandParams)
  case result of
    Right customer -> print (defaultCard customer) -- Will be an `ExpandedCard`
    Left stripeError -> print stripeError
```

## [MetaData](https://stripe.com/docs/api#metadata)
  Stripe objects allow the embedding of arbitrary metadata.
  Any Stripe object that supports the embedding of metadata is available via this API.
  As an example:

```haskell
import Web.Stripe
import Web.Stripe.Coupon

main :: IO ()
main = do
  let config = StripeConfig (StripeKey "secret key") Nothing
  result <- stripe config $ updateCoupon (CouponId "couponid") [("key1", "value2"), ("key2", "value2")]
  case result of
    Right coupon -> print $ couponMetaData coupon
    Left stripeError -> print stripeError
```

## [Issues](https://github.com/dmjio/stripe-haskell/issues)
  Any API recommendations or bugs can be reported on the GitHub issue tracker.
  Pull requests welcome!

## Contributors

### Code Contributors

This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].

### Financial Contributors

Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/haskell-stripe/contribute)]

#### Individuals

#### Organizations

Support this project with your organization.  [[Contribute](https://opencollective.com/haskell-stripe/contribute)]

repository: dmjio/stripe

gha_language: Haskell

repo_name: dmjio/stripe


text:
#Image Captioning

## [LSTM](https://github.com/NervanaSystems/ModelZoo/tree/master/ImageCaptioning/LSTM)

LSTM image captioning model based on [CVPR 2015 paper](http://arxiv.org/abs/1411.4555):

    Show and tell: A neural image caption generator.
    O. Vinyals, A. Toshev, S. Bengio, and D. Erhan.
    CVPR, 2015 (arXiv ref. cs1411.4555)

and code from Karpathy's [NeuralTalk](https://github.com/karpathy/neuraltalk).

repository: antreev-brar/ModelZoo

repo_name: antreev-brar/ModelZoo


text:
# NetworkLocation
**OS X menu bar app useful for quickly switching between network locations.**

- Switch between different profiles (have a profile for work with proxy setup, home without proxy, etc...).
- Quick access from menu bar - no need to enter System Preferences anymore!

<img src="https://raw.githubusercontent.com/carmichaelalonso/NetworkLocation/master/NetworkScreenshot.png">

repository: carmichaelalonso/NetworkLocation

repo_name: carmichaelalonso/NetworkLocation


text:
---
layout: post
title: How to publish your libraries to JCenter()
post_author: Eric Cugota
---

Searching on the internet how to publish a library into jcenter() can put one into trouble.
One may even find himself trapped into a spider web of gradle scripts, build configs and ./gradlew commands.
fear not, CptEric has a solution to this.

### Setting up Bintray

To get your api key you must be registered on [bintray](https://bintray.com).

You can find it on your user panel (click in your name, click on edit, click on api key row).

After that  you have to create a new maven repository (package name, image, description, github link, favourite coffee brand... )

### Configuring your library

First of all, you must have project with a library module setup.

Inside the library module’s (from now on, lib) build.gradle, you must add this just under apply plugin line :

```groovy
ext {
   PUBLISH_GROUP_ID = 'com.yourpackagename'
   PUBLISH_ARTIFACT_ID = 'yourmodulename'
   PUBLISH_VERSION = '0.0.2'
}
```

 - Group id : your package name.
 - Artifact id : the thing you’re building, it has to match the module library name.
 - Publish version : no comment required, your current module version.

This , when uploaded, will allow you to put compile `'com.cpteric:ericutils2:0.0.2'` (as an example) in your gradle files.

On the bottom of the file, you must put this line

```groovy
apply from: 'https://raw.githubusercontent.com/blundell/release-android-library/master/android-release-aar.gradle'
```

Other tutorials will make you run a lot of clutter code and build a lot of methods in gradle, but that apply from does it automatically.
The only thing that's not cool about this approach is that you have to manually upload the zips.

Now, go to your project build.gradle file and add this on dependencies :

```groovy
dependencies {
	classpath 'com.android.tools.build:gradle:1.2.3'
	classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
	classpath 'com.github.dcendents:android-maven-plugin:1.2'
}
```

This makes the prior apply from work.

Now on your `local.properties` file you must add this:

```groovy
bintray.user=YOUR BINTRAY USERNAME
bintray.apikey=YOUR BINTRAY API KEY
```

Once done, on the android studio terminal run  the next sequence :

```groovy
./gradlew clean build generateRelease
```

It will generate a zip.

### Publishing to Jcentral()

On your maven repository, click add new version, add the name you want to, add the number you want to, click accept, & enter into the version page.

Inside the general tab , on the right side, click add files via GUI, click on upload, add the generated zip, _and pick the checkbox that says explode on upload._

Click send, and after that, go to your package and click on the “link to jcenter” (bottom right).

Fill the questionary, and it takes between some minutes up to 3 days to be accepted into the jcenter repository.

After that, you can find you package via `compile 'com.cpteric:ericutils2:0.0.2'` or whatever you picked as `'package : Artifact : version'`.

#### About the author

*Eric Cugota is an Android and ios developer for [UseIT Easy Interfaces](http://www.useit.es/) since 2014, has three foundation degrees on software development and computer hardware, and is currently stuying a 3D, animation , posproduction and videogame creation one. gotta catch 'em all.*

branch_name: refs/heads/gh-pages

gha_language: CSS

gha_license_id: NOASSERTION


text:
# Click-In-Text-Chrome

Adapted from [TransOver](https://github.com/artemave/translate_onhover), the amazing chrome extension under MIT license

If you don't know much about chrome extensions: \
Read [google extension official overview](https://developer.chrome.com/extensions/overview) to know the basic relationship of the files.
Specifically `contentscript.js` `background.js`.

## Install

Under project root directory

- `yarn`

## Directory Structure

##### What's compiled by webpack and goes into zipped build

`./src/icons`: Icon of this extension in different resolution. Check `./icons/README.md` for how to generate icons.

`./src/lib`: Core Javascript code that are reusable (browser invariant).
ECMAScript Module is used.

`./src/browser/background.ts` `./src/browser/contentscript.ts` `./options.html`: Chrome-extension specific files

##### Others

`./libexec`: build/dev scripts. Node scripts are preferred over shell script for cross-platform compatibility.

`./src/embedded/test.html`: Test page for cypress to test the UI of the extension.

`./src/test.ts`: Test script that goes with `test.html` to make sure core javascript code and can be thoroughly tested.
It basically mocks the functions in `contentscript.ts` and `background.ts` to run the plugin.

### why `./src/test.ts`

We use cypress to do integration tests,
while it's not possible to test the plugin's UI as a specific browser plugin as cypress lacks the access to their API.
For example in cypress you can't detect plugin menu on the upper right side of Chrome.
You can't open `options.html` as a chrome plugin settings page
because it's not possible for cypress to click on the menu nor get the url of the page
(which is allocated by chrome and only accessible through chrome API `getURL`,
the `crhome://extensions/safdjsaifjg/options.html` url you'll see in the browser is understood
 and routed by chrome and it's not possible to visit inside cypress)

`test.ts` mocks the browser apis to make the extension code work embedded on a web-page.

## Development Routine

1. `yarn dev` (This will watch file changes and repack everything to `./dist` upon file change)

2. Write some bugs. Files will be regenerated in `./dist`

3. Test as embedded javascript: Make sure you have disabled this extension on your browser. `yarn test` to run cypress tests. (It uses `test.html` `test.ts` and runs the extension code as embedded javascript, as explained earlier)

4. (Optional) Manual Testing as an extension: Make sure you have installed the extension in development mode as instructed below. The installation only needs to be done once for any browser. Create any new tab or reload an existing tab to test the changes you just made.

5. Go back to 2. Write more bugs.

Pro tips/Notes:

- You can `npx cypress open` and do everything in cypress built-in chrome. Everything will be the same plus at Step 3 You can use
cypress testing UI and make everything faster by omitting the need to restart a browser.

- As explained earlier. Cypress test at Step 3 tests the extension code as embedded javascript enabled by `test.ts`. Depending on the consistency between `test.ts` and browser API behaviors. Cypress may go through a
 different user experience than what a real user would go through via a browser extension.
 You may want to do manual testing now and then to really find out.

- If you frequently do manual testing, step 5 and 6 of going to a different tab to refresh extension and going back to reload page may be exhausting. Use
this chrome extension as a development tool in your browser.
https://chrome.google.com/webstore/detail/extensions-reloader/fimgfedafeadlieiabdeeaodndnlbhid?hl=en This extension provides
a fake url `http://reload.extensions`. You can visit this url on any tab to reload your extension and reload the tab at one go.

(FYI, if you use cypress browser. Downloaded extensions do persist with your cypress browser over cypress restarts
 so you don't need to worry about re-downloading the tool)

## Install dev

1. On the browser, go to `chrome://extensions`. Toggle on developer mode ![developer_mode.png](readme_assets/developer_mode.png). This enables
you to load local unzipped directories as chrome extensions.

2. Click on "Load unpacked" ![load_unpacked.png](readme_assets/load_unpacked.png)  and choose the generated `./dist` directory.
This loads the code generated in `./dist` as a chrome plugin.

## Linter

run `yarn run lint` or `yarn run lint-fix` under project root.

We also have a Github action that runs `yarn run lint-fix` and commits automatically to enforce formatting.

> Just let `yarn` scripts do the work. Do not run `eslint` yourself, it by default only lints `.js` files but not `.ts` files [and it's not configurable through
eslintrc](https://github.com/eslint/eslint/issues/11223).

## Embedded version

We publish embedded version on npm with `npm publish`. With our `.npmignore`, only `dist/embedded.js` is published.

Other website maintainers can include this one liner in their HTML and get click-in-text on their page:

`<script src="https://unpkg.com/@altlab/click-in-text/dist/embedded"></script>`

More todo:

Do we need an option/configuration page in this embedded version? Current chrome extension supports configuration by
a chrome proprietary menu, where you can set things like `translation delay`, `translation key - alt/ctrl`, `hover or click` etc.

If we do need a option page for embedded version, in what form do we present the options page? I think a hovering widget
is ideal.

## Todo: Adapt to multiple browsers

Seems like there are ways to write a cross-browser extension in one codebase,
see more at Mozilla's [Build a cross browser extension](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Build_a_cross_browser_extension)

repository: UAlbertaALTLab/click-in-text-chrome

repo_name: UAlbertaALTLab/click-in-text-chrome


text:
---
title: Chessboard | Generate Days | Sum Range
date: "2021-07-20"
description: Little scripts that were solutions to some coding exercises
tags: [Learning, JavaScript]
---

These are three small scripts that I created as I tried to get a better understanding of JavaScript. I didn't look at any solutions or examples online, and just wanted to create my own solutions, however imperfect they might be.

## Chessboard

I found this exercise in _Eloquent JavaScript (3rd Edition)_ by Marijn Haverbeke.

The tasks was to create a chessboard out of '#'s and spaces. The function takes width and height arguments and outputs a grid of the corresponding width and height.

```js
const chessboard = (width, height) => {
  let i = 1
  let hash1 = "# "
  let hash2 = " #"

  while (i <= height) {
    let hashWide = i % 2 === 0 ? hash1.repeat(width) : hash2.repeat(width)
    console.log(hashWide)
    i += 1
  }
}

// Example
chessboard(10, 8)

//Output
# # # # # # # # # #
# # # # # # # # # #
 # # # # # # # # # #
# # # # # # # # # #
 # # # # # # # # # #
# # # # # # # # # #
 # # # # # # # # # #
# # # # # # # # # #
```

## Generate Days

I keep a daily journal in Google docs, and I like to have a formatted heading for each day because then I can see each day in the document outline. I also wanted to have each day in the following format: `{Month} {Day of Month}, {Year}, {Day of Week}`, and it was annoying to manually write date each day, I created this script that creates as many dates in this format and outputs it to console where I can then copy them to a Google doc.

The function takes argument days as a number of days we need from the current date.

```js
const generateDays = days => {
  var t = 0
  var weekdays = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
  ]
  const months = [
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December",
  ]

  var today = new Date()
  var day_in_milliseconds = 1000 * 60 * 60 * 24

  while (t < days) {
    var today = new Date(Date.now() + day_in_milliseconds * t)
    var weekday = weekdays[today.getDay()]
    var month = months[today.getMonth()]
    var day = today.getDate()
    var year = today.getFullYear()
    console.log(`${month} ${day}, ${year}, ${weekday}`)
    t++
  }
}

//Example (today's date is July 20, 2021)
generateDays(10)

//Output
July 20, 2021, Tuesday
July 21, 2021, Wednesday
July 22, 2021, Thursday
July 23, 2021, Friday
July 24, 2021, Saturday
July 25, 2021, Sunday
July 26, 2021, Monday
July 27, 2021, Tuesday
July 28, 2021, Wednesday
July 29, 2021, Thursday
```

The only thing left after this is to copy this output to Google doc, selecting the output and then formatting as a heading by selecting the desired heading size in the editing bar or by using `ctrl + alt + {desired heading size that corresponds to numbers 1-5 (I use 5)}`

## Sum and Range

This exercise was also in _Eloquent Javascript_. The task was to create a function that will take the starting and ending numbers and then create an array that will have have those two numbers and all numbers between them. The third argument is the number by which to increment the numbers in the array.

```js
const range = (start, end, increment) => {
  let arrayNumbers = []
  while (start <= end) {
    arrayNumbers.push(start)
    start += increment ? increment : 1
  }
  return arrayNumbers
}

const sum = range => {
  let sum = 0
  let i = 0
  while (i < range.length) {
    sum += range[i]
    i += 1
  }
  return sum
}

//Example
console.log(range(1, 10)) //Output: [(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)]
console.log(sum(range(1, 10))) //Output: 55
```


text:
#\#ify (Hashify)
=======

\#ify is a way of finding links that people are talking about. Search engines are good for finding information relating to a string of words that articles have included in them. #ify is for finding articles that people are talking about on the topic. Instead of any website that uses the word "iPhone" in it; we look for what people are linking to with the hashtag "#iPhone". This means you see the articles that people are talking about.

###How to setup hashify
Before you can use hashify you will need to get API keys from Google, Facebook and Twitter. You can do this from their developer websites. You will then need to change the key variables in search.php to your own keys for results to show up.

###Can I see a live demo?
Sorry, not right now. It will be back up soon.

repository: NickGeek/hashify

gha_language: PHP

repo_name: NickGeek/hashify


text:
# kBundle(ANDROID)

Better, type safe version of creating bundle.

### Code Formatting

```gradle
./gradlew spotlessApply
```

*Make sure you update [spotless.license.kt](spotless.license.kt) and [LICENSE.md](LICENSE.md) to reflect your own license and author info!* Other settings for this plugin can be tweaked in [gradle/spotless_plugin_config.gradle](gradle/spotless_plugin_config.gradle).

### Check if Dependencies Are Up-to-Date

```gradle
./gradlew dependencyUpdates
```

Settings can be tweaked for this plugin within [gradle/versions_plugin_config.gradle](gradle/versions_plugin_config.gradle).

### Publishing the Library to Bintray -> jCenter

This repository is setup to automatically publish to Bintray when you create a new release from
GitHub.

But there are some pre-requisites:

1. Update [library_info.gradle](library_info.gradle) to contain your library's information (group, description, etc.).
2. From your GitHub repository settings, add **secrets** for `BINTRAY_ORG`, `BINTRAY_USER`, and `BINTRAY_API_KEY`.
These will be used by the `Bintray Release` GitHub Actions workflow.
3. With each release, update the version name and code in [library_info.gradle](library_info.gradle#L6-L8).
4. Once you've deployed to Bintray for the first time, you can link your Bintray repository to jCenter so
people can depend on your library from Android projects _without_ having to add any special Maven repositories.

How does releasing work?

1. **Automatically** when you create a [Release](https://help.github.com/en/github/administering-a-repository/releasing-projects-on-github)
in your GitHub repository.
2. OR if you set the three environment variables mentioned above, and invoke `./gradlew bintrayUpload`.

repository: hanibalsk/kbundle

repo_name: hanibalsk/kbundle