From e712c0dd9349315f96519fffc54533d6436d9c49 Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Sat, 4 Jul 2026 14:02:39 +0530 Subject: [PATCH] feat: Port attribute interface from pure-ts:attribute.ts --- .editorconfig | 9 +++++ cli/src/index.ts | 101 +++++++++++++++++++++++++++++++++++++++++++++- eslint.config.mjs | 4 +- 3 files changed, 111 insertions(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index e69de29..9d08a1a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/cli/src/index.ts b/cli/src/index.ts index cb0ff5c..5ac5ac5 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -1 +1,100 @@ -export {}; +export enum AttributeVisibility { + PUBLIC = "PUBLIC", + PRIVATE = "PRIVATE", +} + +export class Attribute { + readonly name: string; + private value: string; + private visibility: AttributeVisibility; + private allowedEntities: Set; + + constructor(name: string, value: string, visibility: AttributeVisibility) { + this.name = name; + this.value = value; + this.visibility = visibility; + this.allowedEntities = new Set(); + } + + setValue(newValue: string) { + this.value = newValue; + } + + getValue(): string { + return this.value; + } + + hasAccess(objectId: string): boolean { + return ( + this.visibility === AttributeVisibility.PUBLIC || + this.allowedEntities.has(objectId) + ); + } + + getVisibility(): AttributeVisibility { + return this.visibility; + } + + setPublic() { + this.visibility = AttributeVisibility.PUBLIC; + } + + setPrivate() { + this.allowedEntities.clear(); + this.visibility = AttributeVisibility.PRIVATE; + } + + grandAccess(objectId: string) { + if (this.visibility === AttributeVisibility.PRIVATE) { + this.allowedEntities.add(objectId); + } + } + + revokeAccess(objectId: string) { + if ( + this.visibility === AttributeVisibility.PRIVATE && + this.allowedEntities.has(objectId) + ) { + this.allowedEntities.delete(objectId); + } + } +} + +export interface IAttribute { + id: string; + attributes: Map; + + addAttribute( + name: string, + value: string, + visibility: AttributeVisibility, + ): void; + getVisibileAttributesFor(viewerId: string): Attribute[]; +} + +export abstract class AttributableObject implements IAttribute { + readonly id: string = crypto.randomUUID(); + readonly attributes: Map = new Map(); + + addAttribute( + name: string, + value: string, + visibility: AttributeVisibility, + ): void { + if (this.attributes.has(name)) + throw Error(`Attribute ${name} already exists`); + this.attributes.set(name, new Attribute(name, value, visibility)); + } + + removeAttribute(name: string): void { + if (!this.attributes.has(name)) + throw Error(`Attribute ${name} does not exist`); + this.attributes.delete(name); + } + + getVisibileAttributesFor(viewerId: string): Attribute[] { + return Array.from(this.attributes.values()).filter((attr) => + attr.hasAccess(viewerId), + ); + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs index bcf14ce..d9af63b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,5 +1,5 @@ import eslintConfigPrettier from "eslint-config-prettier"; -import js from "eslint/js"; +import js from "@eslint/js"; import globals from "globals"; import tseslint from "typescript-eslint"; @@ -8,7 +8,7 @@ export default [ ignores: ["**/dist/**", "**/node_modules/**"], }, - js.configs.recommend, + js.configs.recommended, ...tseslint.configs.recommended,