@stackone/hub 0.1.0

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 (48) hide show
  1. package/.github/workflows/node-ci.yml +20 -0
  2. package/.github/workflows/release-please.yml +37 -0
  3. package/.github/workflows/semantic-pull-request.yml +31 -0
  4. package/.nvmrc +1 -0
  5. package/.release-please-manifest.json +1 -0
  6. package/.yalc/@stackone/malachite/README.md +1 -0
  7. package/.yalc/@stackone/malachite/package.json +37 -0
  8. package/.yalc/@stackone/malachite/yalc.sig +1 -0
  9. package/CHANGELOG.md +30 -0
  10. package/README.md +225 -0
  11. package/biome.json +77 -0
  12. package/dev/index.html +11 -0
  13. package/dev/main.css +80 -0
  14. package/dev/main.tsx +96 -0
  15. package/dev/vite-env.d.ts +15 -0
  16. package/index.html +14 -0
  17. package/package.json +44 -0
  18. package/release-please-config.json +5 -0
  19. package/rollup.config.mjs +72 -0
  20. package/src/StackOneHub.tsx +99 -0
  21. package/src/WebComponentWrapper.tsx +14 -0
  22. package/src/index.ts +1 -0
  23. package/src/modules/csv-importer.tsx/CsvImporter.tsx +35 -0
  24. package/src/modules/integration-picker/IntegrationPicker.tsx +89 -0
  25. package/src/modules/integration-picker/components/IntegrationFields.tsx +115 -0
  26. package/src/modules/integration-picker/components/IntegrationList.tsx +71 -0
  27. package/src/modules/integration-picker/components/IntegrationPickerContent.tsx +107 -0
  28. package/src/modules/integration-picker/components/cardFooter.tsx +88 -0
  29. package/src/modules/integration-picker/components/cardTitle.tsx +51 -0
  30. package/src/modules/integration-picker/components/views/ErrorView.tsx +9 -0
  31. package/src/modules/integration-picker/components/views/IntegrationFormView.tsx +22 -0
  32. package/src/modules/integration-picker/components/views/IntegrationListView.tsx +19 -0
  33. package/src/modules/integration-picker/components/views/LoadingView.tsx +11 -0
  34. package/src/modules/integration-picker/components/views/SuccessView.tsx +10 -0
  35. package/src/modules/integration-picker/components/views/index.ts +5 -0
  36. package/src/modules/integration-picker/hooks/useIntegrationPicker.ts +221 -0
  37. package/src/modules/integration-picker/queries.ts +78 -0
  38. package/src/modules/integration-picker/types.ts +60 -0
  39. package/src/shared/categories.ts +55 -0
  40. package/src/shared/components/error.tsx +33 -0
  41. package/src/shared/components/errorBoundary.tsx +31 -0
  42. package/src/shared/components/loading.tsx +30 -0
  43. package/src/shared/components/success.tsx +33 -0
  44. package/src/shared/httpClient.ts +79 -0
  45. package/src/types/types.ts +1 -0
  46. package/tsconfig.json +19 -0
  47. package/vite.config.ts +11 -0
  48. package/yalc.lock +9 -0
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+
3
+ class ErrorBoundary extends React.Component<
4
+ { fallback: React.ReactNode; children: React.ReactNode },
5
+ { hasError: boolean }
6
+ > {
7
+ constructor(props: { fallback: React.ReactNode; children: React.ReactNode }) {
8
+ super(props);
9
+ this.state = { hasError: false };
10
+ }
11
+
12
+ static getDerivedStateFromError(_error: Error) {
13
+ // Update state so the next render will show the fallback UI.
14
+ return { hasError: true };
15
+ }
16
+
17
+ componentDidCatch(_error: Error, _info: React.ErrorInfo) {
18
+ // TODO: Log error to Sentry
19
+ }
20
+
21
+ render() {
22
+ if (this.state.hasError) {
23
+ // You can render any custom fallback UI
24
+ return this.props.fallback;
25
+ }
26
+
27
+ return this.props.children;
28
+ }
29
+ }
30
+
31
+ export default ErrorBoundary;
@@ -0,0 +1,30 @@
1
+ import {
2
+ Flex,
3
+ FlexAlign,
4
+ FlexDirection,
5
+ FlexGapSize,
6
+ FlexJustify,
7
+ Spinner,
8
+ Typography,
9
+ } from '@stackone/malachite';
10
+
11
+ export const Loading: React.FC<{
12
+ title: string;
13
+ description: string;
14
+ }> = ({ title, description }) => {
15
+ return (
16
+ <Flex
17
+ justify={FlexJustify.Center}
18
+ align={FlexAlign.Center}
19
+ direction={FlexDirection.Vertical}
20
+ gapSize={FlexGapSize.Small}
21
+ fullHeight
22
+ >
23
+ <Spinner size="xxxsmall" />
24
+ <Typography.Text fontWeight="bold" size="large">
25
+ {title}
26
+ </Typography.Text>
27
+ <Typography.SecondaryText>{description}</Typography.SecondaryText>
28
+ </Flex>
29
+ );
30
+ };
@@ -0,0 +1,33 @@
1
+ import {
2
+ CustomIcons,
3
+ Flex,
4
+ FlexAlign,
5
+ FlexDirection,
6
+ FlexGapSize,
7
+ FlexJustify,
8
+ Typography,
9
+ } from '@stackone/malachite';
10
+
11
+ interface SuccessProps {
12
+ integrationName: string;
13
+ }
14
+
15
+ const Success: React.FC<SuccessProps> = ({ integrationName }) => (
16
+ <Flex
17
+ justify={FlexJustify.Center}
18
+ align={FlexAlign.Center}
19
+ direction={FlexDirection.Vertical}
20
+ gapSize={FlexGapSize.Small}
21
+ fullHeight
22
+ >
23
+ <CustomIcons.CheckCircleFilledIcon />
24
+ <Typography.Text fontWeight="bold" size="large">
25
+ Connection Successful
26
+ </Typography.Text>
27
+ <Typography.SecondaryText>
28
+ Account successfully connected to {integrationName}
29
+ </Typography.SecondaryText>
30
+ </Flex>
31
+ );
32
+
33
+ export default Success;
@@ -0,0 +1,79 @@
1
+ export interface ErrorDetails {
2
+ message: string;
3
+ statusCode: number;
4
+ }
5
+
6
+ export const isErrorsDetails = (error: unknown): error is ErrorDetails => {
7
+ return (error as ErrorDetails).statusCode !== undefined;
8
+ };
9
+
10
+ export interface RequestParams {
11
+ url: string;
12
+ body?: Record<string, unknown>;
13
+ headers?: Record<string, string>;
14
+ requestFn?: typeof fetch;
15
+ logger?: Console;
16
+ }
17
+
18
+ const isTokenExpired = (response: Response): boolean => {
19
+ if (response?.status === 401 || response?.status === 403) {
20
+ return true;
21
+ }
22
+ return false;
23
+ };
24
+
25
+ export async function request<T>({
26
+ url,
27
+ body,
28
+ headers,
29
+ method,
30
+ requestFn = fetch,
31
+ logger = console,
32
+ }: RequestParams & { method: 'PATCH' | 'POST' | 'DELETE' | 'GET' }): Promise<T | null> {
33
+ try {
34
+ const response = await requestFn(url, {
35
+ method,
36
+ headers,
37
+ body: JSON.stringify(body),
38
+ });
39
+
40
+ if (isTokenExpired(response)) {
41
+ logger.warn('Token expired');
42
+ return null;
43
+ } else {
44
+ if (!response.ok) {
45
+ const errorResponse = (await response.json()) as ErrorDetails;
46
+ if (errorResponse && isErrorsDetails(errorResponse)) {
47
+ throw new Error(
48
+ JSON.stringify({
49
+ status: errorResponse.statusCode,
50
+ message: errorResponse.message,
51
+ }),
52
+ );
53
+ }
54
+ }
55
+
56
+ return (await response.json()) as T;
57
+ }
58
+ } catch (error) {
59
+ logger.error(`Error making request to ${url}`, error);
60
+
61
+ throw error;
62
+ }
63
+ }
64
+
65
+ export async function postRequest<T>(params: RequestParams): Promise<T | null> {
66
+ return request<T>({ ...params, method: 'POST' });
67
+ }
68
+
69
+ export async function patchRequest<T>(params: RequestParams): Promise<T | null> {
70
+ return request<T>({ ...params, method: 'PATCH' });
71
+ }
72
+
73
+ export async function deleteRequest<T>(params: RequestParams): Promise<T | null> {
74
+ return request<T>({ ...params, method: 'DELETE' });
75
+ }
76
+
77
+ export async function getRequest<T>(params: RequestParams): Promise<T | null> {
78
+ return request<T>({ ...params, method: 'GET' });
79
+ }
@@ -0,0 +1 @@
1
+ export type HubModes = 'integration-picker' | 'csv-importer';
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES6",
4
+ "module": "ESNext",
5
+ "jsx": "react-jsx",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "moduleResolution": "Node",
10
+ "declaration": false,
11
+ "outDir": "dist",
12
+ "sourceMap": true,
13
+ "jsxImportSource": "react",
14
+ "forceConsistentCasingInFileNames": true
15
+ },
16
+ "include": ["src"],
17
+ "exclude": ["**/*.d.ts"],
18
+ "files": ["src/index.ts"]
19
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,11 @@
1
+ import react from '@vitejs/plugin-react-swc';
2
+ import { defineConfig } from 'vite';
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ server: {
7
+ port: 3000,
8
+ // hmr: true,
9
+ },
10
+ root: 'dev',
11
+ });
package/yalc.lock ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "v1",
3
+ "packages": {
4
+ "@stackone/malachite": {
5
+ "signature": "b3621bd0c8195b6fd4451f514c72a618",
6
+ "file": true
7
+ }
8
+ }
9
+ }