Merge branch 'master' into BUDI-9127/extract-env-input
This commit is contained in:
commit
95e992dee9
|
@ -55,6 +55,11 @@
|
|||
active={$isActive("./oauth2")}
|
||||
/>
|
||||
{/if}
|
||||
<SideNavItem
|
||||
text="App scripts"
|
||||
url={$url("./scripts")}
|
||||
active={$isActive("./scripts")}
|
||||
/>
|
||||
<div class="delete-action">
|
||||
<AbsTooltip
|
||||
position={TooltipPosition.Bottom}
|
||||
|
|
|
@ -170,7 +170,7 @@
|
|||
<Layout noPadding>
|
||||
<Layout gap="XS" noPadding>
|
||||
<Heading>Automations</Heading>
|
||||
<Body size="S">See your automation history and edit advanced settings</Body>
|
||||
<Body>See your automation history and edit advanced settings</Body>
|
||||
</Layout>
|
||||
<Divider />
|
||||
|
||||
|
@ -251,7 +251,6 @@
|
|||
data={runHistory}
|
||||
{customRenderers}
|
||||
placeholderText="No history found"
|
||||
border={false}
|
||||
/>
|
||||
<div class="pagination">
|
||||
<Pagination
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
Tags,
|
||||
Tag,
|
||||
Table,
|
||||
ButtonGroup,
|
||||
} from "@budibase/bbui"
|
||||
import { backups, licensing, auth, admin } from "@/stores/portal"
|
||||
import { appStore } from "@/stores/builder"
|
||||
|
@ -180,25 +181,17 @@
|
|||
{#if !$auth.accountPortalAccess && $admin.cloud}
|
||||
<Body>Contact your account holder to upgrade your plan.</Body>
|
||||
{/if}
|
||||
<div class="pro-buttons">
|
||||
{#if $auth.accountPortalAccess}
|
||||
<Button
|
||||
primary
|
||||
disabled={!$auth.accountPortalAccess && $admin.cloud}
|
||||
on:click={$licensing.goToUpgradePage()}
|
||||
>
|
||||
Upgrade
|
||||
</Button>
|
||||
<ButtonGroup>
|
||||
{#if $admin.cloud && $auth.accountPortalAccess}
|
||||
<Button primary on:click={$licensing.goToUpgradePage}>Upgrade</Button>
|
||||
{/if}
|
||||
<Button
|
||||
secondary
|
||||
on:click={() => {
|
||||
window.open("https://budibase.com/pricing/", "_blank")
|
||||
}}
|
||||
on:click={() => window.open("https://budibase.com/pricing/", "_blank")}
|
||||
>
|
||||
View plans
|
||||
</Button>
|
||||
</div>
|
||||
</ButtonGroup>
|
||||
{:else if !backupData?.length && !loading && !filterOpt && !dateRange?.length}
|
||||
<div class="center">
|
||||
<Layout noPadding gap="S" justifyItems="center">
|
||||
|
@ -311,12 +304,7 @@
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--spacing-m);
|
||||
}
|
||||
|
||||
.pro-buttons {
|
||||
display: flex;
|
||||
gap: var(--spacing-m);
|
||||
gap: var(--spacing-l);
|
||||
}
|
||||
|
||||
.center {
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
<script lang="ts">
|
||||
import {
|
||||
Body,
|
||||
Button,
|
||||
Link,
|
||||
Divider,
|
||||
Heading,
|
||||
Layout,
|
||||
Table,
|
||||
Label,
|
||||
Input,
|
||||
TextArea,
|
||||
Select,
|
||||
Helpers,
|
||||
notifications,
|
||||
Tag,
|
||||
Tags,
|
||||
ButtonGroup,
|
||||
} from "@budibase/bbui"
|
||||
import { appStore } from "@/stores/builder"
|
||||
import { type AppScript } from "@budibase/types"
|
||||
import { getSequentialName } from "@/helpers/duplicate"
|
||||
import ConfirmDialog from "@/components/common/ConfirmDialog.svelte"
|
||||
import { licensing, auth, admin } from "@/stores/portal"
|
||||
|
||||
const schema = {
|
||||
name: {
|
||||
type: "string",
|
||||
label: "Name",
|
||||
},
|
||||
location: {
|
||||
type: "string",
|
||||
label: "Location",
|
||||
},
|
||||
}
|
||||
|
||||
let selectedScript: AppScript | undefined
|
||||
let isNew = false
|
||||
let confirmDeleteModal: any
|
||||
|
||||
$: nameError = selectedScript?.name ? undefined : "Please enter a name"
|
||||
$: invalid = !!nameError
|
||||
$: enabled = $licensing.customAppScriptsEnabled
|
||||
|
||||
const addScript = () => {
|
||||
const name = getSequentialName($appStore.scripts, "Script ", {
|
||||
getName: script => script.name,
|
||||
numberFirstItem: true,
|
||||
})
|
||||
selectedScript = { id: Helpers.uuid(), location: "Head", name }
|
||||
isNew = true
|
||||
}
|
||||
|
||||
const editScript = (e: any) => {
|
||||
selectedScript = { ...(e.detail as AppScript) }
|
||||
isNew = false
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
selectedScript = undefined
|
||||
}
|
||||
|
||||
const save = async () => {
|
||||
if (!selectedScript) {
|
||||
return
|
||||
}
|
||||
const newScripts = $appStore.scripts
|
||||
.filter(script => script.id !== selectedScript!.id)
|
||||
.concat([selectedScript])
|
||||
await appStore.updateApp({ scripts: newScripts })
|
||||
notifications.success("Script saved successfully")
|
||||
selectedScript = undefined
|
||||
}
|
||||
|
||||
const requestDeletion = () => {
|
||||
confirmDeleteModal?.show()
|
||||
}
|
||||
|
||||
const deleteScript = async () => {
|
||||
if (!selectedScript) {
|
||||
return
|
||||
}
|
||||
const newScripts = $appStore.scripts.filter(
|
||||
script => script.id !== selectedScript!.id
|
||||
)
|
||||
await appStore.updateApp({ scripts: newScripts })
|
||||
notifications.success("Script deleted successfully")
|
||||
selectedScript = undefined
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout noPadding>
|
||||
<Layout gap="XS" noPadding>
|
||||
<div class="title">
|
||||
<Heading>App scripts</Heading>
|
||||
{#if !enabled}
|
||||
<Tags>
|
||||
<Tag icon="LockClosed">Enterprise</Tag>
|
||||
</Tags>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
<Body>
|
||||
Inject analytics, scripts or stylesheets into your app<br />
|
||||
<Link href="https://docs.budibase.com/docs/app-scripts" target="_blank">
|
||||
Learn more about script injection in the docs
|
||||
</Link>
|
||||
</Body>
|
||||
{#if !selectedScript && enabled}
|
||||
<Button cta on:click={addScript}>Add script</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</Layout>
|
||||
<Divider />
|
||||
{#if !enabled}
|
||||
{#if $admin.cloud && !$auth.accountPortalAccess}
|
||||
<Body>Contact your account holder to upgrade your plan.</Body>
|
||||
{/if}
|
||||
<ButtonGroup>
|
||||
{#if $admin.cloud && $auth.accountPortalAccess}
|
||||
<Button cta on:click={$licensing.goToUpgradePage}>Upgrade</Button>
|
||||
{/if}
|
||||
<Button
|
||||
secondary
|
||||
on:click={() => window.open("https://budibase.com/pricing/", "_blank")}
|
||||
>
|
||||
View plans
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
{:else if selectedScript}
|
||||
<Heading size="S">{isNew ? "Add new script" : "Edit script"}</Heading>
|
||||
<div class="form">
|
||||
<Label size="L">Name</Label>
|
||||
<Input bind:value={selectedScript.name} error={nameError} />
|
||||
<Label size="L">Location</Label>
|
||||
<Select
|
||||
bind:value={selectedScript.location}
|
||||
options={["Head", "Body"]}
|
||||
placeholder={false}
|
||||
/>
|
||||
<Label size="L">HTML</Label>
|
||||
<TextArea
|
||||
bind:value={selectedScript.html}
|
||||
minHeight={200}
|
||||
placeholder="<script>...</script>"
|
||||
/>
|
||||
<div />
|
||||
<div class="buttons">
|
||||
{#if !isNew}
|
||||
<Button warning quiet on:click={requestDeletion}>Delete</Button>
|
||||
{/if}
|
||||
<Button secondary on:click={cancel}>Cancel</Button>
|
||||
<Button cta disabled={invalid} on:click={save}>Save</Button>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<Table
|
||||
on:click={editScript}
|
||||
{schema}
|
||||
data={$appStore.scripts}
|
||||
allowSelectRows={false}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
placeholderText="You haven't added any scripts yet"
|
||||
/>
|
||||
{/if}
|
||||
</Layout>
|
||||
|
||||
<ConfirmDialog
|
||||
bind:this={confirmDeleteModal}
|
||||
title="Delete script"
|
||||
body="Are you sure you want to delete this script?"
|
||||
onOk={deleteScript}
|
||||
/>
|
||||
|
||||
<style>
|
||||
.title,
|
||||
.subtitle {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
gap: var(--spacing-l);
|
||||
}
|
||||
.subtitle {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.form {
|
||||
display: grid;
|
||||
grid-template-columns: 100px 480px;
|
||||
row-gap: var(--spacing-l);
|
||||
}
|
||||
.form :global(.spectrum-FieldLabel) {
|
||||
padding-top: 7px;
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
gap: var(--spacing-l);
|
||||
}
|
||||
</style>
|
|
@ -4,9 +4,12 @@ import {
|
|||
App,
|
||||
AppFeatures,
|
||||
AppIcon,
|
||||
AppScript,
|
||||
AutomationSettings,
|
||||
Plugin,
|
||||
UpdateAppRequest,
|
||||
} from "@budibase/types"
|
||||
import { get } from "svelte/store"
|
||||
|
||||
interface ClientFeatures {
|
||||
spectrumThemes: boolean
|
||||
|
@ -46,6 +49,7 @@ interface AppMetaState {
|
|||
revertableVersion?: string
|
||||
upgradableVersion?: string
|
||||
icon?: AppIcon
|
||||
scripts: AppScript[]
|
||||
}
|
||||
|
||||
export const INITIAL_APP_META_STATE: AppMetaState = {
|
||||
|
@ -79,6 +83,7 @@ export const INITIAL_APP_META_STATE: AppMetaState = {
|
|||
usedPlugins: [],
|
||||
automations: {},
|
||||
routes: {},
|
||||
scripts: [],
|
||||
}
|
||||
|
||||
export class AppMetaStore extends BudiStore<AppMetaState> {
|
||||
|
@ -90,20 +95,12 @@ export class AppMetaStore extends BudiStore<AppMetaState> {
|
|||
this.store.set({ ...INITIAL_APP_META_STATE })
|
||||
}
|
||||
|
||||
syncAppPackage(pkg: {
|
||||
application: App
|
||||
clientLibPath: string
|
||||
hasLock: boolean
|
||||
}) {
|
||||
const { application: app, clientLibPath, hasLock } = pkg
|
||||
|
||||
syncApp(app: App) {
|
||||
this.update(state => ({
|
||||
...state,
|
||||
name: app.name,
|
||||
appId: app.appId,
|
||||
url: app.url || "",
|
||||
hasLock,
|
||||
clientLibPath,
|
||||
libraries: app.componentLibraries,
|
||||
version: app.version,
|
||||
appInstance: app.instance,
|
||||
|
@ -118,9 +115,24 @@ export class AppMetaStore extends BudiStore<AppMetaState> {
|
|||
initialised: true,
|
||||
automations: app.automations || {},
|
||||
hasAppPackage: true,
|
||||
scripts: app.scripts || [],
|
||||
}))
|
||||
}
|
||||
|
||||
syncAppPackage(pkg: {
|
||||
application: App
|
||||
clientLibPath: string
|
||||
hasLock: boolean
|
||||
}) {
|
||||
const { application, clientLibPath, hasLock } = pkg
|
||||
this.update(state => ({
|
||||
...state,
|
||||
hasLock,
|
||||
clientLibPath,
|
||||
}))
|
||||
this.syncApp(application)
|
||||
}
|
||||
|
||||
syncClientFeatures(features: Partial<ClientFeatures>) {
|
||||
this.update(state => ({
|
||||
...state,
|
||||
|
@ -146,6 +158,11 @@ export class AppMetaStore extends BudiStore<AppMetaState> {
|
|||
}))
|
||||
}
|
||||
|
||||
async updateApp(updates: UpdateAppRequest) {
|
||||
const app = await API.saveAppMetadata(get(this.store).appId, updates)
|
||||
this.syncApp(app)
|
||||
}
|
||||
|
||||
// Returned from socket
|
||||
syncMetadata(metadata: { name: string; url: string; icon?: AppIcon }) {
|
||||
const { name, url, icon } = metadata
|
||||
|
|
|
@ -36,6 +36,7 @@ interface LicensingState {
|
|||
budibaseAIEnabled: boolean
|
||||
customAIConfigsEnabled: boolean
|
||||
auditLogsEnabled: boolean
|
||||
customAppScriptsEnabled: boolean
|
||||
syncAutomationsEnabled: boolean
|
||||
triggerAutomationRunEnabled: boolean
|
||||
// the currently used quotas from the db
|
||||
|
@ -77,6 +78,7 @@ class LicensingStore extends BudiStore<LicensingState> {
|
|||
budibaseAIEnabled: false,
|
||||
customAIConfigsEnabled: false,
|
||||
auditLogsEnabled: false,
|
||||
customAppScriptsEnabled: false,
|
||||
syncAutomationsEnabled: false,
|
||||
triggerAutomationRunEnabled: false,
|
||||
// the currently used quotas from the db
|
||||
|
@ -182,6 +184,9 @@ class LicensingStore extends BudiStore<LicensingState> {
|
|||
const customAIConfigsEnabled = features.includes(
|
||||
Constants.Features.AI_CUSTOM_CONFIGS
|
||||
)
|
||||
const customAppScriptsEnabled = features.includes(
|
||||
Constants.Features.CUSTOM_APP_SCRIPTS
|
||||
)
|
||||
this.update(state => {
|
||||
return {
|
||||
...state,
|
||||
|
@ -202,6 +207,7 @@ class LicensingStore extends BudiStore<LicensingState> {
|
|||
syncAutomationsEnabled,
|
||||
triggerAutomationRunEnabled,
|
||||
perAppBuildersEnabled,
|
||||
customAppScriptsEnabled,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -154,6 +154,21 @@ const requiresMigration = async (ctx: Ctx) => {
|
|||
return latestMigrationApplied !== latestMigration
|
||||
}
|
||||
|
||||
const getAppScriptHTML = (
|
||||
app: App,
|
||||
location: "Head" | "Body",
|
||||
nonce: string
|
||||
) => {
|
||||
if (!app.scripts?.length) {
|
||||
return ""
|
||||
}
|
||||
return app.scripts
|
||||
.filter(script => script.location === location && script.html?.length)
|
||||
.map(script => script.html)
|
||||
.join("\n")
|
||||
.replaceAll("<script", `<script nonce="${nonce}"`)
|
||||
}
|
||||
|
||||
export const serveApp = async function (ctx: UserCtx<void, ServeAppResponse>) {
|
||||
if (ctx.url.includes("apple-touch-icon.png")) {
|
||||
ctx.redirect("/builder/bblogo.png")
|
||||
|
@ -190,6 +205,9 @@ export const serveApp = async function (ctx: UserCtx<void, ServeAppResponse>) {
|
|||
const hideFooter =
|
||||
ctx?.user?.license?.features?.includes(Feature.BRANDING) || false
|
||||
const themeVariables = getThemeVariables(appInfo?.theme)
|
||||
const addAppScripts =
|
||||
ctx?.user?.license?.features?.includes(Feature.CUSTOM_APP_SCRIPTS) ||
|
||||
false
|
||||
|
||||
if (!env.isJest()) {
|
||||
const plugins = await objectStore.enrichPluginURLs(appInfo.usedPlugins)
|
||||
|
@ -199,7 +217,8 @@ export const serveApp = async function (ctx: UserCtx<void, ServeAppResponse>) {
|
|||
* BudibaseApp.svelte file as we can never detect if the types are correct. To get around this
|
||||
* I've created a type which expects what the app will expect to receive.
|
||||
*/
|
||||
const props: BudibaseAppProps = {
|
||||
const nonce = ctx.state.nonce || ""
|
||||
let props: BudibaseAppProps = {
|
||||
title: branding?.platformTitle || `${appInfo.name}`,
|
||||
showSkeletonLoader: appInfo.features?.skeletonLoader ?? false,
|
||||
hideDevTools,
|
||||
|
@ -218,7 +237,13 @@ export const serveApp = async function (ctx: UserCtx<void, ServeAppResponse>) {
|
|||
? await objectStore.getGlobalFileUrl("settings", "faviconUrl")
|
||||
: "",
|
||||
appMigrating: needMigrations,
|
||||
nonce: ctx.state.nonce,
|
||||
nonce,
|
||||
}
|
||||
|
||||
// Add custom app scripts if enabled
|
||||
if (addAppScripts) {
|
||||
props.headAppScripts = getAppScriptHTML(appInfo, "Head", nonce)
|
||||
props.bodyAppScripts = getAppScriptHTML(appInfo, "Body", nonce)
|
||||
}
|
||||
|
||||
const { head, html, css } = AppComponent.render({ props })
|
||||
|
@ -273,10 +298,22 @@ export const serveBuilderPreview = async function (
|
|||
const templateLoc = join(__dirname, "templates")
|
||||
const previewLoc = fs.existsSync(templateLoc) ? templateLoc : __dirname
|
||||
const previewHbs = loadHandlebarsFile(join(previewLoc, "preview.hbs"))
|
||||
ctx.body = await processString(previewHbs, {
|
||||
const nonce = ctx.state.nonce || ""
|
||||
const addAppScripts =
|
||||
ctx?.user?.license?.features?.includes(Feature.CUSTOM_APP_SCRIPTS) ||
|
||||
false
|
||||
let props: any = {
|
||||
clientLibPath: objectStore.clientLibraryUrl(appId!, appInfo.version),
|
||||
nonce: ctx.state.nonce,
|
||||
})
|
||||
nonce,
|
||||
}
|
||||
|
||||
// Add custom app scripts if enabled
|
||||
if (addAppScripts) {
|
||||
props.headAppScripts = getAppScriptHTML(appInfo, "Head", nonce)
|
||||
props.bodyAppScripts = getAppScriptHTML(appInfo, "Body", nonce)
|
||||
}
|
||||
|
||||
ctx.body = await processString(previewHbs, props)
|
||||
} else {
|
||||
// just return the app info for jest to assert on
|
||||
ctx.body = { ...appInfo, builderPreview: true }
|
||||
|
|
|
@ -88,6 +88,9 @@
|
|||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||
{@html props.headAppScripts || ""}
|
||||
</svelte:head>
|
||||
|
||||
<body id="app">
|
||||
|
@ -135,4 +138,7 @@
|
|||
document.getElementById("error").style.display = "flex"
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||
{@html props.bodyAppScripts || ""}
|
||||
</body>
|
||||
|
|
|
@ -5,14 +5,12 @@
|
|||
})
|
||||
</script>
|
||||
<head>
|
||||
<script nonce="{{ nonce }}">
|
||||
window["##BUDIBASE_APP_ID##"] = "{{appId}}"
|
||||
window["##BUDIBASE_APP_EMBEDDED##"] = "{{embedded}}"
|
||||
</script>
|
||||
{{{head}}}
|
||||
<style>{{{css}}}</style>
|
||||
</head>
|
||||
|
||||
<script nonce="{{ nonce }}">
|
||||
window["##BUDIBASE_APP_ID##"] = "{{appId}}"
|
||||
window["##BUDIBASE_APP_EMBEDDED##"] = "{{embedded}}"
|
||||
</script>
|
||||
|
||||
{{{body}}}
|
||||
</html>
|
||||
|
|
|
@ -108,6 +108,9 @@
|
|||
window.addEventListener("message", receiveMessage)
|
||||
window.parent.postMessage({ type: "ready" })
|
||||
</script>
|
||||
{{ headAppScripts }}
|
||||
</head>
|
||||
<body></body>
|
||||
<body>
|
||||
{{ bodyAppScripts }}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -29,6 +29,7 @@ export interface App extends Document {
|
|||
snippets?: Snippet[]
|
||||
creationVersion?: string
|
||||
updatedBy?: string
|
||||
scripts?: AppScript[]
|
||||
}
|
||||
|
||||
export interface AppInstance {
|
||||
|
@ -82,3 +83,10 @@ export interface AppFeatures {
|
|||
export interface AutomationSettings {
|
||||
chainAutomations?: boolean
|
||||
}
|
||||
|
||||
export interface AppScript {
|
||||
id: string
|
||||
name: string
|
||||
location: "Head" | "Body"
|
||||
html?: string
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ export enum Feature {
|
|||
APP_BUILDERS = "appBuilders",
|
||||
OFFLINE = "offline",
|
||||
EXPANDED_PUBLIC_API = "expandedPublicApi",
|
||||
CUSTOM_APP_SCRIPTS = "customAppScripts",
|
||||
// deprecated - no longer licensed
|
||||
VIEW_PERMISSIONS = "viewPermissions",
|
||||
VIEW_READONLY_COLUMNS = "viewReadonlyColumns",
|
||||
|
|
|
@ -14,4 +14,6 @@ export interface BudibaseAppProps {
|
|||
sideNav?: boolean
|
||||
hideFooter?: boolean
|
||||
nonce?: string
|
||||
headAppScripts?: string
|
||||
bodyAppScripts?: string
|
||||
}
|
||||
|
|
15
yarn.lock
15
yarn.lock
|
@ -2699,17 +2699,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
|
||||
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
|
||||
|
||||
"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
||||
version "7.25.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2"
|
||||
integrity sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/runtime@^7.8.3":
|
||||
version "7.26.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433"
|
||||
integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==
|
||||
"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
||||
version "7.26.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.10.tgz#a07b4d8fa27af131a633d7b3524db803eb4764c2"
|
||||
integrity sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
|
|
Loading…
Reference in New Issue