@api-client/core 0.19.22 → 0.19.24

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.
Files changed (98) hide show
  1. package/build/src/browser.d.ts +3 -0
  2. package/build/src/browser.d.ts.map +1 -1
  3. package/build/src/browser.js +2 -0
  4. package/build/src/browser.js.map +1 -1
  5. package/build/src/index.d.ts +3 -0
  6. package/build/src/index.d.ts.map +1 -1
  7. package/build/src/index.js +2 -0
  8. package/build/src/index.js.map +1 -1
  9. package/build/src/modeling/ApiModel.d.ts.map +1 -1
  10. package/build/src/modeling/ApiModel.js +37 -13
  11. package/build/src/modeling/ApiModel.js.map +1 -1
  12. package/build/src/modeling/ExposedEntity.d.ts.map +1 -1
  13. package/build/src/modeling/ExposedEntity.js +54 -15
  14. package/build/src/modeling/ExposedEntity.js.map +1 -1
  15. package/build/src/modeling/actions/Action.js +2 -2
  16. package/build/src/modeling/actions/Action.js.map +1 -1
  17. package/build/src/modeling/rules/AccessRule.d.ts +5 -1
  18. package/build/src/modeling/rules/AccessRule.d.ts.map +1 -1
  19. package/build/src/modeling/rules/AccessRule.js +4 -1
  20. package/build/src/modeling/rules/AccessRule.js.map +1 -1
  21. package/build/src/modeling/rules/AllowAuthenticated.d.ts +4 -1
  22. package/build/src/modeling/rules/AllowAuthenticated.d.ts.map +1 -1
  23. package/build/src/modeling/rules/AllowAuthenticated.js +2 -2
  24. package/build/src/modeling/rules/AllowAuthenticated.js.map +1 -1
  25. package/build/src/modeling/rules/AllowPublic.d.ts +4 -1
  26. package/build/src/modeling/rules/AllowPublic.d.ts.map +1 -1
  27. package/build/src/modeling/rules/AllowPublic.js +2 -2
  28. package/build/src/modeling/rules/AllowPublic.js.map +1 -1
  29. package/build/src/modeling/rules/MatchEmailDomain.d.ts +4 -1
  30. package/build/src/modeling/rules/MatchEmailDomain.d.ts.map +1 -1
  31. package/build/src/modeling/rules/MatchEmailDomain.js +2 -2
  32. package/build/src/modeling/rules/MatchEmailDomain.js.map +1 -1
  33. package/build/src/modeling/rules/MatchResourceOwner.d.ts +4 -1
  34. package/build/src/modeling/rules/MatchResourceOwner.d.ts.map +1 -1
  35. package/build/src/modeling/rules/MatchResourceOwner.js +2 -2
  36. package/build/src/modeling/rules/MatchResourceOwner.js.map +1 -1
  37. package/build/src/modeling/rules/MatchUserProperty.d.ts +4 -1
  38. package/build/src/modeling/rules/MatchUserProperty.d.ts.map +1 -1
  39. package/build/src/modeling/rules/MatchUserProperty.js +2 -2
  40. package/build/src/modeling/rules/MatchUserProperty.js.map +1 -1
  41. package/build/src/modeling/rules/MatchUserRole.d.ts +4 -1
  42. package/build/src/modeling/rules/MatchUserRole.d.ts.map +1 -1
  43. package/build/src/modeling/rules/MatchUserRole.js +2 -2
  44. package/build/src/modeling/rules/MatchUserRole.js.map +1 -1
  45. package/build/src/modeling/rules/index.d.ts +4 -1
  46. package/build/src/modeling/rules/index.d.ts.map +1 -1
  47. package/build/src/modeling/rules/index.js +7 -7
  48. package/build/src/modeling/rules/index.js.map +1 -1
  49. package/build/src/models/store/CustomDomain.d.ts +50 -0
  50. package/build/src/models/store/CustomDomain.d.ts.map +1 -0
  51. package/build/src/models/store/CustomDomain.js +79 -0
  52. package/build/src/models/store/CustomDomain.js.map +1 -0
  53. package/build/src/models/store/Deployment.d.ts +81 -0
  54. package/build/src/models/store/Deployment.d.ts.map +1 -0
  55. package/build/src/models/store/Deployment.js +124 -0
  56. package/build/src/models/store/Deployment.js.map +1 -0
  57. package/build/src/models/store/DeploymentCustomDomain.d.ts +52 -0
  58. package/build/src/models/store/DeploymentCustomDomain.d.ts.map +1 -0
  59. package/build/src/models/store/DeploymentCustomDomain.js +84 -0
  60. package/build/src/models/store/DeploymentCustomDomain.js.map +1 -0
  61. package/build/tsconfig.tsbuildinfo +1 -1
  62. package/package.json +1 -1
  63. package/src/modeling/ApiModel.ts +37 -13
  64. package/src/modeling/ExposedEntity.ts +62 -16
  65. package/src/modeling/actions/Action.ts +2 -2
  66. package/src/modeling/rules/AccessRule.ts +8 -1
  67. package/src/modeling/rules/AllowAuthenticated.ts +5 -2
  68. package/src/modeling/rules/AllowPublic.ts +5 -2
  69. package/src/modeling/rules/MatchEmailDomain.ts +5 -2
  70. package/src/modeling/rules/MatchResourceOwner.ts +5 -2
  71. package/src/modeling/rules/MatchUserProperty.ts +5 -2
  72. package/src/modeling/rules/MatchUserRole.ts +5 -2
  73. package/src/models/store/CustomDomain.ts +119 -0
  74. package/src/models/store/Deployment.ts +173 -0
  75. package/src/models/store/DeploymentCustomDomain.ts +120 -0
  76. package/tests/unit/modeling/actions/Action.spec.ts +13 -10
  77. package/tests/unit/modeling/actions/CreateAction.spec.ts +7 -6
  78. package/tests/unit/modeling/actions/DeleteAction.spec.ts +7 -6
  79. package/tests/unit/modeling/actions/ListAction.spec.ts +5 -4
  80. package/tests/unit/modeling/actions/ReadAction.spec.ts +9 -8
  81. package/tests/unit/modeling/actions/SearchAction.spec.ts +5 -4
  82. package/tests/unit/modeling/actions/UpdateAction.spec.ts +7 -6
  83. package/tests/unit/modeling/actions/helpers.ts +7 -0
  84. package/tests/unit/modeling/api_model.spec.ts +3 -1
  85. package/tests/unit/modeling/api_model_expose_entity.spec.ts +5 -17
  86. package/tests/unit/modeling/exposed_entity.spec.ts +6 -2
  87. package/tests/unit/modeling/exposed_entity_actions.spec.ts +0 -4
  88. package/tests/unit/modeling/rules/AccessRule.spec.ts +6 -5
  89. package/tests/unit/modeling/rules/AllowAuthenticated.spec.ts +4 -3
  90. package/tests/unit/modeling/rules/AllowPublic.spec.ts +4 -3
  91. package/tests/unit/modeling/rules/MatchEmailDomain.spec.ts +6 -5
  92. package/tests/unit/modeling/rules/MatchResourceOwner.spec.ts +7 -6
  93. package/tests/unit/modeling/rules/MatchUserProperty.spec.ts +6 -5
  94. package/tests/unit/modeling/rules/MatchUserRole.spec.ts +6 -5
  95. package/tests/unit/modeling/rules/restoring_rules.spec.ts +19 -21
  96. package/tests/unit/models/store/CustomDomain.spec.ts +111 -0
  97. package/tests/unit/models/store/Deployment.spec.ts +134 -0
  98. package/tests/unit/models/store/DeploymentCustomDomain.spec.ts +122 -0
@@ -0,0 +1,173 @@
1
+ import type { FieldValidationMessage } from '../../exceptions/validation_error.js'
2
+ import { nanoid } from '../../nanoid.js'
3
+
4
+ /**
5
+ * Status of the deployment
6
+ */
7
+ export enum DeploymentStatus {
8
+ /**
9
+ * Deployment is pending
10
+ */
11
+ Pending = 0,
12
+ /**
13
+ * Deployment is active
14
+ */
15
+ Active = 1,
16
+ /**
17
+ * Deployment is inactive
18
+ */
19
+ Inactive = 2,
20
+ /**
21
+ * Deployment has failed
22
+ */
23
+ Failed = 3,
24
+ }
25
+
26
+ export interface DeploymentSchema {
27
+ /**
28
+ * Primary key (nanoid)
29
+ */
30
+ id: string
31
+ /**
32
+ * ID of the organization
33
+ */
34
+ orgId: string
35
+ /**
36
+ * The file ID representing the API
37
+ */
38
+ apiId: string
39
+ /**
40
+ * The version of the deployment (e.g., 'v1', 'v2')
41
+ */
42
+ deploymentVersion: string
43
+ /**
44
+ * The semantic version of the deployed API model (e.g., '1.0.1')
45
+ */
46
+ apiModelVersion: string
47
+ /**
48
+ * Status of the deployment
49
+ */
50
+ status: DeploymentStatus
51
+ /**
52
+ * Optional custom path for staging (e.g., '/dev')
53
+ */
54
+ stagingPath?: string
55
+ /**
56
+ * Reference to the optimized model in MongoDB
57
+ */
58
+ mongoModelId?: string
59
+ /**
60
+ * Timestamp of creation
61
+ */
62
+ createdAt: number
63
+ /**
64
+ * Timestamp of last update
65
+ */
66
+ updatedAt: number
67
+ }
68
+
69
+ export class Deployment implements DeploymentSchema {
70
+ id: string
71
+ orgId: string
72
+ apiId: string
73
+ deploymentVersion: string
74
+ apiModelVersion: string
75
+ status: DeploymentStatus
76
+ stagingPath?: string
77
+ mongoModelId?: string
78
+ createdAt: number
79
+ updatedAt: number
80
+
81
+ static createSchema(input: Partial<DeploymentSchema> = {}): DeploymentSchema {
82
+ const id = input.id ?? nanoid()
83
+ const result: DeploymentSchema = {
84
+ id,
85
+ orgId: input.orgId || '',
86
+ apiId: input.apiId || '',
87
+ deploymentVersion: input.deploymentVersion || 'v0',
88
+ apiModelVersion: input.apiModelVersion || '0.0.0',
89
+ status: input.status ?? DeploymentStatus.Pending,
90
+ createdAt: input.createdAt ?? Date.now(),
91
+ updatedAt: input.updatedAt ?? Date.now(),
92
+ }
93
+ if (input.stagingPath) {
94
+ result.stagingPath = input.stagingPath
95
+ }
96
+ if (input.mongoModelId) {
97
+ result.mongoModelId = input.mongoModelId
98
+ }
99
+ return result
100
+ }
101
+
102
+ constructor(state?: Partial<DeploymentSchema>) {
103
+ const init = Deployment.createSchema(state)
104
+ this.id = init.id
105
+ this.orgId = init.orgId
106
+ this.apiId = init.apiId
107
+ this.deploymentVersion = init.deploymentVersion
108
+ this.apiModelVersion = init.apiModelVersion
109
+ this.status = init.status
110
+ if (init.stagingPath) {
111
+ this.stagingPath = init.stagingPath
112
+ }
113
+ if (init.mongoModelId) {
114
+ this.mongoModelId = init.mongoModelId
115
+ }
116
+ this.createdAt = init.createdAt
117
+ this.updatedAt = init.updatedAt
118
+ }
119
+
120
+ toJSON(): DeploymentSchema {
121
+ const result: DeploymentSchema = {
122
+ id: this.id,
123
+ orgId: this.orgId,
124
+ apiId: this.apiId,
125
+ deploymentVersion: this.deploymentVersion,
126
+ apiModelVersion: this.apiModelVersion,
127
+ status: this.status,
128
+ createdAt: this.createdAt,
129
+ updatedAt: this.updatedAt,
130
+ }
131
+ if (this.stagingPath) {
132
+ result.stagingPath = this.stagingPath
133
+ }
134
+ if (this.mongoModelId) {
135
+ result.mongoModelId = this.mongoModelId
136
+ }
137
+ return result
138
+ }
139
+
140
+ validate(): FieldValidationMessage[] {
141
+ const result: FieldValidationMessage[] = []
142
+
143
+ if (this.orgId === '') {
144
+ result.push({
145
+ field: 'orgId',
146
+ message: 'Org ID must not be empty',
147
+ rule: 'notEmpty',
148
+ })
149
+ }
150
+ if (this.apiId === '') {
151
+ result.push({
152
+ field: 'apiId',
153
+ message: 'API ID must not be empty',
154
+ rule: 'notEmpty',
155
+ })
156
+ }
157
+ if (this.deploymentVersion === '') {
158
+ result.push({
159
+ field: 'deploymentVersion',
160
+ message: 'Deployment version must not be empty',
161
+ rule: 'notEmpty',
162
+ })
163
+ }
164
+ if (this.apiModelVersion === '') {
165
+ result.push({
166
+ field: 'apiModelVersion',
167
+ message: 'API model version must not be empty',
168
+ rule: 'notEmpty',
169
+ })
170
+ }
171
+ return result
172
+ }
173
+ }
@@ -0,0 +1,120 @@
1
+ import type { FieldValidationMessage } from '../../exceptions/validation_error.js'
2
+ import { nanoid } from '../../nanoid.js'
3
+
4
+ export enum SslStatus {
5
+ Initializing = 0,
6
+ PendingDns = 1,
7
+ Issuing = 2,
8
+ Active = 3,
9
+ Error = 4,
10
+ }
11
+
12
+ export interface DeploymentCustomDomainSchema {
13
+ /**
14
+ * Primary key (nanoid)
15
+ */
16
+ id: string
17
+ /**
18
+ * ID of the deployment
19
+ */
20
+ deploymentId: string
21
+ /**
22
+ * ID of the custom domain
23
+ */
24
+ customDomainId: string
25
+ /**
26
+ * The base path for the deployment
27
+ */
28
+ basePath: string
29
+ /**
30
+ * Status of the SSL certificate
31
+ */
32
+ sslStatus: SslStatus
33
+ /**
34
+ * Timestamp of creation
35
+ */
36
+ createdAt: number
37
+ /**
38
+ * Timestamp of last update
39
+ */
40
+ updatedAt: number
41
+ }
42
+
43
+ export class DeploymentCustomDomainModel implements DeploymentCustomDomainSchema {
44
+ id: string
45
+ deploymentId: string
46
+ customDomainId: string
47
+ basePath: string
48
+ sslStatus: SslStatus
49
+ createdAt: number
50
+ updatedAt: number
51
+
52
+ static createSchema(input: Partial<DeploymentCustomDomainSchema> = {}): DeploymentCustomDomainSchema {
53
+ const id = input.id ?? nanoid()
54
+ return {
55
+ id,
56
+ deploymentId: input.deploymentId || '',
57
+ customDomainId: input.customDomainId || '',
58
+ basePath: input.basePath ?? '/',
59
+ sslStatus: input.sslStatus ?? SslStatus.PendingDns,
60
+ createdAt: input.createdAt ?? Date.now(),
61
+ updatedAt: input.updatedAt ?? Date.now(),
62
+ }
63
+ }
64
+
65
+ constructor(state?: Partial<DeploymentCustomDomainSchema>) {
66
+ const init = DeploymentCustomDomainModel.createSchema(state)
67
+ this.id = init.id
68
+ this.deploymentId = init.deploymentId
69
+ this.customDomainId = init.customDomainId
70
+ this.basePath = init.basePath
71
+ this.sslStatus = init.sslStatus
72
+ this.createdAt = init.createdAt
73
+ this.updatedAt = init.updatedAt
74
+ }
75
+
76
+ toJSON(): DeploymentCustomDomainSchema {
77
+ return {
78
+ id: this.id,
79
+ deploymentId: this.deploymentId,
80
+ customDomainId: this.customDomainId,
81
+ basePath: this.basePath,
82
+ sslStatus: this.sslStatus,
83
+ createdAt: this.createdAt,
84
+ updatedAt: this.updatedAt,
85
+ }
86
+ }
87
+
88
+ validate(): FieldValidationMessage[] {
89
+ const result: FieldValidationMessage[] = []
90
+
91
+ if (this.basePath === '') {
92
+ result.push({
93
+ field: 'basePath',
94
+ message: 'Base path must not be empty',
95
+ rule: 'notEmpty',
96
+ })
97
+ } else if (!this.basePath.startsWith('/')) {
98
+ result.push({
99
+ field: 'basePath',
100
+ message: 'Base path must start with a slash',
101
+ rule: 'startsWithSlash',
102
+ })
103
+ }
104
+ if (!this.deploymentId) {
105
+ result.push({
106
+ field: 'deploymentId',
107
+ message: 'Deployment ID must not be empty',
108
+ rule: 'notEmpty',
109
+ })
110
+ }
111
+ if (!this.customDomainId) {
112
+ result.push({
113
+ field: 'customDomainId',
114
+ message: 'Custom domain ID must not be empty',
115
+ rule: 'notEmpty',
116
+ })
117
+ }
118
+ return result
119
+ }
120
+ }
@@ -2,10 +2,11 @@ import { test } from '@japa/runner'
2
2
  import { Action, AccessRule, RateLimitingConfiguration } from '../../../../src/modeling/index.js'
3
3
  import { type ActionSchema } from '../../../../src/modeling/actions/Action.js'
4
4
  import { type ExposedEntity } from '../../../../src/modeling/ExposedEntity.js'
5
+ import { mockExposedEntity } from './helpers.js'
5
6
 
6
7
  test.group('Action', () => {
7
8
  test('initializes with default values', ({ assert }) => {
8
- const action = new Action({} as unknown as ExposedEntity)
9
+ const action = new Action(mockExposedEntity())
9
10
  assert.equal(action.kind, '')
10
11
  assert.deepEqual(action.accessRule, [])
11
12
  assert.isUndefined(action.rateLimiting)
@@ -17,7 +18,7 @@ test.group('Action', () => {
17
18
  accessRule: [{ type: 'allowPublic' }],
18
19
  rateLimiting: { rules: [] },
19
20
  }
20
- const action = new Action({} as unknown as ExposedEntity, schema)
21
+ const action = new Action(mockExposedEntity(), schema)
21
22
  assert.equal(action.kind, 'read')
22
23
  assert.lengthOf(action.accessRule, 1)
23
24
  assert.instanceOf(action.accessRule[0], AccessRule)
@@ -26,7 +27,7 @@ test.group('Action', () => {
26
27
  }).tags(['@modeling', '@action'])
27
28
 
28
29
  test('serializes to JSON', ({ assert }) => {
29
- const action = new Action({} as unknown as ExposedEntity, {
30
+ const action = new Action(mockExposedEntity(), {
30
31
  kind: 'write',
31
32
  accessRule: [{ type: 'allowPublic' }],
32
33
  rateLimiting: { rules: [] },
@@ -39,7 +40,7 @@ test.group('Action', () => {
39
40
  }).tags(['@modeling', '@action'])
40
41
 
41
42
  test('notifies change when kind changes', async ({ assert }) => {
42
- const action = new Action({} as unknown as ExposedEntity, { kind: 'read' })
43
+ const action = new Action(mockExposedEntity(), { kind: 'read' })
43
44
  let notified = false
44
45
  action.addEventListener('change', () => {
45
46
  notified = true
@@ -53,19 +54,19 @@ test.group('Action', () => {
53
54
  }).tags(['@modeling', '@action', '@observed'])
54
55
 
55
56
  test('notifies change when accessRule array is replaced', async ({ assert }) => {
56
- const action = new Action({} as unknown as ExposedEntity)
57
+ const action = new Action(mockExposedEntity())
57
58
  let notified = false
58
59
  action.addEventListener('change', () => {
59
60
  notified = true
60
61
  })
61
62
 
62
- action.accessRule = [new AccessRule({ type: 'allowPublic' })]
63
+ action.accessRule = [new AccessRule(mockExposedEntity(), { type: 'allowPublic' })]
63
64
  await Promise.resolve()
64
65
  assert.isTrue(notified)
65
66
  }).tags(['@modeling', '@action', '@observed'])
66
67
 
67
68
  test('notifies change when rateLimiting is replaced', async ({ assert }) => {
68
- const action = new Action({} as unknown as ExposedEntity)
69
+ const action = new Action(mockExposedEntity())
69
70
  let notified = false
70
71
  action.addEventListener('change', () => {
71
72
  notified = true
@@ -78,7 +79,7 @@ test.group('Action', () => {
78
79
 
79
80
  test('constructor copies accessRule array (immutability)', ({ assert }) => {
80
81
  const rules = [{ type: 'allowPublic' }]
81
- const action = new Action({} as unknown as ExposedEntity, { kind: 'read', accessRule: rules })
82
+ const action = new Action(mockExposedEntity(), { kind: 'read', accessRule: rules })
82
83
 
83
84
  // Modify original array
84
85
  rules.push({ type: 'other' })
@@ -89,7 +90,7 @@ test.group('Action', () => {
89
90
  }).tags(['@modeling', '@action', '@immutability'])
90
91
 
91
92
  test('toJSON returns safe copy', ({ assert }) => {
92
- const action = new Action({} as unknown as ExposedEntity, {
93
+ const action = new Action(mockExposedEntity(), {
93
94
  kind: 'read',
94
95
  accessRule: [{ type: 'allowPublic' }],
95
96
  rateLimiting: { rules: [] },
@@ -110,7 +111,8 @@ test.group('Action', () => {
110
111
 
111
112
  test('getAllRules() aggregates rules from action and parent', ({ assert }) => {
112
113
  const parent = {
113
- getAllRules: () => [new AccessRule({ type: 'allowPublic' })],
114
+ getAllRules: () => [new AccessRule(mockExposedEntity(), { type: 'allowPublic' })],
115
+ notifyChange: () => {},
114
116
  } as unknown as ExposedEntity
115
117
 
116
118
  const action = new Action(parent, {
@@ -127,6 +129,7 @@ test.group('Action', () => {
127
129
  const parentLimiter = new RateLimitingConfiguration({ rules: [{ rate: 10, interval: 'second' }] })
128
130
  const parent = {
129
131
  getAllRateLimiters: () => [parentLimiter],
132
+ notifyChange: () => {},
130
133
  } as unknown as ExposedEntity
131
134
 
132
135
  const action = new Action(parent, {
@@ -1,16 +1,17 @@
1
1
  import { test } from '@japa/runner'
2
2
  import { CreateAction } from '../../../../src/modeling/actions/CreateAction.js'
3
3
  import { AccessRule } from '../../../../src/modeling/rules/index.js'
4
+ import { mockExposedEntity } from './helpers.js'
4
5
 
5
6
  test.group('CreateAction', () => {
6
7
  test('initializes with default values', ({ assert }) => {
7
- const action = new CreateAction({} as any)
8
+ const action = new CreateAction(mockExposedEntity())
8
9
  assert.equal(action.kind, 'create')
9
10
  assert.isEmpty(action.accessRule) // Inherited from Action
10
11
  }).tags(['@modeling', '@action', '@create-action'])
11
12
 
12
13
  test('initializes with inherited values', ({ assert }) => {
13
- const action = new CreateAction({} as any, {
14
+ const action = new CreateAction(mockExposedEntity(), {
14
15
  accessRule: [{ type: 'allowPublic' }],
15
16
  })
16
17
 
@@ -22,7 +23,7 @@ test.group('CreateAction', () => {
22
23
  test('constructor copies arrays (immutability)', ({ assert }) => {
23
24
  const rules = [{ type: 'allowPublic' }]
24
25
 
25
- const action = new CreateAction({} as any, {
26
+ const action = new CreateAction(mockExposedEntity(), {
26
27
  accessRule: rules,
27
28
  })
28
29
 
@@ -35,7 +36,7 @@ test.group('CreateAction', () => {
35
36
  }).tags(['@modeling', '@action', '@create-action', '@immutability'])
36
37
 
37
38
  test('toJSON returns valid schema', ({ assert }) => {
38
- const action = new CreateAction({} as any, {
39
+ const action = new CreateAction(mockExposedEntity(), {
39
40
  accessRule: [{ type: 'allowPublic' }],
40
41
  })
41
42
 
@@ -51,14 +52,14 @@ test.group('CreateAction', () => {
51
52
  }).tags(['@modeling', '@action', '@create-action', '@serialization'])
52
53
 
53
54
  test('notifies change when inherited property changes', async ({ assert }) => {
54
- const action = new CreateAction({} as any)
55
+ const action = new CreateAction(mockExposedEntity())
55
56
  let notified = false
56
57
  action.addEventListener('change', () => {
57
58
  notified = true
58
59
  })
59
60
 
60
61
  // Modify inherited property
61
- action.accessRule = [new AccessRule({ type: 'allowPublic' })]
62
+ action.accessRule = [new AccessRule(mockExposedEntity(), { type: 'allowPublic' })]
62
63
  await Promise.resolve()
63
64
  assert.isTrue(notified)
64
65
  }).tags(['@modeling', '@action', '@create-action', '@observed'])
@@ -1,9 +1,10 @@
1
1
  import { test } from '@japa/runner'
2
2
  import { DeleteAction } from '../../../../src/modeling/actions/DeleteAction.js'
3
+ import { mockExposedEntity } from './helpers.js'
3
4
 
4
5
  test.group('DeleteAction', () => {
5
6
  test('initializes with default values', ({ assert }) => {
6
- const action = new DeleteAction({} as any)
7
+ const action = new DeleteAction(mockExposedEntity())
7
8
  assert.equal(action.kind, 'delete')
8
9
  assert.equal(action.strategy, 'soft')
9
10
  assert.equal(action.retentionPeriod, 30)
@@ -11,7 +12,7 @@ test.group('DeleteAction', () => {
11
12
  }).tags(['@modeling', '@action', '@delete-action'])
12
13
 
13
14
  test('initializes with provided values', ({ assert }) => {
14
- const action = new DeleteAction({} as any, {
15
+ const action = new DeleteAction(mockExposedEntity(), {
15
16
  strategy: 'hard',
16
17
  retentionPeriod: 0,
17
18
  accessRule: [{ type: 'allowPublic' }],
@@ -27,7 +28,7 @@ test.group('DeleteAction', () => {
27
28
  test('constructor copies arrays (immutability)', ({ assert }) => {
28
29
  const rules = [{ type: 'allowPublic' }]
29
30
 
30
- const action = new DeleteAction({} as any, {
31
+ const action = new DeleteAction(mockExposedEntity(), {
31
32
  accessRule: rules,
32
33
  })
33
34
 
@@ -40,7 +41,7 @@ test.group('DeleteAction', () => {
40
41
  }).tags(['@modeling', '@action', '@delete-action', '@immutability'])
41
42
 
42
43
  test('toJSON returns valid schema', ({ assert }) => {
43
- const action = new DeleteAction({} as any, {
44
+ const action = new DeleteAction(mockExposedEntity(), {
44
45
  strategy: 'hard',
45
46
  retentionPeriod: 0,
46
47
  })
@@ -53,7 +54,7 @@ test.group('DeleteAction', () => {
53
54
  }).tags(['@modeling', '@action', '@delete-action', '@serialization'])
54
55
 
55
56
  test('notifies change when strategy changes', async ({ assert }) => {
56
- const action = new DeleteAction({} as any)
57
+ const action = new DeleteAction(mockExposedEntity())
57
58
  let notified = false
58
59
  action.addEventListener('change', () => {
59
60
  notified = true
@@ -65,7 +66,7 @@ test.group('DeleteAction', () => {
65
66
  }).tags(['@modeling', '@action', '@delete-action', '@observed'])
66
67
 
67
68
  test('notifies change when retentionPeriod changes', async ({ assert }) => {
68
- const action = new DeleteAction({} as any)
69
+ const action = new DeleteAction(mockExposedEntity())
69
70
  let notified = false
70
71
  action.addEventListener('change', () => {
71
72
  notified = true
@@ -1,9 +1,10 @@
1
1
  import { test } from '@japa/runner'
2
2
  import { ListAction } from '../../../../src/modeling/actions/ListAction.js'
3
+ import { mockExposedEntity } from './helpers.js'
3
4
 
4
5
  test.group('ListAction', () => {
5
6
  test('initializes with default values', ({ assert }) => {
6
- const action = new ListAction({} as any)
7
+ const action = new ListAction(mockExposedEntity())
7
8
  assert.equal(action.kind, 'list')
8
9
  assert.isUndefined(action.cacheTtl)
9
10
  assert.isEmpty(action.accessRule) // Inherited from Action
@@ -12,7 +13,7 @@ test.group('ListAction', () => {
12
13
  test('initializes with provided values', ({ assert }) => {
13
14
  const cacheTtl = 100
14
15
 
15
- const action = new ListAction({} as any, {
16
+ const action = new ListAction(mockExposedEntity(), {
16
17
  cacheTtl,
17
18
  })
18
19
 
@@ -20,7 +21,7 @@ test.group('ListAction', () => {
20
21
  }).tags(['@modeling', '@action', '@list-action'])
21
22
 
22
23
  test('toJSON returns safe copy', ({ assert }) => {
23
- const action = new ListAction({} as any, {
24
+ const action = new ListAction(mockExposedEntity(), {
24
25
  cacheTtl: 100,
25
26
  })
26
27
 
@@ -33,7 +34,7 @@ test.group('ListAction', () => {
33
34
  }).tags(['@modeling', '@action', '@list-action', '@immutability'])
34
35
 
35
36
  test('notifies change when cacheTtl changes', async ({ assert }) => {
36
- const action = new ListAction({} as any)
37
+ const action = new ListAction(mockExposedEntity())
37
38
  let notified = false
38
39
  action.addEventListener('change', () => {
39
40
  notified = true
@@ -1,16 +1,17 @@
1
1
  import { test } from '@japa/runner'
2
2
  import { ReadAction } from '../../../../src/modeling/actions/ReadAction.js'
3
3
  import { AccessRule } from '../../../../src/modeling/rules/index.js'
4
+ import { mockExposedEntity } from './helpers.js'
4
5
 
5
6
  test.group('ReadAction', () => {
6
7
  test('initializes with default values', ({ assert }) => {
7
- const action = new ReadAction({} as any)
8
+ const action = new ReadAction(mockExposedEntity())
8
9
  assert.equal(action.kind, 'read')
9
10
  assert.isEmpty(action.accessRule) // Inherited from Action
10
11
  }).tags(['@modeling', '@action', '@read-action'])
11
12
 
12
13
  test('initializes with inherited values', ({ assert }) => {
13
- const action = new ReadAction({} as any, {
14
+ const action = new ReadAction(mockExposedEntity(), {
14
15
  accessRule: [{ type: 'allowPublic' }],
15
16
  })
16
17
 
@@ -22,7 +23,7 @@ test.group('ReadAction', () => {
22
23
  test('constructor copies arrays (immutability)', ({ assert }) => {
23
24
  const rules = [{ type: 'allowPublic' }]
24
25
 
25
- const action = new ReadAction({} as any, {
26
+ const action = new ReadAction(mockExposedEntity(), {
26
27
  accessRule: rules,
27
28
  })
28
29
 
@@ -35,7 +36,7 @@ test.group('ReadAction', () => {
35
36
  }).tags(['@modeling', '@action', '@read-action', '@immutability'])
36
37
 
37
38
  test('toJSON returns valid schema', ({ assert }) => {
38
- const action = new ReadAction({} as any, {
39
+ const action = new ReadAction(mockExposedEntity(), {
39
40
  accessRule: [{ type: 'allowPublic' }],
40
41
  })
41
42
 
@@ -51,26 +52,26 @@ test.group('ReadAction', () => {
51
52
  }).tags(['@modeling', '@action', '@read-action', '@serialization'])
52
53
 
53
54
  test('notifies change when inherited property changes', async ({ assert }) => {
54
- const action = new ReadAction({} as any)
55
+ const action = new ReadAction(mockExposedEntity())
55
56
  let notified = false
56
57
  action.addEventListener('change', () => {
57
58
  notified = true
58
59
  })
59
60
 
60
61
  // Modify inherited property
61
- action.accessRule = [new AccessRule({ type: 'allowPublic' })]
62
+ action.accessRule = [new AccessRule(mockExposedEntity(), { type: 'allowPublic' })]
62
63
  await Promise.resolve()
63
64
  assert.isTrue(notified)
64
65
  }).tags(['@modeling', '@action', '@read-action', '@observed'])
65
66
 
66
67
  test('notifies change when accessRule value change', async ({ assert }) => {
67
- const action = new ReadAction({} as any)
68
+ const action = new ReadAction(mockExposedEntity())
68
69
  let notified = false
69
70
  action.addEventListener('change', () => {
70
71
  notified = true
71
72
  })
72
73
 
73
- action.accessRule.push(new AccessRule({ type: 'allowPublic' }))
74
+ action.accessRule.push(new AccessRule(mockExposedEntity(), { type: 'allowPublic' }))
74
75
  await Promise.resolve()
75
76
  assert.isTrue(notified)
76
77
  }).tags(['@modeling', '@action', '@read-action', '@observed'])
@@ -1,9 +1,10 @@
1
1
  import { test } from '@japa/runner'
2
2
  import { SearchAction } from '../../../../src/modeling/actions/SearchAction.js'
3
+ import { mockExposedEntity } from './helpers.js'
3
4
 
4
5
  test.group('SearchAction', () => {
5
6
  test('initializes with default values', ({ assert }) => {
6
- const action = new SearchAction({} as any)
7
+ const action = new SearchAction(mockExposedEntity())
7
8
  assert.equal(action.kind, 'search')
8
9
  assert.isUndefined(action.maxAstDepth)
9
10
  assert.isEmpty(action.accessRule)
@@ -11,7 +12,7 @@ test.group('SearchAction', () => {
11
12
 
12
13
  test('initializes with provided values', ({ assert }) => {
13
14
  const maxAstDepth = 10
14
- const action = new SearchAction({} as any, {
15
+ const action = new SearchAction(mockExposedEntity(), {
15
16
  maxAstDepth,
16
17
  })
17
18
 
@@ -20,7 +21,7 @@ test.group('SearchAction', () => {
20
21
  }).tags(['@modeling', '@action', '@search-action'])
21
22
 
22
23
  test('toJSON returns valid schema', ({ assert }) => {
23
- const action = new SearchAction({} as any, {
24
+ const action = new SearchAction(mockExposedEntity(), {
24
25
  maxAstDepth: 10,
25
26
  })
26
27
 
@@ -34,7 +35,7 @@ test.group('SearchAction', () => {
34
35
  }).tags(['@modeling', '@action', '@search-action', '@serialization', '@immutability'])
35
36
 
36
37
  test('notifies change when maxAstDepth changes', async ({ assert }) => {
37
- const action = new SearchAction({} as any)
38
+ const action = new SearchAction(mockExposedEntity())
38
39
  let notified = false
39
40
  action.addEventListener('change', () => {
40
41
  notified = true