@api-client/core 0.19.23 → 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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@api-client/core",
3
3
  "description": "The API Client's core client library. Works in NodeJS and in a ES enabled browser.",
4
- "version": "0.19.23",
4
+ "version": "0.19.24",
5
5
  "license": "UNLICENSED",
6
6
  "exports": {
7
7
  "./browser.js": {
@@ -0,0 +1,119 @@
1
+ import type { FieldValidationMessage } from '../../exceptions/validation_error.js'
2
+ import { nanoid } from '../../nanoid.js'
3
+
4
+ export interface CustomDomainSchema {
5
+ /**
6
+ * Primary key (nanoid)
7
+ */
8
+ id: string
9
+ /**
10
+ * ID of the organization
11
+ */
12
+ orgId: string
13
+ /**
14
+ * The custom domain
15
+ */
16
+ domain: string
17
+ /**
18
+ * The DNS target for the custom domain
19
+ */
20
+ dnsTarget: string
21
+ /**
22
+ * Whether the DNS has been verified
23
+ */
24
+ dnsVerified: boolean
25
+ /**
26
+ * Timestamp of last DNS verification
27
+ */
28
+ lastVerifiedAt?: number
29
+ /**
30
+ * Timestamp of creation
31
+ */
32
+ createdAt: number
33
+ /**
34
+ * Timestamp of last update
35
+ */
36
+ updatedAt: number
37
+ }
38
+
39
+ export class CustomDomainModel implements CustomDomainSchema {
40
+ id: string
41
+ orgId: string
42
+ domain: string
43
+ dnsTarget: string
44
+ dnsVerified: boolean
45
+ lastVerifiedAt?: number
46
+ createdAt: number
47
+ updatedAt: number
48
+
49
+ static createSchema(input: Partial<CustomDomainSchema> = {}): CustomDomainSchema {
50
+ const id = input.id ?? nanoid()
51
+ const result: CustomDomainSchema = {
52
+ id,
53
+ orgId: input.orgId || '',
54
+ domain: input.domain || '',
55
+ dnsTarget: input.dnsTarget || '',
56
+ dnsVerified: input.dnsVerified ?? false,
57
+ createdAt: input.createdAt ?? Date.now(),
58
+ updatedAt: input.updatedAt ?? Date.now(),
59
+ }
60
+ if (typeof input.lastVerifiedAt === 'number') {
61
+ result.lastVerifiedAt = input.lastVerifiedAt
62
+ }
63
+ return result
64
+ }
65
+
66
+ constructor(state?: Partial<CustomDomainSchema>) {
67
+ const init = CustomDomainModel.createSchema(state)
68
+ this.id = init.id
69
+ this.orgId = init.orgId
70
+ this.domain = init.domain
71
+ this.dnsTarget = init.dnsTarget
72
+ this.dnsVerified = init.dnsVerified
73
+ this.lastVerifiedAt = init.lastVerifiedAt
74
+ this.createdAt = init.createdAt
75
+ this.updatedAt = init.updatedAt
76
+ }
77
+
78
+ toJSON(): CustomDomainSchema {
79
+ const result: CustomDomainSchema = {
80
+ id: this.id,
81
+ orgId: this.orgId,
82
+ domain: this.domain,
83
+ dnsTarget: this.dnsTarget,
84
+ dnsVerified: this.dnsVerified,
85
+ createdAt: this.createdAt,
86
+ updatedAt: this.updatedAt,
87
+ }
88
+ if (typeof this.lastVerifiedAt === 'number') {
89
+ result.lastVerifiedAt = this.lastVerifiedAt
90
+ }
91
+ return result
92
+ }
93
+
94
+ validate(): FieldValidationMessage[] {
95
+ const result: FieldValidationMessage[] = []
96
+ if (!this.domain) {
97
+ result.push({
98
+ field: 'domain',
99
+ message: 'Domain must not be empty',
100
+ rule: 'notEmpty',
101
+ })
102
+ }
103
+ if (!this.orgId) {
104
+ result.push({
105
+ field: 'orgId',
106
+ message: 'Org ID must not be empty',
107
+ rule: 'notEmpty',
108
+ })
109
+ }
110
+ if (!this.dnsTarget) {
111
+ result.push({
112
+ field: 'dnsTarget',
113
+ message: 'DNS target must not be empty',
114
+ rule: 'notEmpty',
115
+ })
116
+ }
117
+ return result
118
+ }
119
+ }
@@ -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
+ }
@@ -0,0 +1,111 @@
1
+ import { test } from '@japa/runner'
2
+ import { CustomDomainModel } from '../../../../src/models/store/CustomDomain.js'
3
+ import type { CustomDomainSchema } from '../../../../src/models/store/CustomDomain.js'
4
+
5
+ test.group('CustomDomain model', () => {
6
+ test('createSchema() returns default values', ({ assert }) => {
7
+ const result = CustomDomainModel.createSchema()
8
+ assert.isString(result.id)
9
+ assert.equal(result.orgId, '')
10
+ assert.equal(result.domain, '')
11
+ assert.equal(result.dnsTarget, '')
12
+ assert.isFalse(result.dnsVerified)
13
+ assert.isUndefined(result.lastVerifiedAt)
14
+ assert.isNumber(result.createdAt)
15
+ assert.isNumber(result.updatedAt)
16
+ })
17
+
18
+ test('createSchema(init) assigns values', ({ assert }) => {
19
+ const init: Partial<CustomDomainSchema> = {
20
+ id: 'test-id',
21
+ orgId: 'org-1',
22
+ domain: 'api.example.com',
23
+ dnsTarget: 'target.example.com',
24
+ dnsVerified: true,
25
+ lastVerifiedAt: 11111,
26
+ createdAt: 12345,
27
+ updatedAt: 67890,
28
+ }
29
+ const result = CustomDomainModel.createSchema(init)
30
+ assert.equal(result.id, 'test-id')
31
+ assert.equal(result.orgId, 'org-1')
32
+ assert.equal(result.domain, 'api.example.com')
33
+ assert.equal(result.dnsTarget, 'target.example.com')
34
+ assert.isTrue(result.dnsVerified)
35
+ assert.equal(result.lastVerifiedAt, 11111)
36
+ assert.equal(result.createdAt, 12345)
37
+ assert.equal(result.updatedAt, 67890)
38
+ })
39
+
40
+ test('constructor() initializes with default values', ({ assert }) => {
41
+ const model = new CustomDomainModel()
42
+ assert.isString(model.id)
43
+ assert.equal(model.orgId, '')
44
+ assert.equal(model.domain, '')
45
+ assert.equal(model.dnsTarget, '')
46
+ assert.isFalse(model.dnsVerified)
47
+ assert.isUndefined(model.lastVerifiedAt)
48
+ assert.isNumber(model.createdAt)
49
+ assert.isNumber(model.updatedAt)
50
+ })
51
+
52
+ test('constructor(init) assigns values', ({ assert }) => {
53
+ const init: Partial<CustomDomainSchema> = {
54
+ orgId: 'org-1',
55
+ domain: 'api.example.com',
56
+ dnsVerified: true,
57
+ }
58
+ const model = new CustomDomainModel(init)
59
+ assert.equal(model.orgId, 'org-1')
60
+ assert.equal(model.domain, 'api.example.com')
61
+ assert.isTrue(model.dnsVerified)
62
+ })
63
+
64
+ test('toJSON() returns the schema representation', ({ assert }) => {
65
+ const init: Partial<CustomDomainSchema> = {
66
+ id: 'test-id',
67
+ orgId: 'org-1',
68
+ domain: 'api.example.com',
69
+ dnsTarget: 'target.example.com',
70
+ dnsVerified: true,
71
+ lastVerifiedAt: 11111,
72
+ createdAt: 12345,
73
+ updatedAt: 67890,
74
+ }
75
+ const model = new CustomDomainModel(init)
76
+ const result = model.toJSON()
77
+ assert.deepEqual(result, {
78
+ id: 'test-id',
79
+ orgId: 'org-1',
80
+ domain: 'api.example.com',
81
+ dnsTarget: 'target.example.com',
82
+ dnsVerified: true,
83
+ lastVerifiedAt: 11111,
84
+ createdAt: 12345,
85
+ updatedAt: 67890,
86
+ })
87
+ })
88
+
89
+ test('validate() returns errors for empty fields', ({ assert }) => {
90
+ const model = new CustomDomainModel({
91
+ domain: '',
92
+ orgId: '',
93
+ dnsTarget: '',
94
+ })
95
+ const errors = model.validate()
96
+ assert.lengthOf(errors, 3)
97
+ assert.deepEqual(errors[0], { field: 'domain', message: 'Domain must not be empty', rule: 'notEmpty' })
98
+ assert.deepEqual(errors[1], { field: 'orgId', message: 'Org ID must not be empty', rule: 'notEmpty' })
99
+ assert.deepEqual(errors[2], { field: 'dnsTarget', message: 'DNS target must not be empty', rule: 'notEmpty' })
100
+ })
101
+
102
+ test('validate() returns no errors for valid model', ({ assert }) => {
103
+ const model = new CustomDomainModel({
104
+ domain: 'api.example.com',
105
+ orgId: 'org-1',
106
+ dnsTarget: 'target.example.com',
107
+ })
108
+ const errors = model.validate()
109
+ assert.lengthOf(errors, 0)
110
+ })
111
+ })
@@ -0,0 +1,134 @@
1
+ import { test } from '@japa/runner'
2
+ import { Deployment, DeploymentStatus } from '../../../../src/models/store/Deployment.js'
3
+ import type { DeploymentSchema } from '../../../../src/models/store/Deployment.js'
4
+
5
+ test.group('Deployment model', () => {
6
+ test('createSchema() returns default values', ({ assert }) => {
7
+ const result = Deployment.createSchema()
8
+ assert.isString(result.id)
9
+ assert.equal(result.orgId, '')
10
+ assert.equal(result.apiId, '')
11
+ assert.equal(result.deploymentVersion, 'v0')
12
+ assert.equal(result.apiModelVersion, '0.0.0')
13
+ assert.equal(result.status, DeploymentStatus.Pending)
14
+ assert.isUndefined(result.stagingPath)
15
+ assert.isUndefined(result.mongoModelId)
16
+ assert.isNumber(result.createdAt)
17
+ assert.isNumber(result.updatedAt)
18
+ })
19
+
20
+ test('createSchema(init) assigns values', ({ assert }) => {
21
+ const init: Partial<DeploymentSchema> = {
22
+ id: 'test-id',
23
+ orgId: 'org-1',
24
+ apiId: 'api-1',
25
+ deploymentVersion: 'v1',
26
+ apiModelVersion: '1.0.0',
27
+ status: DeploymentStatus.Active,
28
+ stagingPath: '/stage',
29
+ mongoModelId: 'mongo-1',
30
+ createdAt: 12345,
31
+ updatedAt: 67890,
32
+ }
33
+ const result = Deployment.createSchema(init)
34
+ assert.equal(result.id, 'test-id')
35
+ assert.equal(result.orgId, 'org-1')
36
+ assert.equal(result.apiId, 'api-1')
37
+ assert.equal(result.deploymentVersion, 'v1')
38
+ assert.equal(result.apiModelVersion, '1.0.0')
39
+ assert.equal(result.status, DeploymentStatus.Active)
40
+ assert.equal(result.stagingPath, '/stage')
41
+ assert.equal(result.mongoModelId, 'mongo-1')
42
+ assert.equal(result.createdAt, 12345)
43
+ assert.equal(result.updatedAt, 67890)
44
+ })
45
+
46
+ test('constructor() initializes with default values', ({ assert }) => {
47
+ const deployment = new Deployment()
48
+ assert.isString(deployment.id)
49
+ assert.equal(deployment.orgId, '')
50
+ assert.equal(deployment.apiId, '')
51
+ assert.equal(deployment.deploymentVersion, 'v0')
52
+ assert.equal(deployment.apiModelVersion, '0.0.0')
53
+ assert.equal(deployment.status, DeploymentStatus.Pending)
54
+ assert.isUndefined(deployment.stagingPath)
55
+ assert.isUndefined(deployment.mongoModelId)
56
+ assert.isNumber(deployment.createdAt)
57
+ assert.isNumber(deployment.updatedAt)
58
+ })
59
+
60
+ test('constructor(init) assigns values', ({ assert }) => {
61
+ const init: Partial<DeploymentSchema> = {
62
+ orgId: 'org-1',
63
+ apiId: 'api-1',
64
+ stagingPath: '/stage',
65
+ }
66
+ const deployment = new Deployment(init)
67
+ assert.equal(deployment.orgId, 'org-1')
68
+ assert.equal(deployment.apiId, 'api-1')
69
+ assert.equal(deployment.stagingPath, '/stage')
70
+ })
71
+
72
+ test('toJSON() returns the schema representation', ({ assert }) => {
73
+ const init: Partial<DeploymentSchema> = {
74
+ id: 'test-id',
75
+ orgId: 'org-1',
76
+ apiId: 'api-1',
77
+ deploymentVersion: 'v1',
78
+ apiModelVersion: '1.0.0',
79
+ status: DeploymentStatus.Active,
80
+ stagingPath: '/stage',
81
+ mongoModelId: 'mongo-1',
82
+ createdAt: 12345,
83
+ updatedAt: 67890,
84
+ }
85
+ const deployment = new Deployment(init)
86
+ const result = deployment.toJSON()
87
+ assert.deepEqual(result, {
88
+ id: 'test-id',
89
+ orgId: 'org-1',
90
+ apiId: 'api-1',
91
+ deploymentVersion: 'v1',
92
+ apiModelVersion: '1.0.0',
93
+ status: DeploymentStatus.Active,
94
+ stagingPath: '/stage',
95
+ mongoModelId: 'mongo-1',
96
+ createdAt: 12345,
97
+ updatedAt: 67890,
98
+ })
99
+ })
100
+
101
+ test('validate() returns errors for empty fields', ({ assert }) => {
102
+ const deployment = new Deployment({
103
+ orgId: '',
104
+ apiId: '',
105
+ })
106
+ deployment.deploymentVersion = ''
107
+ deployment.apiModelVersion = ''
108
+ const errors = deployment.validate()
109
+ assert.lengthOf(errors, 4)
110
+ assert.deepEqual(errors[0], { field: 'orgId', message: 'Org ID must not be empty', rule: 'notEmpty' })
111
+ assert.deepEqual(errors[1], { field: 'apiId', message: 'API ID must not be empty', rule: 'notEmpty' })
112
+ assert.deepEqual(errors[2], {
113
+ field: 'deploymentVersion',
114
+ message: 'Deployment version must not be empty',
115
+ rule: 'notEmpty',
116
+ })
117
+ assert.deepEqual(errors[3], {
118
+ field: 'apiModelVersion',
119
+ message: 'API model version must not be empty',
120
+ rule: 'notEmpty',
121
+ })
122
+ })
123
+
124
+ test('validate() returns no errors for valid model', ({ assert }) => {
125
+ const deployment = new Deployment({
126
+ orgId: 'org-1',
127
+ apiId: 'api-1',
128
+ deploymentVersion: 'v1',
129
+ apiModelVersion: '1.0.0',
130
+ })
131
+ const errors = deployment.validate()
132
+ assert.lengthOf(errors, 0)
133
+ })
134
+ })