@shipfox/client-secrets 12.0.2 → 14.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.
@@ -1,2 +1,2 @@
1
1
  $ shipfox-swc
2
- Successfully compiled: 22 files with swc (415.34ms)
2
+ Successfully compiled: 22 files with swc (468.79ms)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @shipfox/client-secrets
2
2
 
3
+ ## 14.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [baa7594]
8
+ - Updated dependencies [f8a98cb]
9
+ - Updated dependencies [1267eb3]
10
+ - Updated dependencies [b2d4550]
11
+ - @shipfox/react-ui@0.5.0
12
+ - @shipfox/client-ui@14.0.0
13
+ - @shipfox/client-shell@14.0.0
14
+
15
+ ## 13.0.0
16
+
17
+ ### Major Changes
18
+
19
+ - e405e92: Move client routes to slug-based `/w/$workspaceSlug` and `/p/$projectSlug` URLs, enforce the new composition contract, and support bounded project-slug resolution.
20
+
21
+ ### Patch Changes
22
+
23
+ - f78740d: Remove Unicode dash punctuation from package prose and source comments.
24
+ - Updated dependencies [e405e92]
25
+ - Updated dependencies [f78740d]
26
+ - Updated dependencies [9969937]
27
+ - Updated dependencies [3c73365]
28
+ - Updated dependencies [54c820e]
29
+ - Updated dependencies [6adc228]
30
+ - Updated dependencies [e1efaee]
31
+ - @shipfox/client-shell@13.0.0
32
+ - @shipfox/client-ui@13.0.0
33
+ - @shipfox/react-ui@0.4.0
34
+ - @shipfox/api-secrets-dto@12.0.0
35
+
3
36
  ## 12.0.2
4
37
 
5
38
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Copies a bare key name (e.g. `MY_TOKEN`) to the clipboard. Guarded because
3
- * `navigator.clipboard` is undefined in insecure contexts and older browsers
3
+ * `navigator.clipboard` is undefined in insecure contexts and older browsers.
4
4
  * a missing API or a rejected write surfaces a toast instead of an unhandled
5
5
  * rejection.
6
6
  */
@@ -1,7 +1,7 @@
1
1
  import { toast } from '@shipfox/react-ui/toast';
2
2
  /**
3
3
  * Copies a bare key name (e.g. `MY_TOKEN`) to the clipboard. Guarded because
4
- * `navigator.clipboard` is undefined in insecure contexts and older browsers
4
+ * `navigator.clipboard` is undefined in insecure contexts and older browsers.
5
5
  * a missing API or a rejected write surfaces a toast instead of an unhandled
6
6
  * rejection.
7
7
  */ export async function copyKeyName(key) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/copy-key.ts"],"sourcesContent":["import {toast} from '@shipfox/react-ui/toast';\n\n/**\n * Copies a bare key name (e.g. `MY_TOKEN`) to the clipboard. Guarded because\n * `navigator.clipboard` is undefined in insecure contexts and older browsers —\n * a missing API or a rejected write surfaces a toast instead of an unhandled\n * rejection.\n */\nexport async function copyKeyName(key: string): Promise<void> {\n const clipboard = typeof navigator === 'undefined' ? undefined : navigator.clipboard;\n if (!clipboard?.writeText) {\n toast.error('Clipboard is not available in this browser.');\n return;\n }\n try {\n await clipboard.writeText(key);\n toast.success(`Copied ${key}`);\n } catch {\n toast.error('Could not copy to the clipboard.');\n }\n}\n"],"names":["toast","copyKeyName","key","clipboard","navigator","undefined","writeText","error","success"],"mappings":"AAAA,SAAQA,KAAK,QAAO,0BAA0B;AAE9C;;;;;CAKC,GACD,OAAO,eAAeC,YAAYC,GAAW;IAC3C,MAAMC,YAAY,OAAOC,cAAc,cAAcC,YAAYD,UAAUD,SAAS;IACpF,IAAI,CAACA,WAAWG,WAAW;QACzBN,MAAMO,KAAK,CAAC;QACZ;IACF;IACA,IAAI;QACF,MAAMJ,UAAUG,SAAS,CAACJ;QAC1BF,MAAMQ,OAAO,CAAC,CAAC,OAAO,EAAEN,KAAK;IAC/B,EAAE,OAAM;QACNF,MAAMO,KAAK,CAAC;IACd;AACF"}
1
+ {"version":3,"sources":["../../src/components/copy-key.ts"],"sourcesContent":["import {toast} from '@shipfox/react-ui/toast';\n\n/**\n * Copies a bare key name (e.g. `MY_TOKEN`) to the clipboard. Guarded because\n * `navigator.clipboard` is undefined in insecure contexts and older browsers.\n * a missing API or a rejected write surfaces a toast instead of an unhandled\n * rejection.\n */\nexport async function copyKeyName(key: string): Promise<void> {\n const clipboard = typeof navigator === 'undefined' ? undefined : navigator.clipboard;\n if (!clipboard?.writeText) {\n toast.error('Clipboard is not available in this browser.');\n return;\n }\n try {\n await clipboard.writeText(key);\n toast.success(`Copied ${key}`);\n } catch {\n toast.error('Could not copy to the clipboard.');\n }\n}\n"],"names":["toast","copyKeyName","key","clipboard","navigator","undefined","writeText","error","success"],"mappings":"AAAA,SAAQA,KAAK,QAAO,0BAA0B;AAE9C;;;;;CAKC,GACD,OAAO,eAAeC,YAAYC,GAAW;IAC3C,MAAMC,YAAY,OAAOC,cAAc,cAAcC,YAAYD,UAAUD,SAAS;IACpF,IAAI,CAACA,WAAWG,WAAW;QACzBN,MAAMO,KAAK,CAAC;QACZ;IACF;IACA,IAAI;QACF,MAAMJ,UAAUG,SAAS,CAACJ;QAC1BF,MAAMQ,OAAO,CAAC,CAAC,OAAO,EAAEN,KAAK;IAC/B,EAAE,OAAM;QACNF,MAAMO,KAAK,CAAC;IACd;AACF"}
@@ -60,7 +60,7 @@ export function VariableForm({ workspaceId, mode, existingKey, existingValue, ex
60
60
  form
61
61
  ]);
62
62
  // The full value must be loaded before a save is allowed, otherwise submitting would
63
- // overwrite the stored value with the truncated preview. Block until it arrives
63
+ // overwrite the stored value with the truncated preview. Block until it arrives.
64
64
  // whether the fetch is still pending or has failed.
65
65
  const awaitingFullValue = needsFullValue && fullValueQuery.data === undefined;
66
66
  const loadingFullValue = needsFullValue && fullValueQuery.isPending;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/variable-form.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {\n FormField,\n FormFieldInput,\n FormFieldTextarea,\n fieldError,\n} from '@shipfox/react-ui/form-field';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport {useEffect, useRef, useState} from 'react';\nimport {\n normalizeStoreKey,\n STORE_KEY_HELP,\n shouldWarnSensitiveVariableName,\n validateNewStoreKey,\n workspaceStoreScope,\n} from '#core/store.js';\nimport {usePutVariableMutation, useVariableQuery} from '#hooks/api/variables.js';\nimport {secretsErrorToFormError} from './form-errors.js';\nimport {FormBody, FormFooter} from './form-shell.js';\n\nexport const VARIABLE_FORM_ID = 'variable-form';\n\nexport function VariableForm({\n workspaceId,\n mode,\n existingKey,\n existingValue,\n existingValueTruncated = false,\n reservedKeys = [],\n onSaved,\n onCancel,\n}: {\n workspaceId: string;\n mode: 'create' | 'edit';\n existingKey?: string | undefined;\n existingValue?: string | undefined;\n existingValueTruncated?: boolean | undefined;\n reservedKeys?: readonly string[] | undefined;\n onSaved: () => void;\n onCancel: () => void;\n}) {\n const putVariable = usePutVariableMutation();\n const [formError, setFormError] = useState<string | undefined>();\n\n // The list value is only a preview, so a truncated variable must load its full\n // value before editing to avoid saving the truncated preview back.\n const needsFullValue = mode === 'edit' && existingValueTruncated;\n const fullValueQuery = useVariableQuery(workspaceId, needsFullValue ? existingKey : undefined);\n\n const form = useForm({\n defaultValues: {key: existingKey ?? '', value: existingValue ?? ''},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n try {\n await putVariable.mutateAsync({\n workspaceId,\n key: normalizeStoreKey(value.key),\n value: value.value,\n scope: workspaceStoreScope,\n });\n onSaved();\n } catch (error) {\n const mapped = secretsErrorToFormError(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n } else {\n setFormError(mapped.message);\n }\n }\n },\n });\n\n const populatedRef = useRef(false);\n useEffect(() => {\n if (needsFullValue && fullValueQuery.data && !populatedRef.current) {\n populatedRef.current = true;\n form.setFieldValue('value', fullValueQuery.data.value);\n }\n }, [needsFullValue, fullValueQuery.data, form]);\n\n // The full value must be loaded before a save is allowed, otherwise submitting would\n // overwrite the stored value with the truncated preview. Block until it arrives —\n // whether the fetch is still pending or has failed.\n const awaitingFullValue = needsFullValue && fullValueQuery.data === undefined;\n const loadingFullValue = needsFullValue && fullValueQuery.isPending;\n\n return (\n <>\n <FormBody>\n <form\n id={VARIABLE_FORM_ID}\n className=\"flex w-full flex-col gap-16\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <form.Field\n name=\"key\"\n validators={{\n onBlur: ({value}) =>\n validateNewStoreKey(value, {mode, reservedKeys, kind: 'variable'}),\n onSubmit: ({value}) =>\n validateNewStoreKey(value, {mode, reservedKeys, kind: 'variable'}),\n }}\n >\n {(field) => (\n <FormField\n label=\"Name\"\n id=\"variable-key\"\n description={STORE_KEY_HELP}\n error={fieldError(field)}\n >\n <FormFieldInput\n className=\"font-code\"\n autoComplete=\"off\"\n spellCheck={false}\n disabled={mode === 'edit'}\n placeholder=\"LOG_LEVEL\"\n value={field.state.value}\n onChange={(event) => field.handleChange(normalizeStoreKey(event.target.value))}\n onBlur={field.handleBlur}\n />\n {shouldWarnSensitiveVariableName(field.state.value) ? (\n <Callout role=\"alert\" type=\"warning\">\n <Text size=\"sm\" aria-live=\"polite\">\n This looks like it may be sensitive. Variables are stored in plaintext and are\n not redacted from logs. Use a Secret if this value contains private data.\n </Text>\n </Callout>\n ) : null}\n </FormField>\n )}\n </form.Field>\n\n <form.Field name=\"value\">\n {(field) => (\n <FormField\n label=\"Value\"\n id=\"variable-value\"\n error={fieldError(field)}\n description={loadingFullValue ? 'Loading the current value…' : undefined}\n >\n <FormFieldTextarea\n className=\"font-code\"\n autoComplete=\"off\"\n spellCheck={false}\n rows={3}\n disabled={awaitingFullValue}\n placeholder=\"debug\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </form>\n {awaitingFullValue && fullValueQuery.isError ? (\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">Could not load the current value. Close and try again.</Text>\n </Callout>\n ) : null}\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">{formError}</Text>\n </Callout>\n ) : null}\n </FormBody>\n <FormFooter>\n <Button variant=\"secondary\" type=\"button\" onClick={onCancel}>\n Cancel\n </Button>\n <Button\n type=\"submit\"\n form={VARIABLE_FORM_ID}\n isLoading={putVariable.isPending}\n disabled={awaitingFullValue}\n >\n {mode === 'edit' ? 'Update variable' : 'Create variable'}\n </Button>\n </FormFooter>\n </>\n );\n}\n"],"names":["Button","Callout","FormField","FormFieldInput","FormFieldTextarea","fieldError","Text","useForm","useEffect","useRef","useState","normalizeStoreKey","STORE_KEY_HELP","shouldWarnSensitiveVariableName","validateNewStoreKey","workspaceStoreScope","usePutVariableMutation","useVariableQuery","secretsErrorToFormError","FormBody","FormFooter","VARIABLE_FORM_ID","VariableForm","workspaceId","mode","existingKey","existingValue","existingValueTruncated","reservedKeys","onSaved","onCancel","putVariable","formError","setFormError","needsFullValue","fullValueQuery","undefined","form","defaultValues","key","value","onSubmit","mutateAsync","scope","error","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","populatedRef","data","current","setFieldValue","awaitingFullValue","loadingFullValue","isPending","id","className","noValidate","event","preventDefault","stopPropagation","handleSubmit","Field","name","validators","onBlur","label","description","autoComplete","spellCheck","disabled","placeholder","state","onChange","handleChange","target","handleBlur","role","type","size","aria-live","rows","isError","variant","onClick","isLoading"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/components/variable-form.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {\n FormField,\n FormFieldInput,\n FormFieldTextarea,\n fieldError,\n} from '@shipfox/react-ui/form-field';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport {useEffect, useRef, useState} from 'react';\nimport {\n normalizeStoreKey,\n STORE_KEY_HELP,\n shouldWarnSensitiveVariableName,\n validateNewStoreKey,\n workspaceStoreScope,\n} from '#core/store.js';\nimport {usePutVariableMutation, useVariableQuery} from '#hooks/api/variables.js';\nimport {secretsErrorToFormError} from './form-errors.js';\nimport {FormBody, FormFooter} from './form-shell.js';\n\nexport const VARIABLE_FORM_ID = 'variable-form';\n\nexport function VariableForm({\n workspaceId,\n mode,\n existingKey,\n existingValue,\n existingValueTruncated = false,\n reservedKeys = [],\n onSaved,\n onCancel,\n}: {\n workspaceId: string;\n mode: 'create' | 'edit';\n existingKey?: string | undefined;\n existingValue?: string | undefined;\n existingValueTruncated?: boolean | undefined;\n reservedKeys?: readonly string[] | undefined;\n onSaved: () => void;\n onCancel: () => void;\n}) {\n const putVariable = usePutVariableMutation();\n const [formError, setFormError] = useState<string | undefined>();\n\n // The list value is only a preview, so a truncated variable must load its full\n // value before editing to avoid saving the truncated preview back.\n const needsFullValue = mode === 'edit' && existingValueTruncated;\n const fullValueQuery = useVariableQuery(workspaceId, needsFullValue ? existingKey : undefined);\n\n const form = useForm({\n defaultValues: {key: existingKey ?? '', value: existingValue ?? ''},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n try {\n await putVariable.mutateAsync({\n workspaceId,\n key: normalizeStoreKey(value.key),\n value: value.value,\n scope: workspaceStoreScope,\n });\n onSaved();\n } catch (error) {\n const mapped = secretsErrorToFormError(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n } else {\n setFormError(mapped.message);\n }\n }\n },\n });\n\n const populatedRef = useRef(false);\n useEffect(() => {\n if (needsFullValue && fullValueQuery.data && !populatedRef.current) {\n populatedRef.current = true;\n form.setFieldValue('value', fullValueQuery.data.value);\n }\n }, [needsFullValue, fullValueQuery.data, form]);\n\n // The full value must be loaded before a save is allowed, otherwise submitting would\n // overwrite the stored value with the truncated preview. Block until it arrives.\n // whether the fetch is still pending or has failed.\n const awaitingFullValue = needsFullValue && fullValueQuery.data === undefined;\n const loadingFullValue = needsFullValue && fullValueQuery.isPending;\n\n return (\n <>\n <FormBody>\n <form\n id={VARIABLE_FORM_ID}\n className=\"flex w-full flex-col gap-16\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <form.Field\n name=\"key\"\n validators={{\n onBlur: ({value}) =>\n validateNewStoreKey(value, {mode, reservedKeys, kind: 'variable'}),\n onSubmit: ({value}) =>\n validateNewStoreKey(value, {mode, reservedKeys, kind: 'variable'}),\n }}\n >\n {(field) => (\n <FormField\n label=\"Name\"\n id=\"variable-key\"\n description={STORE_KEY_HELP}\n error={fieldError(field)}\n >\n <FormFieldInput\n className=\"font-code\"\n autoComplete=\"off\"\n spellCheck={false}\n disabled={mode === 'edit'}\n placeholder=\"LOG_LEVEL\"\n value={field.state.value}\n onChange={(event) => field.handleChange(normalizeStoreKey(event.target.value))}\n onBlur={field.handleBlur}\n />\n {shouldWarnSensitiveVariableName(field.state.value) ? (\n <Callout role=\"alert\" type=\"warning\">\n <Text size=\"sm\" aria-live=\"polite\">\n This looks like it may be sensitive. Variables are stored in plaintext and are\n not redacted from logs. Use a Secret if this value contains private data.\n </Text>\n </Callout>\n ) : null}\n </FormField>\n )}\n </form.Field>\n\n <form.Field name=\"value\">\n {(field) => (\n <FormField\n label=\"Value\"\n id=\"variable-value\"\n error={fieldError(field)}\n description={loadingFullValue ? 'Loading the current value…' : undefined}\n >\n <FormFieldTextarea\n className=\"font-code\"\n autoComplete=\"off\"\n spellCheck={false}\n rows={3}\n disabled={awaitingFullValue}\n placeholder=\"debug\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </form>\n {awaitingFullValue && fullValueQuery.isError ? (\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">Could not load the current value. Close and try again.</Text>\n </Callout>\n ) : null}\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">{formError}</Text>\n </Callout>\n ) : null}\n </FormBody>\n <FormFooter>\n <Button variant=\"secondary\" type=\"button\" onClick={onCancel}>\n Cancel\n </Button>\n <Button\n type=\"submit\"\n form={VARIABLE_FORM_ID}\n isLoading={putVariable.isPending}\n disabled={awaitingFullValue}\n >\n {mode === 'edit' ? 'Update variable' : 'Create variable'}\n </Button>\n </FormFooter>\n </>\n );\n}\n"],"names":["Button","Callout","FormField","FormFieldInput","FormFieldTextarea","fieldError","Text","useForm","useEffect","useRef","useState","normalizeStoreKey","STORE_KEY_HELP","shouldWarnSensitiveVariableName","validateNewStoreKey","workspaceStoreScope","usePutVariableMutation","useVariableQuery","secretsErrorToFormError","FormBody","FormFooter","VARIABLE_FORM_ID","VariableForm","workspaceId","mode","existingKey","existingValue","existingValueTruncated","reservedKeys","onSaved","onCancel","putVariable","formError","setFormError","needsFullValue","fullValueQuery","undefined","form","defaultValues","key","value","onSubmit","mutateAsync","scope","error","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","populatedRef","data","current","setFieldValue","awaitingFullValue","loadingFullValue","isPending","id","className","noValidate","event","preventDefault","stopPropagation","handleSubmit","Field","name","validators","onBlur","label","description","autoComplete","spellCheck","disabled","placeholder","state","onChange","handleChange","target","handleBlur","role","type","size","aria-live","rows","isError","variant","onClick","isLoading"],"mappings":"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"}
package/dist/feature.d.ts CHANGED
@@ -14,11 +14,11 @@ export declare const secretsSettingsSections: readonly [{
14
14
  export declare const secretsFeature: {
15
15
  readonly id: "shipfox.secrets";
16
16
  readonly routes: readonly [{
17
- readonly path: "/workspaces/$wid/settings/secrets";
17
+ readonly path: "/w/$workspaceSlug/settings/secrets";
18
18
  readonly parent: "workspaceSettings";
19
19
  readonly impl: "@shipfox/client-secrets/routes/secrets-settings";
20
20
  }, {
21
- readonly path: "/workspaces/$wid/settings/variables";
21
+ readonly path: "/w/$workspaceSlug/settings/variables";
22
22
  readonly parent: "workspaceSettings";
23
23
  readonly impl: "@shipfox/client-secrets/routes/variables-settings";
24
24
  }];
package/dist/feature.js CHANGED
@@ -19,12 +19,12 @@ export const secretsFeature = defineClientFeature({
19
19
  id: 'shipfox.secrets',
20
20
  routes: [
21
21
  {
22
- path: '/workspaces/$wid/settings/secrets',
22
+ path: '/w/$workspaceSlug/settings/secrets',
23
23
  parent: 'workspaceSettings',
24
24
  impl: '@shipfox/client-secrets/routes/secrets-settings'
25
25
  },
26
26
  {
27
- path: '/workspaces/$wid/settings/variables',
27
+ path: '/w/$workspaceSlug/settings/variables',
28
28
  parent: 'workspaceSettings',
29
29
  impl: '@shipfox/client-secrets/routes/variables-settings'
30
30
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/feature.ts"],"sourcesContent":["import {defineClientFeature, type SettingsSectionEntry} from '@shipfox/client-shell';\n\nexport const secretsSettingsSections = [\n {id: 'settings.secrets', pathSegment: 'secrets', label: 'Secrets', icon: 'keyLine', order: 500},\n {\n id: 'settings.variables',\n pathSegment: 'variables',\n label: 'Variables',\n icon: 'bracesLine',\n order: 600,\n },\n] as const satisfies readonly SettingsSectionEntry[];\n\nexport const secretsFeature = defineClientFeature({\n id: 'shipfox.secrets',\n routes: [\n {\n path: '/workspaces/$wid/settings/secrets',\n parent: 'workspaceSettings',\n impl: '@shipfox/client-secrets/routes/secrets-settings',\n },\n {\n path: '/workspaces/$wid/settings/variables',\n parent: 'workspaceSettings',\n impl: '@shipfox/client-secrets/routes/variables-settings',\n },\n ],\n settingsSections: secretsSettingsSections,\n});\n"],"names":["defineClientFeature","secretsSettingsSections","id","pathSegment","label","icon","order","secretsFeature","routes","path","parent","impl","settingsSections"],"mappings":"AAAA,SAAQA,mBAAmB,QAAkC,wBAAwB;AAErF,OAAO,MAAMC,0BAA0B;IACrC;QAACC,IAAI;QAAoBC,aAAa;QAAWC,OAAO;QAAWC,MAAM;QAAWC,OAAO;IAAG;IAC9F;QACEJ,IAAI;QACJC,aAAa;QACbC,OAAO;QACPC,MAAM;QACNC,OAAO;IACT;CACD,CAAoD;AAErD,OAAO,MAAMC,iBAAiBP,oBAAoB;IAChDE,IAAI;IACJM,QAAQ;QACN;YACEC,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;KACD;IACDC,kBAAkBX;AACpB,GAAG"}
1
+ {"version":3,"sources":["../src/feature.ts"],"sourcesContent":["import {defineClientFeature, type SettingsSectionEntry} from '@shipfox/client-shell';\n\nexport const secretsSettingsSections = [\n {id: 'settings.secrets', pathSegment: 'secrets', label: 'Secrets', icon: 'keyLine', order: 500},\n {\n id: 'settings.variables',\n pathSegment: 'variables',\n label: 'Variables',\n icon: 'bracesLine',\n order: 600,\n },\n] as const satisfies readonly SettingsSectionEntry[];\n\nexport const secretsFeature = defineClientFeature({\n id: 'shipfox.secrets',\n routes: [\n {\n path: '/w/$workspaceSlug/settings/secrets',\n parent: 'workspaceSettings',\n impl: '@shipfox/client-secrets/routes/secrets-settings',\n },\n {\n path: '/w/$workspaceSlug/settings/variables',\n parent: 'workspaceSettings',\n impl: '@shipfox/client-secrets/routes/variables-settings',\n },\n ],\n settingsSections: secretsSettingsSections,\n});\n"],"names":["defineClientFeature","secretsSettingsSections","id","pathSegment","label","icon","order","secretsFeature","routes","path","parent","impl","settingsSections"],"mappings":"AAAA,SAAQA,mBAAmB,QAAkC,wBAAwB;AAErF,OAAO,MAAMC,0BAA0B;IACrC;QAACC,IAAI;QAAoBC,aAAa;QAAWC,OAAO;QAAWC,MAAM;QAAWC,OAAO;IAAG;IAC9F;QACEJ,IAAI;QACJC,aAAa;QACbC,OAAO;QACPC,MAAM;QACNC,OAAO;IACT;CACD,CAAoD;AAErD,OAAO,MAAMC,iBAAiBP,oBAAoB;IAChDE,IAAI;IACJM,QAAQ;QACN;YACEC,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;KACD;IACDC,kBAAkBX;AACpB,GAAG"}