@neuralinnovations/dataisland-sdk 0.0.1-dev1 → 0.0.1-dev2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/jest.config.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * https://jestjs.io/docs/configuration
4
4
  */
5
5
 
6
- import type {Config} from 'jest';
6
+ import type { Config } from 'jest'
7
7
 
8
8
  const config: Config = {
9
9
  // All imported modules in your tests should be mocked automatically
@@ -25,7 +25,7 @@ const config: Config = {
25
25
  // collectCoverageFrom: undefined,
26
26
 
27
27
  // The directory where Jest should output its coverage files
28
- coverageDirectory: "coverage",
28
+ coverageDirectory: 'coverage',
29
29
 
30
30
  // An array of regexp pattern strings used to skip coverage collection
31
31
  // coveragePathIgnorePatterns: [
@@ -134,7 +134,7 @@ const config: Config = {
134
134
  // runner: "jest-runner",
135
135
 
136
136
  // The paths to modules that run some code to configure or set up the testing environment before each test
137
- // setupFiles: [],
137
+ setupFiles: ['./jest.setup.ts']
138
138
 
139
139
  // A list of paths to modules that run some code to configure or set up the testing framework before each test
140
140
  // setupFilesAfterEnv: [],
@@ -194,6 +194,6 @@ const config: Config = {
194
194
 
195
195
  // Whether to use watchman for file crawling
196
196
  // watchman: true,
197
- };
197
+ }
198
198
 
199
- export default config;
199
+ export default config
package/jest.setup.ts ADDED
@@ -0,0 +1,2 @@
1
+ import * as dotenv from 'dotenv'
2
+ dotenv.config({ path: '.env.test' })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuralinnovations/dataisland-sdk",
3
- "version": "0.0.1-dev1",
3
+ "version": "0.0.1-dev2",
4
4
  "description": "SDK for DataIsland project",
5
5
  "licenses": [
6
6
  {
@@ -55,6 +55,7 @@
55
55
  "yargs": "17.7.2"
56
56
  },
57
57
  "dependencies": {
58
+ "dotenv": "^16.3.2",
58
59
  "jsdom": "^23.2.0"
59
60
  }
60
61
  }
package/src/appBuilder.ts CHANGED
@@ -2,15 +2,22 @@ import type { Middleware } from './middleware'
2
2
  import type { CredentialBase } from './credentials'
3
3
  import type { Service, ServiceContext } from './services/service'
4
4
  import type { Constructor } from './internal/registry'
5
+ import { CommandHandler, Command } from './services/commandService'
6
+ import { Context } from './context'
5
7
 
6
8
  /**
7
9
  * DataIsland App builder.
8
10
  */
9
11
  export abstract class AppBuilder {
12
+ /**
13
+ * Set custom data.
14
+ */
15
+ abstract get env(): Record<string, any>
16
+
10
17
  /**
11
18
  * Add a middleware to the app.
12
19
  */
13
- abstract addMiddleware(middleware: Middleware): AppBuilder
20
+ abstract registerMiddleware(middleware: Middleware): AppBuilder
14
21
 
15
22
  /**
16
23
  * Host of the app.
@@ -36,4 +43,16 @@ export abstract class AppBuilder {
36
43
  type: Constructor<T>,
37
44
  factory: (context: ServiceContext) => T
38
45
  ): AppBuilder
46
+
47
+ /**
48
+ * Register a command to the app.
49
+ * @param messageType
50
+ * @param commandFactory
51
+ */
52
+ abstract registerCommand<T extends Command>(
53
+ messageType: Constructor<T>,
54
+ commandFactory:
55
+ | ((context: Context) => CommandHandler<T>)
56
+ | ((context: Context) => (context: Context) => Promise<void>)
57
+ ): AppBuilder
39
58
  }
package/src/appSdk.ts CHANGED
@@ -1,40 +1,59 @@
1
1
  import type { Lifetime } from './disposable'
2
2
  import type { CredentialBase } from './credentials'
3
+ import { Context } from './context'
3
4
  import type { Constructor } from './internal/registry'
5
+ import { Organizations } from './storages/organizations'
6
+ import { UserProfile } from './storages/userProfile'
4
7
 
5
8
  /**
6
9
  * DataIsland App instance.
7
10
  */
8
- export interface AppSdk {
11
+ export abstract class AppSdk {
9
12
  /**
10
13
  * The name of this app.
11
14
  */
12
- get name(): string
15
+ abstract get name(): string
13
16
 
14
17
  /**
15
18
  * The host of this app.
16
19
  */
17
- get host(): string
20
+ abstract get host(): string
18
21
 
19
22
  /**
20
23
  * The automaticDataCollectionEnabled of this app.
21
24
  */
22
- get automaticDataCollectionEnabled(): boolean
25
+ abstract get automaticDataCollectionEnabled(): boolean
23
26
 
24
27
  /**
25
28
  * The lifetime of this app.
26
29
  */
27
- get lifetime(): Lifetime
30
+ abstract get lifetime(): Lifetime
28
31
 
29
32
  /**
30
33
  * The credential of this app.
31
34
  */
32
- get credential(): CredentialBase | undefined
35
+ abstract get credential(): CredentialBase | undefined
33
36
 
34
- set credential(value: CredentialBase)
37
+ abstract set credential(value: CredentialBase)
35
38
 
36
39
  /**
37
- * Gets the service registered with the given type.
40
+ * The context of this app.
38
41
  */
39
- resolve: <T>(type: Constructor<T>) => T | undefined
42
+ abstract get context(): Context
43
+
44
+ /**
45
+ * User's organizations.
46
+ */
47
+ abstract get organizations(): Organizations
48
+
49
+ /**
50
+ * User's profile.
51
+ */
52
+ abstract get userProfile(): UserProfile
53
+
54
+ /**
55
+ * Resolve a service from the app.
56
+ * @param type
57
+ */
58
+ abstract resolve<T>(type: Constructor<T>): T | undefined
40
59
  }
@@ -0,0 +1,14 @@
1
+ import { CommandHandler, Command } from '../services/commandService'
2
+ import { UserProfileService } from '../services/userProfileService'
3
+
4
+ export class StartCommand extends Command {}
5
+
6
+ export class StartCommandHandler extends CommandHandler<StartCommand> {
7
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
8
+ async execute(message: StartCommand): Promise<void> {
9
+ const service = this.context.resolve(
10
+ UserProfileService
11
+ ) as UserProfileService
12
+ await service.fetch()
13
+ }
14
+ }
package/src/context.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { type Constructor, type Registry } from './internal/registry'
2
+ import { type Lifetime } from './disposable'
3
+ import { Command, CommandService } from './services/commandService'
4
+
5
+ /**
6
+ * DataIsland App context.
7
+ */
8
+ export class Context {
9
+ constructor(
10
+ private readonly registry: Registry,
11
+ public readonly lifetime: Lifetime,
12
+ public readonly appName: string
13
+ ) {}
14
+
15
+ /**
16
+ * Resolve a service from the context.
17
+ * @param type of the service
18
+ */
19
+ resolve<T>(type: Constructor<T>): T | undefined {
20
+ return this.registry.get(type)
21
+ }
22
+
23
+ /**
24
+ * Execute a command.
25
+ * @param command to execute
26
+ */
27
+ async execute<T extends Command>(command: T): Promise<void> {
28
+ const service = this.resolve(CommandService) as CommandService
29
+ await service.execute(command)
30
+ }
31
+ }
@@ -1,6 +1,6 @@
1
1
  import { MiddlewareService } from './services/middlewareService'
2
2
  import { type Lifetime } from './disposable'
3
- import { type Context } from './internal/context'
3
+ import { type Context } from './context'
4
4
 
5
5
  /**
6
6
  * DataIsland App credential.
@@ -34,7 +34,7 @@ export class BasicCredential extends CredentialBase {
34
34
  lifetime.add(
35
35
  service.useMiddleware(async (req, next) => {
36
36
  req.headers.set('Authorization', `Basic ${this.email}:${this.password}`)
37
- await next(req)
37
+ return await next(req)
38
38
  })
39
39
  )
40
40
  }
@@ -56,7 +56,7 @@ export class BearerCredential extends CredentialBase {
56
56
  lifetime.add(
57
57
  service.useMiddleware(async (req, next) => {
58
58
  req.headers.set('Authorization', `Bearer ${this.token}`)
59
- await next(req)
59
+ return await next(req)
60
60
  })
61
61
  )
62
62
  }
package/src/disposable.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Represents an object that can be disposed.
3
3
  */
4
4
  export interface Disposable {
5
- dispose: () => void
5
+ dispose(): void
6
6
  }
7
7
 
8
8
  /**
@@ -0,0 +1,37 @@
1
+ export interface UserInfoResponse {
2
+ adminInOrganization: string[]
3
+ organizations: OrganizationDto[]
4
+ user: UserDto
5
+ }
6
+
7
+ export interface UserDto {
8
+ id: string
9
+ isDeleted: boolean
10
+ created_at: number
11
+ modified_at: number
12
+ profile: ProfileDto
13
+ settings: UserSettings
14
+ }
15
+
16
+ export interface ProfileDto {
17
+ name: string
18
+ email: string
19
+ }
20
+
21
+ export interface UserSettings {
22
+ activeOrganizationId: string
23
+ activeWorkspaceId: string
24
+ }
25
+
26
+ export interface OrganizationProfileDto {
27
+ name: string
28
+ description: string
29
+ }
30
+
31
+ export interface OrganizationDto {
32
+ id: string
33
+ createdAt: number
34
+ modifiedAt: number
35
+ membersCount: number
36
+ profile: OrganizationProfileDto
37
+ }
package/src/events.ts CHANGED
@@ -1,9 +1,5 @@
1
1
  import { type Disposable, DisposableContainer } from './disposable'
2
2
 
3
- export interface Events<TE, TD> {
4
- get events(): EventDispatcher<TE, TD>
5
- }
6
-
7
3
  export interface Input<ET, DT> {
8
4
  type?: ET
9
5
  data: DT
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export * from './types'
8
8
  export * from './disposable'
9
9
  export * from './types'
10
10
  export * from './credentials'
11
+ export * from './appSdk'
11
12
 
12
13
  const _appsNotReady = new Map<string, Promise<AppSdk>>()
13
14
  const _appsReady = new Map<string, AppSdk>()
@@ -25,7 +26,7 @@ export const DEFAULT_NAME = '[DEFAULT]'
25
26
  /**
26
27
  * Default DataIsland App host.
27
28
  */
28
- export const DEFAULT_HOST = 'https://dataisland.com.ua'
29
+ export const DEFAULT_HOST = 'https://api.dataisland.com.ua'
29
30
 
30
31
  export function sdks(): AppSdk[] {
31
32
  return Array.from(_appsReady.values())
@@ -62,8 +63,15 @@ export async function appSdk(
62
63
  })
63
64
  .catch(reason => {
64
65
  console.error(`Error: ${reason}`)
66
+ _appsNotReady.delete(name ?? DEFAULT_NAME)
65
67
  })
66
68
  _appsNotReady.set(name, appPromise)
69
+ } else {
70
+ if (setup !== undefined) {
71
+ throw new Error(
72
+ `App ${name} is initializing. You can't setup the same again.`
73
+ )
74
+ }
67
75
  }
68
76
  return await appPromise
69
77
  }
@@ -2,16 +2,26 @@ import { DEFAULT_HOST } from '../index'
2
2
  import { type AppBuilder } from '../appBuilder'
3
3
  import { AppBuilderImplementation } from './appBuilder.impl'
4
4
  import { type Constructor, Registry } from './registry'
5
- import { Context } from './context'
5
+ import { Context } from '../context'
6
6
  import { DisposableContainer, type Lifetime } from '../disposable'
7
7
  import { type Service, ServiceContext } from '../services/service'
8
8
  import { CredentialService } from '../services/credentialService'
9
9
  import { MiddlewareService } from '../services/middlewareService'
10
10
  import { type CredentialBase } from '../credentials'
11
- import { type AppSdk } from '../appSdk'
12
- import { RpcService, RpcServiceImpl } from '../services/rpcService'
13
-
14
- export class AppImplementation implements AppSdk {
11
+ import { AppSdk } from '../appSdk'
12
+ import { RpcService } from '../services/rpcService'
13
+ import { CommandService } from '../services/commandService'
14
+ import {
15
+ StartCommandHandler,
16
+ StartCommand
17
+ } from '../commands/startCommandHandler'
18
+ import { UserProfileService } from '../services/userProfileService'
19
+ import { OrganizationService } from '../services/organizationService'
20
+ import { Organizations } from '../storages/organizations'
21
+ import { UserProfile } from '../storages/userProfile'
22
+ import { isUnitTest, UnitTest } from '../unitTest'
23
+
24
+ export class AppImplementation extends AppSdk {
15
25
  readonly name: string
16
26
  private _host: string = DEFAULT_HOST
17
27
  private _automaticDataCollectionEnabled: boolean = true
@@ -20,10 +30,17 @@ export class AppImplementation implements AppSdk {
20
30
  private readonly _disposable: DisposableContainer
21
31
 
22
32
  constructor(name: string) {
33
+ super()
23
34
  this.name = name
24
35
  this._registry = new Registry()
25
36
  this._disposable = new DisposableContainer()
26
- this._context = new Context(this._registry, this._disposable.lifetime)
37
+ this._context = new Context(this._registry, this._disposable.lifetime, name)
38
+
39
+ this._registry.map(Context).asValue(this._context)
40
+ }
41
+
42
+ get context(): Context {
43
+ return this._context
27
44
  }
28
45
 
29
46
  get credential(): CredentialBase | undefined {
@@ -48,12 +65,52 @@ export class AppImplementation implements AppSdk {
48
65
  return this._host
49
66
  }
50
67
 
68
+ get organizations(): Organizations {
69
+ return this.resolve(OrganizationService)?.organizations as Organizations
70
+ }
71
+
72
+ get userProfile(): UserProfile {
73
+ return this.resolve(UserProfileService)?.userProfile as UserProfile
74
+ }
75
+
51
76
  async initialize(
52
77
  setup: ((builder: AppBuilder) => Promise<void>) | undefined
53
78
  ): Promise<void> {
54
79
  // create app builder
55
80
  const builder = new AppBuilderImplementation()
56
81
 
82
+ // register commands
83
+ builder.registerCommand(StartCommand, (context: Context) => {
84
+ return new StartCommandHandler(context)
85
+ })
86
+
87
+ // register services
88
+ builder.registerService(CredentialService, (context: ServiceContext) => {
89
+ return new CredentialService(context)
90
+ })
91
+ builder.registerService(MiddlewareService, (context: ServiceContext) => {
92
+ return new MiddlewareService(context)
93
+ })
94
+ builder.registerService(RpcService, (context: ServiceContext) => {
95
+ return new RpcService(context, builder.host)
96
+ })
97
+ builder.registerService(CommandService, (context: ServiceContext) => {
98
+ return new CommandService(context)
99
+ })
100
+ builder.registerService(UserProfileService, (context: ServiceContext) => {
101
+ return new UserProfileService(context)
102
+ })
103
+ builder.registerService(OrganizationService, (context: ServiceContext) => {
104
+ return new OrganizationService(context)
105
+ })
106
+
107
+ // register middlewares
108
+ builder.registerMiddleware(async (req, next) => {
109
+ req.headers.set('accept', 'text/plain')
110
+ req.headers.set('content-type', 'application/json')
111
+ return await next(req)
112
+ })
113
+
57
114
  // call customer setup
58
115
  if (setup !== undefined) {
59
116
  await setup(builder)
@@ -66,17 +123,6 @@ export class AppImplementation implements AppSdk {
66
123
  this._automaticDataCollectionEnabled =
67
124
  builder.automaticDataCollectionEnabled
68
125
 
69
- // register services
70
- builder.registerService(CredentialService, (context: ServiceContext) => {
71
- return new CredentialService(context)
72
- })
73
- builder.registerService(MiddlewareService, (context: ServiceContext) => {
74
- return new MiddlewareService(context)
75
- })
76
- builder.registerService(RpcService, (context: ServiceContext) => {
77
- return new RpcServiceImpl(context, builder.host) as RpcService
78
- })
79
-
80
126
  // register services
81
127
  const services: Array<[ServiceContext, Service]> = []
82
128
  builder.services.forEach(serviceFactory => {
@@ -89,31 +135,53 @@ export class AppImplementation implements AppSdk {
89
135
  }, serviceContext)
90
136
  const serviceInstance = serviceFactory[1](serviceContext)
91
137
  services.push([serviceContext, serviceInstance])
92
- this._registry.set(serviceFactory[0], {
93
- provide: () => serviceInstance
94
- })
138
+ this._registry.map(serviceFactory[0]).asValue(serviceInstance)
95
139
  })
96
140
 
97
141
  builder.middlewares.forEach(middleware => {
98
142
  this.resolve(MiddlewareService)?.useMiddleware(middleware)
99
143
  })
100
144
 
145
+ builder.commands.forEach(command => {
146
+ this.resolve(CommandService)?.register(command[0], command[1])
147
+ })
148
+
149
+ this.credential = builder.credential
150
+
151
+ //-------------------------------------------------------------------------
152
+ // register services
153
+ //-------------------------------------------------------------------------
101
154
  const waitList: Array<Promise<void>> = []
102
155
  // call onRegister service's callback
103
156
  services.forEach(([serviceContext]) => {
104
157
  waitList.push(serviceContext.onRegister())
105
158
  })
106
159
 
160
+ // wait for all services to register
107
161
  await Promise.all(waitList)
162
+ //-------------------------------------------------------------------------
108
163
 
164
+ //-------------------------------------------------------------------------
165
+ // start services
166
+ //-------------------------------------------------------------------------
109
167
  waitList.length = 0
110
168
  // call onStart service's callback
111
169
  services.forEach(([serviceContext]) => {
112
170
  waitList.push(serviceContext.onStart())
113
171
  })
114
172
 
173
+ // wait for all services to start
115
174
  await Promise.all(waitList)
175
+ //-------------------------------------------------------------------------
116
176
 
117
- await Promise.resolve()
177
+ // start app, execute start command
178
+ if (!isUnitTest(UnitTest.DO_NOT_START)) {
179
+ await this.context.execute(new StartCommand())
180
+ }
181
+
182
+ // log app initialized
183
+ if (!isUnitTest(UnitTest.DO_NOT_PRINT_INITIALIZED_LOG)) {
184
+ console.log(`AppSDK ${this.name} initialized`)
185
+ }
118
186
  }
119
187
  }
@@ -4,13 +4,26 @@ import { type CredentialBase, DefaultCredential } from '../credentials'
4
4
  import type { Middleware } from '../middleware'
5
5
  import { type Service, type ServiceContext } from '../services/service'
6
6
  import { type Constructor } from './registry'
7
+ import { Command, CommandHandler } from '../services/commandService'
8
+ import { Context } from '../context'
9
+ import { UnitTest } from '../unitTest'
7
10
 
8
11
  export class AppBuilderImplementation extends AppBuilder {
12
+ envData: Record<string, any> = {
13
+ unitTest: UnitTest.DO_NOTHING
14
+ }
9
15
  host: string = DEFAULT_HOST
10
16
  automaticDataCollectionEnabled: boolean = true
11
17
  credential: CredentialBase = new DefaultCredential()
12
18
  middlewares: Middleware[] = []
13
19
  services: Array<[Constructor<any>, (context: ServiceContext) => Service]> = []
20
+ commands: Array<
21
+ [Constructor<any>, (context: Context) => CommandHandler<any>]
22
+ > = []
23
+
24
+ get env(): Record<string, any> {
25
+ return this.envData
26
+ }
14
27
 
15
28
  useHost(host: string): AppBuilder {
16
29
  this.host = host ?? DEFAULT_HOST
@@ -35,7 +48,7 @@ export class AppBuilderImplementation extends AppBuilder {
35
48
  return this
36
49
  }
37
50
 
38
- addMiddleware(middleware: Middleware): AppBuilder {
51
+ registerMiddleware(middleware: Middleware): AppBuilder {
39
52
  if (middleware === undefined || middleware === null) {
40
53
  throw new Error('addMiddleware, middleware is undefined|null')
41
54
  }
@@ -56,4 +69,18 @@ export class AppBuilderImplementation extends AppBuilder {
56
69
  this.services.push([type, factory])
57
70
  return this
58
71
  }
72
+
73
+ registerCommand<T extends Command>(
74
+ messageType: Constructor<T>,
75
+ commandFactory: (context: Context) => CommandHandler<T>
76
+ ): AppBuilder {
77
+ if (messageType === undefined || messageType === null) {
78
+ throw new Error('registerCommand, messageType is undefined|null')
79
+ }
80
+ if (commandFactory === undefined || commandFactory === null) {
81
+ throw new Error('registerCommand, commandFactory is undefined|null')
82
+ }
83
+ this.commands.push([messageType, commandFactory])
84
+ return this
85
+ }
59
86
  }
package/src/middleware.ts CHANGED
@@ -4,4 +4,4 @@
4
4
  export type Middleware = (
5
5
  req: Request,
6
6
  next: (req: Request) => Promise<Response>
7
- ) => Promise<void>
7
+ ) => Promise<Response>
@@ -0,0 +1,44 @@
1
+ import { Service } from './service'
2
+ import { Context } from '../context'
3
+ import { Constructor } from '../internal/registry'
4
+
5
+ export abstract class CommandHandler<T> {
6
+ constructor(protected readonly context: Context) {}
7
+
8
+ resolve<T>(type: Constructor<T>): T | undefined {
9
+ return this.context.resolve<T>(type)
10
+ }
11
+
12
+ abstract execute(message: T): Promise<void>
13
+ }
14
+
15
+ export abstract class Command {}
16
+
17
+ export class CommandService extends Service {
18
+ private readonly _registry: Map<
19
+ Constructor<any>,
20
+ (context: Context) => CommandHandler<any>
21
+ > = new Map()
22
+ private _lastPromise: Promise<void> = Promise.resolve()
23
+
24
+ register<T extends Command>(
25
+ messageType: Constructor<T>,
26
+ commandFactory: (context: Context) => CommandHandler<T>
27
+ ): void {
28
+ this._registry.set(messageType, commandFactory)
29
+ }
30
+
31
+ async execute<T extends Command>(message: T): Promise<void> {
32
+ const commandFactory = this._registry.get((message as any).constructor)
33
+ if (commandFactory) {
34
+ const command = commandFactory(this.context)
35
+ await this._lastPromise
36
+ this._lastPromise = command.execute(message)
37
+ await this._lastPromise
38
+ } else {
39
+ throw new Error(
40
+ `Command not found for message type ${message.constructor.name}`
41
+ )
42
+ }
43
+ }
44
+ }
@@ -24,10 +24,12 @@ export class MiddlewareService extends Service {
24
24
  const processNext = async (request: Request): Promise<Response> => {
25
25
  index++
26
26
  if (index < middlewares.length) {
27
- await middlewares[index](request, processNext)
27
+ return await middlewares[index](request, processNext)
28
+ } else {
29
+ return await next(request)
28
30
  }
29
- return await next(request)
30
31
  }
32
+
31
33
  return await processNext(req)
32
34
  }
33
35
  }
@@ -0,0 +1,51 @@
1
+ import { Organization, OrganizationId } from '../storages/organizations'
2
+ import { Disposable } from '../disposable'
3
+ import { OrganizationDto } from '../dto/userInfoResponse'
4
+ import { OrganizationService } from './organizationService'
5
+ import { OrganizationsImpl } from './organizationsImpl'
6
+
7
+ export class OrganizationImpl extends Organization implements Disposable {
8
+ private _isDisposed: boolean = false
9
+ private _isAdmin: boolean = false
10
+ private _content?: OrganizationDto
11
+
12
+ constructor(
13
+ private readonly service: OrganizationService,
14
+ private readonly organizations: OrganizationsImpl
15
+ ) {
16
+ super()
17
+ }
18
+
19
+ get isAdmin(): boolean {
20
+ return this._isAdmin
21
+ }
22
+
23
+ get isDisposed(): boolean {
24
+ return this._isDisposed
25
+ }
26
+
27
+ dispose(): void {
28
+ this._isDisposed = true
29
+ }
30
+
31
+ public initFrom(
32
+ content: OrganizationDto,
33
+ isAdmin: boolean
34
+ ): OrganizationImpl {
35
+ this._content = content
36
+ this._isAdmin = isAdmin
37
+ return this
38
+ }
39
+
40
+ get id(): OrganizationId {
41
+ return <OrganizationId>this._content?.id
42
+ }
43
+
44
+ get name(): string {
45
+ return <OrganizationId>this._content?.profile.name
46
+ }
47
+
48
+ get description(): string {
49
+ return <OrganizationId>this._content?.profile.description
50
+ }
51
+ }