@supernova-studio/model 0.47.28 → 0.47.29
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/dist/index.d.mts +222 -93
- package/dist/index.d.ts +222 -93
- package/dist/index.js +54 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +53 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/export/export-destinations.ts +8 -8
- package/src/export/export-jobs.ts +3 -2
- package/src/export/export-runner/export-context.ts +1 -0
- package/src/integrations/git.ts +14 -4
- package/src/integrations/integration.ts +28 -21
- package/src/utils/common.ts +4 -0
- package/src/utils/errors.ts +5 -0
package/package.json
CHANGED
|
@@ -22,8 +22,8 @@ export const ExporterDestinationGithub = z.object({
|
|
|
22
22
|
relativePath: nullishToOptional(z.string()),
|
|
23
23
|
|
|
24
24
|
// Legacy deprecated fields. Use `credentialId` instead
|
|
25
|
-
connectionId: z.string()
|
|
26
|
-
userId: z.number()
|
|
25
|
+
connectionId: nullishToOptional(z.string()),
|
|
26
|
+
userId: nullishToOptional(z.number()),
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
export const ExporterDestinationAzure = z.object({
|
|
@@ -42,8 +42,8 @@ export const ExporterDestinationAzure = z.object({
|
|
|
42
42
|
url: nullishToOptional(z.string()),
|
|
43
43
|
|
|
44
44
|
// Legacy deprecated fields. Use `credentialId` instead
|
|
45
|
-
connectionId: z.string()
|
|
46
|
-
userId: z.number()
|
|
45
|
+
connectionId: nullishToOptional(z.string()),
|
|
46
|
+
userId: nullishToOptional(z.number()),
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
export const ExporterDestinationGitlab = z.object({
|
|
@@ -60,8 +60,8 @@ export const ExporterDestinationGitlab = z.object({
|
|
|
60
60
|
url: nullishToOptional(z.string()),
|
|
61
61
|
|
|
62
62
|
// Legacy deprecated fields. Use `credentialId` instead
|
|
63
|
-
connectionId: z.string()
|
|
64
|
-
userId: z.number()
|
|
63
|
+
connectionId: nullishToOptional(z.string()),
|
|
64
|
+
userId: nullishToOptional(z.number()),
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
export const ExporterDestinationBitbucket = z.object({
|
|
@@ -77,8 +77,8 @@ export const ExporterDestinationBitbucket = z.object({
|
|
|
77
77
|
relativePath: nullishToOptional(z.string()),
|
|
78
78
|
|
|
79
79
|
// Legacy deprecated fields. Use `credentialId` instead
|
|
80
|
-
connectionId: z.string()
|
|
81
|
-
userId: z.number()
|
|
80
|
+
connectionId: nullishToOptional(z.string()),
|
|
81
|
+
userId: nullishToOptional(z.number()),
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
export const ExportDestinationsMap = z.object({
|
|
@@ -57,6 +57,7 @@ export const ExportJobResult = z.object({
|
|
|
57
57
|
gitlab: nullishToOptional(ExportJobPullRequestDestinationResult),
|
|
58
58
|
bitbucket: nullishToOptional(ExportJobPullRequestDestinationResult),
|
|
59
59
|
sndocs: nullishToOptional(ExportJobDocsDestinationResult),
|
|
60
|
+
logs: nullishToOptional(ExportJobLogEntry.array()),
|
|
60
61
|
});
|
|
61
62
|
|
|
62
63
|
export type ExportJobLogEntry = z.infer<typeof ExportJobLogEntry>;
|
|
@@ -71,8 +72,8 @@ export type ExportJobResult = z.infer<typeof ExportJobResult>;
|
|
|
71
72
|
|
|
72
73
|
export const ExportJob = z.object({
|
|
73
74
|
id: z.string(),
|
|
74
|
-
createdAt: z.date(),
|
|
75
|
-
finishedAt: z.date().optional(),
|
|
75
|
+
createdAt: z.coerce.date(),
|
|
76
|
+
finishedAt: z.coerce.date().optional(),
|
|
76
77
|
designSystemId: z.string(),
|
|
77
78
|
designSystemVersionId: z.string(),
|
|
78
79
|
workspaceId: z.string(),
|
package/src/integrations/git.ts
CHANGED
|
@@ -14,26 +14,36 @@ export const GitOrganization = z.object({
|
|
|
14
14
|
id: z.string(),
|
|
15
15
|
name: z.string(),
|
|
16
16
|
url: z.string(),
|
|
17
|
+
slug: z.string(),
|
|
17
18
|
});
|
|
18
|
-
export type GitOrganization = z.infer<typeof GitOrganization>;
|
|
19
19
|
|
|
20
20
|
export const GitProject = z.object({
|
|
21
21
|
id: z.string(),
|
|
22
22
|
name: z.string(),
|
|
23
23
|
url: z.string(),
|
|
24
|
+
slug: z.string(),
|
|
24
25
|
});
|
|
25
|
-
export type GitProject = z.infer<typeof GitProject>;
|
|
26
26
|
|
|
27
27
|
export const GitRepository = z.object({
|
|
28
28
|
id: z.string(),
|
|
29
29
|
name: z.string(),
|
|
30
30
|
url: z.string(),
|
|
31
|
-
|
|
31
|
+
slug: z.string(),
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Can be undefined when:
|
|
35
|
+
* - there are no branches in the repository yet
|
|
36
|
+
* - Git provider doesn't expose this information on a repository via their API
|
|
37
|
+
*/
|
|
38
|
+
defaultBranch: z.string().optional(),
|
|
32
39
|
});
|
|
33
|
-
export type GitRepository = z.infer<typeof GitRepository>;
|
|
34
40
|
|
|
35
41
|
export const GitBranch = z.object({
|
|
36
42
|
name: z.string(),
|
|
37
43
|
lastCommitId: z.string(),
|
|
38
44
|
});
|
|
45
|
+
|
|
46
|
+
export type GitOrganization = z.infer<typeof GitOrganization>;
|
|
47
|
+
export type GitProject = z.infer<typeof GitProject>;
|
|
48
|
+
export type GitRepository = z.infer<typeof GitRepository>;
|
|
39
49
|
export type GitBranch = z.infer<typeof GitBranch>;
|
|
@@ -15,6 +15,9 @@ export type IntegrationDesignSystem = z.infer<typeof IntegrationDesignSystem>;
|
|
|
15
15
|
export const IntegrationCredentialsType = z.enum(["OAuth2", "PAT", "GithubApp"]);
|
|
16
16
|
export type IntegrationCredentialsType = z.infer<typeof IntegrationCredentialsType>;
|
|
17
17
|
|
|
18
|
+
export const IntegrationCredentialsState = z.enum(["Active", "Inactive"]);
|
|
19
|
+
export type IntegrationCredentialsState = z.infer<typeof IntegrationCredentialsState>;
|
|
20
|
+
|
|
18
21
|
export const IntegrationCredentialsProfile = z.object({
|
|
19
22
|
id: nullishToOptional(z.string()),
|
|
20
23
|
email: nullishToOptional(z.string()),
|
|
@@ -22,6 +25,7 @@ export const IntegrationCredentialsProfile = z.object({
|
|
|
22
25
|
type: nullishToOptional(z.string()),
|
|
23
26
|
avatarUrl: nullishToOptional(z.string()),
|
|
24
27
|
organization: nullishToOptional(z.string()),
|
|
28
|
+
collection: nullishToOptional(z.string()),
|
|
25
29
|
});
|
|
26
30
|
|
|
27
31
|
export type IntegrationCredentialsProfile = z.infer<typeof IntegrationCredentialsProfile>;
|
|
@@ -41,6 +45,8 @@ export const IntegrationCredentials = z.object({
|
|
|
41
45
|
appInstallationId: z.string().optional(),
|
|
42
46
|
profile: IntegrationCredentialsProfile.optional(),
|
|
43
47
|
customUrl: z.string().optional(),
|
|
48
|
+
state: IntegrationCredentialsState,
|
|
49
|
+
|
|
44
50
|
user: UserMinified.optional(),
|
|
45
51
|
});
|
|
46
52
|
|
|
@@ -76,9 +82,6 @@ export type ExtendedIntegration = Omit<Integration, "type"> & {
|
|
|
76
82
|
integrationDesignSystems?: IntegrationDesignSystem[];
|
|
77
83
|
};
|
|
78
84
|
|
|
79
|
-
// Custom URL validation
|
|
80
|
-
const forbiddenCustomUrldomainList = ["github.com", "gitlab.com", "bitbucket.org", "figma.com", "dev.azure.com"];
|
|
81
|
-
|
|
82
85
|
export const IntegrationToken = z
|
|
83
86
|
.object({
|
|
84
87
|
access_token: z.string(),
|
|
@@ -86,16 +89,14 @@ export const IntegrationToken = z
|
|
|
86
89
|
expires_in: z.union([z.number().optional(), z.string().optional()]),
|
|
87
90
|
token_type: z.string().optional(),
|
|
88
91
|
token_name: z.string().optional(),
|
|
89
|
-
token_azure_organization_name: z.string().optional(), // Azure only
|
|
92
|
+
token_azure_organization_name: z.string().optional(), // Azure Cloud PAT only
|
|
93
|
+
token_azure_collection_name: z.string().optional(), // Azure Server PAT only
|
|
90
94
|
token_bitbucket_username: z.string().optional(), // Bitbucket only
|
|
91
95
|
custom_url: z
|
|
92
96
|
.string()
|
|
97
|
+
.url()
|
|
93
98
|
.optional()
|
|
94
|
-
.
|
|
95
|
-
if (!value) return true;
|
|
96
|
-
if (forbiddenCustomUrldomainList.some(domain => value.includes(domain))) return false;
|
|
97
|
-
return true;
|
|
98
|
-
}, "Custom URL validation failed"),
|
|
99
|
+
.transform(value => value && formatCustomUrl(value)),
|
|
99
100
|
})
|
|
100
101
|
.refine(data => {
|
|
101
102
|
if (data.custom_url && data.token_azure_organization_name) {
|
|
@@ -112,19 +113,25 @@ export const IntegrationToken = z
|
|
|
112
113
|
tokenName: data.token_name,
|
|
113
114
|
tokenBitbucketUsername: data.token_bitbucket_username,
|
|
114
115
|
tokenAzureOrganizationName: data.token_azure_organization_name,
|
|
115
|
-
|
|
116
|
+
tokenAzureCollection: data.token_azure_collection_name,
|
|
117
|
+
customUrl: data.custom_url,
|
|
116
118
|
};
|
|
117
|
-
|
|
118
|
-
function formatCustomUrl(url: string): string {
|
|
119
|
-
let formattedUrl = url.trim();
|
|
120
|
-
if (!formattedUrl.startsWith("http://") && !formattedUrl.startsWith("https://")) {
|
|
121
|
-
formattedUrl = "http://" + formattedUrl;
|
|
122
|
-
}
|
|
123
|
-
if (formattedUrl.endsWith("/")) {
|
|
124
|
-
formattedUrl = formattedUrl.slice(0, -1);
|
|
125
|
-
}
|
|
126
|
-
return formattedUrl;
|
|
127
|
-
}
|
|
128
119
|
});
|
|
129
120
|
|
|
130
121
|
export type IntegrationToken = z.infer<typeof IntegrationToken>;
|
|
122
|
+
|
|
123
|
+
// Custom URL validation
|
|
124
|
+
const forbiddenCustomUrlDomainList = ["github.com", "gitlab.com", "bitbucket.org", "figma.com", "dev.azure.com"];
|
|
125
|
+
|
|
126
|
+
function formatCustomUrl(url: string): string | undefined {
|
|
127
|
+
let formattedUrl = url.trim().toLowerCase();
|
|
128
|
+
if (!formattedUrl.startsWith("http://") && !formattedUrl.startsWith("https://")) {
|
|
129
|
+
formattedUrl = "https://" + formattedUrl;
|
|
130
|
+
}
|
|
131
|
+
if (formattedUrl.endsWith("/")) {
|
|
132
|
+
formattedUrl = formattedUrl.slice(0, -1);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// do not store default urls that we incorrectly provided as custom urls
|
|
136
|
+
return forbiddenCustomUrlDomainList.some(domain => formattedUrl.includes(domain)) ? undefined : formattedUrl;
|
|
137
|
+
}
|
package/src/utils/common.ts
CHANGED
|
@@ -115,6 +115,10 @@ export async function sleep(ms: number): Promise<void> {
|
|
|
115
115
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
export function uniqueBy<K, V>(items: V[], prop: (v: V) => K): V[] {
|
|
119
|
+
return Array.from(mapByUnique(items, prop).values());
|
|
120
|
+
}
|
|
121
|
+
|
|
118
122
|
export type Pagination = {
|
|
119
123
|
skip?: number;
|
|
120
124
|
take?: number;
|
package/src/utils/errors.ts
CHANGED
|
@@ -15,6 +15,7 @@ export type SupernovaExceptionType =
|
|
|
15
15
|
| "MissingWorkspacePermission"
|
|
16
16
|
| "MissingExporterPermission"
|
|
17
17
|
| "MissingIntegration"
|
|
18
|
+
| "MissingIntegrationAccess"
|
|
18
19
|
| "NoAccess"
|
|
19
20
|
| "MissingCredentials"
|
|
20
21
|
| "ValidationError"
|
|
@@ -85,6 +86,10 @@ export class SupernovaException extends Error {
|
|
|
85
86
|
return new SupernovaException("MissingIntegration", message);
|
|
86
87
|
}
|
|
87
88
|
|
|
89
|
+
static missingIntegrationAccess(message?: string): SupernovaException {
|
|
90
|
+
return new SupernovaException("MissingIntegrationAccess", message);
|
|
91
|
+
}
|
|
92
|
+
|
|
88
93
|
static noAccess(message?: string): SupernovaException {
|
|
89
94
|
return new SupernovaException("NoAccess", message);
|
|
90
95
|
}
|