import { importShared } from './__federation_fn_import-BBEx2jc4.js';
import { j as jsxRuntimeExports } from './jsx-runtime-XI9uIe3W.js';
import { g as get, s as set, c as appendErrors, a as useForm, d as useFieldArray, e as useWatch } from './index.esm-DWHSrnct.js';
import { s as storageAdapterEntityType, c as createStoragePluginDefinitionSchema } from './plugin-definition-BODH3hW9.js';
/* empty css                */

const r=(t,r,o)=>{if(t&&"reportValidity"in t){const s=get(o,r);t.setCustomValidity(s&&s.message||""),t.reportValidity();}},o=(e,t)=>{for(const o in t.fields){const s=t.fields[o];s&&s.ref&&"reportValidity"in s.ref?r(s.ref,o,e):s&&s.refs&&s.refs.forEach(t=>r(t,o,e));}},s$1=(r,s)=>{s.shouldUseNativeValidation&&o(r,s);const n={};for(const o in r){const f=get(s.fields,o),c=Object.assign(r[o]||{},{ref:f&&f.ref});if(i(s.names||Object.keys(r),o)){const r=Object.assign({},get(n,o));set(r,"root",c),set(n,o,r);}else set(n,o,c);}return n},i=(e,t)=>{const r=n$1(t);return e.some(e=>n$1(e).match(`^${r}\\.\\d+`))};function n$1(e){return e.replace(/\]|\[/g,"")}

function n(r,e){for(var n={};r.length;){var s=r[0],t=s.code,i=s.message,a=s.path.join(".");if(!n[a])if("unionErrors"in s){var u=s.unionErrors[0].errors[0];n[a]={message:u.message,type:u.code};}else n[a]={message:i,type:t};if("unionErrors"in s&&s.unionErrors.forEach(function(e){return e.errors.forEach(function(e){return r.push(e)})}),e){var c=n[a].types,f=c&&c[s.code];n[a]=appendErrors(a,e,n,t,f?[].concat(f,s.message):s.message);}r.shift();}return n}function s(o$1,s,t){return void 0===t&&(t={}),function(i,a,u){try{return Promise.resolve(function(e,n){try{var a=Promise.resolve(o$1["sync"===t.mode?"parse":"parseAsync"](i,s)).then(function(e){return u.shouldUseNativeValidation&&o({},u),{errors:{},values:t.raw?Object.assign({},i):e}});}catch(r){return n(r)}return a&&a.then?a.then(void 0,n):a}(0,function(r){if(function(r){return Array.isArray(null==r?void 0:r.errors)}(r))return {values:{},errors:s$1(n(r.errors,!u.shouldUseNativeValidation&&"all"===u.criteriaMode),u)};throw r}))}catch(r){return Promise.reject(r)}}}

const {authModelConfigSpec} = await importShared('@baseplate-dev/project-builder-lib');

const FILE_MODEL_FIELDS = [
  {
    name: "id",
    type: "uuid",
    options: { genUuid: true }
  },
  // Core fields
  {
    name: "filename",
    type: "string"
  },
  {
    name: "mimeType",
    type: "string"
  },
  {
    name: "encoding",
    type: "string",
    isOptional: true
  },
  {
    name: "size",
    type: "int"
  },
  // Storage info
  {
    name: "category",
    type: "string"
  },
  {
    name: "adapter",
    type: "string"
  },
  {
    name: "storagePath",
    type: "string"
  },
  // Status tracking via timestamps
  {
    name: "referencedAt",
    type: "dateTime",
    isOptional: true
  },
  {
    name: "expiredAt",
    type: "dateTime",
    isOptional: true
  },
  // Relations
  {
    name: "uploaderId",
    type: "uuid",
    isOptional: true
  },
  // Timestamps
  {
    name: "createdAt",
    type: "dateTime",
    options: { defaultToNow: true }
  },
  {
    name: "updatedAt",
    type: "dateTime",
    options: { defaultToNow: true, updatedAt: true }
  }
];
function createStorageModels({ storageFeatureRef }, projectDefinitionContainer) {
  const authModelConfig = projectDefinitionContainer.pluginStore.getPluginSpec(authModelConfigSpec);
  const userAccountModel = authModelConfig.getUserModel(
    projectDefinitionContainer.definition
  );
  if (!userAccountModel) {
    throw new Error(
      "User account model is required for storage plugin. Please enable an auth plugin."
    );
  }
  return {
    file: {
      name: "File",
      featureRef: storageFeatureRef,
      model: {
        fields: FILE_MODEL_FIELDS,
        primaryKeyFieldRefs: ["id"],
        relations: [
          {
            name: "uploader",
            references: [{ localRef: "uploaderId", foreignRef: "id" }],
            modelRef: userAccountModel,
            foreignRelationName: "files",
            onDelete: "Cascade",
            onUpdate: "Restrict"
          }
        ]
      },
      graphql: {
        objectType: {
          enabled: true,
          fields: ["id", "filename"]
        }
      }
    }
  };
}

const {Button: Button$1,Dialog,DialogContent,DialogDescription,DialogFooter,DialogHeader,DialogTitle,DialogTrigger,InputFieldController} = await importShared('@baseplate-dev/ui-components');
const {useId} = await importShared('react');
const z = await importShared('zod');

const adapterSchema = z.object({
  id: z.string(),
  name: z.string().min(1, "Name is required"),
  bucketConfigVar: z.string().min(1, "Bucket config variable is required"),
  hostedUrlConfigVar: z.string().optional()
});
function AdapterDialog({
  open,
  onOpenChange,
  adapter,
  isNew = false,
  onSave,
  asChild,
  children
}) {
  const form = useForm({
    resolver: s(adapterSchema),
    values: adapter
  });
  const { control, handleSubmit } = form;
  const onSubmit = handleSubmit((data) => {
    onSave(data);
    onOpenChange?.(false);
  });
  const formId = useId();
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Dialog, { open, onOpenChange, children: [
    /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTrigger, { asChild, children }),
    /* @__PURE__ */ jsxRuntimeExports.jsx(DialogContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
      "form",
      {
        id: formId,
        onSubmit: (e) => {
          e.stopPropagation();
          return onSubmit(e);
        },
        children: [
          /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { children: isNew ? "Add Adapter" : "Edit Adapter" }),
            /* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { children: isNew ? "Enter the details for the new S3 adapter." : "Update the adapter details below." })
          ] }),
          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "storage:space-y-4 storage:py-4", children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx(
              InputFieldController,
              {
                label: "Adapter Name",
                name: "name",
                control,
                placeholder: "Enter adapter name"
              }
            ),
            /* @__PURE__ */ jsxRuntimeExports.jsx(
              InputFieldController,
              {
                label: "AWS Bucket Name Environment Variable",
                name: "bucketConfigVar",
                control,
                placeholder: "e.g. UPLOADS_BUCKET",
                description: "The environment variable that contains the name of the S3 bucket to use for this adapter."
              }
            ),
            /* @__PURE__ */ jsxRuntimeExports.jsx(
              InputFieldController,
              {
                label: "Bucket URL Prefix Environment Variable",
                name: "hostedUrlConfigVar",
                control,
                placeholder: "e.g. UPLOADS_URL_PREFIX",
                description: "The environment variable that contains the domain of the S3 bucket. Optional if bucket is not publicly accessible."
              }
            )
          ] }),
          /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogFooter, { children: [
            /* @__PURE__ */ jsxRuntimeExports.jsx(
              Button$1,
              {
                type: "button",
                variant: "outline",
                onClick: () => {
                  onOpenChange?.(false);
                },
                children: "Cancel"
              }
            ),
            /* @__PURE__ */ jsxRuntimeExports.jsxs(Button$1, { form: formId, type: "submit", children: [
              isNew ? "Add" : "Update",
              " Adapter"
            ] })
          ] })
        ]
      }
    ) })
  ] });
}

const {Button,RecordView,RecordViewActions,RecordViewItem,RecordViewItemList,SectionListSection: SectionListSection$1,SectionListSectionContent: SectionListSectionContent$1,SectionListSectionDescription: SectionListSectionDescription$1,SectionListSectionHeader: SectionListSectionHeader$1,SectionListSectionTitle: SectionListSectionTitle$1,useConfirmDialog} = await importShared('@baseplate-dev/ui-components');

const {useState} = await importShared('react');
function AdapterEditorForm({ className, control }) {
  const { requestConfirm } = useConfirmDialog();
  const { append, update, remove } = useFieldArray({
    control,
    name: "s3Adapters"
  });
  const [adapterToEdit, setAdapterToEdit] = useState();
  const [isEditing, setIsEditing] = useState(false);
  const adapters = useWatch({ control, name: "s3Adapters" });
  function handleSaveAdapter(newAdapter) {
    const existingIndex = adapters.findIndex(
      (adapter) => adapter.id === newAdapter.id
    );
    if (existingIndex === -1) {
      append(newAdapter);
    } else {
      update(existingIndex, newAdapter);
    }
  }
  function handleDeleteAdapter(adapterIdx) {
    const adapter = adapters[adapterIdx];
    requestConfirm({
      title: "Delete Adapter",
      content: `Are you sure you want to delete the adapter "${adapter.name}"?`,
      onConfirm: () => {
        remove(adapterIdx);
      }
    });
  }
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(SectionListSection$1, { className, children: [
    /* @__PURE__ */ jsxRuntimeExports.jsxs(SectionListSectionHeader$1, { children: [
      /* @__PURE__ */ jsxRuntimeExports.jsx(SectionListSectionTitle$1, { children: "S3 Adapters" }),
      /* @__PURE__ */ jsxRuntimeExports.jsx(SectionListSectionDescription$1, { children: "Configure S3 storage adapters for file uploads. Each adapter can have its own bucket and configuration." })
    ] }),
    /* @__PURE__ */ jsxRuntimeExports.jsxs(SectionListSectionContent$1, { className: "storage:space-y-4", children: [
      adapters.map((adapter, adapterIdx) => /* @__PURE__ */ jsxRuntimeExports.jsxs(RecordView, { children: [
        /* @__PURE__ */ jsxRuntimeExports.jsxs(RecordViewItemList, { children: [
          /* @__PURE__ */ jsxRuntimeExports.jsx(RecordViewItem, { title: "Name", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "storage:flex storage:items-center storage:gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: adapter.name }) }) }),
          /* @__PURE__ */ jsxRuntimeExports.jsx(RecordViewItem, { title: "Bucket Config Variable", children: adapter.bucketConfigVar || /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "storage:text-muted-foreground", children: "Not configured" }) }),
          /* @__PURE__ */ jsxRuntimeExports.jsx(RecordViewItem, { title: "URL Prefix Config Variable", children: adapter.hostedUrlConfigVar ?? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "storage:text-muted-foreground", children: "Not configured" }) })
        ] }),
        /* @__PURE__ */ jsxRuntimeExports.jsxs(RecordViewActions, { children: [
          /* @__PURE__ */ jsxRuntimeExports.jsx(
            Button,
            {
              variant: "ghost",
              size: "icon",
              title: "Edit",
              "aria-label": "Edit adapter",
              onClick: () => {
                setAdapterToEdit(adapter);
                setIsEditing(true);
              },
              children: "Edit"
            }
          ),
          /* @__PURE__ */ jsxRuntimeExports.jsx(
            Button,
            {
              variant: "ghostDestructive",
              size: "icon",
              title: "Delete",
              "aria-label": "Delete adapter",
              onClick: () => {
                handleDeleteAdapter(adapterIdx);
              },
              children: "Delete"
            }
          )
        ] })
      ] }, adapter.id)),
      /* @__PURE__ */ jsxRuntimeExports.jsx(
        AdapterDialog,
        {
          open: isEditing,
          onOpenChange: setIsEditing,
          adapter: adapterToEdit,
          isNew: adapterToEdit ? !adapters.some((a) => a.id === adapterToEdit.id) : true,
          onSave: handleSaveAdapter
        }
      ),
      /* @__PURE__ */ jsxRuntimeExports.jsx(
        Button,
        {
          variant: "secondary",
          size: "sm",
          onClick: () => {
            setAdapterToEdit({
              id: storageAdapterEntityType.generateNewId(),
              name: "",
              bucketConfigVar: "",
              hostedUrlConfigVar: ""
            });
            setIsEditing(true);
          },
          children: "Add Adapter"
        }
      )
    ] })
  ] });
}

const {createAndApplyModelMergerResults,createModelMergerResults,doesModelMergerResultsHaveChanges,FeatureUtils,ModelUtils,PluginUtils} = await importShared('@baseplate-dev/project-builder-lib');

const {FeatureComboboxFieldController,ModelComboboxFieldController,ModelMergerResultAlert,useBlockUnsavedChangesNavigate,useDefinitionSchema,useProjectDefinition,useResettableForm} = await importShared('@baseplate-dev/project-builder-lib/web');

const {FormActionBar,SectionList,SectionListSection,SectionListSectionContent,SectionListSectionDescription,SectionListSectionHeader,SectionListSectionTitle} = await importShared('@baseplate-dev/ui-components');
const {useMemo} = await importShared('react');
function StorageDefinitionEditor({
  definition: pluginMetadata,
  metadata,
  onSave
}) {
  const { definition, definitionContainer, saveDefinitionWithFeedback } = useProjectDefinition();
  const storagePluginDefinitionSchema = useDefinitionSchema(
    createStoragePluginDefinitionSchema
  );
  const defaultValues = useMemo(() => {
    if (pluginMetadata?.config) {
      return pluginMetadata.config;
    }
    return {
      modelRefs: {
        file: ModelUtils.getModelIdByNameOrDefault(definition, "File")
      },
      storageFeatureRef: FeatureUtils.getFeatureIdByNameOrDefault(
        definition,
        "storage"
      ),
      s3Adapters: []
    };
  }, [definition, pluginMetadata?.config]);
  const form = useResettableForm({
    resolver: s(storagePluginDefinitionSchema),
    defaultValues
  });
  const { control, reset, handleSubmit, watch } = form;
  const modelRefs = watch("modelRefs");
  const storageFeatureRef = watch("storageFeatureRef");
  const pendingModelChanges = useMemo(() => {
    const desiredModels = createStorageModels(
      { storageFeatureRef },
      definitionContainer
    );
    return createModelMergerResults(
      modelRefs,
      desiredModels,
      definitionContainer
    );
  }, [definitionContainer, storageFeatureRef, modelRefs]);
  const onSubmit = handleSubmit(
    (data) => saveDefinitionWithFeedback(
      (draftConfig) => {
        const featureRef = FeatureUtils.ensureFeatureByNameRecursively(
          draftConfig,
          data.storageFeatureRef
        );
        const updatedData = {
          ...data,
          storageFeatureRef: featureRef
        };
        createAndApplyModelMergerResults(
          draftConfig,
          updatedData.modelRefs,
          createStorageModels(updatedData, definitionContainer),
          definitionContainer
        );
        PluginUtils.setPluginConfig(
          draftConfig,
          metadata,
          data,
          definitionContainer.pluginStore
        );
      },
      {
        successMessage: pluginMetadata ? "Successfully saved storage plugin!" : "Successfully enabled storage plugin!",
        onSuccess: () => {
          onSave();
        }
      }
    )
  );
  useBlockUnsavedChangesNavigate({ control, reset, onSubmit });
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
    "form",
    {
      onSubmit,
      className: "storage:mb-[--action-bar-height] storage:max-w-6xl",
      children: [
        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "storage:pb-16", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(SectionList, { children: [
          /* @__PURE__ */ jsxRuntimeExports.jsxs(SectionListSection, { children: [
            /* @__PURE__ */ jsxRuntimeExports.jsxs(SectionListSectionHeader, { children: [
              /* @__PURE__ */ jsxRuntimeExports.jsx(SectionListSectionTitle, { children: "Storage Configuration" }),
              /* @__PURE__ */ jsxRuntimeExports.jsx(SectionListSectionDescription, { children: "Configure your storage settings, file models, and S3 adapters." })
            ] }),
            /* @__PURE__ */ jsxRuntimeExports.jsxs(SectionListSectionContent, { className: "storage:space-y-6", children: [
              /* @__PURE__ */ jsxRuntimeExports.jsx(
                ModelMergerResultAlert,
                {
                  pendingModelChanges
                }
              ),
              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "storage:grid storage:grid-cols-1 storage:gap-6 storage:md:grid-cols-2", children: [
                /* @__PURE__ */ jsxRuntimeExports.jsx(
                  ModelComboboxFieldController,
                  {
                    label: "File Model",
                    name: "modelRefs.file",
                    control,
                    canCreate: true,
                    description: "The model to use for file storage"
                  }
                ),
                /* @__PURE__ */ jsxRuntimeExports.jsx(
                  FeatureComboboxFieldController,
                  {
                    label: "Storage Feature Path",
                    name: "storageFeatureRef",
                    control,
                    canCreate: true,
                    description: "Specify the feature path where storage endpoints will be generated"
                  }
                )
              ] })
            ] })
          ] }),
          /* @__PURE__ */ jsxRuntimeExports.jsx(AdapterEditorForm, { control })
        ] }) }),
        /* @__PURE__ */ jsxRuntimeExports.jsx(
          FormActionBar,
          {
            form,
            allowSaveWithoutDirty: !pluginMetadata || doesModelMergerResultsHaveChanges(pendingModelChanges)
          }
        )
      ]
    }
  );
}

const {createPlatformPluginExport,webConfigSpec} = await importShared('@baseplate-dev/project-builder-lib');
const web = createPlatformPluginExport({
  dependencies: {
    webConfig: webConfigSpec
  },
  exports: {},
  initialize: ({ webConfig }, { pluginKey }) => {
    webConfig.registerWebConfigComponent(pluginKey, StorageDefinitionEditor);
    return {};
  }
});

export { web as default };
//# sourceMappingURL=__federation_expose_storageCoreWeb-C6ppx84F.js.map
