nucleus-core-ts 0.9.851 → 0.9.852

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.
@@ -0,0 +1,6 @@
1
+ import type { IntegrationSource, IntegrationsActions } from '../types';
2
+ export type ConnectionExportProps = {
3
+ actions: IntegrationsActions;
4
+ source: IntegrationSource | null;
5
+ };
6
+ export declare function ConnectionExport({ actions, source }: ConnectionExportProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,104 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import { useIntegrationsStore } from '../store';
5
+ import { integrationsPageTheme as theme } from '../theme';
6
+ import { Notice } from './Primitives';
7
+ /**
8
+ * Taking one whole integration somewhere else.
9
+ *
10
+ * A connection is the address, the calls it makes, the parameters those calls
11
+ * take from each other, and the mappings that turn the answers into rows.
12
+ * Rebuilding that by hand in a second environment is hours of work and a fresh
13
+ * chance to get one field wrong in a way nobody notices until an import writes
14
+ * it. So it travels as one file.
15
+ *
16
+ * ## Why this is not next to Import
17
+ *
18
+ * It was, and it could not be pressed. Both buttons lived in the connection
19
+ * rail, and Export is only meaningful once a connection is CHOSEN — but
20
+ * choosing one replaces the rail with the connection's own screens, taking the
21
+ * button with it. So the button existed, was correct, and was reachable only in
22
+ * the state where it was disabled.
23
+ *
24
+ * Import belongs where there is nothing chosen yet, because that is when you
25
+ * bring one in. Export belongs here, on the connection being exported.
26
+ *
27
+ * The file carries NO credentials — deliberately, and it says so on both sides,
28
+ * because a connection that arrives looking configured and cannot authenticate
29
+ * is a confusing half hour otherwise.
30
+ */ /** A filename somebody can still recognise a week later. */ const fileNameFor = (slug)=>`integration-${slug || 'connection'}.json`;
31
+ export function ConnectionExport({ actions, source }) {
32
+ const store = useIntegrationsStore();
33
+ const [busy, setBusy] = useState(false);
34
+ const [note, setNote] = useState(null);
35
+ if (!source) return null;
36
+ const exportOne = ()=>{
37
+ setBusy(true);
38
+ setNote(null);
39
+ store.setError(null);
40
+ actions.exportConnection(source.id).then((document)=>{
41
+ setBusy(false);
42
+ if (!document) {
43
+ store.setError('The connection could not be exported.');
44
+ return;
45
+ }
46
+ // Written from the browser rather than served as a download, so the file
47
+ // never travels back through a URL somebody could share by accident.
48
+ const blob = new Blob([
49
+ JSON.stringify(document, null, 2)
50
+ ], {
51
+ type: 'application/json'
52
+ });
53
+ const url = URL.createObjectURL(blob);
54
+ const link = window.document.createElement('a');
55
+ link.href = url;
56
+ link.download = fileNameFor(source.slug);
57
+ link.click();
58
+ URL.revokeObjectURL(url);
59
+ setNote('Exported. Credentials are not in the file — enter them wherever it lands.');
60
+ }).catch((error)=>{
61
+ setBusy(false);
62
+ store.setError(error instanceof Error ? error.message : 'The request failed.');
63
+ });
64
+ };
65
+ return /*#__PURE__*/ _jsxs("section", {
66
+ className: theme.card.wrapper,
67
+ children: [
68
+ /*#__PURE__*/ _jsxs("header", {
69
+ className: theme.card.header,
70
+ children: [
71
+ /*#__PURE__*/ _jsx("h3", {
72
+ className: theme.card.title,
73
+ children: "Take this connection elsewhere"
74
+ }),
75
+ /*#__PURE__*/ _jsx("button", {
76
+ className: theme.button.secondary,
77
+ disabled: busy,
78
+ onClick: exportOne,
79
+ type: "button",
80
+ children: busy ? 'Exporting…' : 'Export'
81
+ })
82
+ ]
83
+ }),
84
+ /*#__PURE__*/ _jsxs("div", {
85
+ className: theme.card.body,
86
+ children: [
87
+ /*#__PURE__*/ _jsx("p", {
88
+ className: theme.field.hint,
89
+ children: "One file holding this connection, its calls and its mappings — enough to rebuild the whole integration in another installation. Bring it in there with Import, on the connections screen."
90
+ }),
91
+ /*#__PURE__*/ _jsx(Notice, {
92
+ title: "No secrets travel in the file",
93
+ tone: "info",
94
+ children: "Tokens, passwords and keys are left out on purpose. Whatever this connection authenticates with has to be entered again wherever the file lands."
95
+ }),
96
+ note ? /*#__PURE__*/ _jsx("p", {
97
+ className: theme.field.hint,
98
+ children: note
99
+ }) : null
100
+ ]
101
+ })
102
+ ]
103
+ });
104
+ }
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useIntegrationsStore } from '../store';
4
4
  import { integrationsPageTheme as theme } from '../theme';
5
5
  import { ConnectionDelete } from './ConnectionDelete';
6
+ import { ConnectionExport } from './ConnectionExport';
6
7
  import { ConnectionForm } from './ConnectionForm';
7
8
  import { ConnectionTest } from './ConnectionTest';
8
9
  import { CredentialFields } from './CredentialFields';
@@ -53,6 +54,10 @@ import { CredentialFields } from './CredentialFields';
53
54
  loading: waitingForRecord,
54
55
  source: source
55
56
  }),
57
+ /*#__PURE__*/ _jsx(ConnectionExport, {
58
+ actions: actions,
59
+ source: source
60
+ }),
56
61
  /*#__PURE__*/ _jsx(ConnectionDelete, {
57
62
  actions: actions,
58
63
  onDeleted: onDeleted,
@@ -6,7 +6,7 @@ import { useIntegrationsStore } from '../store';
6
6
  import { integrationsPageTheme } from '../theme';
7
7
  import { Notice } from './Primitives';
8
8
  /**
9
- * Taking a whole integration somewhere else, and bringing one back.
9
+ * Bringing a whole integration in from another installation.
10
10
  *
11
11
  * A connection is the connection, the calls it makes, the parameters those calls
12
12
  * take from each other, and the mappings that turn the answers into rows.
@@ -17,46 +17,20 @@ import { Notice } from './Primitives';
17
17
  * The file carries NO credentials — deliberately, and it says so on both sides,
18
18
  * because a connection that arrives looking configured and cannot authenticate
19
19
  * is a confusing half hour otherwise.
20
+ *
21
+ * Export used to sit beside this button and could never be pressed: it needs a
22
+ * connection to be CHOSEN, and choosing one replaces this rail with that
23
+ * connection's own screens. It now lives there, on the thing being exported —
24
+ * see ConnectionExport. Importing is the one that belongs here, because
25
+ * importing is what you do when you have nothing chosen yet.
20
26
  */ const theme = integrationsPageTheme;
21
27
  const messageOf = (error)=>error instanceof Error ? error.message : 'The request failed.';
22
- /** A filename somebody can still recognise a week later. */ const fileNameFor = (slug)=>`integration-${slug || 'connection'}.json`;
23
28
  export function ConnectionTransfer({ actions, onImported }) {
24
29
  const store = useIntegrationsStore();
25
30
  const fileRef = useRef(null);
26
31
  const [busy, setBusy] = useState(false);
27
32
  const [problems, setProblems] = useState([]);
28
33
  const [note, setNote] = useState(null);
29
- const selected = store.sources.find((source)=>source.id === store.selectedSourceId);
30
- const exportOne = ()=>{
31
- if (!selected) return;
32
- setBusy(true);
33
- setProblems([]);
34
- setNote(null);
35
- actions.exportConnection(selected.id).then((document)=>{
36
- setBusy(false);
37
- if (!document) {
38
- store.setError('The connection could not be exported.');
39
- return;
40
- }
41
- // Written from the browser rather than served as a download, so the file
42
- // never travels back through a URL somebody could share by accident.
43
- const blob = new Blob([
44
- JSON.stringify(document, null, 2)
45
- ], {
46
- type: 'application/json'
47
- });
48
- const url = URL.createObjectURL(blob);
49
- const link = window.document.createElement('a');
50
- link.href = url;
51
- link.download = fileNameFor(selected.slug);
52
- link.click();
53
- URL.revokeObjectURL(url);
54
- setNote('Exported. Credentials are not in the file — enter them wherever it lands.');
55
- }).catch((error)=>{
56
- setBusy(false);
57
- store.setError(messageOf(error));
58
- });
59
- };
60
34
  const importFile = (file)=>{
61
35
  setBusy(true);
62
36
  setProblems([]);
@@ -97,25 +71,12 @@ export function ConnectionTransfer({ actions, onImported }) {
97
71
  return /*#__PURE__*/ _jsxs("section", {
98
72
  className: "flex flex-col gap-2",
99
73
  children: [
100
- /*#__PURE__*/ _jsxs("div", {
101
- className: "grid grid-cols-2 gap-2",
102
- children: [
103
- /*#__PURE__*/ _jsx("button", {
104
- className: cn(theme.button.secondary, 'w-full justify-center whitespace-nowrap'),
105
- disabled: busy || !selected,
106
- onClick: exportOne,
107
- title: selected ? `Export ${selected.name} — its calls and mappings, without any credential` : 'Choose a connection to export',
108
- type: "button",
109
- children: busy ? 'Working…' : 'Export'
110
- }),
111
- /*#__PURE__*/ _jsx("button", {
112
- className: cn(theme.button.secondary, 'w-full justify-center whitespace-nowrap'),
113
- disabled: busy,
114
- onClick: ()=>fileRef.current?.click(),
115
- type: "button",
116
- children: "Import"
117
- })
118
- ]
74
+ /*#__PURE__*/ _jsx("button", {
75
+ className: cn(theme.button.secondary, 'w-full justify-center whitespace-nowrap'),
76
+ disabled: busy,
77
+ onClick: ()=>fileRef.current?.click(),
78
+ type: "button",
79
+ children: busy ? 'Working…' : 'Import a connection file'
119
80
  }),
120
81
  /*#__PURE__*/ _jsx("input", {
121
82
  accept: "application/json,.json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nucleus-core-ts",
3
- "version": "0.9.851",
3
+ "version": "0.9.852",
4
4
  "description": "Production-ready, enterprise-grade TypeScript framework for building multi-tenant APIs",
5
5
  "author": "Hidayet Can Özcan <hidayetcan@gmail.com>",
6
6
  "license": "SEE LICENSE IN LICENSE",