Compare commits
4 commits
8f3aeec10b
...
ae7b911b16
Author | SHA1 | Date | |
---|---|---|---|
Julien Oculi | ae7b911b16 | ||
Julien Oculi | 94632dbc07 | ||
Julien Oculi | e4b2f335a5 | ||
Julien Oculi | 11bdf8d53b |
1
.env.example
Normal file
1
.env.example
Normal file
|
@ -0,0 +1 @@
|
|||
DB_PATH = './db.sqlite'
|
15
deno.json
15
deno.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@cohabit/ressources",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"exports": {
|
||||
".": "./mod.ts",
|
||||
"./models": "./src/models/mod.ts"
|
||||
|
@ -14,16 +14,11 @@
|
|||
"semiColons": false
|
||||
},
|
||||
"imports": {
|
||||
"@/": "./",
|
||||
"@models": "./src/models/mod.ts",
|
||||
"@models/": "./src/models/src/",
|
||||
"@api": "./src/api/server.ts",
|
||||
"@api/": "./src/api/",
|
||||
"@db": "./src/db/mod.ts",
|
||||
"@db/": "./src/db/",
|
||||
"@std/json": "jsr:@std/json@^0.223.0"
|
||||
},
|
||||
"exclude": [
|
||||
"./docs"
|
||||
]
|
||||
"./docs",
|
||||
"./tmp"
|
||||
],
|
||||
"unstable": ["kv"]
|
||||
}
|
||||
|
|
4
mod.ts
4
mod.ts
|
@ -1,2 +1,2 @@
|
|||
export * from '@models'
|
||||
export { Db } from '@db'
|
||||
export * from './src/models/mod.ts'
|
||||
export { Db } from './src/db/mod.ts'
|
||||
|
|
|
@ -6,15 +6,15 @@ import {
|
|||
type Ressource,
|
||||
Service,
|
||||
User,
|
||||
} from '@models'
|
||||
import type { CredentialCategory } from '@models/credential.ts'
|
||||
} from '../models/mod.ts'
|
||||
import type { CredentialCategory } from '../models/src/credential.ts'
|
||||
|
||||
//!TODO link ressources (get, list)
|
||||
//!TODO Purge unused ressources (delete)
|
||||
|
||||
export class Db {
|
||||
#kv: Deno.Kv
|
||||
static async init(path?: string) {
|
||||
static async init(path?: string): Promise<Db> {
|
||||
const kv = await Deno.openKv(path ?? Deno.env.get('DB_PATH'))
|
||||
return new Db(kv)
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ export class Db {
|
|||
this.#kv = kv
|
||||
}
|
||||
|
||||
get storage() {
|
||||
get storage(): Deno.Kv {
|
||||
return this.#kv
|
||||
}
|
||||
|
||||
get prefix() {
|
||||
get prefix(): { ressource: 'ressource' } {
|
||||
return {
|
||||
ressource: 'ressource',
|
||||
}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
export {
|
||||
Ref,
|
||||
type RefResolver,
|
||||
type RefString,
|
||||
} from '@/src/models/utils/ref.ts'
|
||||
export { Credential } from '@models/credential.ts'
|
||||
export { Group } from '@models/group.ts'
|
||||
export { Machine } from '@models/machine.ts'
|
||||
export type { Ressource } from '@models/ressource.ts'
|
||||
export { Service } from '@models/service.ts'
|
||||
export { User } from '@models/user.ts'
|
||||
export { Ref, type RefResolver, type RefString } from './utils/ref.ts'
|
||||
export { Credential } from './src/credential.ts'
|
||||
export { Group } from './src/group.ts'
|
||||
export { Machine } from './src/machine.ts'
|
||||
export type { Ressource } from './src/ressource.ts'
|
||||
export { Service } from './src/service.ts'
|
||||
export { User } from './src/user.ts'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Base64String, ToJson, UUID } from '@/types.ts'
|
||||
import { Ressource } from '@models/ressource.ts'
|
||||
import type { Ref } from '@models'
|
||||
import { Avatar } from '@/src/models/utils/avatar.ts'
|
||||
import type { Base64String, ToJson, UUID } from '../../../types.ts'
|
||||
import { Ressource } from './ressource.ts'
|
||||
import type { Ref } from '../utils/ref.ts'
|
||||
import { Avatar } from '../utils/avatar.ts'
|
||||
|
||||
export class Credential<T extends CredentialCategory> extends Ressource {
|
||||
static fromJSON<T extends CredentialCategory>(
|
||||
|
@ -65,11 +65,11 @@ export class Credential<T extends CredentialCategory> extends Ressource {
|
|||
return 'credential'
|
||||
}
|
||||
|
||||
get category() {
|
||||
get category(): T {
|
||||
return this.#category
|
||||
}
|
||||
|
||||
get store() {
|
||||
get store(): Readonly<CredentialStore<T>['store']> {
|
||||
return this.#store
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Posix, ToJson, UUID } from '@/types.ts'
|
||||
import { Ressource } from '@models/ressource.ts'
|
||||
import { Ref } from '@models'
|
||||
import { Avatar } from '@/src/models/utils/avatar.ts'
|
||||
import type { Posix, ToJson, UUID } from '../../../types.ts'
|
||||
import { Ressource } from './ressource.ts'
|
||||
import { Ref } from '../utils/ref.ts'
|
||||
import { Avatar } from '../utils/avatar.ts'
|
||||
|
||||
export class Group extends Ressource {
|
||||
static fromJSON(
|
||||
|
@ -50,13 +50,7 @@ export class Group extends Ressource {
|
|||
}
|
||||
|
||||
#posix?: Posix
|
||||
#permissions: Readonly<{
|
||||
[serviceOrMachine: UUID]: {
|
||||
read: boolean
|
||||
write: boolean
|
||||
execute: boolean
|
||||
}
|
||||
}>
|
||||
#permissions: Readonly<GroupPermissions>
|
||||
#groups: readonly Ref<Group>[]
|
||||
|
||||
private constructor(
|
||||
|
@ -93,15 +87,15 @@ export class Group extends Ressource {
|
|||
return 'group'
|
||||
}
|
||||
|
||||
get posix() {
|
||||
get posix(): Posix | undefined {
|
||||
return this.#posix
|
||||
}
|
||||
|
||||
get permissions() {
|
||||
get permissions(): Readonly<GroupPermissions> {
|
||||
return this.#permissions
|
||||
}
|
||||
|
||||
get groups() {
|
||||
get groups(): readonly Ref<Group>[] {
|
||||
return this.#groups
|
||||
}
|
||||
|
||||
|
@ -134,11 +128,13 @@ export interface Group extends Ressource {
|
|||
type: 'group'
|
||||
posix: Posix | undefined
|
||||
groups: readonly Ref<Group>[]
|
||||
permissions: Readonly<{
|
||||
[serviceOrMachine: UUID]: {
|
||||
read: boolean
|
||||
write: boolean
|
||||
execute: boolean
|
||||
}
|
||||
}>
|
||||
permissions: Readonly<GroupPermissions>
|
||||
}
|
||||
|
||||
export type GroupPermissions = {
|
||||
[serviceOrMachine: UUID]: {
|
||||
read: boolean
|
||||
write: boolean
|
||||
execute: boolean
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Ref } from '@/src/models/utils/ref.ts'
|
||||
import type { ToJson, UrlString } from '@/types.ts'
|
||||
import type { Group } from '@models/group.ts'
|
||||
import { Ressource } from '@models/ressource.ts'
|
||||
import { Avatar } from '@/src/models/utils/avatar.ts'
|
||||
import { Ref } from '../utils/ref.ts'
|
||||
import type { ToJson, UrlString } from '../../../types.ts'
|
||||
import type { Group } from './group.ts'
|
||||
import { Ressource } from './ressource.ts'
|
||||
import { Avatar } from '../utils/avatar.ts'
|
||||
|
||||
export class Machine extends Ressource {
|
||||
static fromJSON(
|
||||
|
@ -14,7 +14,7 @@ export class Machine extends Ressource {
|
|||
}
|
||||
|
||||
static create(
|
||||
{ tags, url, status, groups, avatar }: Pick<
|
||||
{ tags, url, status, groups, avatar, name }: Pick<
|
||||
Machine,
|
||||
'name' | 'tags' | 'url' | 'status' | 'avatar' | 'groups'
|
||||
>,
|
||||
|
@ -53,13 +53,7 @@ export class Machine extends Ressource {
|
|||
|
||||
#tags: readonly string[]
|
||||
#url: UrlString
|
||||
#status:
|
||||
| 'ready'
|
||||
| 'busy'
|
||||
| 'unavailable'
|
||||
| 'discontinued'
|
||||
| 'error'
|
||||
| 'unknown'
|
||||
#status: MachineStatus
|
||||
#groups: readonly Ref<Group>[]
|
||||
|
||||
private constructor(
|
||||
|
@ -83,16 +77,16 @@ export class Machine extends Ressource {
|
|||
get type(): 'machine' {
|
||||
return 'machine'
|
||||
}
|
||||
get tags() {
|
||||
get tags(): readonly string[] {
|
||||
return this.#tags
|
||||
}
|
||||
get url() {
|
||||
get url(): UrlString {
|
||||
return this.#url
|
||||
}
|
||||
get status() {
|
||||
get status(): MachineStatus {
|
||||
return this.#status
|
||||
}
|
||||
get groups() {
|
||||
get groups(): readonly Ref<Group>[] {
|
||||
return this.#groups
|
||||
}
|
||||
|
||||
|
@ -128,12 +122,14 @@ export interface Machine extends Ressource {
|
|||
type: 'machine'
|
||||
tags: readonly string[]
|
||||
url: UrlString
|
||||
status:
|
||||
| 'ready'
|
||||
| 'busy'
|
||||
| 'unavailable'
|
||||
| 'discontinued'
|
||||
| 'error'
|
||||
| 'unknown'
|
||||
status: MachineStatus
|
||||
groups: readonly Ref<Group>[]
|
||||
}
|
||||
|
||||
export type MachineStatus =
|
||||
| 'ready'
|
||||
| 'busy'
|
||||
| 'unavailable'
|
||||
| 'discontinued'
|
||||
| 'error'
|
||||
| 'unknown'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Ref } from '@/src/models/utils/ref.ts'
|
||||
import type { DateString, ToJson, UrlString, UUID } from '@/types.ts'
|
||||
import { regex } from '@/utils.ts'
|
||||
import { Ref } from '../utils/ref.ts'
|
||||
import type { DateString, ToJson, UrlString, UUID } from '../../../types.ts'
|
||||
import { regex } from '../../../utils.ts'
|
||||
|
||||
export class Ressource {
|
||||
static fromJSON(
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Ref } from '@/src/models/utils/ref.ts'
|
||||
import type { ToJson, UrlString } from '@/types.ts'
|
||||
import type { Group } from '@models/group.ts'
|
||||
import { Ressource } from '@models/ressource.ts'
|
||||
import { Avatar } from '@/src/models/utils/avatar.ts'
|
||||
import { Ref } from '../utils/ref.ts'
|
||||
import type { ToJson, UrlString } from '../../../types.ts'
|
||||
import type { Group } from './group.ts'
|
||||
import { Ressource } from './ressource.ts'
|
||||
import { Avatar } from '../utils/avatar.ts'
|
||||
|
||||
export class Service extends Ressource {
|
||||
static fromJSON(
|
||||
|
@ -52,7 +52,7 @@ export class Service extends Ressource {
|
|||
return this.create({ name, avatar, tags, url, category, groups })
|
||||
}
|
||||
|
||||
#category: 'web' | 'fs' | 'git'
|
||||
#category: ServiceCategory
|
||||
#url: UrlString
|
||||
#groups: readonly Ref<Group>[]
|
||||
#tags: readonly string[]
|
||||
|
@ -92,19 +92,19 @@ export class Service extends Ressource {
|
|||
return 'service'
|
||||
}
|
||||
|
||||
get category() {
|
||||
get category(): ServiceCategory {
|
||||
return this.#category
|
||||
}
|
||||
|
||||
get tags() {
|
||||
get tags(): readonly string[] {
|
||||
return this.#tags
|
||||
}
|
||||
|
||||
get url() {
|
||||
get url(): UrlString {
|
||||
return this.#url
|
||||
}
|
||||
|
||||
get groups() {
|
||||
get groups(): readonly Ref<Group>[] {
|
||||
return this.#groups
|
||||
}
|
||||
|
||||
|
@ -138,8 +138,10 @@ export class Service extends Ressource {
|
|||
|
||||
export interface Service extends Ressource {
|
||||
type: 'service'
|
||||
category: 'web' | 'fs' | 'git'
|
||||
category: ServiceCategory
|
||||
tags: readonly string[]
|
||||
url: UrlString
|
||||
groups: readonly Ref<Group>[]
|
||||
}
|
||||
|
||||
export type ServiceCategory = 'web' | 'fs' | 'git'
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Ref } from '@/src/models/utils/ref.ts'
|
||||
import type { Login, MailAddress, Posix, ToJson } from '@/types.ts'
|
||||
import { regex, toLogin } from '@/utils.ts'
|
||||
import type { Credential, CredentialCategory } from '@models/credential.ts'
|
||||
import type { Group } from '@models/group.ts'
|
||||
import { Ressource } from '@models/ressource.ts'
|
||||
import { Avatar } from '@/src/models/utils/avatar.ts'
|
||||
import { Ref } from '../utils/ref.ts'
|
||||
import type { Login, MailAddress, Posix, ToJson } from '../../../types.ts'
|
||||
import { regex, toLogin } from '../../../utils.ts'
|
||||
import type { Credential, CredentialCategory } from './credential.ts'
|
||||
import type { Group } from './group.ts'
|
||||
import { Ressource } from './ressource.ts'
|
||||
import { Avatar } from '../utils/avatar.ts'
|
||||
|
||||
export class User extends Ressource {
|
||||
static fromJSON(json: ToJson<User>): User {
|
||||
|
@ -150,25 +150,25 @@ export class User extends Ressource {
|
|||
get type(): 'user' {
|
||||
return 'user'
|
||||
}
|
||||
get firstname() {
|
||||
get firstname(): string {
|
||||
return this.#firstname
|
||||
}
|
||||
get lastname() {
|
||||
get lastname(): string {
|
||||
return this.#lastname
|
||||
}
|
||||
get login() {
|
||||
get login(): Login {
|
||||
return this.#login
|
||||
}
|
||||
get mail() {
|
||||
get mail(): MailAddress {
|
||||
return this.#mail
|
||||
}
|
||||
get groups() {
|
||||
get groups(): readonly Ref<Group>[] {
|
||||
return this.#groups
|
||||
}
|
||||
get posix() {
|
||||
get posix(): Posix | undefined {
|
||||
return this.#posix
|
||||
}
|
||||
get credentials() {
|
||||
get credentials(): readonly Ref<Credential<CredentialCategory>>[] {
|
||||
return this.#credentials
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { UrlString } from '@/types.ts'
|
||||
import type { UrlString } from '../../../types.ts'
|
||||
|
||||
export class Avatar {
|
||||
static fromEmoji(emoji: string): UrlString {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Db } from '@/mod.ts'
|
||||
import type { UUID } from '@/types.ts'
|
||||
import type { Db } from '../../db/mod.ts'
|
||||
import type { UUID } from '../../../types.ts'
|
||||
import {
|
||||
Credential,
|
||||
Group,
|
||||
|
@ -7,7 +7,7 @@ import {
|
|||
type Ressource,
|
||||
Service,
|
||||
User,
|
||||
} from '@models'
|
||||
} from '../mod.ts'
|
||||
|
||||
export type RefString<T extends Ressource> =
|
||||
| `@ref/${T['type']}#${UUID}`
|
||||
|
@ -22,7 +22,9 @@ export class Ref<T extends Ressource> extends String {
|
|||
return `@ref/${type}#${uuid}` as const
|
||||
}
|
||||
|
||||
static parse<T extends Ressource>(string: RefString<T>) {
|
||||
static parse<T extends Ressource>(
|
||||
string: RefString<T>,
|
||||
): { type: T['type']; uuid: UUID } {
|
||||
const [_, value] = string.split('/')
|
||||
const [type, uuid] = value.split('#') as [T['type'], UUID]
|
||||
|
||||
|
@ -33,11 +35,13 @@ export class Ref<T extends Ressource> extends String {
|
|||
return new Ref<T>(ressource)
|
||||
}
|
||||
|
||||
static fromString<T extends Ressource>(string: RefString<T>) {
|
||||
static fromString<T extends Ressource>(string: RefString<T>): Ref<T> {
|
||||
return new Ref<T>(Ref.parse(string))
|
||||
}
|
||||
|
||||
static dbResolver(db: Db) {
|
||||
static dbResolver(
|
||||
db: Db,
|
||||
): <T extends Ressource>(ref: RefString<T>) => Promise<T> {
|
||||
return <T extends Ressource>(ref: RefString<T>): Promise<T> => {
|
||||
const { type, uuid } = Ref.parse(ref)
|
||||
//@ts-expect-error force type casting to fix
|
||||
|
@ -45,27 +49,29 @@ export class Ref<T extends Ressource> extends String {
|
|||
}
|
||||
}
|
||||
|
||||
static restResolver(endpoint: string | URL) {
|
||||
return async <T extends Ressource>(ref: RefString<T>) => {
|
||||
static restResolver(
|
||||
endpoint: string | URL,
|
||||
): <T extends Ressource>(ref: RefString<T>) => Promise<T> {
|
||||
return async <T extends Ressource>(ref: RefString<T>): Promise<T> => {
|
||||
const { type, uuid } = Ref.parse(ref)
|
||||
const url = new URL(`${type}s/${uuid}`, endpoint)
|
||||
const response = await fetch(url)
|
||||
const json = await response.json()
|
||||
|
||||
if (type === 'user') {
|
||||
return User.fromJSON(json)
|
||||
return User.fromJSON(json) as unknown as T
|
||||
}
|
||||
if (type === 'machine') {
|
||||
return Machine.fromJSON(json)
|
||||
return Machine.fromJSON(json) as unknown as T
|
||||
}
|
||||
if (type === 'service') {
|
||||
return Service.fromJSON(json)
|
||||
return Service.fromJSON(json) as unknown as T
|
||||
}
|
||||
if (type === 'group') {
|
||||
return Group.fromJSON(json)
|
||||
return Group.fromJSON(json) as unknown as T
|
||||
}
|
||||
if (type === 'credential') {
|
||||
return Credential.fromJSON(json)
|
||||
return Credential.fromJSON(json) as unknown as T
|
||||
}
|
||||
|
||||
throw new TypeError(`unknown ref type "${type}"`)
|
||||
|
@ -81,23 +87,23 @@ export class Ref<T extends Ressource> extends String {
|
|||
#type: T['type']
|
||||
#uuid: UUID
|
||||
|
||||
get type() {
|
||||
get type(): T['type'] {
|
||||
return this.#type
|
||||
}
|
||||
|
||||
get uuid() {
|
||||
get uuid(): UUID {
|
||||
return this.#uuid
|
||||
}
|
||||
|
||||
ref(resolver: RefResolver<T>) {
|
||||
ref(resolver: RefResolver<T>): T | Promise<T> {
|
||||
return resolver(this.toString())
|
||||
}
|
||||
|
||||
toString() {
|
||||
toString(): `@ref/${T['type']}#${UUID}` {
|
||||
return Ref.#toString<T>({ uuid: this.uuid, type: this.type })
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
toJSON(): `@ref/${T['type']}#${UUID}` {
|
||||
return this.toString()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue