datocms-plugin-record-bin 2.0.0 → 3.0.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.
- package/README.md +113 -11
- package/build/assets/index-BnrW9Ts8.js +15 -0
- package/build/assets/index-aWCW2c0n.css +1 -0
- package/build/index.html +13 -1
- package/index.html +12 -0
- package/package.json +24 -18
- package/src/entrypoints/BinOutlet.tsx +262 -37
- package/src/entrypoints/ConfigScreen.tsx +939 -38
- package/src/entrypoints/ErrorModal.tsx +86 -2
- package/src/index.tsx +73 -28
- package/src/react-app-env.d.ts +1 -1
- package/src/types/types.ts +36 -8
- package/src/utils/binCleanup.test.ts +107 -0
- package/src/utils/binCleanup.ts +71 -23
- package/src/utils/debugLogger.ts +27 -0
- package/src/utils/deployProviders.test.ts +33 -0
- package/src/utils/deployProviders.ts +28 -0
- package/src/utils/getDeploymentUrlFromParameters.test.ts +26 -0
- package/src/utils/getDeploymentUrlFromParameters.ts +21 -0
- package/src/utils/getRuntimeMode.test.ts +57 -0
- package/src/utils/getRuntimeMode.ts +23 -0
- package/src/utils/lambdaLessCapture.test.ts +218 -0
- package/src/utils/lambdaLessCapture.ts +160 -0
- package/src/utils/lambdaLessCleanup.test.ts +125 -0
- package/src/utils/lambdaLessCleanup.ts +69 -0
- package/src/utils/lambdaLessRestore.test.ts +248 -0
- package/src/utils/lambdaLessRestore.ts +159 -0
- package/src/utils/recordBinModel.ts +108 -0
- package/src/utils/recordBinPayload.test.ts +103 -0
- package/src/utils/recordBinPayload.ts +136 -0
- package/src/utils/recordBinWebhook.test.ts +253 -0
- package/src/utils/recordBinWebhook.ts +305 -0
- package/src/utils/render.tsx +17 -8
- package/src/utils/restoreError.test.ts +112 -0
- package/src/utils/restoreError.ts +221 -0
- package/src/utils/verifyLambdaHealth.test.ts +248 -0
- package/src/utils/verifyLambdaHealth.ts +422 -0
- package/vite.config.ts +11 -0
- package/build/asset-manifest.json +0 -13
- package/build/static/css/main.10f29737.css +0 -2
- package/build/static/css/main.10f29737.css.map +0 -1
- package/build/static/js/main.53795e3b.js +0 -3
- package/build/static/js/main.53795e3b.js.LICENSE.txt +0 -47
- package/build/static/js/main.53795e3b.js.map +0 -1
- package/src/entrypoints/InstallationModal.tsx +0 -107
- package/src/entrypoints/PreInstallConfig.tsx +0 -28
- package/src/utils/attemptVercelInitialization.ts +0 -16
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-display:auto;font-family:colfax-web;font-style:normal;font-weight:700;src:url(https://use.typekit.net/af/522c51/00000000000000003b9acde6/27/l?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n5&v=3) format("woff2"),url(https://use.typekit.net/af/522c51/00000000000000003b9acde6/27/d?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n5&v=3) format("woff"),url(https://use.typekit.net/af/522c51/00000000000000003b9acde6/27/a?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n5&v=3) format("opentype")}@font-face{font-display:auto;font-family:colfax-web;font-style:italic;font-weight:700;src:url(https://use.typekit.net/af/4e71b3/00000000000000003b9acde7/27/l?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i5&v=3) format("woff2"),url(https://use.typekit.net/af/4e71b3/00000000000000003b9acde7/27/d?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i5&v=3) format("woff"),url(https://use.typekit.net/af/4e71b3/00000000000000003b9acde7/27/a?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i5&v=3) format("opentype")}@font-face{font-display:auto;font-family:colfax-web;font-style:normal;font-weight:500;src:url(https://use.typekit.net/af/522c51/00000000000000003b9acde6/27/l?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n5&v=3) format("woff2"),url(https://use.typekit.net/af/522c51/00000000000000003b9acde6/27/d?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n5&v=3) format("woff"),url(https://use.typekit.net/af/522c51/00000000000000003b9acde6/27/a?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n5&v=3) format("opentype")}@font-face{font-display:auto;font-family:colfax-web;font-style:italic;font-weight:500;src:url(https://use.typekit.net/af/4e71b3/00000000000000003b9acde7/27/l?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i5&v=3) format("woff2"),url(https://use.typekit.net/af/4e71b3/00000000000000003b9acde7/27/d?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i5&v=3) format("woff"),url(https://use.typekit.net/af/4e71b3/00000000000000003b9acde7/27/a?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i5&v=3) format("opentype")}@font-face{font-display:auto;font-family:colfax-web;font-style:normal;font-weight:400;src:url(https://use.typekit.net/af/bac079/00000000000000003b9acde4/27/l?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n4&v=3) format("woff2"),url(https://use.typekit.net/af/bac079/00000000000000003b9acde4/27/d?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n4&v=3) format("woff"),url(https://use.typekit.net/af/bac079/00000000000000003b9acde4/27/a?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=n4&v=3) format("opentype")}@font-face{font-display:auto;font-family:colfax-web;font-style:italic;font-weight:400;src:url(https://use.typekit.net/af/c1cc04/00000000000000003b9acde5/27/l?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i4&v=3) format("woff2"),url(https://use.typekit.net/af/c1cc04/00000000000000003b9acde5/27/d?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i4&v=3) format("woff"),url(https://use.typekit.net/af/c1cc04/00000000000000003b9acde5/27/a?primer=f592e0a4b9356877842506ce344308576437e4f677d7c9b78ca2162e6cad991a&fvd=i4&v=3) format("opentype")}html{font-size:16px;height:auto}body,html{margin:0;padding:0}._button_474wk_1{-webkit-appearance:none;-moz-appearance:none;background-color:transparent;border:0;border-radius:4px;box-sizing:border-box;color:var(--base-body-color);cursor:pointer;display:inline-block;font-family:inherit;font-weight:var(--font-weight-bold);line-height:inherit;opacity:1;text-decoration:none;transition:all .3s var(--material-ease);vertical-align:middle;white-space:nowrap}._button_474wk_1:focus,._button_474wk_1:hover{opacity:.8}._button_474wk_1:active{opacity:.7}._disabled_474wk_30{cursor:not-allowed}._buttonType-muted_474wk_34{background-color:var(--light-color);color:var(--accent-color)}._buttonType-muted_474wk_34._disabled_474wk_30{background-color:var(--light-bg-color);color:#0003}._buttonType-muted_474wk_34._disabled_474wk_30:active,._buttonType-muted_474wk_34._disabled_474wk_30:focus,._buttonType-muted_474wk_34._disabled_474wk_30:hover{color:#0003}._buttonType-primary_474wk_50{background-color:var(--accent-color);color:#fff}._buttonType-primary_474wk_50:active,._buttonType-primary_474wk_50:focus,._buttonType-primary_474wk_50:hover{color:#fff}._buttonType-primary_474wk_50._disabled_474wk_30{background-color:var(--disabled-bg-color);color:#0003}._buttonType-primary_474wk_50._disabled_474wk_30:active,._buttonType-primary_474wk_50._disabled_474wk_30:focus,._buttonType-primary_474wk_50._disabled_474wk_30:hover{color:#0003}._buttonType-negative_474wk_71,._buttonType-negative_474wk_71:active,._buttonType-negative_474wk_71:focus,._buttonType-negative_474wk_71:hover{background-color:var(--alert-color);color:#fff}._buttonType-negative_474wk_71._disabled_474wk_30{background-color:var(--disabled-bg-color);color:#0003}._buttonSize-xxs_474wk_88{font-size:1em;padding:.5em .8em}._buttonSize-xs_474wk_93{font-size:1em;padding:.6em .8em}._buttonSize-s_474wk_98{font-size:1em;padding:.7em 1em}._buttonSize-m_474wk_103{font-size:1.1em;padding:.7em 1em}._buttonSize-l_474wk_108{font-size:1.2em;padding:.7em 1em}._buttonSize-xl_474wk_113{font-size:1.2em;padding:1em}._fullWidth_474wk_118{display:block;text-align:center;width:100%}._button__leftIcon_474wk_124,._button__rightIcon_474wk_125{display:inline-block;line-height:.6;vertical-align:middle}._button__leftIcon_474wk_124 svg,._button__rightIcon_474wk_125 svg{fill:var(--accent-color)}._button__leftIcon_474wk_124{margin-right:.5em}._button__leftIcon_474wk_124:last-child{margin-right:0}._button__rightIcon_474wk_125{margin-left:.5em}._button__rightIcon_474wk_125:first-child{margin-left:0}._Button_1h1w1_1{justify-column:center;align-items:center;-webkit-appearance:none;-moz-appearance:none;background-color:#fff;border:0;border-right:1px solid var(--border-color);border:1px solid var(--border-color);border-left-width:0;box-sizing:border-box;color:var(--base-body-color);color:rgba(var(--base-body-color-rgb-components,.6));cursor:pointer;display:flex;font-family:inherit;font-size:inherit;line-height:inherit;padding:7px 13px}._Button_1h1w1_1:hover{background-color:var(--light-bg-color)}._Button_1h1w1_1 svg{fill:var(--light-body-color)}._Button--s_1h1w1_32{padding:3px 10px}._Button--disabled_1h1w1_36{color:var(--light-body-color);cursor:not-allowed}._Button--disabled_1h1w1_36:hover{background:#fff}._Button--selected_1h1w1_45{background-color:var(--accent-color);border-color:var(--accent-color);color:#fff}._Button--selected_1h1w1_45 svg{fill:#fff}._Button--selected_1h1w1_45:hover{background-color:var(--accent-color)}._Button--selected_1h1w1_45._Button--disabled_1h1w1_36,._Button--selected_1h1w1_45:hover{background-color:rgba(var(--accent-color-rgb-components),.8);border-color:rgba(var(--accent-color-rgb-components),.8)}._Button_1h1w1_1:first-child{border-left-width:1px;border-radius:4px 0 0 4px}._Button_1h1w1_1:last-child{border-radius:0 4px 4px 0}._Group_10mj4_1{align-items:stretch;background-color:#fff;display:flex;overflow:hidden}._themeVariables_2dr1w_1{--base-body-color-rgb-components:52,54,58;--base-body-color:rgb(var(--base-body-color-rgb-components));--light-body-color-rgb-components:132,132,132;--light-body-color:rgb(var(--light-body-color-rgb-components));--placeholder-body-color-rgb-components:198,198,198;--placeholder-body-color:rgb(var(--placeholder-body-color-rgb-components));--light-bg-color-rgb-components:245,245,245;--light-bg-color:rgb(var(--light-bg-color-rgb-components));--lighter-bg-color-rgb-components:248,248,248;--lighter-bg-color:rgb(var(--lighter-bg-color-rgb-components));--disabled-bg-color-rgb-components:237,237,237;--disabled-bg-color:rgb(var(--disabled-bg-color-rgb-components));--border-color-rgb-components:240,240,240;--border-color:rgb(var(--border-color-rgb-components));--darker-border-color-rgb-components:215,215,215;--darker-border-color:rgb(var(--darker-border-color-rgb-components));--alert-color-rgb-components:255,94,73;--alert-color:rgb(var(--alert-color-rgb-components));--warning-color-rgb-components:255,215,0;--warning-color:rgb(var(--warning-color-rgb-components));--notice-color-rgb-components:70,215,0;--notice-color:rgb(var(--notice-color-rgb-components));--warning-bg-color-rgb-components:255,255,229;--warning-bg-color:rgb(var(--warning-bg-color-rgb-components));--add-color-rgb-components:76,176,109;--add-color:rgb(var(--add-color-rgb-components));--remove-color-rgb-components:235,87,106;--remove-color:rgb(var(--remove-color-rgb-components));--base-font-family:"colfax-web","Roboto","Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;--monospaced-font-family:"Roboto Mono","Menlo","Bitstream Vera Sans Mono",Consolas,Courier,monospace;--font-weight-bold:500;--spacing-s:.375rem;--spacing-m:.75rem;--spacing-l:1.5rem;--spacing-xl:2.25rem;--spacing-xxl:3.75rem;--spacing-xxxl:6rem;--negative-spacing-s:-.375rem;--negative-spacing-m:-.75rem;--negative-spacing-l:-1.5rem;--negative-spacing-xl:-2.25rem;--negative-spacing-xxl:-3.75rem;--negative-spacing-xxxl:-6rem;--font-size-xxs:.6875rem;--font-size-xs:.75rem;--font-size-s:.875rem;--font-size-m:.9375rem;--font-size-l:1.0625rem;--font-size-xl:1.1875rem;--font-size-xxl:1.5625rem;--font-size-xxxl:1.875rem;--material-ease:cubic-bezier(.55,0,.1,1);--inertial-ease:cubic-bezier(.19,1,.22,1)}._canvas_2dr1w_70{-webkit-text-size-adjust:100%;text-rendering:optimizeLegibility;color:var(--base-body-color);font-family:var(--base-font-family);font-size:var(--font-size-m);line-height:1.5}._inspector_u6041_1{margin:var(--spacing-l) 0}._panel_u6041_5{border-bottom:1px solid var(--border-color)}._panelHandle_u6041_9{all:inherit;background:var(--light-bg-color);border:0;box-sizing:border-box;cursor:pointer;display:block;font-weight:var(--font-weight-bold);padding:5px 10px;width:100%}._panelHandle_u6041_9:hover{background:var(--lighter-bg-color)}._panelBody_u6041_25{border-left:1px solid var(--border-color);border-right:1px solid var(--border-color);padding:20px}._groupDescription_u6041_31{font-size:var(--font-size-s);line-height:1.2;margin-bottom:20px}._propertyGroup_u6041_37{border:1px solid var(--border-color);border-radius:5px}._propertyOrMethod_u6041_42{border-bottom:1px solid var(--border-color);line-height:1.2}._propertyOrMethod_u6041_42 p{margin:0}._propertyOrMethodBody_u6041_51{padding:15px}._propertyOrMethodExample_u6041_55{position:relative}._propertyOrMethodExample_u6041_55 pre{background:var(--light-bg-color);font-size:.8em;margin:0;max-height:240px;overflow:auto;padding:15px}._propertyOrMethodName_u6041_68{color:var(--light-body-color);display:block;font-family:var(--monospaced-font-family);font-size:.9em;font-weight:700;margin-bottom:5px;text-decoration:none}._propertyOrMethodName_u6041_68:hover{text-decoration:underline}._propertyOrMethodExampleActions_u6041_82{background:#fff;display:flex;padding:15px}._propertyOrMethodExampleActions_u6041_82>*{margin-right:10px}._fieldError_qi0xk_1{color:var(--alert-color);font-size:var(--font-size-xs);line-height:1.2;margin-top:var(--spacing-s)}._FieldGroup_uz9ju_1{display:block}._FieldGroup__item_uz9ju_5{display:block;margin-bottom:var(--spacing-l)}._FieldGroup__item_uz9ju_5:last-child{margin-bottom:0}._fieldHint_1avon_1{color:var(--light-body-color);font-size:var(--font-size-xs);line-height:1.2;margin-top:var(--spacing-s)}._fieldHint_1avon_1 a{color:inherit}._fieldHint_1avon_1 a:hover{text-decoration:none}._Form_5qspp_1,._Form__item_5qspp_5{display:block}._Form__item_5qspp_5:last-child{margin-bottom:0}._Form__item--default_5qspp_13{margin-bottom:var(--spacing-l)}._Form__item--condensed_5qspp_17{margin-bottom:var(--spacing-m)}._formLabel_tcjrv_1{align-items:center;color:var(--light-body-color);display:flex;margin-bottom:var(--spacing-s)}._formLabel_tcjrv_1:hover ._formLabel__code_tcjrv_8{opacity:1}._formLabel--error_tcjrv_14{color:var(--alert-color)}._formLabel__label_tcjrv_18{flex:1}._formLabel__code_tcjrv_8{font-family:var(--monospaced-font-family);font-size:.95em;opacity:0;position:absolute;transition:opacity .2s var(--material-ease)}._hotKey_1eko8_1{align-items:center;display:inline-flex;gap:15px}._label_1eko8_7{align-items:center;display:flex}._keys_1eko8_12{align-items:center;display:inline-flex;gap:4px}._hotKeyKey_1eko8_18{background:var(--light-color);border-radius:3px;padding:5px 8px}._Section_zh95u_1{position:relative}._Section--highlighted_zh95u_5:before{animation:_pageContentSectionHighligh_zh95u_1 4s ease-in-out .25s forwards;border-radius:4px;box-shadow:0 0 0 4px var(--accent-color);content:"";inset:-20px -30px;pointer-events:none;position:absolute;z-index:10}._Section__header_zh95u_19{margin-bottom:var(--spacing-l);margin-left:var(--negative-spacing-l);margin-right:var(--negative-spacing-l);position:relative}._Section__header_zh95u_19:before{background-color:var(--border-color);content:"";display:block;height:1px;left:0;position:absolute;right:0;top:50%;z-index:1}._Section__title_zh95u_38{align-items:center;background-color:#fff;display:inline-flex;font-size:var(--font-size-l);font-weight:var(--font-weight-bold);margin-left:var(--spacing-m);margin-right:var(--spacing-l);padding-left:var(--spacing-m);padding-right:var(--spacing-m);position:relative;z-index:2}._Section__arrow_zh95u_55{all:initial;align-self:stretch;cursor:pointer;margin-right:.3em;width:15px}._Section__arrow_zh95u_55:before{border-bottom:6px solid transparent;border-left:6px solid var(--base-body-color);border-top:6px solid transparent;content:"";height:0;left:14px;margin-top:-6px;position:absolute;top:50%;transform-origin:50% 50%;transition:transform .2s ease-out;width:0}._Section__arrow_zh95u_55:hover:before{opacity:.7}._Section__arrow--is-open_zh95u_82:before{transform:rotate(90deg)}@keyframes _pageContentSectionHighligh_zh95u_1{0%{box-shadow:0 0 0 4px var(--accent-color),0 0 0 4px rgba(var(--accent-color-rgb-components),.7)}15%{box-shadow:0 0 0 4px var(--accent-color),0 0 0 80px transparent}75%{box-shadow:0 0 0 4px var(--accent-color),0 0 0 80px transparent}to{box-shadow:0 0 0 4px transparent,0 0 0 80px transparent}}._SidebarPanel_4uwco_1{border-bottom:1px solid var(--border-color)}._SidebarPanel__header_4uwco_5{align-items:center;-webkit-appearance:none;-moz-appearance:none;background-color:#fff;background-color:var(--light-bg-color);border:0;box-sizing:border-box;color:var(--base-body-color);cursor:pointer;display:flex;font-family:inherit;font-size:inherit;line-height:inherit;padding:0;text-align:left;-webkit-user-select:none;user-select:none;width:100%}._SidebarPanel__header_4uwco_5:focus,._SidebarPanel__header_4uwco_5:hover{background-color:var(--lighter-bg-color)}._SidebarPanel__header__title_4uwco_30{flex:1;font-weight:500;padding:0 20px}._SidebarPanel__header__chevron_4uwco_36{align-items:center;display:flex;padding:13px 15px}._SidebarPanel__content_4uwco_42{background-color:#fff;padding:20px}._SidebarPanel__content--no-padding_4uwco_47{padding:0}._Spinner--inline_oumod_1{display:inline-block;position:relative;vertical-align:middle}._Spinner--centered_oumod_7{left:50%;position:absolute;top:50%}._Spinner__bar_oumod_13{animation:_Spinner__spin_oumod_1 1.2s linear infinite;background-color:var(--light-body-color);height:14%;left:-20%;position:absolute;top:0;width:40%}@keyframes _Spinner__spin_oumod_1{0%{opacity:1}to{opacity:.15}}._switchField__flex_16z4j_1{align-items:center;display:flex}._switchField__switchInput_16z4j_6{width:55px}._switchField__label_16z4j_10{color:var(--base-body-color);flex:1;line-height:1.1;line-height:20px;margin-bottom:0;pointer-events:none;-moz-user-select:text;-ms-user-select:text;-webkit-user-select:text;user-select:text}._switchField__below_16z4j_22{margin-left:55px;margin-top:var(--spacing-s)}._switchInput__inner_1knbg_1{color:#fff;font-size:12px;left:24px;position:absolute}._switchInput_1knbg_1{background-color:#ccc;border:1px solid #ccc;border-radius:20px;box-sizing:border-box;cursor:pointer;display:inline-block;height:22px;line-height:20px;position:relative;transition:all .3s cubic-bezier(.35,0,.25,1);vertical-align:middle;width:44px}._switchInput_1knbg_1:after{animation-duration:.3s;animation-name:_switchInput__off_1knbg_1;animation-timing-function:cubic-bezier(.35,0,.25,1);background-color:#fff;border-radius:50%;box-shadow:0 2px 5px #00000042;content:" ";cursor:pointer;height:18px;left:2px;position:absolute;top:1px;transform:scale(1);transition:left .3s cubic-bezier(.35,0,.25,1);width:18px}._switchInput_1knbg_1:focus:after,._switchInput_1knbg_1:hover{animation-name:_switchInput__on_1knbg_1;transform:scale(1.1)}._switchInput__checked_1knbg_47{background-color:var(--accent-color);border:1px solid var(--accent-color)}._switchInput__checked_1knbg_47 ._switchInput__inner_1knbg_1{left:6px}._switchInput__checked_1knbg_47:after{left:22px}._switchInput__disabled_1knbg_60{background:#ccc;border-color:#ccc;cursor:no-drop}._switchInput__disabled_1knbg_60:after{animation-name:_none_1knbg_1;background:#9e9e9e;cursor:no-drop}._switchInput__disabled_1knbg_60:focus:after,._switchInput__disabled_1knbg_60:hover{animation-name:_none_1knbg_1;transform:scale(1)}@keyframes _switchInput__on_1knbg_1{0%{transform:scale(1)}50%{transform:scale(1.25)}to{transform:scale(1.1)}}@keyframes _switchInput__off_1knbg_1{0%{transform:scale(1.1)}to{transform:scale(1)}}._TextInput_x2oj2_1{appearance:none;background-image:none;border:1px solid var(--border-color);border-radius:0;box-sizing:border-box;display:block;font-family:inherit;font-size:var(--font-size-m);padding:10px;resize:none;transition:border .2s var(--material-ease);width:100%}._TextInput_x2oj2_1::placeholder{color:var(--placeholder-body-color)}._TextInput_x2oj2_1:hover{border-color:var(--darker-border-color)}._TextInput_x2oj2_1:focus{border-color:var(--accent-color);box-shadow:0 0 0 3px var(--semi-transparent-accent-color);outline:0}._TextInput--monospaced_x2oj2_30{font-family:var(--monospaced-font-family);font-size:var(--font-size-s)}._TextInput--disabled_x2oj2_35{background:var(--lighter-bg-color);border-color:var(--border-color);color:var(--light-body-color)}._TextInput--error_x2oj2_41,._TextInput--error_x2oj2_41:focus,._TextInput--error_x2oj2_41:hover{border-color:var(--alert-color)}._TextInput--error_x2oj2_41:focus{box-shadow:0 0 0 3px rgba(var(--alert-color-rgb-components),.2)}._TextareaInput_1wnu9_1{appearance:none;background-image:none;border:1px solid var(--border-color);border-radius:0;box-sizing:border-box;display:block;font-family:inherit;font-size:var(--font-size-m);padding:10px;resize:none;transition:border .2s var(--material-ease);width:100%}._TextareaInput_1wnu9_1::placeholder{color:var(--placeholder-body-color)}._TextareaInput_1wnu9_1:hover{border-color:var(--darker-border-color)}._TextareaInput_1wnu9_1:focus{border-color:var(--accent-color);box-shadow:0 0 0 3px var(--semi-transparent-accent-color);outline:0}._TextareaInput--monospaced_1wnu9_30{font-family:var(--monospaced-font-family);font-size:var(--font-size-s)}._TextareaInput--disabled_1wnu9_35{background:var(--lighter-bg-color);border-color:var(--border-color);color:var(--light-body-color)}._TextareaInput--error_1wnu9_41,._TextareaInput--error_1wnu9_41:focus,._TextareaInput--error_1wnu9_41:hover{border-color:var(--alert-color)}._TextareaInput--error_1wnu9_41:focus{box-shadow:0 0 0 3px rgba(var(--alert-color-rgb-components),.2)}._Button_fy6g6_1{align-items:center;-webkit-appearance:none;-moz-appearance:none;background-color:transparent;border:0;border-left:1px solid var(--border-color);border-right:1px solid var(--border-color);box-sizing:border-box;color:var(--base-body-color);cursor:pointer;display:flex;font-family:inherit;justify-content:center;line-height:inherit;min-height:49px;padding:0;width:49px}._Button_fy6g6_1:focus,._Button_fy6g6_1:hover{background-color:var(--light-bg-color)}._Button_fy6g6_1:first-child{border-left:0}._Button_fy6g6_1:last-child{border-right:0}@media screen and (min-width:380px){._Button_fy6g6_1{min-height:59px;width:59px}._Button_fy6g6_1 svg{font-size:20px}}._Stack_1nnzo_1{align-items:center;display:flex;flex:1;flex-direction:row;justify-content:center;padding:10px 15px}._Stack--s_1nnzo_10{padding-bottom:var(--spacing-s);padding-top:var(--spacing-s)}._Stack--l_1nnzo_15{padding-left:var(--spacing-xl);padding-right:var(--spacing-xl)}._Title_1dx5n_1{font-size:var(--font-size-l);font-weight:500;line-height:1.1;margin-right:15px}@media screen and (min-width:380px){._Title_1dx5n_1{font-size:var(--font-size-xl)}}._Toolbar_1cwb8_1{align-items:stretch;border-bottom:1px solid var(--border-color);border-top:1px solid var(--border-color);display:flex;position:relative}._Toolbar_1cwb8_1:first-child{border-top-width:0}._Toolbar_1cwb8_1:last-child{border-bottom-width:0}._tooltip_3z5rn_1{word-wrap:break-word;background:#fff;border-radius:4px;box-shadow:0 1px 9px #0003;-webkit-hyphens:auto;hyphens:auto;max-width:400px;overflow-wrap:break-word;padding:10px 15px}._Dropdown_nie0g_1{position:relative}._Dropdown__spacer_nie0g_5{inset:0;pointer-events:none;position:absolute}._Dropdown__menu__search_nie0g_11{border-bottom:1px solid var(--border-color);padding:7px}._Dropdown__menu__search__input_nie0g_16{appearance:none;background-image:none;border:1px solid var(--border-color);border-radius:3px;box-sizing:border-box;display:block;font-family:inherit;font-size:.9em;padding:8px;resize:none;transition:border .2s var(--material-ease);width:100%}._Dropdown__menu__search__input_nie0g_16::placeholder{color:var(--placeholder-body-color)}._Dropdown__menu__search__input_nie0g_16:hover{border-color:var(--darker-border-color)}._Dropdown__menu__search__input_nie0g_16:focus{border-color:var(--accent-color);box-shadow:0 0 0 3px var(--semi-transparent-accent-color);outline:0}._Dropdown__menu-container_nie0g_45{position:fixed;visibility:hidden}._Dropdown__menu_nie0g_11{background-color:#fff;border-radius:4px;box-shadow:0 3px 10px #0003;margin-bottom:var(--spacing-xl);margin-top:10px;min-width:200px;padding:1px 0;text-align:initial}._Dropdown__menu__inner_nie0g_61{margin:7px 0}._Dropdown__menu__group__title_nie0g_65{background-color:var(--light-bg-color);color:var(--light-body-color);font-size:var(--font-size-xs);padding:5px 15px 3px;text-transform:uppercase}._Dropdown__menu__group__content_nie0g_73{margin:8px 0}._Dropdown__menu__text_nie0g_77{color:var(--light-body-color);display:block;line-height:1.2;padding:4px 15px;position:relative;text-align:left}._Dropdown__menu__option_nie0g_86{align-items:center;color:var(--base-body-color);display:flex;padding:4px 15px;position:relative;text-align:left;text-decoration:none;white-space:nowrap}._Dropdown__menu__option_nie0g_86:focus,._Dropdown__menu__option_nie0g_86:hover{background-color:var(--light-bg-color)}._Dropdown__menu__option_nie0g_86>a{color:inherit;display:block;text-decoration:none}._Dropdown__menu__option--is-selected_nie0g_108{background-color:var(--light-bg-color)}._Dropdown__menu__option--is-disabled_nie0g_112{opacity:.5}._Dropdown__menu__option--is-disabled_nie0g_112 ._Dropdown__menu__option__content_nie0g_115{cursor:not-allowed}._Dropdown__menu__option--is-dangerous_nie0g_120{color:var(--alert-color)}._Dropdown__menu__option--is-dangerous_nie0g_120 svg{fill:var(--alert-color)}._Dropdown__menu__option--is-dangerous_nie0g_120:focus,._Dropdown__menu__option--is-dangerous_nie0g_120:hover{background-color:var(--alert-color);color:#fff}._Dropdown__menu__option--is-dangerous_nie0g_120:focus svg,._Dropdown__menu__option--is-dangerous_nie0g_120:hover svg{fill:#fff}._Dropdown__menu__option--is-active_nie0g_138{font-weight:500}._Dropdown__menu__option--is-active_nie0g_138:focus,._Dropdown__menu__option--is-active_nie0g_138:hover{background-color:none}._Dropdown__menu__option--is-invalid_nie0g_151,._Dropdown__menu__option--is-valid_nie0g_147{padding-left:35px}._Dropdown__menu__option--is-invalid_nie0g_151:before{background-color:var(--alert-color);border-radius:4px;content:"";font-size:12px;height:8px;left:15px;position:absolute;top:50%;transform:translateY(-50%);width:8px}._Dropdown__menu__option__content_nie0g_115{-webkit-appearance:none;-moz-appearance:none;background-color:transparent;border:0;box-sizing:border-box;color:inherit;cursor:pointer;flex:1;font-family:inherit;font-size:inherit;font-weight:inherit;line-height:inherit;padding:0;text-align:left}._Dropdown__menu__option__content_nie0g_115>svg{fill:var(--light-body-color);color:var(--light-body-color);display:inline-block;font-size:13px;padding-right:8px;vertical-align:middle}._Dropdown__menu__option__icons_nie0g_194{align-items:center;display:flex;padding-left:15px}._Dropdown__menu__option__icon_nie0g_194{-webkit-appearance:none;-moz-appearance:none;background-color:transparent;border:0;box-sizing:border-box;color:var(--base-body-color);color:var(--light-body-color);cursor:pointer;display:inline-block;font-family:inherit;font-size:inherit;font-size:13px;line-height:inherit;line-height:10px;opacity:0;padding:3px;position:relative;top:-1px;transition:transform .1s ease-in-out;width:100%;width:auto}._Dropdown__menu__option_nie0g_86:focus ._Dropdown__menu__option__icon_nie0g_194,._Dropdown__menu__option_nie0g_86:hover ._Dropdown__menu__option__icon_nie0g_194{opacity:1}._Dropdown__menu__option__icon_nie0g_194:focus,._Dropdown__menu__option__icon_nie0g_194:hover{transform:scale(1.2)}._Dropdown__menu__option__icon_nie0g_194 svg{fill:var(--light-body-color)}._Dropdown__menu__option__icon--delete_nie0g_241{color:var(--alert-color)}._Dropdown__menu__option__icon--delete_nie0g_241 svg{fill:var(--alert-color)}._Dropdown__menu__separator_nie0g_248{background-color:var(--border-color);height:1px;margin:8px 0}._Dropdown__menu_nie0g_11{overflow-y:auto}._SplitViewPane_1cl1f_1{height:100%;overflow-y:auto;position:absolute;width:100%}._SplitViewSash_tds51_1{align-items:center;background-color:rgba(var(--light-color-components),0);display:flex;height:100%;justify-content:center;position:absolute;top:0;transition:background-color .2s .15s;width:100%;z-index:2}._SplitViewSash--dragging_tds51_15,._SplitViewSash_tds51_1:hover{background-color:var(--light-color)}._SplitViewSash--dragging_tds51_15:has(._SplitViewSash__content_tds51_19:hover),._SplitViewSash_tds51_1:hover:has(._SplitViewSash__content_tds51_19:hover){background-color:transparent}._SplitViewSash--no-resize_tds51_24{pointer-events:none}._SplitViewSash--vertical_tds51_28{cursor:col-resize}._SplitViewSash--horizontal_tds51_32{cursor:row-resize}._SplitViewSash__content_tds51_19{cursor:pointer;left:50%;padding:15px 0;pointer-events:auto;position:absolute;top:50%;transform:translate(-50%,-50%)}._SplitViewSash__content__button_tds51_46{align-items:center;background:#fff;border:1px solid var(--border-color);border-radius:6px;color:var(--light-body-color);display:flex;font-size:10px;height:20px;justify-content:center;width:20px;z-index:2}._SplitViewSash__content__button_tds51_46 svg{fill:currentColor;display:block}._SplitViewSash__content_tds51_19:hover ._SplitViewSash__content__button_tds51_46{background:var(--light-bg-color);color:var(--base-body-color)}._SplitView_1oi17_1{flex:1;height:100%;position:relative;width:100%}._SplitView--dragging_1oi17_8._SplitView--vertical_1oi17_8{cursor:col-resize}._SplitView--dragging_1oi17_8._SplitView--horizontal_1oi17_12{cursor:row-resize}._SplitView--disable-select_1oi17_16{-webkit-user-select:none;user-select:none}._SplitView--disable-select_1oi17_16 ._SplitViewPane_1oi17_20{pointer-events:none}._VerticalSplitPane__expand_80tii_1{background:#fff;cursor:pointer;inset:0;position:absolute;transition:all .3s cubic-bezier(.55,0,.1,1)}._VerticalSplitPane__expand_80tii_1:hover{animation:_VerticalSplitPane__expand_80tii_1 .6s cubic-bezier(.55,0,.1,1);background:var(--light-bg-color)}._VerticalSplitPane__expand_80tii_1._VerticalSplitPane__expand_80tii_1{border-right:1px solid var(--border-color);transform-origin:left}._VerticalSplitPane__expand_80tii_1._VerticalSplitPane__expand--right_80tii_25{border-left:1px solid var(--border-color);transform-origin:right}@keyframes _VerticalSplitPane__expand_80tii_1{0%{transform:scaleX(1)}50%{transform:scaleX(2)}to{transform:scaleX(1)}}._VerticalSplitPaneOverlay_80tii_42{background:linear-gradient(180deg,#30302f80,#30302f4d);height:100%;inset:0;overflow:hidden;position:absolute;z-index:12}._VerticalSplitPaneOverlay__primary_80tii_58{inset:0;position:absolute;z-index:1}._VerticalSplitPaneOverlay__primary--left_80tii_67{margin-right:20px}._VerticalSplitPaneOverlay__primary--right_80tii_71{margin-left:20px}._VerticalSplitPaneOverlay__secondary_80tii_75{background:#fff;bottom:0;box-shadow:0 0 15px #0006;position:absolute;top:0}._VerticalSplitPaneOverlay__secondary--left_80tii_83{left:0}._VerticalSplitPaneOverlay__secondary--right_80tii_87{right:0}._VerticalSplitPaneOverlay__sash_80tii_91{height:100%;position:absolute;top:0}._VerticalSplitPaneOverlay__secondary--left_80tii_83 ._VerticalSplitPaneOverlay__sash_80tii_91{right:0}._VerticalSplitPaneOverlay__secondary--right_80tii_87 ._VerticalSplitPaneOverlay__sash_80tii_91{left:0}
|
package/build/index.html
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<script type="module" crossorigin src="./assets/index-BnrW9Ts8.js"></script>
|
|
7
|
+
<link rel="stylesheet" crossorigin href="./assets/index-aWCW2c0n.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/index.html
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/index.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datocms-plugin-record-bin",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"homepage": "https://github.com/datocms/plugins/tree/master/record-bin#readme",
|
|
4
|
+
"version": "3.0.0",
|
|
5
|
+
"author": "DatoCMS <support@datocms.com>",
|
|
6
6
|
"description": "A plugin to manage and create a backup of deleted records in DatoCMS",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"datocms",
|
|
@@ -16,24 +16,28 @@
|
|
|
16
16
|
"previewImage": "docs/demo.mp4",
|
|
17
17
|
"coverImage": "docs/cover.png",
|
|
18
18
|
"entryPoint": "build/index.html",
|
|
19
|
-
"permissions": [
|
|
19
|
+
"permissions": [
|
|
20
|
+
"currentUserAccessToken"
|
|
21
|
+
]
|
|
20
22
|
},
|
|
21
23
|
"dependencies": {
|
|
22
|
-
"@
|
|
23
|
-
"@types/
|
|
24
|
-
"@types/react
|
|
25
|
-
"
|
|
26
|
-
"datocms-
|
|
27
|
-
"react": "^
|
|
28
|
-
"react
|
|
29
|
-
"react-
|
|
30
|
-
"typescript": "^
|
|
24
|
+
"@datocms/cma-client-browser": "^5.3.0",
|
|
25
|
+
"@types/node": "^25.3.0",
|
|
26
|
+
"@types/react": "^18.3.28",
|
|
27
|
+
"@types/react-dom": "^18.3.7",
|
|
28
|
+
"datocms-plugin-sdk": "^2.1.1",
|
|
29
|
+
"datocms-react-ui": "^2.1.4",
|
|
30
|
+
"react": "^18.3.1",
|
|
31
|
+
"react-dom": "^18.3.1",
|
|
32
|
+
"typescript": "^5.9.3"
|
|
31
33
|
},
|
|
32
34
|
"scripts": {
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
35
|
+
"dev": "vite",
|
|
36
|
+
"start": "npm run dev",
|
|
37
|
+
"build": "vite build",
|
|
38
|
+
"preview": "vite preview",
|
|
39
|
+
"test": "vitest run --passWithNoTests",
|
|
40
|
+
"test:watch": "vitest --passWithNoTests",
|
|
37
41
|
"prepublishOnly": "npm run build"
|
|
38
42
|
},
|
|
39
43
|
"eslintConfig": {
|
|
@@ -54,6 +58,8 @@
|
|
|
54
58
|
]
|
|
55
59
|
},
|
|
56
60
|
"devDependencies": {
|
|
57
|
-
"
|
|
61
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
62
|
+
"vite": "^7.1.12",
|
|
63
|
+
"vitest": "^4.0.0"
|
|
58
64
|
}
|
|
59
65
|
}
|
|
@@ -1,34 +1,224 @@
|
|
|
1
1
|
import { RenderItemFormOutletCtx } from "datocms-plugin-sdk";
|
|
2
|
-
import { Button, Canvas, FieldGroup, Form
|
|
2
|
+
import { Button, Canvas, FieldGroup, Form } from "datocms-react-ui";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { errorObject } from "../types/types";
|
|
5
|
+
import { createDebugLogger, isDebugEnabled } from "../utils/debugLogger";
|
|
6
|
+
import { getDeploymentUrlFromParameters } from "../utils/getDeploymentUrlFromParameters";
|
|
7
|
+
import { getRuntimeMode } from "../utils/getRuntimeMode";
|
|
8
|
+
import {
|
|
9
|
+
isLambdaLessRestoreError,
|
|
10
|
+
restoreRecordWithoutLambda,
|
|
11
|
+
} from "../utils/lambdaLessRestore";
|
|
12
|
+
import {
|
|
13
|
+
buildRestoreErrorPayload,
|
|
14
|
+
isRestoreSuccessResponse,
|
|
15
|
+
parseJsonStringSafely,
|
|
16
|
+
} from "../utils/restoreError";
|
|
17
|
+
|
|
18
|
+
const getPrimaryErrorLine = (restorationError: errorObject): string => {
|
|
19
|
+
const details = restorationError.simplifiedError.details;
|
|
20
|
+
const detailMessage =
|
|
21
|
+
(typeof details.field === "string" && details.field) ||
|
|
22
|
+
(Array.isArray(details.extraneous_attributes) &&
|
|
23
|
+
details.extraneous_attributes.length > 0
|
|
24
|
+
? details.extraneous_attributes.join(", ")
|
|
25
|
+
: undefined) ||
|
|
26
|
+
(typeof details.message === "string" && details.message) ||
|
|
27
|
+
"No details available";
|
|
28
|
+
|
|
29
|
+
return `${restorationError.simplifiedError.code || "UNKNOWN"}: ${detailMessage}`;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getSecondaryErrorLine = (
|
|
33
|
+
restorationError: errorObject
|
|
34
|
+
): string | undefined => {
|
|
35
|
+
const details = restorationError.simplifiedError.details;
|
|
36
|
+
|
|
37
|
+
if (typeof details.code === "string" && details.code.trim().length > 0) {
|
|
38
|
+
return `Details code: ${details.code}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (typeof details.field_id === "string" && details.field_id.trim().length > 0) {
|
|
42
|
+
return `Field ID: ${details.field_id}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
typeof details.field_label === "string" &&
|
|
47
|
+
details.field_label.trim().length > 0
|
|
48
|
+
) {
|
|
49
|
+
return `Field label: ${details.field_label}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return undefined;
|
|
53
|
+
};
|
|
5
54
|
|
|
6
55
|
const BinOutlet = ({ ctx }: { ctx: RenderItemFormOutletCtx }) => {
|
|
56
|
+
const debugLogger = createDebugLogger(
|
|
57
|
+
isDebugEnabled(ctx.plugin.attributes.parameters),
|
|
58
|
+
"BinOutlet"
|
|
59
|
+
);
|
|
7
60
|
const [isLoading, setLoading] = useState(false);
|
|
8
61
|
const [error, setError] = useState<errorObject>();
|
|
9
62
|
|
|
10
63
|
const restorationHandler = async () => {
|
|
64
|
+
debugLogger.log("Starting record restoration", {
|
|
65
|
+
itemId: ctx.item?.id,
|
|
66
|
+
itemTypeId: ctx.itemType.id,
|
|
67
|
+
});
|
|
68
|
+
setError(undefined);
|
|
11
69
|
setLoading(true);
|
|
12
70
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
71
|
+
const runtimeMode = getRuntimeMode(ctx.plugin.attributes.parameters);
|
|
72
|
+
const rawRecordBody = ctx.formValues.record_body;
|
|
73
|
+
let parsedRecordBody: unknown;
|
|
74
|
+
try {
|
|
75
|
+
parsedRecordBody =
|
|
76
|
+
typeof rawRecordBody === "string" ? JSON.parse(rawRecordBody) : rawRecordBody;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
debugLogger.warn("Could not parse record_body JSON before restore", error);
|
|
79
|
+
await ctx.alert("The record body is not valid JSON.");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
16
82
|
|
|
17
83
|
try {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
84
|
+
if (runtimeMode === "lambda") {
|
|
85
|
+
const deploymentURL = getDeploymentUrlFromParameters(
|
|
86
|
+
ctx.plugin.attributes.parameters
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
if (!deploymentURL) {
|
|
90
|
+
debugLogger.warn("Missing deployment URL while restoring record");
|
|
91
|
+
await ctx.alert("The plugin deployment URL is missing.");
|
|
92
|
+
return;
|
|
24
93
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
!parsedRecordBody ||
|
|
97
|
+
typeof parsedRecordBody !== "object" ||
|
|
98
|
+
Array.isArray(parsedRecordBody)
|
|
99
|
+
) {
|
|
100
|
+
debugLogger.warn("record_body must be a JSON object for lambda restore");
|
|
101
|
+
await ctx.alert("The record body is not a valid restore payload.");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!ctx.item?.id) {
|
|
106
|
+
debugLogger.warn("Missing trash record id in lambda restore");
|
|
107
|
+
await ctx.alert("Could not determine the trash record to remove.");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const parsedBody = {
|
|
112
|
+
...(parsedRecordBody as Record<string, unknown>),
|
|
113
|
+
trashRecordID: ctx.item.id,
|
|
114
|
+
};
|
|
115
|
+
const requestBody = JSON.stringify(parsedBody);
|
|
116
|
+
debugLogger.log("Sending restoration request to lambda", {
|
|
117
|
+
deploymentURL,
|
|
118
|
+
requestBodyLength: requestBody.length,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
let restoreResponse: Response;
|
|
122
|
+
try {
|
|
123
|
+
restoreResponse = await fetch(deploymentURL, {
|
|
124
|
+
method: "POST",
|
|
125
|
+
body: requestBody,
|
|
126
|
+
headers: { Accept: "*/*", "Content-Type": "application/json" },
|
|
127
|
+
});
|
|
128
|
+
} catch (error) {
|
|
129
|
+
const restorationError = buildRestoreErrorPayload(error);
|
|
130
|
+
setError(restorationError);
|
|
131
|
+
debugLogger.warn(
|
|
132
|
+
"Restoration request failed before receiving response",
|
|
133
|
+
restorationError
|
|
134
|
+
);
|
|
135
|
+
await ctx.alert("The record could not be restored!");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
debugLogger.log("Received restoration response", {
|
|
140
|
+
status: restoreResponse.status,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const rawResponseBody = await restoreResponse.text();
|
|
144
|
+
const parsedResponse = parseJsonStringSafely(rawResponseBody);
|
|
145
|
+
|
|
146
|
+
if (!restoreResponse.ok || !isRestoreSuccessResponse(parsedResponse)) {
|
|
147
|
+
const fallbackMessage = restoreResponse.ok
|
|
148
|
+
? "The restore API returned an invalid success payload."
|
|
149
|
+
: `The restore API request failed with status ${restoreResponse.status}.`;
|
|
150
|
+
const trimmedResponseBody = rawResponseBody.trim();
|
|
151
|
+
const restorationError = buildRestoreErrorPayload(
|
|
152
|
+
parsedResponse ?? rawResponseBody,
|
|
153
|
+
{
|
|
154
|
+
fullErrorPayload:
|
|
155
|
+
trimmedResponseBody.length > 0 ? trimmedResponseBody : undefined,
|
|
156
|
+
fallbackMessage,
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
setError(restorationError);
|
|
160
|
+
debugLogger.warn("Restoration request failed", {
|
|
161
|
+
status: restoreResponse.status,
|
|
162
|
+
restorationError,
|
|
163
|
+
});
|
|
164
|
+
await ctx.alert("The record could not be restored!");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
debugLogger.log("Restoration succeeded", {
|
|
169
|
+
restoredRecordId: parsedResponse.restoredRecord.id,
|
|
170
|
+
restoredModelId: parsedResponse.restoredRecord.modelID,
|
|
171
|
+
});
|
|
172
|
+
ctx.notice("The record has been successfully restored!");
|
|
173
|
+
ctx.navigateTo(
|
|
174
|
+
"/editor/item_types/" +
|
|
175
|
+
parsedResponse.restoredRecord.modelID +
|
|
176
|
+
"/items/" +
|
|
177
|
+
parsedResponse.restoredRecord.id
|
|
178
|
+
);
|
|
179
|
+
return;
|
|
30
180
|
}
|
|
31
181
|
|
|
182
|
+
if (!ctx.item?.id) {
|
|
183
|
+
debugLogger.warn("Missing trash record id in lambda-less restore");
|
|
184
|
+
await ctx.alert("Could not determine the trash record to remove.");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
debugLogger.log("Sending restoration request through Lambda-less runtime");
|
|
189
|
+
let parsedResponse:
|
|
190
|
+
| Awaited<ReturnType<typeof restoreRecordWithoutLambda>>
|
|
191
|
+
| undefined;
|
|
192
|
+
try {
|
|
193
|
+
parsedResponse = await restoreRecordWithoutLambda({
|
|
194
|
+
currentUserAccessToken: ctx.currentUserAccessToken,
|
|
195
|
+
fallbackEnvironment: ctx.environment,
|
|
196
|
+
recordBody: parsedRecordBody,
|
|
197
|
+
trashRecordID: ctx.item.id,
|
|
198
|
+
});
|
|
199
|
+
} catch (error) {
|
|
200
|
+
if (isLambdaLessRestoreError(error)) {
|
|
201
|
+
setError(error.restorationError);
|
|
202
|
+
debugLogger.warn(
|
|
203
|
+
"Lambda-less restoration request failed",
|
|
204
|
+
error.restorationError
|
|
205
|
+
);
|
|
206
|
+
await ctx.alert("The record could not be restored!");
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
throw error;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!parsedResponse) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
debugLogger.log("Lambda-less restoration succeeded", {
|
|
218
|
+
restoredRecordId: parsedResponse.restoredRecord.id,
|
|
219
|
+
restoredModelId: parsedResponse.restoredRecord.modelID,
|
|
220
|
+
});
|
|
221
|
+
|
|
32
222
|
ctx.notice("The record has been successfully restored!");
|
|
33
223
|
ctx.navigateTo(
|
|
34
224
|
"/editor/item_types/" +
|
|
@@ -37,43 +227,40 @@ const BinOutlet = ({ ctx }: { ctx: RenderItemFormOutletCtx }) => {
|
|
|
37
227
|
parsedResponse.restoredRecord.id
|
|
38
228
|
);
|
|
39
229
|
} catch (error) {
|
|
40
|
-
|
|
230
|
+
debugLogger.error("Restoration flow failed", error);
|
|
41
231
|
await ctx.alert("The record could not be restored!");
|
|
232
|
+
} finally {
|
|
233
|
+
setLoading(false);
|
|
42
234
|
}
|
|
43
235
|
};
|
|
44
236
|
|
|
45
237
|
const errorModalHandler = async () => {
|
|
238
|
+
if (!error) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
debugLogger.log("Opening restoration error modal");
|
|
46
243
|
await ctx.openModal({
|
|
47
244
|
id: "errorModal",
|
|
48
245
|
title: "Restoration error",
|
|
49
246
|
width: "l",
|
|
50
|
-
parameters: { errorPayload: error
|
|
247
|
+
parameters: { errorPayload: error.fullErrorPayload },
|
|
51
248
|
});
|
|
52
249
|
};
|
|
53
250
|
|
|
251
|
+
const primaryErrorLine = error ? getPrimaryErrorLine(error) : undefined;
|
|
252
|
+
const secondaryErrorLine = error ? getSecondaryErrorLine(error) : undefined;
|
|
253
|
+
const restorationErrorBoxStyle = {
|
|
254
|
+
border: "1px solid rgba(var(--alert-color-rgb-components), 0.5)",
|
|
255
|
+
borderRadius: "6px",
|
|
256
|
+
background: "rgba(var(--alert-color-rgb-components), 0.08)",
|
|
257
|
+
padding: "var(--spacing-m)",
|
|
258
|
+
marginBottom: "var(--spacing-m)",
|
|
259
|
+
};
|
|
260
|
+
|
|
54
261
|
return (
|
|
55
262
|
<Canvas ctx={ctx}>
|
|
56
263
|
<Form>
|
|
57
|
-
<FieldGroup>
|
|
58
|
-
{error && (
|
|
59
|
-
<Section title="Restoration error">
|
|
60
|
-
<p>Couldn't restore the record because of the following error:</p>
|
|
61
|
-
<p>
|
|
62
|
-
{error.simplifiedError.code}:{" "}
|
|
63
|
-
{error.simplifiedError.details.field ||
|
|
64
|
-
error.simplifiedError.details.extraneous_attributes}
|
|
65
|
-
</p>
|
|
66
|
-
<p>{error.simplifiedError.details.code}</p>
|
|
67
|
-
<Button onClick={errorModalHandler}>
|
|
68
|
-
See full restoration error report
|
|
69
|
-
</Button>
|
|
70
|
-
<p>
|
|
71
|
-
You can manually correct the errors on the record body, save the
|
|
72
|
-
record, and re-attempt to restore it.
|
|
73
|
-
</p>
|
|
74
|
-
</Section>
|
|
75
|
-
)}
|
|
76
|
-
</FieldGroup>
|
|
77
264
|
<FieldGroup>
|
|
78
265
|
<Button
|
|
79
266
|
buttonType={isLoading ? "muted" : "primary"}
|
|
@@ -84,6 +271,44 @@ const BinOutlet = ({ ctx }: { ctx: RenderItemFormOutletCtx }) => {
|
|
|
84
271
|
Restore record ♻️
|
|
85
272
|
</Button>
|
|
86
273
|
</FieldGroup>
|
|
274
|
+
<FieldGroup>
|
|
275
|
+
{error && (
|
|
276
|
+
<div style={restorationErrorBoxStyle}>
|
|
277
|
+
<h3
|
|
278
|
+
style={{
|
|
279
|
+
marginTop: 0,
|
|
280
|
+
marginBottom: "var(--spacing-s)",
|
|
281
|
+
fontSize: "var(--font-size-m)",
|
|
282
|
+
}}
|
|
283
|
+
>
|
|
284
|
+
Restoration error
|
|
285
|
+
</h3>
|
|
286
|
+
<p style={{ marginTop: 0, marginBottom: "var(--spacing-s)" }}>
|
|
287
|
+
Restoring a record is an optimistic operation. If this record
|
|
288
|
+
references linked records that no longer exist, restoration can fail.
|
|
289
|
+
</p>
|
|
290
|
+
<p style={{ marginTop: 0, marginBottom: "var(--spacing-s)" }}>
|
|
291
|
+
In case of API errors, inspect the details below and update the{" "}
|
|
292
|
+
<code>record_body</code> JSON if needed before trying again.
|
|
293
|
+
</p>
|
|
294
|
+
<p style={{ marginTop: 0, marginBottom: "var(--spacing-s)" }}>
|
|
295
|
+
{primaryErrorLine}
|
|
296
|
+
</p>
|
|
297
|
+
{secondaryErrorLine && (
|
|
298
|
+
<p style={{ marginTop: 0, marginBottom: "var(--spacing-s)" }}>
|
|
299
|
+
{secondaryErrorLine}
|
|
300
|
+
</p>
|
|
301
|
+
)}
|
|
302
|
+
<Button onClick={errorModalHandler}>
|
|
303
|
+
See full restoration error report
|
|
304
|
+
</Button>
|
|
305
|
+
<p style={{ marginTop: "var(--spacing-s)", marginBottom: 0 }}>
|
|
306
|
+
You can manually correct the JSON payload, save the record, and
|
|
307
|
+
re-attempt restoration.
|
|
308
|
+
</p>
|
|
309
|
+
</div>
|
|
310
|
+
)}
|
|
311
|
+
</FieldGroup>
|
|
87
312
|
</Form>
|
|
88
313
|
</Canvas>
|
|
89
314
|
);
|