Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
"extends": [
"./node_modules/@effect-app/eslint-shared-config/src/oxlintrc.json"
],
"ignorePatterns": [
"**/dist/**",
"**/node_modules/**",
"**/*.d.ts",
"**/*.css",
"**/*.scss",
"**/*.vue",
"**/*.json",
"**/*.md",
"**/*.js",
"**/*.jsx",
"**/vitest.config.ts",
"**/eslint.*.mjs",
"**/CHANGELOG.md",
"repos/**"
]
}
4 changes: 3 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"recommendations": [
"oxc.oxc-vscode",
"dprint.dprint",
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"Vue.volar"
]
}
}
47 changes: 25 additions & 22 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,43 @@
"--max-old-space-size=8192"
],
"editor.formatOnSave": true,
"eslint.format.enable": true,
"editor.formatOnSaveMode": "file",
"editor.codeActionsOnSave": {
"source.fixAll.oxc": "explicit",
"source.fixAll.eslint": "explicit",
"source.addMissingImports": "explicit"
},
"editor.defaultFormatter": "dprint.dprint",
"[vue]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": [
"source.addMissingImports"
]
"editor.defaultFormatter": "dprint.dprint"
},
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": [
"source.addMissingImports"
]
"editor.defaultFormatter": "dprint.dprint"
},
"[javascriptreact]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": [
"source.addMissingImports"
]
"editor.defaultFormatter": "dprint.dprint"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
"editor.defaultFormatter": "dprint.dprint"
},
"[jsonc]": {
"editor.defaultFormatter": "dprint.dprint"
},
"[typescript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": [
"source.addMissingImports"
]
"editor.defaultFormatter": "dprint.dprint"
},
"[typescriptvue]": {
"editor.defaultFormatter": "dprint.dprint"
},
"[typescriptreact]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": [
"source.addMissingImports"
]
"editor.defaultFormatter": "dprint.dprint"
},
"eslint.validate": [
"javascript",
"typescript",
"vue"
],
"eslint.format.enable": false,
"csv-preview.separator": ";",
"cSpell.words": [
"codegen",
Expand Down
19 changes: 0 additions & 19 deletions api/eslint.config.mjs

This file was deleted.

2 changes: 1 addition & 1 deletion api/nodemon.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
".env.local"
],
"delay": 333
}
}
2 changes: 1 addition & 1 deletion api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -462,4 +462,4 @@
"bearerAuth": []
}
]
}
}
28 changes: 16 additions & 12 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
"watch": "pnpm build --watch",
"watch2": "pnpm clean-dist && pnpm check -w",
"check": "NODE_OPTIONS=--max-old-space-size=8192 tsc --build",
"lint": "NODE_OPTIONS=--max-old-space-size=8192 ESLINT_TS=1 eslint src test",
"lint:watch": "ESLINT_TS=1 esw -w --changed --clear --ext ts,tsx src test",
"lint-fix": "pnpm lint --fix",
"lint:oxlint": "oxlint --quiet --type-aware src test",
"lint:oxlint:fix": "oxlint --quiet --type-aware --fix src test",
"format": "dprint fmt --config ../dprint.jsonc .",
"format:check": "dprint check --config ../dprint.jsonc .",
"lint": "pnpm lint:oxlint && pnpm format:check",
"lint-fix": "pnpm lint:oxlint:fix && pnpm format",
"test": "vitest",
"test:run": "pnpm run test run --passWithNoTests",
"testsuite": "pnpm circular && pnpm run test:run && pnpm lint",
Expand Down Expand Up @@ -141,12 +144,12 @@
"@azure/cosmos": "^4.9.3",
"@azure/service-bus": "^7.9.5",
"@azure/storage-blob": "^12.31.0",
"@effect-app/infra": "4.0.0-beta.178",
"effect-app": "4.0.0-beta.178",
"@effect/opentelemetry": "4.0.0-beta.59",
"@effect/platform-node": "4.0.0-beta.59",
"@effect/sql-sqlite-node": "4.0.0-beta.59",
"@effect/vitest": "4.0.0-beta.59",
"@effect-app/infra": "4.0.0-beta.218",
"effect-app": "4.0.0-beta.218",
"@effect/opentelemetry": "4.0.0-beta.64",
"@effect/platform-node": "4.0.0-beta.64",
"@effect/sql-sqlite-node": "4.0.0-beta.64",
"@effect/vitest": "4.0.0-beta.64",
"@formatjs/cli": "^6.14.4",
"@formatjs/intl": "4.1.8",
"@mollie/api-client": "^4.5.0",
Expand All @@ -161,7 +164,7 @@
"cross-fetch": "^4.1.0",
"date-fns": "^4.1.0",
"dotenv": "^17.4.2",
"effect": "4.0.0-beta.59",
"effect": "4.0.0-beta.64",
"express": "^5.2.1",
"express-compression": "^1.0.2",
"express-oauth2-jwt-bearer": "^1.8.0",
Expand All @@ -186,8 +189,9 @@
"@types/express": "^5.0.6",
"@types/redis": "^2.8.32",
"@types/swagger-ui-express": "^4.1.8",
"eslint": "^10.3.0",
"dprint": "^0.54.0",
"oxlint": "^1.62.0",
"oxlint-tsgolint": "^0.22.1",
"typescript": "~6.0.2"
}
}
}
4 changes: 2 additions & 2 deletions api/src/Accounts.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ export default Router(AccountsRsc)({
*Index() {
const users = yield* userRepo.all
return users.map((u) =>
new UserItem({
UserItem.make({
id: u.id,
name: S.NonEmptyString2k(`${u.name.firstName} ${u.name.lastName}`)
})
)
},
GetMe: userRepo.getCurrentUser
GetMe: () => userRepo.getCurrentUser
})
}
})
2 changes: 1 addition & 1 deletion api/src/HelloWorld.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default Router(HelloWorldRsc)({
})
)

return new GetHelloWorld.success({
return GetHelloWorld.success.make({
context,
echo,
state,
Expand Down
20 changes: 0 additions & 20 deletions api/src/Operations.controllers.ts

This file was deleted.

8 changes: 6 additions & 2 deletions api/src/Users.controllers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Router } from "#lib/routing"
import { User } from "#models/User"
import { UsersRsc } from "#resources"
import type { UserView } from "#resources/views"
import { UserView } from "#resources/views/UserView"
import { Q, UserRepo } from "#services"
import { Array } from "effect"
import { Effect, Order } from "effect-app"
Expand All @@ -15,7 +16,10 @@ export default Router(UsersRsc)({
userRepo
.query(Q.where("id", "in", req.filterByIds))
.pipe(Effect.map((users) => ({
users: Array.sort(users, Order.mapInput(Order.String, (_: UserView) => _.displayName))
users: Array.sort(
users.map((u) => UserView.make({ id: u.id, role: u.role, displayName: User.displayName(u) })),
Order.mapInput(Order.String, (_: UserView) => _.displayName)
)
})))
})
}
Expand Down
16 changes: 8 additions & 8 deletions api/src/_test-decode.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var lib_1 = require("#resources/lib");
var effect_app_1 = require("effect-app");
var userProfileFromJson = effect_app_1.S.fromJsonString(lib_1.UserProfile.fromEncoded);
"use strict"
Object.defineProperty(exports, "__esModule", { value: true })
var lib_1 = require("#resources/lib")
var effect_app_1 = require("effect-app")
var userProfileFromJson = effect_app_1.S.fromJsonString(lib_1.UserProfile.fromEncoded)
// Force errors to see what the types resolve to
var _checkDS = ds;
var _checkFEDS = feds;
var _checkUPDS = upds;
var _checkDS = ds
var _checkFEDS = feds
var _checkUPDS = upds
2 changes: 1 addition & 1 deletion api/src/config/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const sendgrid = C.all({
apiKey: C.redacted("sendgridApiKey").pipe(C.withDefault(
Redacted.make("")
)),
fakeMailAddress: C.string().pipe(C.withDefault("fake-{i}@example.com")),
fakeMailAddress: C.succeed("fake+{i}@example.com"),
defaultFrom: C.succeed(FROM),
subjectPrefix: env.pipe(C.map((env) => env === "prod" ? "" : `[${serviceName_}] [${env}] `))
})
Expand Down
3 changes: 1 addition & 2 deletions api/src/controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import accountsControllers from "./Accounts.controllers.js"
import blogControllers from "./Blog.controllers.js"
import helloWorldControllers from "./HelloWorld.controllers.js"
import operationsControllers from "./Operations.controllers.js"
import usersControllers from "./Users.controllers.js"

export { accountsControllers, blogControllers, helloWorldControllers, operationsControllers, usersControllers }
export { accountsControllers, blogControllers, helloWorldControllers, usersControllers }
// codegen:end
10 changes: 2 additions & 8 deletions api/src/lib/layers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { FakeSendgrid } from "@effect-app/infra/Emailer/fake"
import { Sendgrid } from "@effect-app/infra/Emailer/Sendgrid"
import { Operations } from "@effect-app/infra/Operations"
import { OperationsRepo } from "@effect-app/infra/OperationsRepo"
import { StoreMakerLayer } from "@effect-app/infra/Store/index"
import { NodeServices } from "@effect/platform-node"
import * as HttpClientNode from "@effect/platform-node/NodeHttpClient"
Expand All @@ -15,12 +13,12 @@ import { apiConfig, baseConfig } from "../config.js"

const ClientLive = SqliteClient
.layer({
filename: "./" + ".data" + "/db.db"
filename: "./.data/db.db"
})
.pipe(Layer.provide(
Effect
.gen(function*() {
const path = "./" + ".data"
const path = "./.data"
if (!fs.existsSync(path)) {
fs.mkdirSync(path)
}
Expand Down Expand Up @@ -48,10 +46,6 @@ export const EmailerLive = Effect
})
.pipe(Layer.unwrap)

export const OperationsDefault = Operations.Live.pipe(
Layer.provide(Layer.effect(OperationsRepo, OperationsRepo.make).pipe(Layer.provide(RepoTest)))
)

export const Platform = HttpClientNode.layerUndici

export const ApiPortTag = Context.Service<{ port: number }>("@services/ApiPortTag")
Expand Down
2 changes: 1 addition & 1 deletion api/src/lib/observability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class MetricsReader extends Context.Service<MetricsReader>()("MetricsRead
static readonly Live = Layer.effect(this, this.make).pipe(Layer.provide(ExporterRunning.Default))
}

const filteredOps = ["Import.AllOperations", "Operations.FindOperation"]
const filteredOps = ["Import.AllOperations"]
const filteredPaths = ["/.well-known/local/server-health", ...filteredOps.map((op) => `/${op}`)]
const filteredMethods = ["OPTIONS"]
const filterAttrs = {
Expand Down
14 changes: 5 additions & 9 deletions api/src/lib/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,8 @@ const RequireRolesLive = Layer.effect(
})
)

class AppMiddlewareImpl extends AppMiddleware {
static Default = this.layer.pipe(Layer.provide([
AllowAnonymousLive,
RequireRolesLive,
DefaultGenericMiddlewaresLive
]))
}

export const { Router, matchAll } = makeRouter(AppMiddlewareImpl)
export const { Router, matchAll } = makeRouter(AppMiddleware.layer.pipe(Layer.provide([
AllowAnonymousLive,
RequireRolesLive,
DefaultGenericMiddlewaresLive
])))
16 changes: 8 additions & 8 deletions api/src/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ export const LastName = S

export type LastName = typeof LastName.Type

export class FullName extends S.Class<FullName, FullName.Encoded>("FullName")({
export class FullName extends S.Opaque<FullName, FullName.Encoded>()(S.Struct({
firstName: FirstName,
lastName: LastName
}) {
})) {
static render(this: void, fn: FullName) {
return S.NonEmptyString2k(`${fn.firstName} ${fn.lastName}`)
}

static create(this: void, firstName: FirstName, lastName: LastName) {
return new FullName({ firstName, lastName })
return FullName.make({ firstName, lastName })
}
}

Expand All @@ -62,15 +62,15 @@ export class UserFromIdResolver extends Context.Service<UserFromIdResolver, {
static readonly getUser = (userId: UserId) => UserFromIdResolver.use((_) => _.get(userId))
}

export class User extends S.Class<User, User.Encoded>("User")({
id: UserId.withDefault,
export class User extends S.Opaque<User, User.Encoded>()(S.Struct({
id: UserId.withConstructorDefault,
name: FullName,
email: S.Email,
role: Role,
// passwordHash: S.NonEmptyString255
}) {
get displayName() {
return S.NonEmptyString2k(this.name.firstName + " " + this.name.lastName)
})) {
static displayName(this: void, u: User) {
return S.NonEmptyString2k(`${u.name.firstName} ${u.name.lastName}`)
}
static readonly resolver = UserFromIdResolver
}
Expand Down
Loading