@fluid-app/fluid-cli-portal 0.1.132 → 0.1.133

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 +1 @@
1
- {"version":3,"file":"src-BuSYN4Co.mjs","names":["isRecord","toPosixPath","isRecord","isRecord","isRecord","isRecord","isRecord"],"sources":["../../../portal/core/src/remote-dom-widget-package.ts","../../widget-tooling/src/errors.ts","../../widget-tooling/src/internal/widget-package-artifacts.ts","../../widget-tooling/src/internal/widget-package-validation.ts","../../widget-tooling/src/development-descriptor.ts","../../widget-tooling/src/dev-routes.ts","../../widget-tooling/src/node-runtime.ts","../../widget-tooling/src/internal/widget-package-config.ts","../../widget-tooling/src/internal/widget-package-builder.ts","../../widget-tooling/src/internal/widget-package-publish-request.ts","../../widget-tooling/src/internal/widget-package-upload.ts","../../widget-tooling/src/workflows.ts","../../widget-tooling/src/company-widget-package.ts"],"sourcesContent":["import type {\n ButtonGroupFieldSchema,\n PropertyField,\n WidgetPropertySchema,\n} from \"./registries/property-schema-types\";\n\nexport const REMOTE_DOM_WIDGET_MANIFEST_VERSION = 1 as const;\nexport const REMOTE_DOM_WIDGET_RUNTIME = \"remote-dom\" as const;\n\nexport type JsonPrimitive = string | number | boolean | null;\n\nexport type JsonValue = JsonPrimitive | readonly JsonValue[] | JsonObject;\n\nexport interface JsonObject {\n readonly [key: string]: JsonValue;\n}\n\ntype SerializableValue<Value> = unknown extends Value\n ? JsonValue\n : Value extends JsonValue\n ? Value\n : Value extends readonly (infer Item)[]\n ? readonly SerializableValue<Item>[]\n : Value extends object\n ? {\n readonly [Key in keyof Value as NonNullable<Value[Key]> extends (\n ...args: never[]\n ) => unknown\n ? never\n : Key]: SerializableValue<Value[Key]>;\n }\n : never;\n\n/**\n * A property field that can be included in published widget metadata.\n *\n * The legacy `color` field is deprecated. Use `colorSelect` so the value is a\n * semantic color token supplied by the portal theme.\n */\nexport type WidgetSourcePropertyField = PropertyField extends infer Field\n ? Field extends ButtonGroupFieldSchema\n ? Omit<SerializableValue<Field>, \"options\"> & {\n /** Serializable button choices. Runtime icon components are not supported. */\n readonly options: readonly {\n readonly label?: string;\n readonly ariaLabel?: string;\n readonly value: string | number;\n }[];\n }\n : SerializableValue<Field>\n : never;\n\n/**\n * JSON-serializable property editor schema accepted by widget source metadata.\n * The build adds `widgetType`; authors must not supply it.\n */\nexport interface WidgetSourcePropertySchema {\n /** Optional tabs used to organize the property editor. */\n readonly tabsConfig?: SerializableValue<\n NonNullable<WidgetPropertySchema[\"tabsConfig\"]>\n >;\n /** Editable fields shown in the property editor. */\n readonly fields: readonly WidgetSourcePropertyField[];\n /** Widget props that data sources can populate. */\n readonly dataSourceTargetProps?: readonly string[];\n /** Optional per-item fields for custom data-source selections. */\n readonly itemConfigSchema?: {\n /** Fields available for each selected item. */\n readonly fields: readonly WidgetSourcePropertyField[];\n /** Help text shown above the per-item editor. */\n readonly description?: string;\n };\n}\n\nexport interface RemoteDomWidgetCapabilityDeclaration {\n readonly name: string;\n readonly version: string;\n}\n\nexport interface RemoteDomWidgetDefinition {\n readonly type: string;\n readonly displayName: string;\n readonly description: string;\n readonly icon: string;\n readonly category: string;\n readonly propertySchema: JsonObject;\n readonly defaultProps: JsonObject;\n readonly container: \"inline\" | \"block\" | \"card\" | \"fullscreen\";\n readonly resizable: boolean | \"horizontal\" | \"vertical\" | \"both\";\n readonly minSdkVersion: string;\n readonly capabilities: readonly RemoteDomWidgetCapabilityDeclaration[];\n}\n\n/**\n * Canonical package contract shared by the CLI, catalog APIs, and portal hosts.\n * Catalog producers resolve every artifact to its public URL before returning\n * this descriptor; consumers do not translate legacy manifest shapes.\n */\nexport interface RemoteDomWidgetPackageDescriptor {\n readonly manifestVersion: typeof REMOTE_DOM_WIDGET_MANIFEST_VERSION;\n readonly runtime: typeof REMOTE_DOM_WIDGET_RUNTIME;\n readonly packageId: string;\n readonly source: \"company\" | \"droplet\";\n readonly version: string;\n readonly workerEntryUrl: string;\n readonly cssUrls: readonly string[];\n readonly assetUrls: readonly string[];\n readonly widgets: readonly RemoteDomWidgetDefinition[];\n}\n\nconst PACKAGE_FIELDS = new Set([\n \"manifestVersion\",\n \"runtime\",\n \"packageId\",\n \"source\",\n \"version\",\n \"workerEntryUrl\",\n \"cssUrls\",\n \"assetUrls\",\n \"widgets\",\n]);\n\nconst WIDGET_FIELDS = new Set([\n \"type\",\n \"displayName\",\n \"description\",\n \"icon\",\n \"category\",\n \"propertySchema\",\n \"defaultProps\",\n \"container\",\n \"resizable\",\n \"minSdkVersion\",\n \"capabilities\",\n]);\n\nconst CAPABILITY_FIELDS = new Set([\"name\", \"version\"]);\nconst UNSAFE_JSON_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nexport function validateRemoteDomWidgetPackageDescriptor(\n value: unknown,\n): asserts value is RemoteDomWidgetPackageDescriptor {\n const invalidReason = getRemoteDomWidgetPackageInvalidReason(value);\n if (invalidReason) {\n throw new TypeError(`Invalid Remote DOM widget package: ${invalidReason}`);\n }\n}\n\nexport function isRemoteDomWidgetPackageDescriptor(\n value: unknown,\n): value is RemoteDomWidgetPackageDescriptor {\n return getRemoteDomWidgetPackageInvalidReason(value) === undefined;\n}\n\nfunction getRemoteDomWidgetPackageInvalidReason(\n value: unknown,\n): string | undefined {\n if (!isRecord(value)) return \"descriptor must be an object\";\n\n const unexpectedFieldReason = getUnexpectedFieldReason(\n value,\n PACKAGE_FIELDS,\n \"descriptor\",\n );\n if (unexpectedFieldReason) return unexpectedFieldReason;\n\n if (value.manifestVersion !== REMOTE_DOM_WIDGET_MANIFEST_VERSION) {\n return `manifestVersion must be ${REMOTE_DOM_WIDGET_MANIFEST_VERSION}`;\n }\n if (value.runtime !== REMOTE_DOM_WIDGET_RUNTIME) {\n return `runtime must be ${REMOTE_DOM_WIDGET_RUNTIME}`;\n }\n\n const packageIdReason = getNonEmptyStringReason(value.packageId, \"packageId\");\n if (packageIdReason) return packageIdReason;\n\n if (value.source !== \"company\" && value.source !== \"droplet\") {\n return \"source must be company or droplet\";\n }\n\n const versionReason = getNonEmptyStringReason(value.version, \"version\");\n if (versionReason) return versionReason;\n\n const workerEntryUrlReason = getHttpUrlReason(\n value.workerEntryUrl,\n \"workerEntryUrl\",\n );\n if (workerEntryUrlReason) return workerEntryUrlReason;\n\n const cssUrlsReason = getUrlArrayReason(value.cssUrls, \"cssUrls\");\n if (cssUrlsReason) return cssUrlsReason;\n\n const assetUrlsReason = getUrlArrayReason(value.assetUrls, \"assetUrls\");\n if (assetUrlsReason) return assetUrlsReason;\n\n if (!Array.isArray(value.widgets) || value.widgets.length === 0) {\n return \"widgets must be a non-empty array\";\n }\n\n const widgetTypes = new Set<string>();\n for (let index = 0; index < value.widgets.length; index += 1) {\n const widget = value.widgets[index];\n const widgetReason = getWidgetReason(widget, `widgets[${index}]`);\n if (widgetReason) return widgetReason;\n\n const widgetType = widget.type;\n if (widgetTypes.has(widgetType)) {\n return `widgets contains duplicate type ${widgetType}`;\n }\n widgetTypes.add(widgetType);\n }\n\n return undefined;\n}\n\nfunction getWidgetReason(value: unknown, path: string): string | undefined {\n if (!isRecord(value)) return `${path} must be an object`;\n\n const unexpectedFieldReason = getUnexpectedFieldReason(\n value,\n WIDGET_FIELDS,\n path,\n );\n if (unexpectedFieldReason) return unexpectedFieldReason;\n\n for (const field of [\n \"type\",\n \"displayName\",\n \"description\",\n \"icon\",\n \"category\",\n \"minSdkVersion\",\n ] as const) {\n const reason = getNonEmptyStringReason(value[field], `${path}.${field}`);\n if (reason) return reason;\n }\n\n if (!isRecord(value.propertySchema) || !isJsonValue(value.propertySchema)) {\n return `${path}.propertySchema must be a JSON object`;\n }\n if (!isRecord(value.defaultProps) || !isJsonValue(value.defaultProps)) {\n return `${path}.defaultProps must be a JSON object`;\n }\n\n if (\n value.container !== \"inline\" &&\n value.container !== \"block\" &&\n value.container !== \"card\" &&\n value.container !== \"fullscreen\"\n ) {\n return `${path}.container is unsupported`;\n }\n\n if (\n typeof value.resizable !== \"boolean\" &&\n value.resizable !== \"horizontal\" &&\n value.resizable !== \"vertical\" &&\n value.resizable !== \"both\"\n ) {\n return `${path}.resizable is unsupported`;\n }\n\n if (!Array.isArray(value.capabilities)) {\n return `${path}.capabilities must be an array`;\n }\n\n const capabilityNames = new Set<string>();\n for (let index = 0; index < value.capabilities.length; index += 1) {\n const capability = value.capabilities[index];\n const capabilityPath = `${path}.capabilities[${index}]`;\n if (!isRecord(capability)) return `${capabilityPath} must be an object`;\n\n const unexpectedFieldReason = getUnexpectedFieldReason(\n capability,\n CAPABILITY_FIELDS,\n capabilityPath,\n );\n if (unexpectedFieldReason) return unexpectedFieldReason;\n\n const capabilityName = capability.name;\n const nameReason = getNonEmptyStringReason(\n capabilityName,\n `${capabilityPath}.name`,\n );\n if (nameReason) return nameReason;\n if (typeof capabilityName !== \"string\") {\n return `${capabilityPath}.name must be a non-empty string`;\n }\n\n const versionReason = getNonEmptyStringReason(\n capability.version,\n `${capabilityPath}.version`,\n );\n if (versionReason) return versionReason;\n\n if (capabilityNames.has(capabilityName)) {\n return `${path}.capabilities contains duplicate name ${capabilityName}`;\n }\n capabilityNames.add(capabilityName);\n }\n\n return undefined;\n}\n\nfunction getUrlArrayReason(value: unknown, path: string): string | undefined {\n if (!Array.isArray(value)) return `${path} must be an array`;\n\n for (let index = 0; index < value.length; index += 1) {\n const reason = getHttpUrlReason(value[index], `${path}[${index}]`);\n if (reason) return reason;\n }\n return undefined;\n}\n\nfunction getHttpUrlReason(value: unknown, path: string): string | undefined {\n const stringReason = getNonEmptyStringReason(value, path);\n if (stringReason) return stringReason;\n if (typeof value !== \"string\") return `${path} must be a non-empty string`;\n\n try {\n const url = new URL(value);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return `${path} must use http or https`;\n }\n if (url.username || url.password) {\n return `${path} must not contain credentials`;\n }\n } catch {\n return `${path} must be an absolute URL`;\n }\n\n return undefined;\n}\n\nfunction getNonEmptyStringReason(\n value: unknown,\n path: string,\n): string | undefined {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return `${path} must be a non-empty string`;\n }\n if (value !== value.trim())\n return `${path} must not have surrounding whitespace`;\n if (/\\p{Cc}/u.test(value))\n return `${path} must not contain control characters`;\n return undefined;\n}\n\nexport function isJsonValue(value: unknown): value is JsonValue {\n return isJsonValueAtDepth(value, new WeakSet<object>(), 0);\n}\n\nfunction isJsonValueAtDepth(\n value: unknown,\n ancestors: WeakSet<object>,\n depth: number,\n): value is JsonValue {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\"\n ) {\n return true;\n }\n if (typeof value === \"number\") return Number.isFinite(value);\n if (typeof value !== \"object\" || depth > 50 || ancestors.has(value)) {\n return false;\n }\n\n ancestors.add(value);\n const prototype = Object.getPrototypeOf(value);\n const isJson = Array.isArray(value)\n ? value.every((item) => isJsonValueAtDepth(item, ancestors, depth + 1))\n : (prototype === Object.prototype || prototype === null) &&\n isRecord(value) &&\n Object.entries(value).every(\n ([key, item]) =>\n !UNSAFE_JSON_KEYS.has(key) &&\n isJsonValueAtDepth(item, ancestors, depth + 1),\n );\n ancestors.delete(value);\n return isJson;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction getUnexpectedFieldReason(\n value: Readonly<Record<string, unknown>>,\n allowedFields: ReadonlySet<string>,\n path: string,\n): string | undefined {\n const unexpectedField = Object.keys(value).find(\n (field) => !allowedFields.has(field),\n );\n return unexpectedField\n ? `${path} contains unsupported field ${unexpectedField}`\n : undefined;\n}\n","import type { WidgetPackageValidationError } from \"./internal/widget-package-validation.js\";\n\nexport type WidgetToolingErrorCode =\n | \"CONFIG_LOAD_FAILED\"\n | \"VALIDATION_FAILED\"\n | \"INVALID_OUTPUT_DIR\"\n | \"BUILD_FAILED\"\n | \"ARTIFACT_VERIFICATION_FAILED\"\n | \"OWNER_MISMATCH\"\n | \"CLIENT_REQUIRED\"\n | \"SESSION_REQUEST_FAILED\"\n | \"INVALID_SESSION_RESPONSE\"\n | \"MISSING_SIGNED_URL\"\n | \"CONTENT_TYPE_MISMATCH\"\n | \"ARTIFACT_UPLOAD_FAILED\"\n | \"COMPLETE_UPLOAD_FAILED\"\n | \"INVALID_COMPLETE_RESPONSE\"\n | \"PUBLISH_FAILED\";\n\nexport interface WidgetToolingErrorOptions extends ErrorOptions {\n readonly details?: string;\n readonly diagnostics?: readonly WidgetPackageValidationError[];\n}\n\nexport class WidgetToolingError extends Error {\n public readonly code: WidgetToolingErrorCode;\n public readonly details?: string;\n public readonly diagnostics?: readonly WidgetPackageValidationError[];\n\n constructor(\n code: WidgetToolingErrorCode,\n message: string,\n options: WidgetToolingErrorOptions = {},\n ) {\n super(message, options);\n this.name = \"WidgetToolingError\";\n this.code = code;\n this.details = options.details;\n this.diagnostics = options.diagnostics;\n }\n}\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\nimport { createHash } from \"node:crypto\";\n\n/** Version of the shared widget-tooling package that produced the artifacts. */\nexport const WIDGET_PACKAGE_BUILDER_VERSION = \"0.1.0\";\n\nexport interface ArtifactMetadata {\n readonly path: string;\n readonly sha256: string;\n readonly bytes: number;\n readonly contentType: string;\n}\n\nexport interface PublishManifestMetadata {\n readonly packageId: string;\n readonly version: string;\n readonly builderVersion: string;\n readonly cliVersion: string;\n readonly runtimeVersion: string;\n readonly manifestHash: string;\n readonly artifacts: readonly ArtifactMetadata[];\n}\n\nconst CONTENT_TYPES: Readonly<Record<string, string>> = {\n \".css\": \"text/css\",\n \".js\": \"application/javascript\",\n \".json\": \"application/json\",\n \".map\": \"application/json\",\n};\nconst CSS_ARTIFACT_PATH_PATTERN = /^[A-Za-z0-9._~-]+\\.css$/;\nconst JS_MAP_ARTIFACT_PATH_PATTERN = /^[A-Za-z0-9._~-]+\\.js\\.map$/;\n\nexport async function computeArtifactMetadata(\n filePath: string,\n baseDir: string,\n): Promise<ArtifactMetadata> {\n const relativePath = toPosixPath(path.relative(baseDir, filePath));\n assertAllowedArtifactPath(relativePath);\n await assertRegularArtifactFile(filePath, relativePath);\n const buffer = await fs.readFile(filePath);\n\n return {\n path: relativePath,\n sha256: sha256(buffer),\n bytes: buffer.byteLength,\n contentType: getArtifactContentType(filePath),\n };\n}\n\nexport async function collectWidgetPackageArtifacts(\n publishDir: string,\n): Promise<ArtifactMetadata[]> {\n const artifactPaths = await findArtifactPaths(publishDir);\n const artifacts = await Promise.all(\n artifactPaths.map((artifactPath) =>\n computeArtifactMetadata(artifactPath, publishDir),\n ),\n );\n\n assertRequiredUploadArtifacts(artifacts);\n\n return artifacts.sort((a, b) => a.path.localeCompare(b.path));\n}\n\nexport function createPublishManifestMetadata(options: {\n readonly packageId: string;\n readonly version: string;\n readonly cliVersion: string;\n readonly runtimeVersion: string;\n readonly manifestContent: string | Buffer;\n readonly artifacts: readonly ArtifactMetadata[];\n readonly builderVersion?: string;\n}): PublishManifestMetadata {\n return {\n packageId: options.packageId,\n version: options.version,\n builderVersion: options.builderVersion ?? WIDGET_PACKAGE_BUILDER_VERSION,\n cliVersion: options.cliVersion,\n runtimeVersion: options.runtimeVersion,\n manifestHash: sha256(options.manifestContent),\n artifacts: options.artifacts,\n };\n}\n\nexport function getArtifactContentType(filePath: string): string {\n const basename = path.basename(filePath);\n if (basename.endsWith(\".js.map\")) {\n return \"application/json\";\n }\n return CONTENT_TYPES[path.extname(filePath)] ?? \"application/octet-stream\";\n}\n\nexport function sha256(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nexport function isWidgetPackageCssArtifactPath(relativePath: string): boolean {\n return CSS_ARTIFACT_PATH_PATTERN.test(relativePath);\n}\n\nexport function isWidgetPackageJsMapArtifactPath(\n relativePath: string,\n): boolean {\n return JS_MAP_ARTIFACT_PATH_PATTERN.test(relativePath);\n}\n\nasync function assertRegularArtifactFile(\n filePath: string,\n relativePath: string,\n): Promise<void> {\n const stat = await fs.lstat(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(\n `Widget publish artifact ${JSON.stringify(relativePath)} must be a regular file and must not be a symbolic link.`,\n );\n }\n if (!stat.isFile()) {\n throw new Error(\n `Widget publish artifact ${JSON.stringify(relativePath)} must be a regular file.`,\n );\n }\n}\n\nasync function findArtifactPaths(\n dir: string,\n baseDir: string = dir,\n): Promise<string[]> {\n if (!(await fs.pathExists(dir))) return [];\n\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const paths = await Promise.all(\n entries.map(async (entry) => {\n const entryPath = path.join(dir, entry.name);\n const relativePath = toPosixPath(path.relative(baseDir, entryPath));\n\n if (entry.isSymbolicLink()) {\n throw new Error(\n `Widget publish artifact ${JSON.stringify(relativePath)} must be a regular file and must not be a symbolic link.`,\n );\n }\n\n if (isUploadArtifact(relativePath)) {\n if (!entry.isFile()) {\n throw new Error(\n `Widget publish artifact ${JSON.stringify(relativePath)} must be a regular file.`,\n );\n }\n return [entryPath];\n }\n\n if (entry.isDirectory()) {\n const nestedPaths = await findArtifactPaths(entryPath, baseDir);\n if (nestedPaths.length === 0) {\n throwUnsupportedArtifactPath(`${relativePath}/`);\n }\n return nestedPaths;\n }\n if (isAllowedGeneratedFile(relativePath)) return [];\n throwUnsupportedArtifactPath(relativePath);\n }),\n );\n\n return paths.flat();\n}\n\nfunction assertRequiredUploadArtifacts(\n artifacts: readonly ArtifactMetadata[],\n): void {\n const artifactPaths = new Set(artifacts.map((artifact) => artifact.path));\n for (const requiredPath of [\"widget.js\", \"manifest.json\"] as const) {\n if (artifactPaths.has(requiredPath)) continue;\n throw new Error(\n `Widget package publish output must include regular file ${JSON.stringify(requiredPath)}.`,\n );\n }\n}\n\nfunction assertAllowedArtifactPath(relativePath: string): void {\n if (isUploadArtifact(relativePath) || isAllowedGeneratedFile(relativePath))\n return;\n throwUnsupportedArtifactPath(relativePath);\n}\n\nfunction isUploadArtifact(relativePath: string): boolean {\n return (\n relativePath === \"widget.js\" ||\n relativePath === \"manifest.json\" ||\n isWidgetPackageCssArtifactPath(relativePath) ||\n isWidgetPackageJsMapArtifactPath(relativePath)\n );\n}\n\nfunction isAllowedGeneratedFile(relativePath: string): boolean {\n return (\n isFlatArtifactPath(relativePath) && relativePath === \"publish-manifest.json\"\n );\n}\n\nfunction isFlatArtifactPath(relativePath: string): boolean {\n return (\n relativePath.length > 0 &&\n !relativePath.includes(\"/\") &&\n !relativePath.includes(\"\\\\\")\n );\n}\n\nfunction throwUnsupportedArtifactPath(relativePath: string): never {\n throw new Error(\n `Unsupported widget publish artifact ${JSON.stringify(relativePath)}. ` +\n \"Allowed files are widget.js, manifest.json, top-level [A-Za-z0-9._~-]+.css, top-level [A-Za-z0-9._~-]+.js.map, and publish-manifest.json.\",\n );\n}\n\nfunction toPosixPath(value: string): string {\n return value.split(path.sep).join(\"/\");\n}\n","import { isWidgetPackageCssArtifactPath } from \"./widget-package-artifacts.js\";\nimport {\n isJsonValue,\n type JsonObject,\n type RemoteDomWidgetDefinition,\n} from \"@fluid-app/portal-core/remote-dom-widget-package\";\n\nconst URL_SAFE_SEGMENT_SOURCE = \"[A-Za-z0-9][A-Za-z0-9_~-]*\";\nconst URL_SAFE_WIDGET_NAME_PATTERN = new RegExp(`^${URL_SAFE_SEGMENT_SOURCE}$`);\nconst URL_SAFE_DOTTED_IDENTIFIER_PATTERN = new RegExp(\n `^${URL_SAFE_SEGMENT_SOURCE}(?:\\\\.${URL_SAFE_SEGMENT_SOURCE})*$`,\n);\nconst SEMVER_CORE_PATTERN = \"(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\";\nconst SEMVER_PRERELEASE_IDENTIFIER_PATTERN =\n \"(?:0|[1-9]\\\\d*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)\";\nconst SEMVER_URL_SAFE_PATTERN = new RegExp(\n `^${SEMVER_CORE_PATTERN}(?:-${SEMVER_PRERELEASE_IDENTIFIER_PATTERN}(?:\\\\.${SEMVER_PRERELEASE_IDENTIFIER_PATTERN})*)?$`,\n);\nconst WIDGET_PACKAGE_MANIFEST_VERSION = 1;\nconst DEFAULT_WIDGET_ICON = \"box\";\nconst DEFAULT_WIDGET_CATEGORY = \"components\";\nconst DEFAULT_WIDGET_CONTAINER = \"block\";\nconst DEFAULT_MIN_SDK_VERSION = \"0.0.0\";\n\nexport type WidgetPackageOwnerKind = \"company\" | \"droplet\";\n\nexport type WidgetRuntimeContainer = RemoteDomWidgetDefinition[\"container\"];\nexport type WidgetRuntimeResizable = RemoteDomWidgetDefinition[\"resizable\"];\n\nexport interface WidgetCapabilityMetadata {\n readonly name: string;\n readonly version?: string;\n}\n\nexport interface SourceWidgetMetadata {\n readonly name: string;\n readonly displayName?: string;\n readonly description?: string;\n readonly icon?: string;\n readonly category?: string;\n readonly propertySchema?: JsonObject;\n readonly defaultProps?: JsonObject;\n readonly container?: unknown;\n readonly minSdkVersion?: string;\n readonly resizable?: unknown;\n readonly capabilities?: readonly WidgetCapabilityMetadata[];\n}\n\nexport interface SourceWidgetPackageMetadata {\n readonly manifestVersion?: number;\n readonly scope?: string;\n readonly packageStableId?: string;\n readonly packageId: string;\n readonly packageType?: string;\n readonly version: string;\n readonly widgets: readonly SourceWidgetMetadata[];\n readonly cssUrls?: readonly string[];\n}\n\nexport interface WidgetDescriptorMetadata extends RemoteDomWidgetDefinition {\n readonly name: string;\n}\n\ndeclare const WIDGET_PACKAGE_ARTIFACT_PATH: unique symbol;\n\n/** A package-local artifact path written into the uploaded manifest. */\nexport type WidgetPackageArtifactPath = string & {\n readonly [WIDGET_PACKAGE_ARTIFACT_PATH]: true;\n};\n\n/**\n * Upload-time manifest whose artifact references are package-local paths.\n *\n * This is deliberately distinct from RemoteDomWidgetPackageDescriptor, whose\n * catalog-facing artifact fields must already be resolved to absolute URLs.\n */\nexport interface WidgetPackagePublishManifest {\n readonly manifestVersion: 1;\n readonly runtime: \"remote-dom\";\n readonly packageId: string;\n readonly source: WidgetPackageOwnerKind;\n readonly version: string;\n readonly workerEntryUrl: WidgetPackageArtifactPath;\n readonly cssUrls: readonly WidgetPackageArtifactPath[];\n readonly assetUrls: readonly WidgetPackageArtifactPath[];\n readonly widgets: readonly RemoteDomWidgetDefinition[];\n}\n\nexport interface ValidatedWidgetPackageBuild {\n readonly sourcePackage: SourceWidgetPackageMetadata;\n readonly packageKey: string;\n readonly packageId: string;\n readonly owner: WidgetPackageOwnerKind;\n readonly version: string;\n readonly widgets: readonly WidgetDescriptorMetadata[];\n}\n\nexport type WidgetPackageValidationErrorCode =\n | \"NO_SOURCE_PACKAGE\"\n | \"MULTIPLE_SOURCE_PACKAGES\"\n | \"INVALID_SOURCE_PACKAGE\"\n | \"INVALID_WIDGET_METADATA\"\n | \"UNSUPPORTED_OWNER\"\n | \"INVALID_PACKAGE_KEY\"\n | \"INVALID_VERSION\"\n | \"NO_WIDGETS\"\n | \"INVALID_WIDGET_NAME\"\n | \"INVALID_WIDGET_TYPE\"\n | \"DUPLICATE_WIDGET\";\n\nexport interface WidgetPackageValidationError {\n readonly code: WidgetPackageValidationErrorCode;\n readonly message: string;\n readonly path?: string;\n}\n\nexport interface WidgetPackageValidationResult {\n readonly success: boolean;\n readonly value?: ValidatedWidgetPackageBuild;\n readonly errors: readonly WidgetPackageValidationError[];\n}\n\nexport interface ValidateSourceWidgetPackageOptions {\n readonly owner?: WidgetPackageOwnerKind;\n}\n\nexport function validateSingleSourceWidgetPackage(\n sourcePackages: readonly unknown[],\n options: ValidateSourceWidgetPackageOptions = {},\n): WidgetPackageValidationResult {\n if (sourcePackages.length === 0) {\n return validationFailure({\n code: \"NO_SOURCE_PACKAGE\",\n message:\n \"No defineWidgetPackage source package was found. Export widgetPackage, widgetPackages, or a default widget package from src/widgets.config.ts.\",\n });\n }\n\n if (sourcePackages.length > 1) {\n return validationFailure({\n code: \"MULTIPLE_SOURCE_PACKAGES\",\n message:\n \"Publish/deploy supports exactly one defineWidgetPackage source package. Export one package or split packages into separate builds.\",\n });\n }\n\n const sourcePackageValue = sourcePackages[0];\n if (!sourcePackageValue) {\n return validationFailure({\n code: \"NO_SOURCE_PACKAGE\",\n message: \"No defineWidgetPackage source package was found.\",\n });\n }\n\n const shapeErrors = validateSourcePackageShape(sourcePackageValue);\n if (shapeErrors.length > 0) {\n return { success: false, errors: shapeErrors };\n }\n const sourcePackage = sourcePackageValue as SourceWidgetPackageMetadata;\n\n const errors: WidgetPackageValidationError[] = [];\n const owner = options.owner ?? sourcePackage.packageType;\n if (owner !== \"company\" && owner !== \"droplet\") {\n errors.push({\n code: \"UNSUPPORTED_OWNER\",\n path: \"packageType\",\n message:\n 'Widget package publish/deploy currently supports company and droplet owners. Set packageType to \"company\" or \"droplet\".',\n });\n } else if (\n options.owner !== undefined &&\n sourcePackage.packageType !== options.owner\n ) {\n errors.push({\n code: \"UNSUPPORTED_OWNER\",\n path: \"packageType\",\n message: `Widget package metadata must set packageType to \"${options.owner}\" for this workflow.`,\n });\n }\n\n const resolvedOwner = owner === \"droplet\" ? \"droplet\" : \"company\";\n if (\n resolvedOwner === \"droplet\" &&\n !readNonEmptyTrimmedString(sourcePackage.packageStableId)\n ) {\n errors.push({\n code: \"INVALID_PACKAGE_KEY\",\n path: \"packageStableId\",\n message:\n \"Droplet widget packages must set packageStableId so published widget types remain stable across builds.\",\n });\n }\n\n const packageKey = resolvePackageKey(sourcePackage, resolvedOwner);\n const packageKeyPath = readNonEmptyTrimmedString(\n sourcePackage.packageStableId,\n )\n ? \"packageStableId\"\n : \"packageId\";\n if (!isUrlSafeDottedIdentifier(packageKey)) {\n errors.push({\n code: \"INVALID_PACKAGE_KEY\",\n path: packageKeyPath,\n message:\n \"Widget package key must be URL-safe dot-separated text (letters, numbers, '.', '_', '~', and '-' only).\",\n });\n }\n\n if (!isUrlSafeSemver(sourcePackage.version)) {\n errors.push({\n code: \"INVALID_VERSION\",\n path: \"version\",\n message:\n \"Widget package version must be a URL-safe SemVer version without build metadata (for example 1.2.3 or 1.2.3-beta.1).\",\n });\n }\n\n if (sourcePackage.widgets.length === 0) {\n errors.push({\n code: \"NO_WIDGETS\",\n path: \"widgets\",\n message: \"Widget package must include at least one widget.\",\n });\n }\n\n const packageId = `${resolvedOwner}.${packageKey}`;\n const seenNames = new Set<string>();\n const seenTypes = new Set<string>();\n const widgets: WidgetDescriptorMetadata[] = [];\n\n sourcePackage.widgets.forEach((widget, index) => {\n const path = `widgets[${index}]`;\n if (!isUrlSafeWidgetName(widget.name)) {\n errors.push({\n code: \"INVALID_WIDGET_NAME\",\n path: `${path}.name`,\n message:\n \"Widget name must be URL-safe text (letters, numbers, '_', '~', and '-' only) and cannot be empty.\",\n });\n return;\n }\n\n if (seenNames.has(widget.name)) {\n errors.push({\n code: \"DUPLICATE_WIDGET\",\n path: `${path}.name`,\n message: `Duplicate widget name \"${widget.name}\" found in package ${packageKey}.`,\n });\n return;\n }\n seenNames.add(widget.name);\n\n const type = `${packageId}.${widget.name}`;\n if (!isUrlSafeDottedIdentifier(type)) {\n errors.push({\n code: \"INVALID_WIDGET_TYPE\",\n path: `${path}.type`,\n message: `Generated widget type \"${type}\" is not URL-safe.`,\n });\n return;\n }\n\n if (seenTypes.has(type)) {\n errors.push({\n code: \"DUPLICATE_WIDGET\",\n path: `${path}.type`,\n message: `Duplicate generated widget type \"${type}\" found.`,\n });\n return;\n }\n seenTypes.add(type);\n\n widgets.push(sourceWidgetToDescriptor(widget, type));\n });\n\n if (errors.length > 0) return { success: false, errors };\n\n return {\n success: true,\n value: {\n sourcePackage,\n packageKey,\n packageId,\n owner: resolvedOwner,\n version: sourcePackage.version,\n widgets,\n },\n errors: [],\n };\n}\n\nexport function buildWidgetPackagePublishManifest(\n validated: ValidatedWidgetPackageBuild,\n options: {\n readonly cssUrls?: readonly string[];\n } = {},\n): WidgetPackagePublishManifest {\n return {\n manifestVersion: WIDGET_PACKAGE_MANIFEST_VERSION,\n runtime: \"remote-dom\",\n packageId: validated.packageId,\n source: validated.owner,\n version: validated.version,\n // Published manifests name package-local artifacts. Catalog producers\n // resolve these paths to absolute URLs before returning the descriptor to\n // a host, where portal-core performs its absolute-URL ingress validation.\n workerEntryUrl: toWidgetPackageArtifactPath(\"widget.js\"),\n cssUrls: mergeCssUrls(validated.sourcePackage.cssUrls, options.cssUrls),\n assetUrls: [],\n widgets: validated.widgets.map(({ name: _name, ...widget }) => widget),\n };\n}\n\nfunction sourceWidgetToDescriptor(\n widget: SourceWidgetMetadata,\n type: string,\n): WidgetDescriptorMetadata {\n const displayName = widget.displayName ?? widget.name;\n\n return {\n type,\n name: widget.name,\n displayName,\n description: widget.description ?? `Custom widget ${displayName}`,\n icon: widget.icon ?? DEFAULT_WIDGET_ICON,\n category: widget.category ?? DEFAULT_WIDGET_CATEGORY,\n propertySchema: normalizePropertySchema(widget.propertySchema, type),\n defaultProps: widget.defaultProps ?? {},\n container: normalizeContainer(widget.container),\n minSdkVersion: widget.minSdkVersion ?? DEFAULT_MIN_SDK_VERSION,\n resizable: normalizeResizable(widget.resizable),\n capabilities: normalizeCapabilities(widget.capabilities ?? []),\n };\n}\n\nfunction normalizeCapabilities(\n capabilities: readonly WidgetCapabilityMetadata[],\n): readonly Required<WidgetCapabilityMetadata>[] {\n return capabilities.map((capability) => ({\n name: capability.name,\n version: capability.version ?? \"1\",\n }));\n}\n\nfunction validationFailure(\n error: WidgetPackageValidationError,\n): WidgetPackageValidationResult {\n return { success: false, errors: [error] };\n}\n\nfunction validateSourcePackageShape(\n value: unknown,\n): WidgetPackageValidationError[] {\n if (!isRecord(value)) {\n return [\n {\n code: \"INVALID_SOURCE_PACKAGE\",\n message: \"Widget source package must be a JSON object.\",\n },\n ];\n }\n\n const errors: WidgetPackageValidationError[] = [];\n requireStringField(value, \"packageId\", \"packageId\", errors);\n requireStringField(value, \"version\", \"version\", errors);\n validateOptionalStringField(value, \"scope\", \"scope\", errors);\n validateOptionalStringField(\n value,\n \"packageStableId\",\n \"packageStableId\",\n errors,\n );\n validateOptionalStringField(value, \"packageType\", \"packageType\", errors);\n\n if (Object.prototype.hasOwnProperty.call(value, \"navigationOrigins\")) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: \"navigationOrigins\",\n message:\n \"navigationOrigins has been removed. Declare the externalNavigation capability and call allowAnchorUrl(url) for each external link.\",\n });\n }\n\n if (value.cssUrls !== undefined) {\n if (!Array.isArray(value.cssUrls)) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: \"cssUrls\",\n message:\n \"Widget package cssUrls must be an array of strings when present.\",\n });\n } else {\n value.cssUrls.forEach((cssUrl, index) => {\n validateCssUrl(cssUrl, `cssUrls[${index}]`, errors);\n });\n }\n }\n\n if (!Array.isArray(value.widgets)) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: \"widgets\",\n message: \"Widget package widgets must be an array.\",\n });\n return errors;\n }\n\n value.widgets.forEach((widget, index) => {\n const widgetPath = `widgets[${index}]`;\n if (!isRecord(widget)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: widgetPath,\n message: \"Widget metadata must be a JSON object.\",\n });\n return;\n }\n\n requireStringField(widget, \"name\", `${widgetPath}.name`, errors, {\n code: \"INVALID_WIDGET_NAME\",\n message: \"Widget name must be a string and cannot be empty.\",\n });\n validateOptionalStringField(\n widget,\n \"displayName\",\n `${widgetPath}.displayName`,\n errors,\n { requireNonEmpty: true },\n );\n validateOptionalStringField(\n widget,\n \"description\",\n `${widgetPath}.description`,\n errors,\n { requireNonEmpty: true },\n );\n validateOptionalStringField(widget, \"icon\", `${widgetPath}.icon`, errors, {\n requireNonEmpty: true,\n });\n validateOptionalStringField(\n widget,\n \"category\",\n `${widgetPath}.category`,\n errors,\n { requireNonEmpty: true },\n );\n validateOptionalStringField(\n widget,\n \"minSdkVersion\",\n `${widgetPath}.minSdkVersion`,\n errors,\n { requireNonEmpty: true },\n );\n validateOptionalJsonRecordField(\n widget,\n \"propertySchema\",\n `${widgetPath}.propertySchema`,\n errors,\n );\n validateOptionalJsonRecordField(\n widget,\n \"defaultProps\",\n `${widgetPath}.defaultProps`,\n errors,\n );\n validateOptionalCapabilities(\n widget,\n \"capabilities\",\n `${widgetPath}.capabilities`,\n errors,\n );\n });\n\n return errors;\n}\n\nfunction requireStringField(\n record: Record<string, unknown>,\n key: string,\n path: string,\n errors: WidgetPackageValidationError[],\n override?: Pick<WidgetPackageValidationError, \"code\" | \"message\">,\n): void {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) return;\n\n errors.push({\n code: override?.code ?? \"INVALID_SOURCE_PACKAGE\",\n path,\n message:\n override?.message ?? `${path} must be a string and cannot be empty.`,\n });\n}\n\nfunction validateOptionalStringField(\n record: Record<string, unknown>,\n key: string,\n path: string,\n errors: WidgetPackageValidationError[],\n options: { readonly requireNonEmpty?: boolean } = {},\n): void {\n const value = record[key];\n if (value === undefined) return;\n if (typeof value === \"string\") {\n if (!options.requireNonEmpty || value.trim().length > 0) return;\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path,\n message: `${path} must be a non-empty string when present.`,\n });\n return;\n }\n\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path,\n message: `${path} must be a string when present.`,\n });\n}\n\nfunction validateCssUrl(\n value: unknown,\n cssUrlPath: string,\n errors: WidgetPackageValidationError[],\n): void {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: cssUrlPath,\n message: \"Widget package cssUrls entries must be non-empty strings.\",\n });\n return;\n }\n\n if (!isWidgetPackageCssArtifactPath(value)) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: cssUrlPath,\n message:\n \"Widget package cssUrls entries must be top-level generated CSS artifact filenames matching [A-Za-z0-9._~-]+.css. Self-host external CSS or fonts via @font-face in widget CSS so the build can isolate them.\",\n });\n }\n}\n\nfunction validateOptionalJsonRecordField(\n record: Record<string, unknown>,\n key: string,\n path: string,\n errors: WidgetPackageValidationError[],\n): void {\n const value = record[key];\n if (value === undefined) return;\n if (isRecord(value) && isJsonValue(value)) return;\n\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path,\n message: `${path} must be a JSON object when present.`,\n });\n}\n\nfunction validateOptionalCapabilities(\n record: Record<string, unknown>,\n key: string,\n path: string,\n errors: WidgetPackageValidationError[],\n): void {\n const value = record[key];\n if (value === undefined) return;\n if (!Array.isArray(value)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path,\n message: `${path} must be an array when present.`,\n });\n return;\n }\n\n const names = new Set<string>();\n value.forEach((candidate, index) => {\n const capabilityPath = `${path}[${index}]`;\n if (!isRecord(candidate)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: capabilityPath,\n message: `${capabilityPath} must be a JSON object.`,\n });\n return;\n }\n\n const name = candidate.name;\n if (!isCanonicalMetadataString(name)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: `${capabilityPath}.name`,\n message: `${capabilityPath}.name must be a non-empty string without surrounding whitespace or control characters.`,\n });\n return;\n }\n\n const version = candidate.version;\n if (version !== undefined && !isCanonicalMetadataString(version)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: `${capabilityPath}.version`,\n message: `${capabilityPath}.version must be a non-empty string without surrounding whitespace or control characters when present.`,\n });\n }\n\n if (names.has(name)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: `${capabilityPath}.name`,\n message: `${path} must not contain duplicate capability name ${JSON.stringify(name)}.`,\n });\n return;\n }\n names.add(name);\n });\n}\n\nfunction isCanonicalMetadataString(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n value.length > 0 &&\n value === value.trim() &&\n !/\\p{Cc}/u.test(value)\n );\n}\n\nfunction mergeCssUrls(\n sourceCssUrls: readonly string[] | undefined,\n generatedCssUrls: readonly string[] | undefined,\n): WidgetPackageArtifactPath[] {\n const generatedCssUrlSet = new Set(generatedCssUrls ?? []);\n generatedCssUrls?.forEach((cssUrl, index) => {\n validateGeneratedCssArtifactUrl(cssUrl, `generated cssUrls[${index}]`);\n });\n sourceCssUrls?.forEach((cssUrl, index) => {\n validateGeneratedCssArtifactUrl(cssUrl, `cssUrls[${index}]`);\n if (generatedCssUrlSet.has(cssUrl)) return;\n\n throw new Error(\n `cssUrls[${index}] URL ${JSON.stringify(cssUrl)} must match a generated top-level CSS artifact. ` +\n \"Import the CSS from the widget package bundle or remove it from cssUrls.\",\n );\n });\n\n return Array.from(\n new Set([...(sourceCssUrls ?? []), ...(generatedCssUrls ?? [])]),\n ).map(toWidgetPackageArtifactPath);\n}\n\nfunction toWidgetPackageArtifactPath(value: string): WidgetPackageArtifactPath {\n return value as WidgetPackageArtifactPath;\n}\n\nfunction validateGeneratedCssArtifactUrl(\n value: string,\n cssUrlPath: string,\n): void {\n if (value.trim().length === 0) {\n throw new Error(`${cssUrlPath} must be a non-empty string.`);\n }\n\n if (!isWidgetPackageCssArtifactPath(value)) {\n throw new Error(\n `${cssUrlPath} must be a top-level generated CSS artifact filename matching [A-Za-z0-9._~-]+.css. Self-host external CSS or fonts via @font-face in widget CSS so the build can isolate them.`,\n );\n }\n}\n\nfunction normalizePropertySchema(\n value: JsonObject | undefined,\n widgetType: string,\n): JsonObject {\n return { ...(value ?? {}), widgetType };\n}\n\nfunction normalizeContainer(value: unknown): WidgetRuntimeContainer {\n if (\n value === \"inline\" ||\n value === \"block\" ||\n value === \"card\" ||\n value === \"fullscreen\"\n ) {\n return value;\n }\n\n return DEFAULT_WIDGET_CONTAINER;\n}\n\nfunction normalizeResizable(value: unknown): WidgetRuntimeResizable {\n if (typeof value === \"boolean\") return value;\n if (value === \"horizontal\" || value === \"vertical\" || value === \"both\") {\n return value;\n }\n if (!isRecord(value)) return false;\n\n const horizontal = value.horizontal === true;\n const vertical = value.vertical === true;\n\n if (horizontal && vertical) return \"both\";\n if (horizontal) return \"horizontal\";\n if (vertical) return \"vertical\";\n return false;\n}\n\nfunction resolvePackageKey(\n sourcePackage: SourceWidgetPackageMetadata,\n owner: WidgetPackageOwnerKind,\n): string {\n const packageStableId = readNonEmptyTrimmedString(\n sourcePackage.packageStableId,\n );\n if (packageStableId) {\n return prefixPackageStableIdWithNonOwnerScope(\n packageStableId,\n sourcePackage.scope,\n );\n }\n\n return stripOwnerScopeFromPackageId(\n sourcePackage.packageId,\n sourcePackage.scope,\n owner,\n );\n}\n\nfunction prefixPackageStableIdWithNonOwnerScope(\n packageStableId: string,\n sourceScope: string | undefined,\n): string {\n const sourceScopeText = readNonEmptyTrimmedString(sourceScope);\n if (!sourceScopeText || isWidgetPackageOwnerKind(sourceScopeText)) {\n return packageStableId;\n }\n\n const sourceScopePrefix = `${sourceScopeText}.`;\n if (packageStableId.startsWith(sourceScopePrefix)) return packageStableId;\n return `${sourceScopeText}.${packageStableId}`;\n}\n\nfunction stripOwnerScopeFromPackageId(\n packageId: string,\n sourceScope: string | undefined,\n owner: WidgetPackageOwnerKind,\n): string {\n const ownerPrefix = `${owner}.`;\n if (\n packageId.startsWith(ownerPrefix) &&\n packageId.length > ownerPrefix.length\n ) {\n return packageId.slice(ownerPrefix.length);\n }\n\n const sourceScopeText = readNonEmptyTrimmedString(sourceScope);\n if (\n isWidgetPackageOwnerKind(sourceScopeText) &&\n packageId.startsWith(`${sourceScopeText}.`) &&\n packageId.length > sourceScopeText.length + 1\n ) {\n return packageId.slice(sourceScopeText.length + 1);\n }\n\n return packageId;\n}\n\nfunction readNonEmptyTrimmedString(\n value: string | undefined,\n): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction isWidgetPackageOwnerKind(\n value: string | undefined,\n): value is WidgetPackageOwnerKind {\n return value === \"company\" || value === \"droplet\";\n}\n\nfunction isUrlSafeDottedIdentifier(value: string): boolean {\n return URL_SAFE_DOTTED_IDENTIFIER_PATTERN.test(value);\n}\n\nfunction isUrlSafeWidgetName(value: string): boolean {\n return URL_SAFE_WIDGET_NAME_PATTERN.test(value);\n}\n\nfunction isUrlSafeSemver(value: string): boolean {\n return SEMVER_URL_SAFE_PATTERN.test(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { RemoteDomWidgetPackageDescriptor } from \"@fluid-app/portal-core/remote-dom-widget-package\";\nimport { WidgetToolingError } from \"./errors.js\";\nimport {\n validateSingleSourceWidgetPackage,\n type ValidatedWidgetPackageBuild,\n type WidgetPackageOwnerKind,\n} from \"./internal/widget-package-validation.js\";\n\nexport interface CreateWidgetPackageDevelopmentDescriptorOptions {\n readonly sourceModule: Readonly<Record<string, unknown>>;\n readonly owner: WidgetPackageOwnerKind;\n readonly origin: string;\n readonly workerEntryPath?: string;\n readonly defaultCssPath?: string;\n}\n\nexport function createWidgetPackageDevelopmentDescriptor(\n options: CreateWidgetPackageDevelopmentDescriptorOptions,\n): RemoteDomWidgetPackageDescriptor {\n const validation = validateSingleSourceWidgetPackage(\n readSourcePackages(options.sourceModule),\n { owner: options.owner },\n );\n if (!validation.success || !validation.value) {\n throw new WidgetToolingError(\n \"VALIDATION_FAILED\",\n validation.errors.map((error) => error.message).join(\"\\n\") ||\n \"Widget package validation failed.\",\n { diagnostics: validation.errors },\n );\n }\n\n return validatedPackageToDescriptor(validation.value, options);\n}\n\nfunction validatedPackageToDescriptor(\n validated: ValidatedWidgetPackageBuild,\n options: CreateWidgetPackageDevelopmentDescriptorOptions,\n): RemoteDomWidgetPackageDescriptor {\n const cssUrls = validated.sourcePackage.cssUrls ?? [];\n const workerEntryPath = options.workerEntryPath ?? \"/__runtime-entry__\";\n const defaultCssPath = options.defaultCssPath ?? \"/styles.css\";\n\n return {\n manifestVersion: 1,\n runtime: \"remote-dom\",\n packageId: validated.packageId,\n source: validated.owner,\n version: validated.version,\n workerEntryUrl: new URL(workerEntryPath, options.origin).href,\n cssUrls:\n cssUrls.length > 0\n ? cssUrls.map((url) => toDevelopmentCssUrl(url, options.origin))\n : [toDevelopmentCssUrl(defaultCssPath, options.origin)],\n assetUrls: [],\n widgets: validated.widgets.map(({ name: _name, ...widget }) => widget),\n };\n}\n\nfunction readSourcePackages(\n sourceModule: Readonly<Record<string, unknown>>,\n): readonly unknown[] {\n const packages = sourceModule[\"widgetPackages\"];\n if (Array.isArray(packages) && packages.length > 0) return packages;\n\n const widgetPackage = sourceModule[\"widgetPackage\"];\n if (widgetPackage !== undefined) return [widgetPackage];\n\n const defaultPackage = sourceModule[\"default\"];\n return defaultPackage === undefined ? [] : [defaultPackage];\n}\n\nfunction toDevelopmentCssUrl(url: string, origin: string): string {\n const { href } = new URL(url, origin);\n return href.includes(\"?\") ? `${href}&direct` : `${href}?direct`;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { RemoteDomWidgetPackageDescriptor } from \"@fluid-app/portal-core/remote-dom-widget-package\";\nimport { createWidgetPackageDevelopmentDescriptor } from \"./development-descriptor.js\";\nimport { WidgetToolingError } from \"./errors.js\";\nimport type { WidgetPackageOwnerKind } from \"./internal/widget-package-validation.js\";\nimport type { Plugin, UserConfig, ViteDevServer } from \"vite\";\n\n/**\n * Layout of the project these dev routes serve.\n *\n * Defaults describe a standalone widget project, which is the only layout that\n * existed when these routes were written. A portal project keeps its package\n * source at `src/widgets.config.ts`, owns it as `company` rather than\n * `droplet`, and has no `startWidgetPackage()` module of its own — so it\n * supplies a generated entry via `entryModulePath`.\n */\nexport interface FluidWidgetDevPluginOptions {\n /** Module the worker bootstrap imports. Must call `startWidgetPackage()`. */\n readonly entryModulePath?: string;\n /** Module exporting `widgetPackage` / `widgetPackages`. */\n readonly configModulePath?: string;\n /** Who owns the published package. */\n readonly owner?: WidgetPackageOwnerKind;\n /**\n * Treat \"the project declares no widget packages\" as an empty catalog rather\n * than an error. A standalone widget project with no package is broken, but a\n * portal that has not been given a custom widget yet is perfectly normal — and\n * its preview polls this route continuously, so erroring would be constant\n * noise for the expected case.\n */\n readonly allowNoPackages?: boolean;\n}\n\n/**\n * Creates the Vite plugin that serves a widget package descriptor and worker entry.\n *\n * @param options - Source layout and ownership overrides. The defaults match the standalone widget template.\n * @returns A serve-only Vite plugin for Fluid widget development.\n */\nexport function fluidWidgetDevPlugin(\n options: FluidWidgetDevPluginOptions = {},\n): Plugin {\n const entryModulePath = options.entryModulePath ?? WIDGET_ENTRY_MODULE_PATH;\n const configModulePath =\n options.configModulePath ?? WIDGET_CONFIG_MODULE_PATH;\n const owner = options.owner ?? \"droplet\";\n\n return {\n name: \"fluid-widget-dev-routes\",\n apply: \"serve\",\n config: createWidgetDevServerConfig,\n configureServer(server) {\n server.middlewares.use(async (request, response, next): Promise<void> => {\n const pathname = (request.url ?? \"\").split(\"?\")[0] ?? \"\";\n\n if (\n pathname === \"/__runtime-entry__\" ||\n pathname === \"/__runtime-entry__/\"\n ) {\n if (handleOptions(request, response)) return;\n const origin = getRequestOrigin(request);\n sendJavaScript(\n request,\n response,\n buildRuntimeEntryBootstrapScript(\n entryModulePath,\n origin,\n await resolveWorkerSdkUrl(server, origin),\n ),\n );\n return;\n }\n\n if (\n pathname === \"/__widget-packages__\" ||\n pathname === \"/__widget-packages__/\"\n ) {\n await sendWidgetPackages(server, request, response, {\n configModulePath,\n owner,\n allowNoPackages: options.allowNoPackages === true,\n });\n return;\n }\n\n next();\n });\n },\n };\n}\n\n/**\n * Widget projects intentionally have no HTML entrypoint, so Vite cannot\n * discover the worker's dependency graph during its normal startup scan.\n * Without an explicit entry, the first live-preview request discovers and\n * optimizes the portal worker after the server reports ready. Vite reloads\n * the worker mid-mount, closing its message thread and stranding the preview\n * in a permanent error state.\n *\n * Pre-optimizing the worker entry makes the initial graph stable before a\n * preview can connect. Vite follows this entry's imports, so React and the\n * Remote DOM worker runtime are optimized in the same startup pass.\n */\nexport function createWidgetDevServerConfig(): UserConfig {\n return {\n optimizeDeps: {\n // The SDK worker entry drags the whole guard subgraph into this same\n // optimization pass, so naming `@fluid-app/widget-runtime/worker`\n // here adds nothing — and cannot work: see the resolve.dedupe note\n // below. Vite answers an unresolvable entry with \"Failed to resolve\n // dependency … present in optimizeDeps.include\" and pre-warms nothing.\n include: [\"@fluid-app/portal-sdk/widgets/worker\"],\n },\n resolve: {\n // One module instance per worker realm (INV-1): a second copy of the\n // SDK worker subgraph gives the network guard two instances (the\n // MIST-PW-01 lockdown failure), and a second copy of react breaks\n // hooks. The Mist renderer dedupes on its side\n // (apps/mist-desktop/vite.renderer.config.ts); the worker's dev server\n // needs the same guarantee.\n //\n // Every entry MUST be resolvable from the project root, which is what\n // dedupe anchors resolution to. `@fluid-app/widget-runtime` is not: a\n // scaffolded widget project depends on it only through\n // `@fluid-app/portal-sdk`, and under pnpm's strict layout it exists\n // solely inside portal-sdk's private node_modules. Listing it made\n // Vite fail to resolve the package and took `/__widget-packages__`\n // down with \"Cannot find module '@fluid-app/widget-runtime/worker'\",\n // i.e. every preview reported \"Widget package failed validation\".\n // Deduping portal-sdk covers the same subgraph, since the guard ships\n // inside its worker entry.\n dedupe: [\"@fluid-app/portal-sdk\", \"react\", \"react-dom\"],\n },\n ssr: {\n // `/__widget-packages__` reads the package source with `ssrLoadModule`.\n // Left external, Vite hands `@fluid-app/portal-sdk` to Node, which loads\n // its TypeScript source directly — and that source uses extensionless\n // relative imports, legal for a bundler and fatal under Node ESM:\n //\n // Cannot find module .../remote/worker/widget-package\n // imported from .../widgets/worker.ts\n //\n // The file is present; Node just will not resolve it without the\n // extension. `noExternal` keeps the SDK inside Vite's graph, where\n // extensionless resolution works.\n //\n // The standalone widget template sets this in its own vite.config. It\n // lives here as well so any host of these routes gets it — a portal\n // project has no reason to know that serving widget descriptors imposes\n // an SSR requirement, and existing portals cannot be retro-edited.\n noExternal: [\"@fluid-app/portal-sdk\"],\n },\n };\n}\n\n/** Source-relative path of a widget project's entry module. The dev\n * scaffold always places it here (see the widget template) — this is\n * the one thing the bootstrap script below needs from the plugin\n * that isn't itself part of the race/preamble fix. */\nconst WIDGET_ENTRY_MODULE_PATH = \"/src/index.ts\";\n\n/** Source-relative path of a standalone widget project's package source. */\nconst WIDGET_CONFIG_MODULE_PATH = \"/fluid.widget.config.ts\";\n\n/** Bare specifier of the SDK worker module the bootstrap prepares. */\nconst WORKER_SDK_SPECIFIER = \"@fluid-app/portal-sdk/widgets/worker\";\n\n/**\n * Resolves the bootstrap's SDK worker import to the same module URL the\n * widget entry's rewritten bare import uses.\n *\n * The bootstrap used to import the hardcoded alias\n * `/@id/@fluid-app/portal-sdk/widgets/worker`. Vite serves the optimized\n * module body inline at that URL while the entry's rewritten import uses the\n * canonical `/node_modules/.vite/deps/...?v=<hash>` URL — same bytes, two\n * resolved URLs, two records in the worker's ES module map. The network\n * guard's re-entry check is module-instance-local, so the second evaluation\n * threw on every dev preview load (MIST-PW-01). Resolving server-side at\n * request time keeps both imports on one module record.\n *\n * Falls back to the `/@id/` alias when resolution fails — no worse than the\n * previous behavior, and the widget-runtime duplicate-install tripwire names\n * the condition if the split ever regresses.\n */\nexport async function resolveWorkerSdkUrl(\n server: ViteDevServer,\n origin: string,\n): Promise<string> {\n const fallback = new URL(`/@id/${WORKER_SDK_SPECIFIER}`, origin).toString();\n try {\n const resolved = await server.pluginContainer.resolveId(\n WORKER_SDK_SPECIFIER,\n undefined,\n { ssr: false },\n );\n if (!resolved?.id) return fallback;\n const url = moduleIdToUrl(resolved.id, server.config.root);\n return url ? new URL(url, origin).toString() : fallback;\n } catch {\n return fallback;\n }\n}\n\n/**\n * Mirrors Vite import-analysis URL normalization for the id shapes the\n * resolver produces here: a file under the served root (the optimized-deps\n * dir lives at `<root>/node_modules/.vite`) becomes a root-relative URL; any\n * other absolute file path is served through `/@fs/`. Ids and root arrive\n * posix-normalized from Vite, Windows drive letters included.\n */\nfunction moduleIdToUrl(id: string, root: string): string | undefined {\n const rootPrefix = root.endsWith(\"/\") ? root : `${root}/`;\n if (id.startsWith(rootPrefix)) return `/${id.slice(rootPrefix.length)}`;\n if (id.startsWith(\"/\") || /^[A-Za-z]:\\//.test(id))\n return `/@fs/${id.replace(/^\\//, \"\")}`;\n return undefined;\n}\n\n/**\n * Builds the `/__runtime-entry__` worker bootstrap. Runtime-verified\n * against a real widget dev server + `@fluid-app/widget-runtime` host\n * in a Playwright harness (styled Leaderboard widget rendering,\n * mutation records flowing, `mounted.ready` resolving) — every piece\n * below exists to fix something that reproduced in that harness:\n *\n * 1. **Message-buffer race (the silent-mount killer).** The host\n * (widget-runtime) posts the \"mount\" message immediately after\n * `new Worker(...)`. A production-built worker bundle evaluates\n * synchronously and never races that message. In dev, though, the\n * worker's module graph loads asynchronously over many HTTP\n * requests (this bootstrap script, then the entry module, then\n * everything it imports, each a separate fetch) — so the \"mount\"\n * message can be dispatched and consumed by the Worker's default\n * (listener-less) handling before the widget entry's own\n * `message` listener, wired up deep inside the awaited import\n * below, is ever attached. The message is dropped silently, with\n * no error anywhere — the old `void import(\"/src/index.ts\")` also\n * swallowed the import's own rejections, compounding the silence.\n * Traced live: host→worker \"mount\" posts, zero worker→host replies\n * until this buffer-and-replay was added; after it, mutation\n * records flow and `mounted.ready` resolves. Fix: buffer every\n * message from the instant the worker boots (before anything else\n * runs), then replay the buffer, in order, once the entry module\n * has finished importing and has had the chance to attach its\n * real listener.\n * 2. **React-refresh preamble.** `@vitejs/plugin-react` injects a\n * preamble into every dev-transformed `.tsx` module referencing\n * `window.$RefreshReg$` / `$RefreshSig$`. A Worker global scope has\n * no `window` and no preamble, so importing a react-based widget\n * entry throws `window is not defined`, and — once `window` is\n * aliased to `globalThis` — throws again on the bare\n * `$RefreshSig$` alias. Installing the canonical preamble\n * (`RefreshRuntime.injectIntoGlobalHook` + no-op `$RefreshReg$` /\n * `$RefreshSig$`) before the entry import fixes both. The\n * `window = globalThis` alias was checked against widget-runtime's\n * worker lockdown / scope detection (which is\n * `globalThis.postMessage`-based) — no conflict. `/@react-refresh`\n * is `@vitejs/plugin-react`'s stable virtual module id, but a\n * widget project isn't guaranteed to use the react plugin, so the\n * whole block is try/catch-guarded — a project with no\n * `/@react-refresh` module (no react plugin) boots straight\n * through to the entry import unaffected.\n * 3. **`await import`, not `void import`.** A genuine failure to\n * import the entry module (syntax error, missing dependency, …)\n * must reject the worker's module evaluation loudly, not vanish\n * the way a fire-and-forget `void import` did.\n * 4. **Absolute dev-server imports.** Mist and portal previews load the\n * worker from another origin, so the host wraps this entry in a blob URL.\n * Root-relative specifiers inside a blob module resolve against the host\n * page (or fail to resolve at all), not this Vite server. Anchoring both\n * imports to the request origin keeps the entire dev module graph on the\n * widget server.\n *\n * Callers obtain `workerSdkUrl` from `resolveWorkerSdkUrl`, which owns the\n * `/@id/` fallback. The parameter is deliberately required: defaulting to the\n * alias here would let a caller silently reintroduce the two-module-record\n * split of MIST-PW-01.\n *\n * Dev-only: this only ever serves from `configureServer` (the\n * plugin's `apply: \"serve\"` gate), never a built/published package.\n */\nexport function buildRuntimeEntryBootstrapScript(\n entryPath: string,\n origin: string,\n workerSdkUrl: string,\n): string {\n const refreshRuntimeUrl = new URL(\"/@react-refresh\", origin).toString();\n const entryUrl = new URL(entryPath, origin).toString();\n\n return [\n \"// Dev-only worker bootstrap — see buildRuntimeEntryBootstrapScript\",\n \"// in packages/cli/widget-tooling/src/dev-routes.ts for why each piece\",\n \"// here exists (message-buffer race, react-refresh preamble,\",\n \"// await-not-void import).\",\n \"const __q = [];\",\n \"const __buf = (e) => { __q.push(e.data); };\",\n 'self.addEventListener(\"message\", __buf);',\n 'if (typeof window === \"undefined\") { globalThis.window = globalThis; }',\n `const { prepareRemoteDomWidgetWorker } = await import(${JSON.stringify(workerSdkUrl)});`,\n \"prepareRemoteDomWidgetWorker();\",\n \"try {\",\n ` const { default: RefreshRuntime } = await import(${JSON.stringify(refreshRuntimeUrl)});`,\n \" RefreshRuntime.injectIntoGlobalHook(window);\",\n \" window.$RefreshReg$ = () => {};\",\n \" window.$RefreshSig$ = () => (type) => type;\",\n \" window.__vite_plugin_react_preamble_installed__ = true;\",\n \"} catch {\",\n \" // No @vitejs/plugin-react in this widget project (no\",\n \" // /@react-refresh virtual module) — nothing to preinstall.\",\n \"}\",\n `await import(${JSON.stringify(entryUrl)});`,\n 'self.removeEventListener(\"message\", __buf);',\n \"for (const data of __q) {\",\n ' self.dispatchEvent(new MessageEvent(\"message\", { data }));',\n \"}\",\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * The shared development descriptor workflow appends Vite's `?direct` query\n * to CSS URLs so preview hosts receive real CSS instead of JS style modules.\n * Published descriptors use a separate build path and never receive it.\n */\nexport function createDevWidgetPackageDescriptors(\n configModule: Readonly<Record<string, unknown>>,\n origin: string,\n owner: WidgetPackageOwnerKind = \"droplet\",\n): readonly RemoteDomWidgetPackageDescriptor[] {\n return [\n createWidgetPackageDevelopmentDescriptor({\n sourceModule: configModule,\n owner,\n origin,\n workerEntryPath: \"/__runtime-entry__\",\n defaultCssPath: \"/styles.css\",\n }),\n ];\n}\n\n/**\n * True when validation failed *only* because the project declares no widget\n * package. Checked against the typed diagnostics rather than message text, and\n * deliberately narrow: a config that declares a package and gets it wrong must\n * still be reported.\n */\nfunction isNoSourcePackageError(error: unknown): boolean {\n if (!(error instanceof WidgetToolingError)) return false;\n const diagnostics = error.diagnostics ?? [];\n return (\n diagnostics.length > 0 &&\n diagnostics.every((diagnostic) => diagnostic.code === \"NO_SOURCE_PACKAGE\")\n );\n}\n\nasync function sendWidgetPackages(\n server: ViteDevServer,\n request: IncomingMessage,\n response: ServerResponse,\n options: {\n readonly configModulePath: string;\n readonly owner: WidgetPackageOwnerKind;\n readonly allowNoPackages: boolean;\n },\n): Promise<void> {\n if (handleOptions(request, response)) return;\n\n try {\n const configModule = (await server.ssrLoadModule(\n options.configModulePath,\n )) as Record<string, unknown>;\n sendJson(\n response,\n createDevWidgetPackageDescriptors(\n configModule,\n getRequestOrigin(request),\n options.owner,\n ),\n );\n } catch (error) {\n // \"This project declares no widget package\" is an expected state for a\n // portal that has not been given a custom widget yet — serve an empty\n // catalog so the preview falls back to built-in widgets. Every other\n // failure (a broken config, a bad manifest) still surfaces loudly.\n if (options.allowNoPackages && isNoSourcePackageError(error)) {\n sendJson(response, []);\n return;\n }\n server.config.logger.error(\n `[fluid] Failed to load widget packages: ${String(error)}`,\n );\n sendJson(response, { error: String(error) }, 500);\n }\n}\n\nfunction sendJavaScript(\n request: IncomingMessage,\n response: ServerResponse,\n source: string,\n): void {\n if (handleOptions(request, response)) return;\n setCorsHeaders(response);\n response.setHeader(\"Content-Type\", \"text/javascript\");\n response.statusCode = 200;\n response.end(source);\n}\n\nfunction sendJson(\n response: ServerResponse,\n body: unknown,\n statusCode = 200,\n): void {\n setCorsHeaders(response);\n response.setHeader(\"Content-Type\", \"application/json\");\n response.statusCode = statusCode;\n response.end(JSON.stringify(body, null, 2));\n}\n\nexport function handleOptions(\n request: IncomingMessage,\n response: ServerResponse,\n): boolean {\n if (request.method !== \"OPTIONS\") return false;\n setCorsHeaders(response);\n response.statusCode = 204;\n response.end();\n return true;\n}\n\nexport function setCorsHeaders(response: ServerResponse): void {\n response.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n response.setHeader(\"Access-Control-Allow-Methods\", \"GET, HEAD, OPTIONS\");\n response.setHeader(\n \"Access-Control-Allow-Headers\",\n \"Content-Type, Authorization\",\n );\n}\n\nfunction getRequestOrigin(request: IncomingMessage): string {\n const host = readHeader(request.headers.host);\n if (!host) throw new Error(\"Widget dev request is missing the Host header.\");\n\n const forwardedProtocol = readHeader(request.headers[\"x-forwarded-proto\"]);\n const protocol = forwardedProtocol === \"https\" ? \"https\" : \"http\";\n return `${protocol}://${host}`;\n}\n\nfunction readHeader(\n value: string | readonly string[] | undefined,\n): string | undefined {\n const candidate = Array.isArray(value) ? value[0] : value;\n return typeof candidate === \"string\" && candidate.trim().length > 0\n ? candidate.trim()\n : undefined;\n}\n","/**\n * How this package runs the helper scripts it generates.\n *\n * Building a widget package writes two scripts to disk and runs them: a config\n * extractor (under `tsx`) and a Vite build. Both used to assume the same thing —\n * that `process.execPath` is Node and that `tsx` is resolvable from this\n * module. Both assumptions hold for a CLI and neither holds in an Electron main\n * process, where `process.execPath` is the Electron binary. Spawning it without\n * `ELECTRON_RUN_AS_NODE` starts a second copy of the app instead of running the\n * script, and `tsx` is not in a packaged app's dependency closure at all.\n *\n * So the host says how to run a script rather than this package guessing. The\n * default reproduces the old behaviour exactly, which is why both CLIs are\n * unchanged by this.\n */\n\nimport { createRequire } from \"node:module\";\n\nexport interface WidgetToolingNodeRuntime {\n /**\n * Executable that runs a Node script.\n *\n * Defaults to `process.execPath`. An Electron host passes its resolved system\n * Node, or its own binary together with `ELECTRON_RUN_AS_NODE` in `env`.\n */\n readonly execPath?: string;\n /**\n * Extra environment for spawned scripts — the place `ELECTRON_RUN_AS_NODE: \"1\"`\n * goes when `execPath` is an Electron binary.\n */\n readonly env?: Readonly<Record<string, string>>;\n /**\n * Absolute path to `tsx`'s CLI entry.\n *\n * Injectable because a host that bundles this package cannot necessarily\n * resolve `tsx` from here — it is a dependency of this package, not of the\n * app that embedded it.\n */\n readonly tsxCliPath?: string;\n}\n\n/** The executable to spawn, and the env to spawn it with. */\nexport function resolveSpawnTarget(runtime?: WidgetToolingNodeRuntime): {\n readonly execPath: string;\n readonly env: Readonly<Record<string, string>>;\n} {\n return {\n execPath: runtime?.execPath ?? process.execPath,\n env: runtime?.env ?? {},\n };\n}\n\n/**\n * Resolves `tsx`'s CLI, preferring an injected path.\n *\n * Deliberately a function rather than a module-scope constant. It used to be\n * `const TSX_CLI_PATH = require.resolve(\"tsx/cli\")`, which runs on IMPORT — so a\n * host that merely imported this package, and never published anything, crashed\n * at startup if `tsx` was absent. Resolving on use means a missing `tsx` is a\n * publish-time error the caller can report, not a boot failure.\n */\nexport function resolveTsxCliPath(runtime?: WidgetToolingNodeRuntime): string {\n if (runtime?.tsxCliPath) return runtime.tsxCliPath;\n const require = createRequire(import.meta.url);\n return require.resolve(\"tsx/cli\");\n}\n","import { execa } from \"execa\";\nimport fs from \"fs-extra\";\nimport path from \"node:path\";\nimport { type Result, success, failure } from \"@fluid-app/fluid-cli\";\nimport {\n resolveSpawnTarget,\n resolveTsxCliPath,\n type WidgetToolingNodeRuntime,\n} from \"../node-runtime.js\";\n\nconst WIDGET_CONFIG_PATH = \"src/widgets.config.ts\";\n/** Long enough for a cold tsx start on a slow machine, short enough to fail. */\nconst CONFIG_EVAL_TIMEOUT_MS = 60_000;\nconst SOURCE_PACKAGE_EXTRACT_FILENAME = \"extract-widget-packages.ts\";\nconst SOURCE_PACKAGE_OUTPUT_FILENAME = \"source-widget-packages.json\";\nconst SOURCE_PACKAGE_OUTPUT_SENTINEL = \"fluid-widget-source-packages:v1\";\n\nexport interface WidgetSourceConfig {\n readonly path: string;\n readonly relativePath: string;\n}\n\nexport interface WidgetSourceConfigLoadError {\n readonly code: \"CONFIG_LOAD_FAILED\" | \"INVALID_FORMAT\";\n readonly message: string;\n readonly details?: string;\n}\n\nexport async function resolvePortalWidgetSourceConfig(\n projectDir: string,\n): Promise<WidgetSourceConfig | undefined> {\n const candidate = path.join(projectDir, WIDGET_CONFIG_PATH);\n return (await fs.pathExists(candidate))\n ? { path: candidate, relativePath: WIDGET_CONFIG_PATH }\n : undefined;\n}\n\nexport async function loadSourceWidgetPackages(\n projectDir: string,\n nodeRuntime?: WidgetToolingNodeRuntime,\n): Promise<Result<unknown[], WidgetSourceConfigLoadError>> {\n const config = await resolvePortalWidgetSourceConfig(projectDir);\n if (!config) return success([]);\n\n let tempDir: string | undefined;\n\n try {\n tempDir = await createTempDirectory(projectDir);\n const extractFile = path.join(tempDir, SOURCE_PACKAGE_EXTRACT_FILENAME);\n const outputFile = path.join(tempDir, SOURCE_PACKAGE_OUTPUT_FILENAME);\n\n await fs.writeFile(\n extractFile,\n createSourcePackageExtractorScript({\n projectDir,\n configPath: config.path,\n }),\n { encoding: \"utf-8\", flag: \"wx\" },\n );\n\n const spawn = resolveSpawnTarget(nodeRuntime);\n await execa(\n spawn.execPath,\n [resolveTsxCliPath(nodeRuntime), extractFile, outputFile],\n {\n cwd: projectDir,\n stdio: \"pipe\",\n env: {\n ...process.env,\n ...spawn.env,\n NODE_ENV: \"production\",\n },\n // `widgets.config.ts` is project code: it is imported and evaluated\n // here, so anything it does at module scope — an await that never\n // settles, a server it starts — runs with no deadline of its own. A\n // caller that awaits this inside a publish would wait forever, and the\n // publish path this feeds serializes on it, so one bad config would\n // wedge publishing for the whole app until it restarts.\n timeout: CONFIG_EVAL_TIMEOUT_MS,\n killSignal: \"SIGKILL\",\n },\n );\n\n const outputResult = await readSourcePackageExtractorOutput(outputFile);\n if (!outputResult.success) return outputResult;\n\n const parsed = outputResult.value;\n if (parsed.length === 0) return success([]);\n\n return success(parsed);\n } catch (err) {\n const error = err as { stderr?: string; message?: string };\n return failure({\n code: \"CONFIG_LOAD_FAILED\",\n message: `Failed to load widget packages from ${config.relativePath}`,\n details: error.stderr ?? error.message ?? String(err),\n });\n } finally {\n if (tempDir) await fs.remove(tempDir).catch(() => {});\n }\n}\n\nasync function createTempDirectory(projectDir: string): Promise<string> {\n const projectTmpDir = path.join(projectDir, \".fluid\", \"tmp\");\n try {\n await fs.ensureDir(projectTmpDir);\n return await fs.mkdtemp(path.join(projectTmpDir, \"widget-packages-\"));\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Unable to create project-local temporary directory at ${projectTmpDir}: ${message}`,\n );\n }\n}\n\nasync function readSourcePackageExtractorOutput(\n outputFile: string,\n): Promise<Result<unknown[], WidgetSourceConfigLoadError>> {\n let output: string;\n try {\n output = await fs.readFile(outputFile, \"utf-8\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return failure({\n code: \"CONFIG_LOAD_FAILED\",\n message: \"Widget package extractor did not write an output file\",\n details: message,\n });\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(output);\n } catch {\n return failure({\n code: \"INVALID_FORMAT\",\n message: \"Failed to parse widget package output file as JSON\",\n details: `Output was: ${output.slice(0, 200)}`,\n });\n }\n\n if (!isRecord(parsed) || parsed.sentinel !== SOURCE_PACKAGE_OUTPUT_SENTINEL) {\n return failure({\n code: \"INVALID_FORMAT\",\n message: \"Widget package extractor output file had an invalid sentinel\",\n });\n }\n\n if (!Array.isArray(parsed.data)) {\n return failure({\n code: \"INVALID_FORMAT\",\n message: \"Extracted widget package output is not an array\",\n details: `Expected an array, got: ${typeof parsed.data}`,\n });\n }\n\n return success(parsed.data);\n}\n\nfunction createSourcePackageExtractorScript(options: {\n readonly projectDir: string;\n readonly configPath: string;\n}): string {\n return `\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createServer, normalizePath } from \"vite\";\n\nconst SOURCE_PACKAGE_MARKER = \"__fluidSourceWidgetPackage\";\nconst OUTPUT_SENTINEL = ${JSON.stringify(SOURCE_PACKAGE_OUTPUT_SENTINEL)};\nconst projectRoot = ${JSON.stringify(options.projectDir)};\nconst widgetConfigPath = ${JSON.stringify(options.configPath)};\nconst outputPath = process.argv[2];\nif (!outputPath) throw new Error(\"Missing widget package extractor output path.\");\n\nfunction toViteModuleId(modulePath) {\n const relativePath = path.relative(projectRoot, modulePath);\n if (!relativePath.startsWith(\"..\") && !path.isAbsolute(relativePath)) {\n return \"/\" + normalizePath(relativePath);\n }\n return normalizePath(modulePath);\n}\n\nconst server = await createServer({\n root: projectRoot,\n mode: \"production\",\n server: { middlewareMode: true },\n appType: \"custom\",\n logLevel: \"error\",\n clearScreen: false,\n resolve: {\n conditions: [\"module\", \"browser\", \"development|production\"],\n },\n ssr: {\n noExternal: [\"@fluid-app/portal-sdk\"],\n resolve: {\n conditions: [\"module\", \"node\", \"development|production\"],\n },\n },\n});\n\ntry {\n const widgetConfig = await server.ssrLoadModule(toViteModuleId(widgetConfigPath));\n\n function isSourceWidgetPackage(value) {\n return Boolean(value && typeof value === \"object\" && value[SOURCE_PACKAGE_MARKER] === true);\n }\n\n function collectSourceWidgetPackages(mod) {\n const candidates = [\n mod.widgetPackage,\n ...(Array.isArray(mod.widgetPackages) ? mod.widgetPackages : []),\n mod.default,\n ];\n const byPackageId = new Map();\n for (const candidate of candidates) {\n if (!isSourceWidgetPackage(candidate)) continue;\n if (!byPackageId.has(candidate.packageId)) byPackageId.set(candidate.packageId, candidate);\n }\n return Array.from(byPackageId.values());\n }\n\n function serializeWidget(widget) {\n if (!widget || typeof widget !== \"object\" || Array.isArray(widget)) {\n return widget;\n }\n const { component, ...metadata } = widget;\n return metadata;\n }\n\n function serializePackage(sourcePackage) {\n return {\n manifestVersion: sourcePackage.manifestVersion,\n scope: sourcePackage.scope,\n packageStableId: sourcePackage.packageStableId,\n packageId: sourcePackage.packageId,\n packageType: sourcePackage.packageType,\n version: sourcePackage.version,\n cssUrls: sourcePackage.cssUrls,\n ...(Object.prototype.hasOwnProperty.call(sourcePackage, \"navigationOrigins\")\n ? { navigationOrigins: sourcePackage.navigationOrigins }\n : {}),\n widgets: Array.isArray(sourcePackage.widgets)\n ? sourcePackage.widgets.map(serializeWidget)\n : sourcePackage.widgets,\n };\n }\n\n await fs.writeFile(\n outputPath,\n JSON.stringify({\n sentinel: OUTPUT_SENTINEL,\n data: collectSourceWidgetPackages(widgetConfig).map(serializePackage),\n }),\n \"utf-8\",\n );\n} finally {\n await server.close();\n}\n`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { execa } from \"execa\";\nimport {\n resolveSpawnTarget,\n type WidgetToolingNodeRuntime,\n} from \"../node-runtime.js\";\nimport fs from \"fs-extra\";\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { pathToFileURL } from \"node:url\";\nimport { type Result, success, failure } from \"@fluid-app/fluid-cli\";\nimport {\n loadSourceWidgetPackages,\n resolvePortalWidgetSourceConfig,\n} from \"./widget-package-config.js\";\nimport {\n buildWidgetPackagePublishManifest,\n validateSingleSourceWidgetPackage,\n type ValidatedWidgetPackageBuild,\n type WidgetPackageOwnerKind,\n} from \"./widget-package-validation.js\";\nimport {\n collectWidgetPackageArtifacts,\n createPublishManifestMetadata,\n isWidgetPackageCssArtifactPath,\n} from \"./widget-package-artifacts.js\";\n\nconst DEFAULT_PUBLISH_DIR = \".fluid/widget-dist\";\nconst DEFAULT_RUNTIME_VERSION = \"1\";\nconst TEMP_BUILD_DIR = \".fluid/widget-build\";\nconst TEMP_CLI_DIR = \".fluid/tmp\";\nconst PROJECT_VITE_CONFIG_CANDIDATES = [\n \"vite.config.ts\",\n \"vite.config.mts\",\n \"vite.config.js\",\n \"vite.config.mjs\",\n] as const;\nconst BLOCKED_FLUID_PROJECT_PLUGIN_NAMES = [\n \"fluid-portal-dev\",\n \"fluid-backend-dev\",\n] as const;\nconst require = createRequire(import.meta.url);\n\nexport interface BuildSharedWidgetPackageOptions {\n readonly projectDir: string;\n readonly publishDir?: string;\n readonly owner?: WidgetPackageOwnerKind;\n readonly cliVersion: string;\n /** How to run the generated helper scripts — see WidgetToolingNodeRuntime. */\n readonly nodeRuntime?: WidgetToolingNodeRuntime;\n /**\n * Stamp this version into the manifests instead of the config's.\n *\n * A company has ONE widget package that several projects publish into, so the\n * version is really a property of that shared package — not of any single\n * project's source file. Two projects both declaring \"0.5.0\" is not a\n * mistake either of them can see, and the server refuses the second one.\n * The caller resolves the version against what is actually published; this\n * is where that answer lands.\n */\n readonly versionOverride?: string;\n}\n\nexport interface SharedWidgetPackageBuildResult {\n readonly publishDir: string;\n readonly packageId: string;\n readonly version: string;\n readonly manifestPath: string;\n readonly publishManifestPath: string;\n readonly widgetScriptPath: string;\n}\n\nexport interface SharedWidgetPackageBuildError {\n readonly code:\n | \"CONFIG_LOAD_FAILED\"\n | \"VALIDATION_FAILED\"\n | \"INVALID_PUBLISH_DIR\"\n | \"WRITE_FAILED\";\n readonly message: string;\n readonly details?: string;\n}\n\nexport interface ValidateSharedWidgetPackagePublishDirOptions {\n readonly optionName?: string;\n}\n\nexport function validateSharedWidgetPackagePublishDir(\n projectDir: string,\n publishDir: string = DEFAULT_PUBLISH_DIR,\n options: ValidateSharedWidgetPackagePublishDirOptions = {},\n): void {\n const label = options.optionName ?? \"publishDir\";\n\n if (path.isAbsolute(publishDir)) {\n throw new Error(`${label} must be relative to the project directory.`);\n }\n\n const normalizedPublishDir = normalizePublishDirForValidation(publishDir);\n if (\n normalizedPublishDir === \".fluid\" ||\n !normalizedPublishDir.startsWith(\".fluid/\")\n ) {\n throw new Error(`${label} must be a relative path under .fluid/.`);\n }\n\n if (isPathWithinReservedDir(normalizedPublishDir, TEMP_BUILD_DIR)) {\n throw new Error(\n `${label} must not be ${TEMP_BUILD_DIR} because it is reserved for temporary builder output.`,\n );\n }\n\n if (isPathWithinReservedDir(normalizedPublishDir, TEMP_CLI_DIR)) {\n throw new Error(\n `${label} must not be ${TEMP_CLI_DIR} because it is reserved for Fluid CLI temporary files.`,\n );\n }\n\n const resolvedProjectDir = path.resolve(projectDir);\n const resolvedPublishDir = path.resolve(resolvedProjectDir, publishDir);\n const relative = path.relative(resolvedProjectDir, resolvedPublishDir);\n\n if (\n relative === \"\" ||\n relative.startsWith(\"..\") ||\n path.isAbsolute(relative)\n ) {\n throw new Error(`${label} must stay inside the project directory.`);\n }\n}\n\n/**\n * Restamps each loaded source package with `version`.\n *\n * Object spread carries own enumerable SYMBOL keys as well as string ones,\n * which matters here: `defineWidgetPackage` marks its result with a symbol that\n * validation uses to recognise a real source package. A copy that dropped it\n * would fail validation with a message about a missing package rather than\n * about the version.\n */\nfunction withVersionOverride(\n sourcePackages: readonly unknown[],\n version: string,\n): readonly unknown[] {\n return sourcePackages.map((sourcePackage) =>\n typeof sourcePackage === \"object\" && sourcePackage !== null\n ? { ...sourcePackage, version }\n : sourcePackage,\n );\n}\n\nexport async function buildSharedWidgetPackage(\n options: BuildSharedWidgetPackageOptions,\n): Promise<\n Result<SharedWidgetPackageBuildResult, SharedWidgetPackageBuildError>\n> {\n const publishDirInput = options.publishDir ?? DEFAULT_PUBLISH_DIR;\n try {\n await validateWidgetPackageOutputPaths(options.projectDir, publishDirInput);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n return failure({\n code: \"INVALID_PUBLISH_DIR\",\n message: \"Unsafe widget package publish directory\",\n details: error.message,\n });\n }\n\n const sourcePackageResult = await loadSourceWidgetPackages(\n options.projectDir,\n options.nodeRuntime,\n );\n if (!sourcePackageResult.success) {\n return failure({\n code: \"CONFIG_LOAD_FAILED\",\n message: sourcePackageResult.error.message,\n details: sourcePackageResult.error.details,\n });\n }\n\n // Applied BEFORE validation, so an overridden version is held to exactly the\n // same SemVer rules as one written in the config — the override is not a way\n // to smuggle an unpublishable version past the checks.\n const sourcePackages = options.versionOverride\n ? withVersionOverride(sourcePackageResult.value, options.versionOverride)\n : sourcePackageResult.value;\n\n const validation = validateSingleSourceWidgetPackage(sourcePackages, {\n owner: options.owner,\n });\n if (!validation.success || !validation.value) {\n return failure({\n code: \"VALIDATION_FAILED\",\n message: validation.errors.map((error) => error.message).join(\"\\n\"),\n });\n }\n\n try {\n await validateWidgetPackageOutputPaths(options.projectDir, publishDirInput);\n\n const publishDir = path.resolve(options.projectDir, publishDirInput);\n const widgetScriptPath = path.join(publishDir, \"widget.js\");\n await fs.emptyDir(publishDir);\n\n const tempDir = path.resolve(options.projectDir, TEMP_BUILD_DIR);\n await fs.emptyDir(tempDir);\n let buildFailure: { readonly error: unknown } | undefined;\n try {\n await buildWidgetScriptBundle({\n projectDir: options.projectDir,\n tempDir,\n publishDir,\n validated: validation.value,\n ...(options.nodeRuntime ? { nodeRuntime: options.nodeRuntime } : {}),\n });\n } catch (error) {\n buildFailure = { error };\n }\n\n try {\n await fs.remove(tempDir);\n } catch {\n const cleanupFailure = new Error(\n \"Failed to remove reserved temporary build directory.\",\n );\n if (buildFailure) {\n const primaryError =\n buildFailure.error instanceof Error\n ? buildFailure.error\n : new Error(String(buildFailure.error));\n throw new AggregateError(\n [primaryError, cleanupFailure],\n `${primaryError.message}\\n${cleanupFailure.message}`,\n );\n }\n throw cleanupFailure;\n }\n\n if (buildFailure) {\n throw buildFailure.error;\n }\n\n const cssUrls = await collectCssUrls(publishDir);\n const descriptor = buildWidgetPackagePublishManifest(validation.value, {\n cssUrls,\n });\n const manifestContent = stableStringify(descriptor);\n const publishPackageId = descriptor.packageId;\n\n const manifestPath = path.join(publishDir, \"manifest.json\");\n const publishManifestPath = path.join(publishDir, \"publish-manifest.json\");\n\n await fs.writeFile(manifestPath, manifestContent, \"utf-8\");\n\n const artifacts = await collectWidgetPackageArtifacts(publishDir);\n const publishManifest = createPublishManifestMetadata({\n packageId: publishPackageId,\n version: validation.value.version,\n cliVersion: options.cliVersion,\n runtimeVersion: DEFAULT_RUNTIME_VERSION,\n manifestContent,\n artifacts,\n });\n await fs.writeFile(\n publishManifestPath,\n stableStringify(publishManifest),\n \"utf-8\",\n );\n\n return success({\n publishDir,\n packageId: validation.value.packageId,\n version: validation.value.version,\n manifestPath,\n publishManifestPath,\n widgetScriptPath,\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n const isPublishDirValidationError =\n /^(publishDir|reserved temporary build directory) /.test(error.message);\n return failure({\n code: isPublishDirValidationError\n ? \"INVALID_PUBLISH_DIR\"\n : \"WRITE_FAILED\",\n message: isPublishDirValidationError\n ? \"Unsafe widget package publish directory\"\n : \"Failed to build shared widget package artifacts\",\n details: error.message,\n });\n }\n}\n\nexport function createWidgetPackageEntrySource(options: {\n readonly configImportPath: string;\n readonly cssImportPath?: string;\n readonly validated: ValidatedWidgetPackageBuild;\n}): string {\n return `import { createElement } from \"react\";\nimport { prepareRemoteDomWidgetWorker, startWidgetPackage } from \"@fluid-app/portal-sdk/widgets/worker\";\n${options.cssImportPath ? `import ${JSON.stringify(options.cssImportPath)};` : \"\"}\n\nprepareRemoteDomWidgetWorker();\nconst widgetConfig = await import(${JSON.stringify(options.configImportPath)});\nconst SOURCE_PACKAGE_MARKER = \"__fluidSourceWidgetPackage\";\nconst descriptors = ${JSON.stringify(options.validated.widgets, null, 2)};\n\nfunction isSourceWidgetPackage(value) {\n return Boolean(value && typeof value === \"object\" && value[SOURCE_PACKAGE_MARKER] === true);\n}\n\nfunction collectSourceWidgetPackages(mod) {\n return [\n mod.widgetPackage,\n ...(Array.isArray(mod.widgetPackages) ? mod.widgetPackages : []),\n mod.default,\n ].filter(isSourceWidgetPackage);\n}\n\nconst sourcePackage = collectSourceWidgetPackages(widgetConfig)[0];\nif (!sourcePackage) {\n throw new Error(\"No Fluid source widget package found while loading widget package worker bundle.\");\n}\n\nconst componentsByName = new Map(\n sourcePackage.widgets.map((widget) => [widget.name, widget.component]),\n);\n\nconst widgets = descriptors.map((descriptor) => {\n const component = componentsByName.get(descriptor.name);\n if (typeof component !== \"function\") {\n throw new Error(\"Widget package is missing Remote DOM component for \" + descriptor.name + \".\");\n }\n return {\n ...descriptor,\n component: (props) => createElement(component, props),\n };\n});\n\nstartWidgetPackage({ widgets });\n`;\n}\n\nasync function buildWidgetScriptBundle(options: {\n readonly projectDir: string;\n readonly tempDir: string;\n readonly publishDir: string;\n readonly validated: ValidatedWidgetPackageBuild;\n readonly nodeRuntime?: WidgetToolingNodeRuntime;\n}): Promise<void> {\n const sourceConfig = await resolvePortalWidgetSourceConfig(\n options.projectDir,\n );\n if (!sourceConfig) {\n throw new Error(\"No portal widget source config found.\");\n }\n\n const entryPath = path.join(options.tempDir, \"widget-entry.ts\");\n const viteConfigPath = path.join(options.tempDir, \"vite.config.mjs\");\n const rootStylesPath = path.join(options.projectDir, \"styles.css\");\n await fs.writeFile(\n entryPath,\n createWidgetPackageEntrySource({\n configImportPath: pathToFileURL(sourceConfig.path).href,\n cssImportPath: (await fs.pathExists(rootStylesPath))\n ? pathToFileURL(rootStylesPath).href\n : undefined,\n validated: options.validated,\n }),\n \"utf-8\",\n );\n await fs.writeFile(\n viteConfigPath,\n createViteConfigSource({\n entryPath,\n publishDir: options.publishDir,\n projectConfigPath: await resolveProjectViteConfigPath(options.projectDir),\n }),\n \"utf-8\",\n );\n\n const viteCliPath = resolveViteCliPath(options.projectDir);\n const spawn = resolveSpawnTarget(options.nodeRuntime);\n await execa(\n spawn.execPath,\n [viteCliPath, \"build\", \"--config\", viteConfigPath],\n {\n cwd: options.projectDir,\n stdio: \"pipe\",\n env: {\n ...process.env,\n ...spawn.env,\n NODE_ENV: \"production\",\n },\n },\n );\n}\n\nexport function resolveViteCliPath(projectDir: string): string {\n const projectRequire = createRequire(path.join(projectDir, \"package.json\"));\n const projectViteCliPath = resolveViteCliPathFromRequire(projectRequire);\n if (projectViteCliPath) return projectViteCliPath;\n\n const cliViteCliPath = resolveViteCliPathFromRequire(require);\n if (cliViteCliPath) return cliViteCliPath;\n\n throw new Error(\n \"Unable to resolve Vite for the portal project. Install the project dependencies and ensure vite is available before building widget packages.\",\n );\n}\n\nexport async function resolveProjectViteConfigPath(\n projectDir: string,\n): Promise<string | undefined> {\n for (const fileName of PROJECT_VITE_CONFIG_CANDIDATES) {\n const candidate = path.join(projectDir, fileName);\n if (await fs.pathExists(candidate)) return candidate;\n }\n\n return undefined;\n}\n\nexport function createViteConfigSource(options: {\n readonly entryPath: string;\n readonly publishDir: string;\n readonly projectConfigPath?: string;\n}): string {\n const widgetConfigSource = createWidgetViteConfigObjectSource({\n ...options,\n disableConfigFileLookup: !options.projectConfigPath,\n });\n\n if (!options.projectConfigPath) {\n return `import { defineConfig } from \"vite\";\n\nexport default defineConfig(${widgetConfigSource});\n`;\n }\n\n return `import { defineConfig, loadConfigFromFile, mergeConfig } from \"vite\";\n\nconst projectConfigPath = ${JSON.stringify(options.projectConfigPath)};\nconst widgetConfig = ${widgetConfigSource};\nconst fluidWidgetDefineInvariants = {\n \"process.env.NODE_ENV\": JSON.stringify(\"production\"),\n};\nconst blockedFluidPluginNames = new Set(${JSON.stringify(BLOCKED_FLUID_PROJECT_PLUGIN_NAMES)});\n\nfunction isAllowedProjectPlugin(plugin) {\n return !plugin || typeof plugin !== \"object\" || !blockedFluidPluginNames.has(plugin.name);\n}\n\nfunction sanitizeProjectPlugins(pluginOption) {\n if (!Array.isArray(pluginOption)) {\n return isAllowedProjectPlugin(pluginOption) ? pluginOption : [];\n }\n\n return pluginOption\n .map((plugin) => Array.isArray(plugin) ? sanitizeProjectPlugins(plugin) : plugin)\n .filter(isAllowedProjectPlugin);\n}\n\nfunction copyProjectConfigValue(source, target, key) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n}\n\nfunction sanitizeProjectConfig(config) {\n if (!config || typeof config !== \"object\") return {};\n\n const sanitized = {};\n if (Object.prototype.hasOwnProperty.call(config, \"plugins\")) {\n sanitized.plugins = sanitizeProjectPlugins(config.plugins);\n }\n copyProjectConfigValue(config, sanitized, \"resolve\");\n copyProjectConfigValue(config, sanitized, \"define\");\n copyProjectConfigValue(config, sanitized, \"css\");\n copyProjectConfigValue(config, sanitized, \"esbuild\");\n copyProjectConfigValue(config, sanitized, \"json\");\n copyProjectConfigValue(config, sanitized, \"assetsInclude\");\n copyProjectConfigValue(config, sanitized, \"envDir\");\n copyProjectConfigValue(config, sanitized, \"envPrefix\");\n return sanitized;\n}\n\nfunction copyConfigDefineValue(value) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? { ...value }\n : {};\n}\n\nfunction mergeFluidWidgetDefineInvariants(mergedConfig, safeProjectConfig, widgetConfig) {\n mergedConfig.define = {\n ...copyConfigDefineValue(safeProjectConfig.define),\n ...copyConfigDefineValue(mergedConfig.define),\n ...copyConfigDefineValue(widgetConfig.define),\n ...fluidWidgetDefineInvariants,\n };\n return mergedConfig;\n}\n\nexport default defineConfig(async (configEnv) => {\n const projectConfig = await loadConfigFromFile(configEnv, projectConfigPath);\n const safeProjectConfig = sanitizeProjectConfig(projectConfig?.config ?? {});\n return mergeFluidWidgetDefineInvariants(mergeConfig(safeProjectConfig, widgetConfig), safeProjectConfig, widgetConfig);\n});\n`;\n}\n\nfunction createWidgetViteConfigObjectSource(options: {\n readonly entryPath: string;\n readonly publishDir: string;\n readonly disableConfigFileLookup: boolean;\n}): string {\n const configFileSource = options.disableConfigFileLookup\n ? \" configFile: false,\\n\"\n : \"\";\n return `(() => {\n const fluidWidgetDefineInvariants = {\n \"process.env.NODE_ENV\": JSON.stringify(\"production\"),\n };\n\n function createFluidWidgetBuildInvariants() {\n return {\n copyPublicDir: false,\n emptyOutDir: false,\n outDir: ${JSON.stringify(options.publishDir)},\n sourcemap: false,\n target: \"esnext\",\n cssCodeSplit: false,\n lib: {\n entry: ${JSON.stringify(options.entryPath)},\n formats: [\"es\"],\n fileName: () => \"widget.js\",\n cssFileName: \"widget\",\n },\n rollupOptions: {\n output: {\n inlineDynamicImports: true,\n hoistTransitiveImports: false,\n },\n },\n };\n }\n\n function fluidWidgetBuildInvariantsPlugin() {\n return {\n name: \"fluid-widget-build-invariants\",\n enforce: \"post\",\n config() {\n return { build: createFluidWidgetBuildInvariants() };\n },\n configResolved(config) {\n config.define = {\n ...(config.define ?? {}),\n ...fluidWidgetDefineInvariants,\n };\n Object.assign(config.build, createFluidWidgetBuildInvariants());\n },\n };\n }\n\n return {\n${configFileSource} publicDir: false,\n define: fluidWidgetDefineInvariants,\n resolve: {\n conditions: [\n \"module\",\n \"browser\",\n \"development|production\",\n ],\n },\n plugins: [fluidWidgetBuildInvariantsPlugin()],\n build: createFluidWidgetBuildInvariants(),\n };\n})()`;\n}\n\nasync function validateWidgetPackageOutputPaths(\n projectDir: string,\n publishDir: string,\n): Promise<void> {\n validateSharedWidgetPackagePublishDir(projectDir, publishDir);\n await rejectSymlinkedPathSegments({\n projectDir,\n relativePath: publishDir,\n label: \"publishDir\",\n });\n await rejectSymlinkedPathSegments({\n projectDir,\n relativePath: TEMP_BUILD_DIR,\n label: \"reserved temporary build directory\",\n });\n}\n\nasync function collectCssUrls(publishDir: string): Promise<string[]> {\n const entries = await fs.readdir(publishDir, { withFileTypes: true });\n return entries\n .filter(\n (entry) => entry.isFile() && isWidgetPackageCssArtifactPath(entry.name),\n )\n .map((entry) => entry.name)\n .sort();\n}\n\nasync function rejectSymlinkedPathSegments(options: {\n readonly projectDir: string;\n readonly relativePath: string;\n readonly label: string;\n}): Promise<void> {\n const resolvedProjectDir = path.resolve(options.projectDir);\n const resolvedTargetPath = path.resolve(\n resolvedProjectDir,\n options.relativePath,\n );\n const relative = path.relative(resolvedProjectDir, resolvedTargetPath);\n const segments = relative.split(path.sep).filter(Boolean);\n let currentPath = resolvedProjectDir;\n\n for (const segment of segments) {\n currentPath = path.join(currentPath, segment);\n let stat: fs.Stats;\n try {\n stat = await fs.lstat(currentPath);\n } catch (err) {\n if (isNodeError(err) && err.code === \"ENOENT\") return;\n throw err;\n }\n\n if (stat.isSymbolicLink()) {\n throw new Error(`${options.label} must not include symbolic links.`);\n }\n }\n}\n\nfunction normalizePublishDirForValidation(value: string): string {\n return toPosixPath(path.normalize(value)).replace(/\\/+$/, \"\") || \".\";\n}\n\nfunction isPathWithinReservedDir(value: string, reservedDir: string): boolean {\n return value === reservedDir || value.startsWith(`${reservedDir}/`);\n}\n\nfunction toPosixPath(value: string): string {\n return value.split(path.sep).join(\"/\");\n}\n\nfunction stableStringify(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nfunction resolveViteCliPathFromRequire(\n moduleRequire: NodeJS.Require,\n): string | undefined {\n try {\n const packageJsonPath = moduleRequire.resolve(\"vite/package.json\");\n const packageJson = moduleRequire(packageJsonPath) as { bin?: unknown };\n const binPath = getViteBinPath(packageJson.bin);\n if (!binPath) return undefined;\n\n return path.resolve(path.dirname(packageJsonPath), binPath);\n } catch (err) {\n if (isModuleResolutionError(err)) return undefined;\n throw err;\n }\n}\n\nfunction getViteBinPath(bin: unknown): string | undefined {\n if (typeof bin === \"string\") return bin;\n if (!isRecord(bin)) return undefined;\n\n const viteBin = bin.vite;\n return typeof viteBin === \"string\" ? viteBin : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeError(value: unknown): value is NodeJS.ErrnoException {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"code\" in value &&\n typeof value.code === \"string\"\n );\n}\n\nfunction isModuleResolutionError(value: unknown): boolean {\n return (\n isNodeError(value) &&\n (value.code === \"MODULE_NOT_FOUND\" || value.code === \"ERR_MODULE_NOT_FOUND\")\n );\n}\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\nimport {\n collectWidgetPackageArtifacts,\n computeArtifactMetadata,\n sha256,\n type ArtifactMetadata,\n type PublishManifestMetadata,\n} from \"./widget-package-artifacts.js\";\nimport type { WidgetPackagePublishRequest } from \"./widget-package-upload.js\";\nimport type { WidgetPackageOwnerKind } from \"./widget-package-validation.js\";\n\nexport async function createWidgetPackagePublishRequest(options: {\n readonly publishDir: string;\n readonly manifestPath: string;\n readonly publishManifestPath: string;\n readonly owner: WidgetPackageOwnerKind;\n}): Promise<WidgetPackagePublishRequest> {\n const manifestContent = await fs.readFile(options.manifestPath);\n const manifest = parseJsonRecord(\n manifestContent.toString(\"utf-8\"),\n options.manifestPath,\n );\n const publishManifest = await readPublishManifest(\n options.publishManifestPath,\n );\n assertManifestIdentityMatches(\n manifest,\n publishManifest,\n options.manifestPath,\n );\n assertMetadataMatches({\n label: \"manifestHash\",\n path: \"manifest.json\",\n expected: publishManifest.manifestHash,\n actual: sha256(manifestContent),\n });\n const collectedArtifacts = await collectWidgetPackageArtifacts(\n options.publishDir,\n );\n assertArtifactInventoryMatches(publishManifest.artifacts, collectedArtifacts);\n const artifacts = await readUploadArtifacts(\n options.publishDir,\n publishManifest.artifacts,\n );\n\n return {\n version: publishManifest.version,\n packageKey: stripOwnerPrefix(publishManifest.packageId, options.owner),\n builderVersion: publishManifest.builderVersion,\n cliVersion: publishManifest.cliVersion,\n runtimeVersion: publishManifest.runtimeVersion,\n manifestHash: publishManifest.manifestHash,\n manifest,\n artifacts,\n };\n}\nasync function readJsonRecord(\n filePath: string,\n): Promise<Record<string, unknown>> {\n return parseJsonRecord(await fs.readFile(filePath, \"utf-8\"), filePath);\n}\n\nfunction parseJsonRecord(\n content: string,\n filePath: string,\n): Record<string, unknown> {\n const value = JSON.parse(content) as unknown;\n if (!isRecord(value) || Array.isArray(value)) {\n throw new Error(`${path.basename(filePath)} must contain a JSON object.`);\n }\n return value;\n}\n\nasync function readPublishManifest(\n filePath: string,\n): Promise<PublishManifestMetadata> {\n const record = await readJsonRecord(filePath);\n const artifactsValue = record[\"artifacts\"];\n if (!Array.isArray(artifactsValue)) {\n throw new Error(\"publish-manifest.json must include an artifacts array.\");\n }\n\n return {\n packageId: readRequiredString(record, \"packageId\", filePath),\n version: readRequiredString(record, \"version\", filePath),\n builderVersion: readRequiredString(record, \"builderVersion\", filePath),\n cliVersion: readRequiredString(record, \"cliVersion\", filePath),\n runtimeVersion: readRequiredString(record, \"runtimeVersion\", filePath),\n manifestHash: readRequiredString(record, \"manifestHash\", filePath),\n artifacts: artifactsValue.map((artifact, index) =>\n readArtifactMetadata(artifact, index),\n ),\n };\n}\n\nfunction readArtifactMetadata(value: unknown, index: number): ArtifactMetadata {\n if (!isRecord(value) || Array.isArray(value)) {\n throw new Error(\n `publish-manifest.json artifacts[${index}] must be a JSON object.`,\n );\n }\n\n return {\n path: readRequiredString(value, \"path\", \"publish-manifest.json\"),\n sha256: readRequiredString(value, \"sha256\", \"publish-manifest.json\"),\n bytes: readRequiredNumber(value, \"bytes\", \"publish-manifest.json\"),\n contentType: readRequiredString(\n value,\n \"contentType\",\n \"publish-manifest.json\",\n ),\n };\n}\n\nasync function readUploadArtifacts(\n publishDir: string,\n artifacts: readonly ArtifactMetadata[],\n): Promise<WidgetPackagePublishRequest[\"artifacts\"]> {\n const resolvedPublishDir = path.resolve(publishDir);\n\n return Promise.all(\n artifacts.map(async (artifact) => {\n const artifactPath = resolveArtifactPath(\n resolvedPublishDir,\n artifact.path,\n );\n const actual = await computeArtifactMetadata(\n artifactPath,\n resolvedPublishDir,\n );\n assertArtifactMetadataMatches(artifact, actual);\n\n return {\n ...actual,\n body: await fs.readFile(artifactPath),\n };\n }),\n );\n}\n\nfunction assertManifestIdentityMatches(\n manifest: Record<string, unknown>,\n publishManifest: PublishManifestMetadata,\n manifestPath: string,\n): void {\n assertMetadataMatches({\n label: \"packageId\",\n path: \"manifest.json\",\n expected: publishManifest.packageId,\n actual: readRequiredString(manifest, \"packageId\", manifestPath),\n });\n assertMetadataMatches({\n label: \"version\",\n path: \"manifest.json\",\n expected: publishManifest.version,\n actual: readRequiredString(manifest, \"version\", manifestPath),\n });\n}\n\nfunction assertArtifactInventoryMatches(\n expected: readonly ArtifactMetadata[],\n actual: readonly ArtifactMetadata[],\n): void {\n const expectedByPath = new Map<string, ArtifactMetadata>();\n for (const artifact of expected) {\n if (expectedByPath.has(artifact.path)) {\n throw new Error(\n `publish-manifest.json artifacts include duplicate path ${JSON.stringify(artifact.path)}. ` +\n \"Rebuild the widget package before publishing.\",\n );\n }\n expectedByPath.set(artifact.path, artifact);\n }\n\n const actualPaths = new Set<string>();\n for (const actualArtifact of actual) {\n actualPaths.add(actualArtifact.path);\n const expectedArtifact = expectedByPath.get(actualArtifact.path);\n if (!expectedArtifact) {\n throw new Error(\n `publish-manifest.json artifacts omit ${JSON.stringify(actualArtifact.path)}. ` +\n \"Rebuild the widget package before publishing.\",\n );\n }\n assertArtifactMetadataMatches(expectedArtifact, actualArtifact);\n }\n\n for (const expectedArtifact of expected) {\n if (actualPaths.has(expectedArtifact.path)) continue;\n throw new Error(\n `publish-manifest.json artifacts include ${JSON.stringify(expectedArtifact.path)}, but that file is not present on disk. ` +\n \"Rebuild the widget package before publishing.\",\n );\n }\n}\n\nfunction assertArtifactMetadataMatches(\n expected: ArtifactMetadata,\n actual: ArtifactMetadata,\n): void {\n assertMetadataMatches({\n label: \"path\",\n path: expected.path,\n expected: expected.path,\n actual: actual.path,\n });\n assertMetadataMatches({\n label: \"sha256\",\n path: expected.path,\n expected: expected.sha256,\n actual: actual.sha256,\n });\n assertMetadataMatches({\n label: \"bytes\",\n path: expected.path,\n expected: expected.bytes,\n actual: actual.bytes,\n });\n assertMetadataMatches({\n label: \"contentType\",\n path: expected.path,\n expected: expected.contentType,\n actual: actual.contentType,\n });\n}\n\nfunction assertMetadataMatches(options: {\n readonly label: string;\n readonly path: string;\n readonly expected: string | number;\n readonly actual: string | number;\n}): void {\n if (options.expected === options.actual) return;\n\n throw new Error(\n `publish-manifest.json ${options.label} for ${JSON.stringify(options.path)} does not match the file on disk. ` +\n `Recorded ${JSON.stringify(options.expected)}, computed ${JSON.stringify(options.actual)}. ` +\n \"Rebuild the widget package before publishing.\",\n );\n}\n\nfunction resolveArtifactPath(publishDir: string, artifactPath: string): string {\n const resolved = path.resolve(publishDir, artifactPath);\n const relative = path.relative(publishDir, resolved);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new Error(\n `Artifact path ${JSON.stringify(artifactPath)} escapes the publish directory.`,\n );\n }\n return resolved;\n}\n\nfunction stripOwnerPrefix(\n packageId: string,\n owner: WidgetPackageOwnerKind,\n): string {\n const prefix = `${owner}.`;\n if (packageId.startsWith(prefix) && packageId.length > prefix.length) {\n return packageId.slice(prefix.length);\n }\n return packageId;\n}\n\nfunction readRequiredString(\n record: Record<string, unknown>,\n key: string,\n filePath: string,\n): string {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) return value;\n throw new Error(`${path.basename(filePath)} must include string ${key}.`);\n}\n\nfunction readRequiredNumber(\n record: Record<string, unknown>,\n key: string,\n filePath: string,\n): number {\n const value = record[key];\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n throw new Error(`${path.basename(filePath)} must include number ${key}.`);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n","/**\n * Shared widget package publish/upload helpers.\n *\n * These utilities cover the two owner scopes currently supported by the\n * portal widget package upload API: marketplace droplets and company-owned\n * Fluid OS packages. They intentionally do not register CLI commands; command\n * implementations can compose the typed payload builders, session/complete\n * requests, signed URL uploads, and dry-run orchestration exposed here.\n */\n\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport {\n fluidOsV0CompleteWidgetPackageVersionUpload,\n fluidOsV0CreateWidgetPackageVersion,\n} from \"@fluid-app/fluidos-api-client/sdk\";\nimport type {\n FluidOsV0CompleteWidgetPackageVersionUploadData,\n FluidOsV0CreateWidgetPackageVersionData,\n} from \"@fluid-app/fluidos-api-client/types\";\nimport type { ArtifactMetadata } from \"./widget-package-artifacts.js\";\n\nexport type WidgetPackageUploadOwner =\n | { readonly kind: \"droplet\"; readonly uuid: string }\n | { readonly kind: \"company\" };\n\nexport type WidgetPackageArtifactMetadata = ArtifactMetadata;\n\nexport interface WidgetPackageUploadArtifact extends WidgetPackageArtifactMetadata {\n readonly body: BodyInit;\n}\n\nexport interface WidgetPackageSessionRequest {\n readonly version: string;\n readonly packageKey: string;\n readonly builderVersion: string;\n readonly cliVersion: string;\n readonly runtimeVersion: string;\n readonly manifestHash: string;\n readonly manifest: Record<string, unknown>;\n readonly artifacts: readonly WidgetPackageArtifactMetadata[];\n}\n\nexport interface WidgetPackagePublishRequest extends Omit<\n WidgetPackageSessionRequest,\n \"artifacts\"\n> {\n readonly artifacts: readonly WidgetPackageUploadArtifact[];\n}\n\nexport type WidgetPackageArtifactPayload = ArtifactMetadata;\n\nexport interface WidgetPackageUploadSessionPayload {\n readonly version: string;\n readonly package_key: string;\n readonly builder_version: string;\n readonly cli_version: string;\n readonly runtime_version: string;\n readonly manifest_hash: string;\n readonly manifest: Record<string, unknown>;\n readonly artifacts: readonly WidgetPackageArtifactPayload[];\n}\n\nexport interface WidgetPackageCompleteUploadPayload {\n readonly package_key: string;\n readonly artifacts: readonly WidgetPackageArtifactPayload[];\n}\n\nexport interface WidgetPackageSignedUpload {\n readonly path: string;\n readonly url: string;\n readonly contentType: string;\n readonly headers: Readonly<Record<string, string>>;\n}\n\nexport interface WidgetPackageUploadSession {\n readonly version: string;\n readonly uploads: readonly WidgetPackageSignedUpload[];\n readonly raw: unknown;\n}\n\nexport interface WidgetPackageArtifactUploadResult {\n readonly path: string;\n readonly status: number;\n readonly contentType: string;\n}\n\nexport interface WidgetPackageCompleteResult {\n readonly version: string;\n readonly status?: string;\n readonly packageKey?: string;\n readonly raw: unknown;\n}\n\nexport interface WidgetPackagePublishResult {\n readonly dryRun: boolean;\n readonly sessionPayload: WidgetPackageUploadSessionPayload;\n readonly session?: WidgetPackageUploadSession;\n readonly uploadedArtifacts?: readonly WidgetPackageArtifactUploadResult[];\n readonly complete?: WidgetPackageCompleteResult;\n}\n\ninterface BasePublishWidgetPackageVersionOptions {\n readonly owner: WidgetPackageUploadOwner;\n readonly request: WidgetPackagePublishRequest;\n readonly fetchImpl?: WidgetPackageUploadFetch;\n}\n\nexport interface DryRunPublishWidgetPackageVersionOptions extends BasePublishWidgetPackageVersionOptions {\n readonly client?: FluidOsHeyApiClient;\n readonly dryRun: true;\n}\n\nexport interface PublishWidgetPackageVersionUploadOptions extends BasePublishWidgetPackageVersionOptions {\n readonly client: FluidOsHeyApiClient;\n readonly dryRun?: boolean;\n}\n\nexport type PublishWidgetPackageVersionOptions =\n | DryRunPublishWidgetPackageVersionOptions\n | PublishWidgetPackageVersionUploadOptions;\n\ntype FluidOsCreateWidgetPackageVersionPayload =\n FluidOsV0CreateWidgetPackageVersionData[\"body\"];\n\ntype FluidOsCompleteWidgetPackageVersionUploadPayload =\n FluidOsV0CompleteWidgetPackageVersionUploadData[\"body\"];\n\nexport type WidgetPackageUploadFetch = (\n input: string | URL,\n init: RequestInit,\n) => Promise<Response>;\n\nexport class WidgetPackageUploadError extends Error {\n public readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = \"WidgetPackageUploadError\";\n this.code = code;\n }\n}\n\nexport function buildWidgetPackageArtifactPayload(\n artifact: WidgetPackageArtifactMetadata,\n): WidgetPackageArtifactPayload {\n return {\n path: artifact.path,\n sha256: artifact.sha256,\n bytes: artifact.bytes,\n contentType: artifact.contentType,\n };\n}\n\nexport function buildWidgetPackageUploadSessionPayload(\n request: WidgetPackageSessionRequest,\n): WidgetPackageUploadSessionPayload {\n return {\n version: request.version,\n package_key: request.packageKey,\n builder_version: request.builderVersion,\n cli_version: request.cliVersion,\n runtime_version: request.runtimeVersion,\n manifest_hash: request.manifestHash,\n manifest: request.manifest,\n artifacts: request.artifacts.map(buildWidgetPackageArtifactPayload),\n };\n}\n\nexport function buildWidgetPackageCompleteUploadPayload(\n packageKey: string,\n artifacts: readonly WidgetPackageArtifactMetadata[],\n): WidgetPackageCompleteUploadPayload {\n return {\n package_key: packageKey,\n artifacts: artifacts.map(buildWidgetPackageArtifactPayload),\n };\n}\n\nexport function getWidgetPackageUploadSessionRoute(\n owner: WidgetPackageUploadOwner,\n): string {\n switch (owner.kind) {\n case \"droplet\":\n return `/api/droplets/${encodeURIComponent(owner.uuid)}/widget_package_versions`;\n case \"company\":\n return \"/api/company/fluid_os/widget_package_versions\";\n }\n}\n\nexport function getWidgetPackageCompleteUploadRoute(\n owner: WidgetPackageUploadOwner,\n version: string,\n): string {\n switch (owner.kind) {\n case \"droplet\":\n return `/api/droplets/${encodeURIComponent(owner.uuid)}/widget_package_versions/${encodeURIComponent(version)}/complete_upload`;\n case \"company\":\n return `/api/company/fluid_os/widget_package_versions/${encodeURIComponent(version)}/complete_upload`;\n }\n}\n\nexport async function requestWidgetPackageUploadSession(\n client: FluidOsHeyApiClient,\n owner: WidgetPackageUploadOwner,\n request: WidgetPackageSessionRequest,\n): Promise<WidgetPackageUploadSession> {\n const payload = buildWidgetPackageUploadSessionPayload(request);\n\n try {\n const response =\n owner.kind === \"company\"\n ? await fluidOsV0CreateWidgetPackageVersion({\n body: payload as FluidOsCreateWidgetPackageVersionPayload,\n client,\n })\n : await client.post({\n body: payload,\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: getWidgetPackageUploadSessionRoute(owner),\n });\n return normalizeWidgetPackageUploadSession(\n response,\n request.version,\n request.artifacts,\n );\n } catch (err) {\n if (err instanceof WidgetPackageUploadError) {\n throw err;\n }\n\n throw new WidgetPackageUploadError(\n \"SESSION_REQUEST_FAILED\",\n `Failed to create widget package upload session: ${formatUnknownError(err)}`,\n );\n }\n}\n\nexport async function uploadWidgetPackageArtifacts(\n session: WidgetPackageUploadSession,\n artifacts: readonly WidgetPackageUploadArtifact[],\n fetchImpl: WidgetPackageUploadFetch = fetch,\n): Promise<WidgetPackageArtifactUploadResult[]> {\n const uploadsByPath = new Map(\n session.uploads.map((upload) => [upload.path, upload] as const),\n );\n const results: WidgetPackageArtifactUploadResult[] = [];\n\n for (const artifact of artifacts) {\n const upload = uploadsByPath.get(artifact.path);\n if (!upload) {\n throw new WidgetPackageUploadError(\n \"MISSING_SIGNED_URL\",\n `Upload session did not include a signed URL for artifact \"${artifact.path}\".`,\n );\n }\n\n if (upload.contentType !== artifact.contentType) {\n throw new WidgetPackageUploadError(\n \"CONTENT_TYPE_MISMATCH\",\n `Upload session expected artifact \"${artifact.path}\" to use content type \"${upload.contentType}\", but local artifact uses \"${artifact.contentType}\".`,\n );\n }\n\n let response: Response;\n try {\n response = await fetchImpl(upload.url, {\n method: \"PUT\",\n headers: mergeUploadHeaders(upload.headers, upload.contentType),\n body: artifact.body,\n });\n } catch (err) {\n throw new WidgetPackageUploadError(\n \"ARTIFACT_UPLOAD_FAILED\",\n `Failed to upload artifact \"${artifact.path}\": ${formatUnknownError(err)}`,\n );\n }\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n const details = body.trim() ? `: ${body.trim().slice(0, 500)}` : \"\";\n throw new WidgetPackageUploadError(\n \"ARTIFACT_UPLOAD_FAILED\",\n `Failed to upload artifact \"${artifact.path}\": PUT returned HTTP ${response.status}${details}`,\n );\n }\n\n results.push({\n path: artifact.path,\n status: response.status,\n contentType: upload.contentType,\n });\n }\n\n return results;\n}\n\nexport async function completeWidgetPackageUpload(\n client: FluidOsHeyApiClient,\n owner: WidgetPackageUploadOwner,\n version: string,\n packageKey: string,\n artifacts: readonly WidgetPackageArtifactMetadata[],\n): Promise<WidgetPackageCompleteResult> {\n const payload = buildWidgetPackageCompleteUploadPayload(\n packageKey,\n artifacts,\n );\n\n try {\n const response =\n owner.kind === \"company\"\n ? await fluidOsV0CompleteWidgetPackageVersionUpload({\n body: payload as FluidOsCompleteWidgetPackageVersionUploadPayload,\n client,\n path: { version },\n })\n : await client.post({\n body: payload,\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: getWidgetPackageCompleteUploadRoute(owner, version),\n });\n return normalizeWidgetPackageCompleteResponse(response, version);\n } catch (err) {\n if (err instanceof WidgetPackageUploadError) {\n throw err;\n }\n\n throw new WidgetPackageUploadError(\n \"COMPLETE_UPLOAD_FAILED\",\n `Failed to complete widget package upload: ${formatUnknownError(err)}`,\n );\n }\n}\n\nexport async function publishWidgetPackageVersion(\n options: PublishWidgetPackageVersionOptions,\n): Promise<WidgetPackagePublishResult> {\n const sessionPayload = buildWidgetPackageUploadSessionPayload(\n options.request,\n );\n\n if (options.dryRun) {\n return { dryRun: true, sessionPayload };\n }\n\n if (!options.client) {\n throw new Error(\"A FluidOS API client is required when dryRun is false.\");\n }\n\n const session = await requestWidgetPackageUploadSession(\n options.client,\n options.owner,\n options.request,\n );\n const uploadedArtifacts = await uploadWidgetPackageArtifacts(\n session,\n options.request.artifacts,\n options.fetchImpl,\n );\n const complete = await completeWidgetPackageUpload(\n options.client,\n options.owner,\n session.version,\n options.request.packageKey,\n options.request.artifacts,\n );\n\n return {\n dryRun: false,\n sessionPayload,\n session,\n uploadedArtifacts,\n complete,\n };\n}\n\nexport function normalizeWidgetPackageUploadSession(\n response: unknown,\n requestedVersion: string,\n requestedArtifacts: readonly WidgetPackageArtifactMetadata[],\n): WidgetPackageUploadSession {\n const record = requireRecord(\n response,\n \"INVALID_SESSION_RESPONSE\",\n \"Upload session response must be a JSON object.\",\n );\n requireFiniteNumberProperty(record, \"version_id\", \"INVALID_SESSION_RESPONSE\");\n requireStringProperty(\n record,\n \"artifact_base_url\",\n \"INVALID_SESSION_RESPONSE\",\n );\n\n const uploadValues = record[\"uploads\"];\n if (!Array.isArray(uploadValues)) {\n throw new WidgetPackageUploadError(\n \"INVALID_SESSION_RESPONSE\",\n 'Upload session response must contain an \"uploads\" array.',\n );\n }\n\n const requestedArtifactsByPath = new Map(\n requestedArtifacts.map((artifact) => [artifact.path, artifact] as const),\n );\n const seenUploadPaths = new Set<string>();\n const uploads = uploadValues.map((value, index) => {\n const upload = requireRecord(\n value,\n \"INVALID_SESSION_RESPONSE\",\n `Upload session uploads[${index}] must be a JSON object.`,\n );\n const path = requireStringProperty(\n upload,\n \"path\",\n \"INVALID_SESSION_RESPONSE\",\n );\n const url = requireStringProperty(\n upload,\n \"upload_url\",\n \"INVALID_SESSION_RESPONSE\",\n );\n requireStringProperty(upload, \"public_url\", \"INVALID_SESSION_RESPONSE\");\n\n const requestedArtifact = requestedArtifactsByPath.get(path);\n if (!requestedArtifact) {\n throw new WidgetPackageUploadError(\n \"INVALID_SESSION_RESPONSE\",\n `Upload session response included unexpected artifact \"${path}\".`,\n );\n }\n if (seenUploadPaths.has(path)) {\n throw new WidgetPackageUploadError(\n \"INVALID_SESSION_RESPONSE\",\n `Upload session response included duplicate artifact \"${path}\".`,\n );\n }\n seenUploadPaths.add(path);\n\n return {\n path,\n url,\n contentType: requestedArtifact.contentType,\n headers: {},\n };\n });\n const missingUploadPaths = requestedArtifacts\n .map((artifact) => artifact.path)\n .filter((artifactPath) => !seenUploadPaths.has(artifactPath));\n\n if (missingUploadPaths.length > 0) {\n throw new WidgetPackageUploadError(\n \"INVALID_SESSION_RESPONSE\",\n `Upload session response is missing signed URLs for artifact(s): ${missingUploadPaths.join(\", \")}.`,\n );\n }\n\n return { version: requestedVersion, uploads, raw: response };\n}\n\nexport function normalizeWidgetPackageCompleteResponse(\n response: unknown,\n requestedVersion: string,\n): WidgetPackageCompleteResult {\n const record = requireRecord(\n response,\n \"INVALID_COMPLETE_RESPONSE\",\n \"Complete upload response must be a JSON object.\",\n );\n const responseVersion = requireStringProperty(\n record,\n \"version\",\n \"INVALID_COMPLETE_RESPONSE\",\n );\n\n if (responseVersion !== requestedVersion) {\n throw new WidgetPackageUploadError(\n \"INVALID_COMPLETE_RESPONSE\",\n `Complete upload response version \"${responseVersion}\" did not match requested version \"${requestedVersion}\".`,\n );\n }\n\n const packageKey = requireStringProperty(\n record,\n \"packageId\",\n \"INVALID_COMPLETE_RESPONSE\",\n );\n const status = requireStringProperty(\n record,\n \"status\",\n \"INVALID_COMPLETE_RESPONSE\",\n );\n requireStringProperty(record, \"scriptUrl\", \"INVALID_COMPLETE_RESPONSE\");\n requireStringProperty(record, \"manifestUrl\", \"INVALID_COMPLETE_RESPONSE\");\n requireStringArrayProperty(record, \"cssUrls\", \"INVALID_COMPLETE_RESPONSE\");\n\n return {\n version: responseVersion,\n status,\n packageKey,\n raw: response,\n };\n}\n\nfunction normalizeHeaderName(name: string): string {\n return name.toLowerCase();\n}\n\nfunction mergeUploadHeaders(\n headers: Readonly<Record<string, string>>,\n contentType: string,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(headers)) {\n if (normalizeHeaderName(key) === \"content-type\") continue;\n merged[key] = value;\n }\n\n merged[\"Content-Type\"] = contentType;\n return merged;\n}\n\nfunction requireRecord(\n value: unknown,\n code: string,\n message: string,\n): Record<string, unknown> {\n if (!isRecord(value) || Array.isArray(value)) {\n throw new WidgetPackageUploadError(code, message);\n }\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction requireStringProperty(\n record: Record<string, unknown>,\n key: string,\n code: string,\n): string {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n throw new WidgetPackageUploadError(\n code,\n `Response field \"${key}\" must be a non-empty string.`,\n );\n}\n\nfunction requireFiniteNumberProperty(\n record: Record<string, unknown>,\n key: string,\n code: string,\n): number {\n const value = record[key];\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n throw new WidgetPackageUploadError(\n code,\n `Response field \"${key}\" must be a finite number.`,\n );\n}\n\nfunction requireStringArrayProperty(\n record: Record<string, unknown>,\n key: string,\n code: string,\n): readonly string[] {\n const value = record[key];\n if (\n Array.isArray(value) &&\n value.every((entry) => typeof entry === \"string\" && entry.trim().length > 0)\n ) {\n return value;\n }\n throw new WidgetPackageUploadError(\n code,\n `Response field \"${key}\" must be an array of non-empty strings.`,\n );\n}\n\nfunction formatUnknownError(err: unknown): string {\n const base = err instanceof Error ? err.message : String(err);\n\n if (isRecord(err) && \"data\" in err) {\n return `${base} — ${safeStringify(err.data)}`;\n }\n\n return base;\n}\n\nfunction safeStringify(value: unknown): string {\n const seen = new WeakSet<object>();\n\n try {\n const serialized = JSON.stringify(value, (_key, item: unknown) => {\n if (typeof item === \"bigint\") return `${item}n`;\n if (typeof item !== \"object\" || item === null) return item;\n if (seen.has(item)) return \"[Circular]\";\n seen.add(item);\n return item;\n });\n return serialized ?? String(value);\n } catch {\n return \"[unserializable error data]\";\n }\n}\n","import type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport { WidgetToolingError, type WidgetToolingErrorCode } from \"./errors.js\";\nimport type { WidgetToolingNodeRuntime } from \"./node-runtime.js\";\nimport {\n buildSharedWidgetPackage,\n type SharedWidgetPackageBuildResult,\n} from \"./internal/widget-package-builder.js\";\nimport {\n loadSourceWidgetPackages,\n resolvePortalWidgetSourceConfig,\n} from \"./internal/widget-package-config.js\";\nimport { createWidgetPackagePublishRequest } from \"./internal/widget-package-publish-request.js\";\nimport {\n publishWidgetPackageVersion,\n WidgetPackageUploadError,\n type WidgetPackagePublishRequest,\n type WidgetPackagePublishResult,\n type WidgetPackageUploadFetch,\n type WidgetPackageUploadOwner,\n} from \"./internal/widget-package-upload.js\";\nimport {\n validateSingleSourceWidgetPackage,\n type SourceWidgetMetadata,\n type SourceWidgetPackageMetadata,\n type ValidatedWidgetPackageBuild,\n type WidgetPackageOwnerKind,\n type WidgetPackageValidationError,\n type WidgetPackageValidationErrorCode,\n} from \"./internal/widget-package-validation.js\";\n\nexport type {\n SourceWidgetMetadata,\n SourceWidgetPackageMetadata,\n ValidatedWidgetPackageBuild,\n WidgetPackageOwnerKind,\n WidgetPackageValidationError,\n WidgetPackageValidationErrorCode,\n};\n\nexport type WidgetPackageOwner = WidgetPackageUploadOwner;\nexport type WidgetPackageBuildResult = SharedWidgetPackageBuildResult;\nexport type WidgetPackagePublishWorkflowRequest = WidgetPackagePublishRequest;\nexport type WidgetPackagePublishWorkflowResult = WidgetPackagePublishResult;\n\nexport interface LoadAndValidateWidgetPackageOptions {\n readonly projectDir: string;\n readonly owner: WidgetPackageOwnerKind;\n /** How to run the generated helper scripts — see WidgetToolingNodeRuntime. */\n readonly nodeRuntime?: WidgetToolingNodeRuntime;\n}\n\nexport interface LoadedWidgetPackage {\n readonly projectDir: string;\n readonly sourceConfigPath: string;\n readonly validated: ValidatedWidgetPackageBuild;\n}\n\nexport async function loadAndValidateWidgetPackage(\n options: LoadAndValidateWidgetPackageOptions,\n): Promise<LoadedWidgetPackage> {\n const sourceConfig = await resolvePortalWidgetSourceConfig(\n options.projectDir,\n );\n const loadResult = await loadSourceWidgetPackages(\n options.projectDir,\n options.nodeRuntime,\n );\n if (!loadResult.success) {\n throw new WidgetToolingError(\n \"CONFIG_LOAD_FAILED\",\n loadResult.error.message,\n { details: loadResult.error.details },\n );\n }\n\n const validation = validateSingleSourceWidgetPackage(loadResult.value, {\n owner: options.owner,\n });\n if (!validation.success || !validation.value) {\n throw new WidgetToolingError(\n \"VALIDATION_FAILED\",\n validation.errors.map((error) => error.message).join(\"\\n\") ||\n \"Widget package validation failed.\",\n { diagnostics: validation.errors },\n );\n }\n\n return {\n projectDir: options.projectDir,\n sourceConfigPath: sourceConfig?.relativePath ?? \"src/widgets.config.ts\",\n validated: validation.value,\n };\n}\n\nexport interface BuildWidgetPackageOptions {\n readonly projectDir: string;\n readonly outDir?: string;\n readonly owner: WidgetPackageOwnerKind;\n readonly cliVersion: string;\n /** Publish as this version instead of the config's — see\n * `BuildSharedWidgetPackageOptions.versionOverride`. */\n readonly version?: string;\n /** How to run the generated helper scripts — see WidgetToolingNodeRuntime. */\n readonly nodeRuntime?: WidgetToolingNodeRuntime;\n}\n\nexport async function buildWidgetPackage(\n options: BuildWidgetPackageOptions,\n): Promise<WidgetPackageBuildResult> {\n const result = await buildSharedWidgetPackage({\n projectDir: options.projectDir,\n publishDir: options.outDir,\n owner: options.owner,\n cliVersion: options.cliVersion,\n ...(options.version ? { versionOverride: options.version } : {}),\n ...(options.nodeRuntime ? { nodeRuntime: options.nodeRuntime } : {}),\n });\n if (result.success) return result.value;\n\n const code: WidgetToolingErrorCode =\n result.error.code === \"CONFIG_LOAD_FAILED\"\n ? \"CONFIG_LOAD_FAILED\"\n : result.error.code === \"VALIDATION_FAILED\"\n ? \"VALIDATION_FAILED\"\n : result.error.code === \"INVALID_PUBLISH_DIR\"\n ? \"INVALID_OUTPUT_DIR\"\n : \"BUILD_FAILED\";\n throw new WidgetToolingError(code, result.error.message, {\n details: result.error.details,\n });\n}\n\ninterface BasePublishWidgetPackageOptions extends BuildWidgetPackageOptions {\n readonly owner: WidgetPackageOwnerKind;\n readonly uploadOwner: WidgetPackageOwner;\n readonly fetchImpl?: WidgetPackageUploadFetch;\n}\n\nexport interface DryRunPublishWidgetPackageOptions extends BasePublishWidgetPackageOptions {\n readonly dryRun: true;\n readonly client?: never;\n}\n\nexport interface UploadWidgetPackageOptions extends BasePublishWidgetPackageOptions {\n readonly dryRun?: false;\n readonly client: FluidOsHeyApiClient;\n}\n\nexport type PublishWidgetPackageOptions =\n | DryRunPublishWidgetPackageOptions\n | UploadWidgetPackageOptions;\n\nexport interface PublishedWidgetPackage {\n readonly build: WidgetPackageBuildResult;\n readonly request: WidgetPackagePublishRequest;\n readonly publish: WidgetPackagePublishResult;\n}\n\nexport async function publishWidgetPackage(\n options: PublishWidgetPackageOptions,\n): Promise<PublishedWidgetPackage> {\n if (options.owner !== options.uploadOwner.kind) {\n throw new WidgetToolingError(\n \"OWNER_MISMATCH\",\n `Widget package build owner \"${options.owner}\" must match upload owner kind \"${options.uploadOwner.kind}\".`,\n );\n }\n\n if (!options.dryRun && !options.client) {\n throw new WidgetToolingError(\n \"CLIENT_REQUIRED\",\n \"A FluidOS API client is required when dryRun is false.\",\n );\n }\n\n const build = await buildWidgetPackage(options);\n\n let request: WidgetPackagePublishRequest;\n try {\n request = await createWidgetPackagePublishRequest({\n publishDir: build.publishDir,\n manifestPath: build.manifestPath,\n publishManifestPath: build.publishManifestPath,\n owner: options.owner,\n });\n } catch (error) {\n throw new WidgetToolingError(\n \"ARTIFACT_VERIFICATION_FAILED\",\n error instanceof Error\n ? error.message\n : \"Failed to verify widget package artifacts.\",\n { cause: error },\n );\n }\n\n try {\n const publish = options.dryRun\n ? await publishWidgetPackageVersion({\n owner: options.uploadOwner,\n request,\n dryRun: true,\n fetchImpl: options.fetchImpl,\n })\n : await publishWidgetPackageVersion({\n client: options.client,\n owner: options.uploadOwner,\n request,\n fetchImpl: options.fetchImpl,\n });\n\n return { build, request, publish };\n } catch (error) {\n if (error instanceof WidgetToolingError) throw error;\n if (error instanceof WidgetPackageUploadError) {\n throw new WidgetToolingError(\n toPublicUploadErrorCode(error.code),\n error.message,\n { cause: error },\n );\n }\n throw new WidgetToolingError(\n \"PUBLISH_FAILED\",\n error instanceof Error\n ? error.message\n : \"Failed to publish widget package.\",\n { cause: error },\n );\n }\n}\n\nfunction toPublicUploadErrorCode(code: string): WidgetToolingErrorCode {\n switch (code) {\n case \"SESSION_REQUEST_FAILED\":\n case \"INVALID_SESSION_RESPONSE\":\n case \"MISSING_SIGNED_URL\":\n case \"CONTENT_TYPE_MISMATCH\":\n case \"ARTIFACT_UPLOAD_FAILED\":\n case \"COMPLETE_UPLOAD_FAILED\":\n case \"INVALID_COMPLETE_RESPONSE\":\n return code;\n default:\n return \"PUBLISH_FAILED\";\n }\n}\n","/**\n * Reads the company's existing widget package key.\n *\n * A company has exactly ONE widget package. Its key is fixed by whichever\n * project publishes first, and every portal project in that company must\n * publish into it. Publishing under any other key is rejected server-side with\n *\n * 422 Package key does not match this widget package\n *\n * which names no key and offers no way to find one. `packageStableId` is not the\n * client's to choose once a company has published; the scaffold writing a guess\n * (`portal-widgets`) is the bug.\n *\n * The key IS discoverable — this route returns it for the ordinary CLI token.\n * `/api/app/widget-packages` is the one that 404s, because it is portal-session\n * scoped, which is what makes this look unreachable from a terminal.\n *\n * Deliberately read-only. The key is NOT injected into the build, because a\n * widget's type is `company.<key>.<Name>` and those types are written into\n * screen JSON. Publishing under a key the project's config does not declare\n * would leave every screen referencing a type that no longer exists — the exact\n * silent breakage this milestone is trying to remove. The config has to be\n * corrected; this module exists so the CLI can say what to correct it to.\n */\n\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport { fluidOsV0ListWidgetPackages } from \"@fluid-app/fluidos-api-client/sdk\";\nimport { resolvePortalWidgetSourceConfig } from \"./internal/widget-package-config.js\";\nimport { collectScreenWidgetTypes } from \"./screen-widget-types.js\";\n\n/** Strips the owner scope so the result can be compared to `packageStableId`. */\nconst COMPANY_PACKAGE_ID_PREFIX = \"company.\";\n\nexport interface CompanyWidgetPackage {\n /** Bare key, comparable to `packageStableId` (no `company.` prefix). */\n readonly key: string;\n readonly version: string;\n /**\n * Fully-qualified widget types this package publishes — `company.<key>.<Name>`,\n * the same strings screen JSON stores. Empty when the response carried no\n * usable manifest, which is a \"cannot tell\", not \"publishes nothing\".\n */\n readonly widgetTypes: readonly string[];\n}\n\n/**\n * Returns every company-scoped widget package the API reports.\n *\n * An empty array is a normal, expected answer: the first publish defines the\n * key, so any configured value is valid until one exists.\n *\n * Never throws for the caller's benefit — a deploy must not be blocked because\n * a preflight lookup failed. An unreachable or unexpected response resolves to\n * an empty array, which degrades to today's behaviour (publish, and let the\n * server reject it) rather than inventing a reason to stop.\n */\nexport async function readCompanyWidgetPackages(\n client: FluidOsHeyApiClient,\n): Promise<CompanyWidgetPackage[]> {\n return (await readCompanyWidgetCatalog(client)) ?? [];\n}\n\n/**\n * The same read, keeping \"the company has published nothing\" apart from \"the\n * lookup did not answer\" — `[]` versus `null`.\n *\n * {@link readCompanyWidgetPackages} folds the two together because a preflight\n * treats both as \"proceed\". A caller deciding whether to START a publish cannot:\n * an empty catalog means publish, and a failed lookup that reads as empty would\n * publish on every attempt, consuming an irreversible version of a package the\n * whole company shares each time.\n */\nexport async function readCompanyWidgetCatalog(\n client: FluidOsHeyApiClient,\n): Promise<CompanyWidgetPackage[] | null> {\n let response: unknown;\n try {\n response = await fluidOsV0ListWidgetPackages({ client });\n } catch {\n return null;\n }\n\n if (!isRecord(response) || !Array.isArray(response.packages)) return null;\n\n const packages: CompanyWidgetPackage[] = [];\n for (const candidate of response.packages) {\n if (!isRecord(candidate)) continue;\n const packageId = candidate.packageId;\n const version = candidate.version;\n if (typeof packageId !== \"string\" || packageId.length === 0) continue;\n if (!packageId.startsWith(COMPANY_PACKAGE_ID_PREFIX)) continue;\n\n const key = packageId.slice(COMPANY_PACKAGE_ID_PREFIX.length);\n if (key.length === 0) continue;\n\n packages.push({\n key,\n version: typeof version === \"string\" ? version : \"unknown\",\n widgetTypes: readWidgetTypes(candidate),\n });\n }\n\n return packages;\n}\n\n/**\n * The types a catalog entry publishes.\n *\n * `type` is the fully-qualified name the publish manifest wrote\n * (`${packageId}.${widget.name}`) — the exact string a screen stores.\n *\n * Read from BOTH the entry itself and a nested `manifest`, because the two\n * disagree and only one of them is real. The generated OpenAPI types describe\n * `FluidOSWidgetPackageCatalogEntry` as carrying an opaque `manifest` object\n * with no top-level `widgets`; the live route returns the manifest FLATTENED\n * onto the entry — `packageId`, `version`, `runtime`, `widgets`, `workerEntryUrl`\n * — and no `manifest` key at all. Verified against\n * `GET /api/company/fluid_os/widget_packages`.\n *\n * Trusting the generated shape found nothing, which does not fail loudly: it\n * looks exactly like a company that has published no widgets. Reading both\n * costs one property access and survives whichever way the route settles.\n */\nfunction readWidgetTypes(entry: Readonly<Record<string, unknown>>): string[] {\n const nested = isRecord(entry.manifest) ? entry.manifest.widgets : undefined;\n const types = new Set<string>();\n for (const source of [entry.widgets, nested]) {\n if (!Array.isArray(source)) continue;\n for (const widget of source) {\n if (!isRecord(widget)) continue;\n if (typeof widget.type === \"string\" && widget.type.length > 0) {\n types.add(widget.type);\n }\n }\n }\n return [...types];\n}\n\n/**\n * Widget types this project's screens reference that this project could publish\n * but has not — the reason to publish widgets before pushing content.\n *\n * A screen node whose type is not in the catalog renders nothing at all: `null`\n * and a `console.warn`. No placeholder, no error, just a gap. Publishing the\n * portal while that is true ships the gap, and the author has no way to tell\n * from the screen that anything is wrong.\n *\n * Every uncertainty answers \"nothing missing\", which is the opposite bias from\n * {@link preflightCompanyPackage} and deliberately so. That one guards a publish\n * the user already asked for, so proceeding costs nothing. This one DECIDES\n * whether to publish, and every company shares one widget package whose versions\n * cannot be rolled back — so a wrong \"missing\" spends a version on EVERY press\n * of the button, and keeps spending one for as long as the type stays missing.\n * A wrong \"nothing missing\" only leaves today's behaviour in place.\n *\n * The test for \"could publish\" is the project's own declared widget list, not\n * its package key. A key match alone says a type is in our namespace; only the\n * list says a publish would actually supply it. Those differ exactly when a\n * screen outlives the widget it points at — a rename or a deletion in\n * `src/widgets.config.ts` — and that gap is unbounded: the publish succeeds,\n * the catalog still lacks the type, and the next press publishes again.\n *\n * Concretely, it answers empty when:\n *\n * - the catalog lookup did not answer, as distinct from answering \"none\"\n * - the project has no `src/widgets.config.ts`, so it has nothing to publish\n * - this project's own package could not be read, so nothing can be attributed\n * - no referenced type is one this project declares\n * - this project's own catalog entry exists but reported no types at all, which\n * cannot be told apart from a response that withheld them\n *\n * Droplet-owned types are excluded rather than reported: they belong to another\n * publisher, and no publish this project can run would supply them. So is\n * anything this project does not itself declare.\n */\nexport async function findUnpublishedWidgetTypes(options: {\n readonly projectDir: string;\n readonly client: FluidOsHeyApiClient;\n /**\n * What this project would publish: its package id and the fully-qualified\n * types it declares.\n *\n * Both halves are load-bearing. The id picks this project's entry out of a\n * catalog that may hold several packages. The type list is what makes\n * \"missing\" mean \"a publish would fix this\" rather than merely \"absent\" —\n * without it a screen still pointing at a renamed or deleted widget is\n * attributed here, published for, and still missing afterwards, on every\n * press.\n *\n * Injected rather than read here because resolving it means evaluating\n * `src/widgets.config.ts` in a spawned process — the same reason\n * {@link preflightCompanyPackage} takes `readConfiguredPackage`. It is called\n * only once a referenced type is absent from the catalog, so the ordinary\n * \"everything is published\" press never pays for it.\n *\n * Absent or unable to answer, nothing is reported. There is no sound\n * substitute: the catalog's own keys are not one, because a company can hold\n * more than one package.\n */\n readonly readConfiguredPackage?: (\n projectDir: string,\n ) => Promise<ConfiguredWidgetPackageTypes | null>;\n}): Promise<string[]> {\n const referenced = (\n await collectScreenWidgetTypes(options.projectDir)\n ).filter((type) => type.startsWith(COMPANY_PACKAGE_ID_PREFIX));\n if (referenced.length === 0) return [];\n\n if (!(await resolvePortalWidgetSourceConfig(options.projectDir))) return [];\n\n const catalog = await readCompanyWidgetCatalog(options.client);\n if (!catalog) return [];\n\n // Cheap pre-filter against every package the company publishes, purely to\n // decide whether the expensive step below is worth taking. It cannot decide\n // ownership — another package's entry may well contain a type of ours' name\n // — so its answer is only ever \"there is something to look into\".\n const anythingAbsent = referenced.some(\n (type) => !catalog.some((entry) => entry.widgetTypes.includes(type)),\n );\n if (!anythingAbsent) return [];\n\n let own: ConfiguredWidgetPackageTypes | null = null;\n try {\n own = (await options.readConfiguredPackage?.(options.projectDir)) ?? null;\n } catch {\n // Unreadable config is the build's failure to report, with far better\n // diagnostics than this has.\n own = null;\n }\n if (!own) return [];\n\n // Ownership decided BEFORE anything else, including the never-published case.\n // A first publish is not a licence to claim a foreign type: a screen copied\n // from another project, or a `packageStableId` renamed before the first\n // publish, would otherwise spend a version on a widget this package does not\n // contain.\n const declared = new Set(own.widgetTypes);\n const ours = referenced.filter((type) => declared.has(type));\n if (ours.length === 0) return [];\n\n const ownKey = own.packageId.replace(/^company\\./u, \"\");\n const entry = catalog.find((candidate) => candidate.key === ownKey) ?? null;\n\n // Never published under this key — every declared type a screen uses is\n // genuinely absent, and this publish is the one that creates them.\n if (!entry) return ours;\n\n // Per-entry rather than aggregate. Another package answering does not mean\n // OURS did: if this project's entry carries no readable type list — the shape\n // drift this module already survived once — its published widgets read as\n // absent and a full publish runs on every press for as long as that lasts.\n if (entry.widgetTypes.length === 0) return [];\n\n const published = new Set(entry.widgetTypes);\n return ours.filter((type) => !published.has(type));\n}\n\n/** What a project's `src/widgets.config.ts` would publish. */\nexport interface ConfiguredWidgetPackageTypes {\n readonly packageId: string;\n /** Fully-qualified `company.<key>.<Name>` types the project declares. */\n readonly widgetTypes: readonly string[];\n}\n\n/**\n * The company's widget package, or `null` when it has never published.\n *\n * A company is expected to have exactly one. This returns the first, and exists\n * for callers that only need \"what is this company's key\" — a preflight must use\n * {@link readCompanyWidgetPackages} and reconcile against the configured key\n * instead, or a second package would make it report a confident, wrong answer.\n */\nexport async function readCompanyWidgetPackage(\n client: FluidOsHeyApiClient,\n): Promise<CompanyWidgetPackage | null> {\n return (await readCompanyWidgetPackages(client))[0] ?? null;\n}\n\n/**\n * The message shown when the project's key disagrees with the company's.\n *\n * Names the actual key and the exact edit, because the failure it replaces gave\n * neither — and because the fix is one line the author can apply immediately.\n */\nexport function formatPackageKeyMismatch(options: {\n readonly configuredKey: string;\n readonly companyKey: string;\n readonly companyVersion: string;\n}): string {\n return [\n `This company already has a widget package: \"${options.companyKey}\" (published v${options.companyVersion}).`,\n \"\",\n `A company has one widget package, and every portal project publishes into it, so`,\n `\"${options.configuredKey}\" would be rejected.`,\n \"\",\n \"Fix — in src/widgets.config.ts:\",\n ` packageStableId: \"${options.companyKey}\",`,\n \"\",\n \"This must be corrected in the file rather than applied at publish time:\",\n \"widget types are `company.<key>.<Name>` and are written into your screen\",\n \"JSON, so publishing under a different key would leave those screens\",\n \"pointing at types that do not exist.\",\n ].join(\"\\n\");\n}\n\n/** What the project's own `src/widgets.config.ts` declares. */\nexport interface ConfiguredWidgetPackage {\n readonly packageId: string;\n readonly version: string;\n}\n\nexport interface CompanyPackagePreflight {\n /** Set when the deploy must not proceed; the text explains the one-line fix. */\n readonly mismatch?: string;\n /** Set when the configured version would collide; publish as this instead. */\n readonly versionOverride?: string;\n /** The version that would have collided, for reporting the substitution. */\n readonly configuredVersion?: string;\n}\n\n/**\n * One round trip against the company's widget package, answering both questions\n * a publish has to settle before it builds anything: is this the right package,\n * and is this version free?\n *\n * Shared so `fluid portal deploy` and any host that drives it reach the same\n * verdict for the same reason.\n *\n * Proceeds on every uncertainty — the company has never published (its first\n * publish defines both key and version), the lookup failed, or the local config\n * could not be read. A preflight exists to replace a confusing failure with a\n * clear one, not to invent new reasons to stop; when it cannot tell, the server\n * still decides.\n */\nexport async function preflightCompanyPackage(options: {\n readonly projectDir: string;\n readonly client: FluidOsHeyApiClient;\n /** Injected so callers bundle their own loader; avoids a cycle back into the build path. */\n readonly readConfiguredPackage: (\n projectDir: string,\n ) => Promise<ConfiguredWidgetPackage | null>;\n}): Promise<CompanyPackagePreflight> {\n let configured: ConfiguredWidgetPackage | null;\n try {\n configured = await options.readConfiguredPackage(options.projectDir);\n } catch {\n // A config that cannot load is the build's error to report, with better\n // diagnostics than this preflight could produce.\n return {};\n }\n if (!configured) return {};\n\n const companyPackages = await readCompanyWidgetPackages(options.client);\n if (companyPackages.length === 0) return {};\n\n const configuredKey = configured.packageId.replace(/^company\\./u, \"\");\n // Reconcile against EVERY company package, not just the first. Taking the\n // first and comparing meant a second company-scoped package (or a paginated\n // response) could produce a confident, wrong refusal — naming a key the\n // project never configured, with a \"fix it in src/widgets.config.ts\"\n // instruction pointing at the wrong value. That is worse than the 422 this\n // replaces, because it looks authoritative, and worse still now that the\n // mismatch is routed to an agent told to apply the edit and change nothing\n // else. A mismatch is only reported when NONE of them matches.\n const companyPackage =\n companyPackages.find((candidate) => candidate.key === configuredKey) ??\n null;\n if (!companyPackage) {\n const first = companyPackages[0]!;\n return {\n mismatch: formatPackageKeyMismatch({\n configuredKey,\n companyKey: first.key,\n companyVersion: first.version,\n }),\n };\n }\n\n const versionOverride = resolvePublishVersion({\n configuredVersion: configured.version,\n publishedVersion: companyPackage.version,\n });\n if (!versionOverride) return {};\n\n return { versionOverride, configuredVersion: configured.version };\n}\n\n/**\n * Returns the version to publish as, or `null` to publish the configured one.\n *\n * A company has ONE widget package and several projects publish into it, so the\n * version belongs to that shared package rather than to any project's source\n * file. Nothing tells a project what the others have already released, so two\n * of them declaring `0.5.0` is inevitable — and republishing a version that\n * exists is refused with `422 Package version already exists`, whose only fix\n * is editing a SemVer string in a TypeScript file. For an author who never\n * opens a terminal that is the end of the road, and it happens on EVERY publish\n * after the first, not in some corner case.\n *\n * So a configured version at or below what is published becomes the next patch\n * after the published one. A configured version ABOVE it is honoured exactly —\n * that is a deliberate minor or major bump and the whole reason to keep the\n * field.\n *\n * Returns `null` on any version this cannot reason about — a prerelease, build\n * metadata, anything not a plain numeric triple. Guessing a successor for those\n * would be worse than letting the server answer.\n */\nexport function resolvePublishVersion(options: {\n readonly configuredVersion: string;\n readonly publishedVersion: string;\n}): string | null {\n const configured = parseVersionTriple(options.configuredVersion);\n const published = parseVersionTriple(options.publishedVersion);\n if (!configured || !published) return null;\n if (compareVersionTriples(configured, published) > 0) return null;\n\n const [major, minor, patch] = published;\n return `${major}.${minor}.${patch + 1}`;\n}\n\ntype VersionTriple = readonly [number, number, number];\n\nfunction parseVersionTriple(version: string): VersionTriple | null {\n const match = /^(\\d+)\\.(\\d+)\\.(\\d+)$/u.exec(version.trim());\n if (!match) return null;\n const [major, minor, patch] = [\n Number(match[1]),\n Number(match[2]),\n Number(match[3]),\n ];\n if (!Number.isSafeInteger(major)) return null;\n if (!Number.isSafeInteger(minor)) return null;\n if (!Number.isSafeInteger(patch)) return null;\n return [major, minor, patch];\n}\n\nfunction compareVersionTriples(a: VersionTriple, b: VersionTriple): number {\n for (let i = 0; i < 3; i++) {\n const left = a[i] ?? 0;\n const right = b[i] ?? 0;\n if (left !== right) return left - right;\n }\n return 0;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"src-Dz9-qBBA.mjs","names":["isRecord","toPosixPath","isRecord","isRecord","isRecord","isRecord","isRecord"],"sources":["../../../portal/core/src/remote-dom-widget-package.ts","../../widget-tooling/src/errors.ts","../../widget-tooling/src/internal/widget-package-artifacts.ts","../../widget-tooling/src/internal/widget-package-validation.ts","../../widget-tooling/src/development-descriptor.ts","../../widget-tooling/src/dev-routes.ts","../../widget-tooling/src/node-runtime.ts","../../widget-tooling/src/internal/widget-package-config.ts","../../widget-tooling/src/internal/widget-package-builder.ts","../../widget-tooling/src/internal/widget-package-publish-request.ts","../../widget-tooling/src/internal/widget-package-upload.ts","../../widget-tooling/src/workflows.ts","../../widget-tooling/src/company-widget-package.ts"],"sourcesContent":["import type {\n ButtonGroupFieldSchema,\n PropertyField,\n WidgetPropertySchema,\n} from \"./registries/property-schema-types\";\n\nexport const REMOTE_DOM_WIDGET_MANIFEST_VERSION = 1 as const;\nexport const REMOTE_DOM_WIDGET_RUNTIME = \"remote-dom\" as const;\n\nexport type JsonPrimitive = string | number | boolean | null;\n\nexport type JsonValue = JsonPrimitive | readonly JsonValue[] | JsonObject;\n\nexport interface JsonObject {\n readonly [key: string]: JsonValue;\n}\n\ntype SerializableValue<Value> = unknown extends Value\n ? JsonValue\n : Value extends JsonValue\n ? Value\n : Value extends readonly (infer Item)[]\n ? readonly SerializableValue<Item>[]\n : Value extends object\n ? {\n readonly [Key in keyof Value as NonNullable<Value[Key]> extends (\n ...args: never[]\n ) => unknown\n ? never\n : Key]: SerializableValue<Value[Key]>;\n }\n : never;\n\n/**\n * A property field that can be included in published widget metadata.\n *\n * The legacy `color` field is deprecated. Use `colorSelect` so the value is a\n * semantic color token supplied by the portal theme.\n */\nexport type WidgetSourcePropertyField = PropertyField extends infer Field\n ? Field extends ButtonGroupFieldSchema\n ? Omit<SerializableValue<Field>, \"options\"> & {\n /** Serializable button choices. Runtime icon components are not supported. */\n readonly options: readonly {\n readonly label?: string;\n readonly ariaLabel?: string;\n readonly value: string | number;\n }[];\n }\n : SerializableValue<Field>\n : never;\n\n/**\n * JSON-serializable property editor schema accepted by widget source metadata.\n * The build adds `widgetType`; authors must not supply it.\n */\nexport interface WidgetSourcePropertySchema {\n /** Optional tabs used to organize the property editor. */\n readonly tabsConfig?: SerializableValue<\n NonNullable<WidgetPropertySchema[\"tabsConfig\"]>\n >;\n /** Editable fields shown in the property editor. */\n readonly fields: readonly WidgetSourcePropertyField[];\n /** Widget props that data sources can populate. */\n readonly dataSourceTargetProps?: readonly string[];\n /** Optional per-item fields for custom data-source selections. */\n readonly itemConfigSchema?: {\n /** Fields available for each selected item. */\n readonly fields: readonly WidgetSourcePropertyField[];\n /** Help text shown above the per-item editor. */\n readonly description?: string;\n };\n}\n\nexport interface RemoteDomWidgetCapabilityDeclaration {\n readonly name: string;\n readonly version: string;\n}\n\nexport interface RemoteDomWidgetDefinition {\n readonly type: string;\n readonly displayName: string;\n readonly description: string;\n readonly icon: string;\n readonly category: string;\n readonly propertySchema: JsonObject;\n readonly defaultProps: JsonObject;\n readonly container: \"inline\" | \"block\" | \"card\" | \"fullscreen\";\n readonly resizable: boolean | \"horizontal\" | \"vertical\" | \"both\";\n readonly minSdkVersion: string;\n readonly capabilities: readonly RemoteDomWidgetCapabilityDeclaration[];\n}\n\n/**\n * Canonical package contract shared by the CLI, catalog APIs, and portal hosts.\n * Catalog producers resolve every artifact to its public URL before returning\n * this descriptor; consumers do not translate legacy manifest shapes.\n */\nexport interface RemoteDomWidgetPackageDescriptor {\n readonly manifestVersion: typeof REMOTE_DOM_WIDGET_MANIFEST_VERSION;\n readonly runtime: typeof REMOTE_DOM_WIDGET_RUNTIME;\n readonly packageId: string;\n readonly source: \"company\" | \"droplet\";\n readonly version: string;\n readonly workerEntryUrl: string;\n readonly cssUrls: readonly string[];\n readonly assetUrls: readonly string[];\n readonly widgets: readonly RemoteDomWidgetDefinition[];\n}\n\nconst PACKAGE_FIELDS = new Set([\n \"manifestVersion\",\n \"runtime\",\n \"packageId\",\n \"source\",\n \"version\",\n \"workerEntryUrl\",\n \"cssUrls\",\n \"assetUrls\",\n \"widgets\",\n]);\n\nconst WIDGET_FIELDS = new Set([\n \"type\",\n \"displayName\",\n \"description\",\n \"icon\",\n \"category\",\n \"propertySchema\",\n \"defaultProps\",\n \"container\",\n \"resizable\",\n \"minSdkVersion\",\n \"capabilities\",\n]);\n\nconst CAPABILITY_FIELDS = new Set([\"name\", \"version\"]);\nconst UNSAFE_JSON_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nexport function validateRemoteDomWidgetPackageDescriptor(\n value: unknown,\n): asserts value is RemoteDomWidgetPackageDescriptor {\n const invalidReason = getRemoteDomWidgetPackageInvalidReason(value);\n if (invalidReason) {\n throw new TypeError(`Invalid Remote DOM widget package: ${invalidReason}`);\n }\n}\n\nexport function isRemoteDomWidgetPackageDescriptor(\n value: unknown,\n): value is RemoteDomWidgetPackageDescriptor {\n return getRemoteDomWidgetPackageInvalidReason(value) === undefined;\n}\n\nfunction getRemoteDomWidgetPackageInvalidReason(\n value: unknown,\n): string | undefined {\n if (!isRecord(value)) return \"descriptor must be an object\";\n\n const unexpectedFieldReason = getUnexpectedFieldReason(\n value,\n PACKAGE_FIELDS,\n \"descriptor\",\n );\n if (unexpectedFieldReason) return unexpectedFieldReason;\n\n if (value.manifestVersion !== REMOTE_DOM_WIDGET_MANIFEST_VERSION) {\n return `manifestVersion must be ${REMOTE_DOM_WIDGET_MANIFEST_VERSION}`;\n }\n if (value.runtime !== REMOTE_DOM_WIDGET_RUNTIME) {\n return `runtime must be ${REMOTE_DOM_WIDGET_RUNTIME}`;\n }\n\n const packageIdReason = getNonEmptyStringReason(value.packageId, \"packageId\");\n if (packageIdReason) return packageIdReason;\n\n if (value.source !== \"company\" && value.source !== \"droplet\") {\n return \"source must be company or droplet\";\n }\n\n const versionReason = getNonEmptyStringReason(value.version, \"version\");\n if (versionReason) return versionReason;\n\n const workerEntryUrlReason = getHttpUrlReason(\n value.workerEntryUrl,\n \"workerEntryUrl\",\n );\n if (workerEntryUrlReason) return workerEntryUrlReason;\n\n const cssUrlsReason = getUrlArrayReason(value.cssUrls, \"cssUrls\");\n if (cssUrlsReason) return cssUrlsReason;\n\n const assetUrlsReason = getUrlArrayReason(value.assetUrls, \"assetUrls\");\n if (assetUrlsReason) return assetUrlsReason;\n\n if (!Array.isArray(value.widgets) || value.widgets.length === 0) {\n return \"widgets must be a non-empty array\";\n }\n\n const widgetTypes = new Set<string>();\n for (let index = 0; index < value.widgets.length; index += 1) {\n const widget = value.widgets[index];\n const widgetReason = getWidgetReason(widget, `widgets[${index}]`);\n if (widgetReason) return widgetReason;\n\n const widgetType = widget.type;\n if (widgetTypes.has(widgetType)) {\n return `widgets contains duplicate type ${widgetType}`;\n }\n widgetTypes.add(widgetType);\n }\n\n return undefined;\n}\n\nfunction getWidgetReason(value: unknown, path: string): string | undefined {\n if (!isRecord(value)) return `${path} must be an object`;\n\n const unexpectedFieldReason = getUnexpectedFieldReason(\n value,\n WIDGET_FIELDS,\n path,\n );\n if (unexpectedFieldReason) return unexpectedFieldReason;\n\n for (const field of [\n \"type\",\n \"displayName\",\n \"description\",\n \"icon\",\n \"category\",\n \"minSdkVersion\",\n ] as const) {\n const reason = getNonEmptyStringReason(value[field], `${path}.${field}`);\n if (reason) return reason;\n }\n\n if (!isRecord(value.propertySchema) || !isJsonValue(value.propertySchema)) {\n return `${path}.propertySchema must be a JSON object`;\n }\n if (!isRecord(value.defaultProps) || !isJsonValue(value.defaultProps)) {\n return `${path}.defaultProps must be a JSON object`;\n }\n\n if (\n value.container !== \"inline\" &&\n value.container !== \"block\" &&\n value.container !== \"card\" &&\n value.container !== \"fullscreen\"\n ) {\n return `${path}.container is unsupported`;\n }\n\n if (\n typeof value.resizable !== \"boolean\" &&\n value.resizable !== \"horizontal\" &&\n value.resizable !== \"vertical\" &&\n value.resizable !== \"both\"\n ) {\n return `${path}.resizable is unsupported`;\n }\n\n if (!Array.isArray(value.capabilities)) {\n return `${path}.capabilities must be an array`;\n }\n\n const capabilityNames = new Set<string>();\n for (let index = 0; index < value.capabilities.length; index += 1) {\n const capability = value.capabilities[index];\n const capabilityPath = `${path}.capabilities[${index}]`;\n if (!isRecord(capability)) return `${capabilityPath} must be an object`;\n\n const unexpectedFieldReason = getUnexpectedFieldReason(\n capability,\n CAPABILITY_FIELDS,\n capabilityPath,\n );\n if (unexpectedFieldReason) return unexpectedFieldReason;\n\n const capabilityName = capability.name;\n const nameReason = getNonEmptyStringReason(\n capabilityName,\n `${capabilityPath}.name`,\n );\n if (nameReason) return nameReason;\n if (typeof capabilityName !== \"string\") {\n return `${capabilityPath}.name must be a non-empty string`;\n }\n\n const versionReason = getNonEmptyStringReason(\n capability.version,\n `${capabilityPath}.version`,\n );\n if (versionReason) return versionReason;\n\n if (capabilityNames.has(capabilityName)) {\n return `${path}.capabilities contains duplicate name ${capabilityName}`;\n }\n capabilityNames.add(capabilityName);\n }\n\n return undefined;\n}\n\nfunction getUrlArrayReason(value: unknown, path: string): string | undefined {\n if (!Array.isArray(value)) return `${path} must be an array`;\n\n for (let index = 0; index < value.length; index += 1) {\n const reason = getHttpUrlReason(value[index], `${path}[${index}]`);\n if (reason) return reason;\n }\n return undefined;\n}\n\nfunction getHttpUrlReason(value: unknown, path: string): string | undefined {\n const stringReason = getNonEmptyStringReason(value, path);\n if (stringReason) return stringReason;\n if (typeof value !== \"string\") return `${path} must be a non-empty string`;\n\n try {\n const url = new URL(value);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return `${path} must use http or https`;\n }\n if (url.username || url.password) {\n return `${path} must not contain credentials`;\n }\n } catch {\n return `${path} must be an absolute URL`;\n }\n\n return undefined;\n}\n\nfunction getNonEmptyStringReason(\n value: unknown,\n path: string,\n): string | undefined {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return `${path} must be a non-empty string`;\n }\n if (value !== value.trim())\n return `${path} must not have surrounding whitespace`;\n if (/\\p{Cc}/u.test(value))\n return `${path} must not contain control characters`;\n return undefined;\n}\n\nexport function isJsonValue(value: unknown): value is JsonValue {\n return isJsonValueAtDepth(value, new WeakSet<object>(), 0);\n}\n\nfunction isJsonValueAtDepth(\n value: unknown,\n ancestors: WeakSet<object>,\n depth: number,\n): value is JsonValue {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\"\n ) {\n return true;\n }\n if (typeof value === \"number\") return Number.isFinite(value);\n if (typeof value !== \"object\" || depth > 50 || ancestors.has(value)) {\n return false;\n }\n\n ancestors.add(value);\n const prototype = Object.getPrototypeOf(value);\n const isJson = Array.isArray(value)\n ? value.every((item) => isJsonValueAtDepth(item, ancestors, depth + 1))\n : (prototype === Object.prototype || prototype === null) &&\n isRecord(value) &&\n Object.entries(value).every(\n ([key, item]) =>\n !UNSAFE_JSON_KEYS.has(key) &&\n isJsonValueAtDepth(item, ancestors, depth + 1),\n );\n ancestors.delete(value);\n return isJson;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction getUnexpectedFieldReason(\n value: Readonly<Record<string, unknown>>,\n allowedFields: ReadonlySet<string>,\n path: string,\n): string | undefined {\n const unexpectedField = Object.keys(value).find(\n (field) => !allowedFields.has(field),\n );\n return unexpectedField\n ? `${path} contains unsupported field ${unexpectedField}`\n : undefined;\n}\n","import type { WidgetPackageValidationError } from \"./internal/widget-package-validation.js\";\n\nexport type WidgetToolingErrorCode =\n | \"CONFIG_LOAD_FAILED\"\n | \"VALIDATION_FAILED\"\n | \"INVALID_OUTPUT_DIR\"\n | \"BUILD_FAILED\"\n | \"ARTIFACT_VERIFICATION_FAILED\"\n | \"OWNER_MISMATCH\"\n | \"CLIENT_REQUIRED\"\n | \"SESSION_REQUEST_FAILED\"\n | \"INVALID_SESSION_RESPONSE\"\n | \"MISSING_SIGNED_URL\"\n | \"CONTENT_TYPE_MISMATCH\"\n | \"ARTIFACT_UPLOAD_FAILED\"\n | \"COMPLETE_UPLOAD_FAILED\"\n | \"INVALID_COMPLETE_RESPONSE\"\n | \"PUBLISH_FAILED\";\n\nexport interface WidgetToolingErrorOptions extends ErrorOptions {\n readonly details?: string;\n readonly diagnostics?: readonly WidgetPackageValidationError[];\n}\n\nexport class WidgetToolingError extends Error {\n public readonly code: WidgetToolingErrorCode;\n public readonly details?: string;\n public readonly diagnostics?: readonly WidgetPackageValidationError[];\n\n constructor(\n code: WidgetToolingErrorCode,\n message: string,\n options: WidgetToolingErrorOptions = {},\n ) {\n super(message, options);\n this.name = \"WidgetToolingError\";\n this.code = code;\n this.details = options.details;\n this.diagnostics = options.diagnostics;\n }\n}\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\nimport { createHash } from \"node:crypto\";\n\n/** Version of the shared widget-tooling package that produced the artifacts. */\nexport const WIDGET_PACKAGE_BUILDER_VERSION = \"0.1.0\";\n\nexport interface ArtifactMetadata {\n readonly path: string;\n readonly sha256: string;\n readonly bytes: number;\n readonly contentType: string;\n}\n\nexport interface PublishManifestMetadata {\n readonly packageId: string;\n readonly version: string;\n readonly builderVersion: string;\n readonly cliVersion: string;\n readonly runtimeVersion: string;\n readonly manifestHash: string;\n readonly artifacts: readonly ArtifactMetadata[];\n}\n\nconst CONTENT_TYPES: Readonly<Record<string, string>> = {\n \".css\": \"text/css\",\n \".js\": \"application/javascript\",\n \".json\": \"application/json\",\n \".map\": \"application/json\",\n};\nconst CSS_ARTIFACT_PATH_PATTERN = /^[A-Za-z0-9._~-]+\\.css$/;\nconst JS_MAP_ARTIFACT_PATH_PATTERN = /^[A-Za-z0-9._~-]+\\.js\\.map$/;\n\nexport async function computeArtifactMetadata(\n filePath: string,\n baseDir: string,\n): Promise<ArtifactMetadata> {\n const relativePath = toPosixPath(path.relative(baseDir, filePath));\n assertAllowedArtifactPath(relativePath);\n await assertRegularArtifactFile(filePath, relativePath);\n const buffer = await fs.readFile(filePath);\n\n return {\n path: relativePath,\n sha256: sha256(buffer),\n bytes: buffer.byteLength,\n contentType: getArtifactContentType(filePath),\n };\n}\n\nexport async function collectWidgetPackageArtifacts(\n publishDir: string,\n): Promise<ArtifactMetadata[]> {\n const artifactPaths = await findArtifactPaths(publishDir);\n const artifacts = await Promise.all(\n artifactPaths.map((artifactPath) =>\n computeArtifactMetadata(artifactPath, publishDir),\n ),\n );\n\n assertRequiredUploadArtifacts(artifacts);\n\n return artifacts.sort((a, b) => a.path.localeCompare(b.path));\n}\n\nexport function createPublishManifestMetadata(options: {\n readonly packageId: string;\n readonly version: string;\n readonly cliVersion: string;\n readonly runtimeVersion: string;\n readonly manifestContent: string | Buffer;\n readonly artifacts: readonly ArtifactMetadata[];\n readonly builderVersion?: string;\n}): PublishManifestMetadata {\n return {\n packageId: options.packageId,\n version: options.version,\n builderVersion: options.builderVersion ?? WIDGET_PACKAGE_BUILDER_VERSION,\n cliVersion: options.cliVersion,\n runtimeVersion: options.runtimeVersion,\n manifestHash: sha256(options.manifestContent),\n artifacts: options.artifacts,\n };\n}\n\nexport function getArtifactContentType(filePath: string): string {\n const basename = path.basename(filePath);\n if (basename.endsWith(\".js.map\")) {\n return \"application/json\";\n }\n return CONTENT_TYPES[path.extname(filePath)] ?? \"application/octet-stream\";\n}\n\nexport function sha256(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nexport function isWidgetPackageCssArtifactPath(relativePath: string): boolean {\n return CSS_ARTIFACT_PATH_PATTERN.test(relativePath);\n}\n\nexport function isWidgetPackageJsMapArtifactPath(\n relativePath: string,\n): boolean {\n return JS_MAP_ARTIFACT_PATH_PATTERN.test(relativePath);\n}\n\nasync function assertRegularArtifactFile(\n filePath: string,\n relativePath: string,\n): Promise<void> {\n const stat = await fs.lstat(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(\n `Widget publish artifact ${JSON.stringify(relativePath)} must be a regular file and must not be a symbolic link.`,\n );\n }\n if (!stat.isFile()) {\n throw new Error(\n `Widget publish artifact ${JSON.stringify(relativePath)} must be a regular file.`,\n );\n }\n}\n\nasync function findArtifactPaths(\n dir: string,\n baseDir: string = dir,\n): Promise<string[]> {\n if (!(await fs.pathExists(dir))) return [];\n\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const paths = await Promise.all(\n entries.map(async (entry) => {\n const entryPath = path.join(dir, entry.name);\n const relativePath = toPosixPath(path.relative(baseDir, entryPath));\n\n if (entry.isSymbolicLink()) {\n throw new Error(\n `Widget publish artifact ${JSON.stringify(relativePath)} must be a regular file and must not be a symbolic link.`,\n );\n }\n\n if (isUploadArtifact(relativePath)) {\n if (!entry.isFile()) {\n throw new Error(\n `Widget publish artifact ${JSON.stringify(relativePath)} must be a regular file.`,\n );\n }\n return [entryPath];\n }\n\n if (entry.isDirectory()) {\n const nestedPaths = await findArtifactPaths(entryPath, baseDir);\n if (nestedPaths.length === 0) {\n throwUnsupportedArtifactPath(`${relativePath}/`);\n }\n return nestedPaths;\n }\n if (isAllowedGeneratedFile(relativePath)) return [];\n throwUnsupportedArtifactPath(relativePath);\n }),\n );\n\n return paths.flat();\n}\n\nfunction assertRequiredUploadArtifacts(\n artifacts: readonly ArtifactMetadata[],\n): void {\n const artifactPaths = new Set(artifacts.map((artifact) => artifact.path));\n for (const requiredPath of [\"widget.js\", \"manifest.json\"] as const) {\n if (artifactPaths.has(requiredPath)) continue;\n throw new Error(\n `Widget package publish output must include regular file ${JSON.stringify(requiredPath)}.`,\n );\n }\n}\n\nfunction assertAllowedArtifactPath(relativePath: string): void {\n if (isUploadArtifact(relativePath) || isAllowedGeneratedFile(relativePath))\n return;\n throwUnsupportedArtifactPath(relativePath);\n}\n\nfunction isUploadArtifact(relativePath: string): boolean {\n return (\n relativePath === \"widget.js\" ||\n relativePath === \"manifest.json\" ||\n isWidgetPackageCssArtifactPath(relativePath) ||\n isWidgetPackageJsMapArtifactPath(relativePath)\n );\n}\n\nfunction isAllowedGeneratedFile(relativePath: string): boolean {\n return (\n isFlatArtifactPath(relativePath) && relativePath === \"publish-manifest.json\"\n );\n}\n\nfunction isFlatArtifactPath(relativePath: string): boolean {\n return (\n relativePath.length > 0 &&\n !relativePath.includes(\"/\") &&\n !relativePath.includes(\"\\\\\")\n );\n}\n\nfunction throwUnsupportedArtifactPath(relativePath: string): never {\n throw new Error(\n `Unsupported widget publish artifact ${JSON.stringify(relativePath)}. ` +\n \"Allowed files are widget.js, manifest.json, top-level [A-Za-z0-9._~-]+.css, top-level [A-Za-z0-9._~-]+.js.map, and publish-manifest.json.\",\n );\n}\n\nfunction toPosixPath(value: string): string {\n return value.split(path.sep).join(\"/\");\n}\n","import { isWidgetPackageCssArtifactPath } from \"./widget-package-artifacts.js\";\nimport {\n isJsonValue,\n type JsonObject,\n type RemoteDomWidgetDefinition,\n} from \"@fluid-app/portal-core/remote-dom-widget-package\";\n\nconst URL_SAFE_SEGMENT_SOURCE = \"[A-Za-z0-9][A-Za-z0-9_~-]*\";\nconst URL_SAFE_WIDGET_NAME_PATTERN = new RegExp(`^${URL_SAFE_SEGMENT_SOURCE}$`);\nconst URL_SAFE_DOTTED_IDENTIFIER_PATTERN = new RegExp(\n `^${URL_SAFE_SEGMENT_SOURCE}(?:\\\\.${URL_SAFE_SEGMENT_SOURCE})*$`,\n);\nconst SEMVER_CORE_PATTERN = \"(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\";\nconst SEMVER_PRERELEASE_IDENTIFIER_PATTERN =\n \"(?:0|[1-9]\\\\d*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)\";\nconst SEMVER_URL_SAFE_PATTERN = new RegExp(\n `^${SEMVER_CORE_PATTERN}(?:-${SEMVER_PRERELEASE_IDENTIFIER_PATTERN}(?:\\\\.${SEMVER_PRERELEASE_IDENTIFIER_PATTERN})*)?$`,\n);\nconst WIDGET_PACKAGE_MANIFEST_VERSION = 1;\nconst DEFAULT_WIDGET_ICON = \"box\";\nconst DEFAULT_WIDGET_CATEGORY = \"components\";\nconst DEFAULT_WIDGET_CONTAINER = \"block\";\nconst DEFAULT_MIN_SDK_VERSION = \"0.0.0\";\n\nexport type WidgetPackageOwnerKind = \"company\" | \"droplet\";\n\nexport type WidgetRuntimeContainer = RemoteDomWidgetDefinition[\"container\"];\nexport type WidgetRuntimeResizable = RemoteDomWidgetDefinition[\"resizable\"];\n\nexport interface WidgetCapabilityMetadata {\n readonly name: string;\n readonly version?: string;\n}\n\nexport interface SourceWidgetMetadata {\n readonly name: string;\n readonly displayName?: string;\n readonly description?: string;\n readonly icon?: string;\n readonly category?: string;\n readonly propertySchema?: JsonObject;\n readonly defaultProps?: JsonObject;\n readonly container?: unknown;\n readonly minSdkVersion?: string;\n readonly resizable?: unknown;\n readonly capabilities?: readonly WidgetCapabilityMetadata[];\n}\n\nexport interface SourceWidgetPackageMetadata {\n readonly manifestVersion?: number;\n readonly scope?: string;\n readonly packageStableId?: string;\n readonly packageId: string;\n readonly packageType?: string;\n readonly version: string;\n readonly widgets: readonly SourceWidgetMetadata[];\n readonly cssUrls?: readonly string[];\n}\n\nexport interface WidgetDescriptorMetadata extends RemoteDomWidgetDefinition {\n readonly name: string;\n}\n\ndeclare const WIDGET_PACKAGE_ARTIFACT_PATH: unique symbol;\n\n/** A package-local artifact path written into the uploaded manifest. */\nexport type WidgetPackageArtifactPath = string & {\n readonly [WIDGET_PACKAGE_ARTIFACT_PATH]: true;\n};\n\n/**\n * Upload-time manifest whose artifact references are package-local paths.\n *\n * This is deliberately distinct from RemoteDomWidgetPackageDescriptor, whose\n * catalog-facing artifact fields must already be resolved to absolute URLs.\n */\nexport interface WidgetPackagePublishManifest {\n readonly manifestVersion: 1;\n readonly runtime: \"remote-dom\";\n readonly packageId: string;\n readonly source: WidgetPackageOwnerKind;\n readonly version: string;\n readonly workerEntryUrl: WidgetPackageArtifactPath;\n readonly cssUrls: readonly WidgetPackageArtifactPath[];\n readonly assetUrls: readonly WidgetPackageArtifactPath[];\n readonly widgets: readonly RemoteDomWidgetDefinition[];\n}\n\nexport interface ValidatedWidgetPackageBuild {\n readonly sourcePackage: SourceWidgetPackageMetadata;\n readonly packageKey: string;\n readonly packageId: string;\n readonly owner: WidgetPackageOwnerKind;\n readonly version: string;\n readonly widgets: readonly WidgetDescriptorMetadata[];\n}\n\nexport type WidgetPackageValidationErrorCode =\n | \"NO_SOURCE_PACKAGE\"\n | \"MULTIPLE_SOURCE_PACKAGES\"\n | \"INVALID_SOURCE_PACKAGE\"\n | \"INVALID_WIDGET_METADATA\"\n | \"UNSUPPORTED_OWNER\"\n | \"INVALID_PACKAGE_KEY\"\n | \"INVALID_VERSION\"\n | \"NO_WIDGETS\"\n | \"INVALID_WIDGET_NAME\"\n | \"INVALID_WIDGET_TYPE\"\n | \"DUPLICATE_WIDGET\";\n\nexport interface WidgetPackageValidationError {\n readonly code: WidgetPackageValidationErrorCode;\n readonly message: string;\n readonly path?: string;\n}\n\nexport interface WidgetPackageValidationResult {\n readonly success: boolean;\n readonly value?: ValidatedWidgetPackageBuild;\n readonly errors: readonly WidgetPackageValidationError[];\n}\n\nexport interface ValidateSourceWidgetPackageOptions {\n readonly owner?: WidgetPackageOwnerKind;\n}\n\nexport function validateSingleSourceWidgetPackage(\n sourcePackages: readonly unknown[],\n options: ValidateSourceWidgetPackageOptions = {},\n): WidgetPackageValidationResult {\n if (sourcePackages.length === 0) {\n return validationFailure({\n code: \"NO_SOURCE_PACKAGE\",\n message:\n \"No defineWidgetPackage source package was found. Export widgetPackage, widgetPackages, or a default widget package from src/widgets.config.ts.\",\n });\n }\n\n if (sourcePackages.length > 1) {\n return validationFailure({\n code: \"MULTIPLE_SOURCE_PACKAGES\",\n message:\n \"Publish/deploy supports exactly one defineWidgetPackage source package. Export one package or split packages into separate builds.\",\n });\n }\n\n const sourcePackageValue = sourcePackages[0];\n if (!sourcePackageValue) {\n return validationFailure({\n code: \"NO_SOURCE_PACKAGE\",\n message: \"No defineWidgetPackage source package was found.\",\n });\n }\n\n const shapeErrors = validateSourcePackageShape(sourcePackageValue);\n if (shapeErrors.length > 0) {\n return { success: false, errors: shapeErrors };\n }\n const sourcePackage = sourcePackageValue as SourceWidgetPackageMetadata;\n\n const errors: WidgetPackageValidationError[] = [];\n const owner = options.owner ?? sourcePackage.packageType;\n if (owner !== \"company\" && owner !== \"droplet\") {\n errors.push({\n code: \"UNSUPPORTED_OWNER\",\n path: \"packageType\",\n message:\n 'Widget package publish/deploy currently supports company and droplet owners. Set packageType to \"company\" or \"droplet\".',\n });\n } else if (\n options.owner !== undefined &&\n sourcePackage.packageType !== options.owner\n ) {\n errors.push({\n code: \"UNSUPPORTED_OWNER\",\n path: \"packageType\",\n message: `Widget package metadata must set packageType to \"${options.owner}\" for this workflow.`,\n });\n }\n\n const resolvedOwner = owner === \"droplet\" ? \"droplet\" : \"company\";\n if (\n resolvedOwner === \"droplet\" &&\n !readNonEmptyTrimmedString(sourcePackage.packageStableId)\n ) {\n errors.push({\n code: \"INVALID_PACKAGE_KEY\",\n path: \"packageStableId\",\n message:\n \"Droplet widget packages must set packageStableId so published widget types remain stable across builds.\",\n });\n }\n\n const packageKey = resolvePackageKey(sourcePackage, resolvedOwner);\n const packageKeyPath = readNonEmptyTrimmedString(\n sourcePackage.packageStableId,\n )\n ? \"packageStableId\"\n : \"packageId\";\n if (!isUrlSafeDottedIdentifier(packageKey)) {\n errors.push({\n code: \"INVALID_PACKAGE_KEY\",\n path: packageKeyPath,\n message:\n \"Widget package key must be URL-safe dot-separated text (letters, numbers, '.', '_', '~', and '-' only).\",\n });\n }\n\n if (!isUrlSafeSemver(sourcePackage.version)) {\n errors.push({\n code: \"INVALID_VERSION\",\n path: \"version\",\n message:\n \"Widget package version must be a URL-safe SemVer version without build metadata (for example 1.2.3 or 1.2.3-beta.1).\",\n });\n }\n\n if (sourcePackage.widgets.length === 0) {\n errors.push({\n code: \"NO_WIDGETS\",\n path: \"widgets\",\n message: \"Widget package must include at least one widget.\",\n });\n }\n\n const packageId = `${resolvedOwner}.${packageKey}`;\n const seenNames = new Set<string>();\n const seenTypes = new Set<string>();\n const widgets: WidgetDescriptorMetadata[] = [];\n\n sourcePackage.widgets.forEach((widget, index) => {\n const path = `widgets[${index}]`;\n if (!isUrlSafeWidgetName(widget.name)) {\n errors.push({\n code: \"INVALID_WIDGET_NAME\",\n path: `${path}.name`,\n message:\n \"Widget name must be URL-safe text (letters, numbers, '_', '~', and '-' only) and cannot be empty.\",\n });\n return;\n }\n\n if (seenNames.has(widget.name)) {\n errors.push({\n code: \"DUPLICATE_WIDGET\",\n path: `${path}.name`,\n message: `Duplicate widget name \"${widget.name}\" found in package ${packageKey}.`,\n });\n return;\n }\n seenNames.add(widget.name);\n\n const type = `${packageId}.${widget.name}`;\n if (!isUrlSafeDottedIdentifier(type)) {\n errors.push({\n code: \"INVALID_WIDGET_TYPE\",\n path: `${path}.type`,\n message: `Generated widget type \"${type}\" is not URL-safe.`,\n });\n return;\n }\n\n if (seenTypes.has(type)) {\n errors.push({\n code: \"DUPLICATE_WIDGET\",\n path: `${path}.type`,\n message: `Duplicate generated widget type \"${type}\" found.`,\n });\n return;\n }\n seenTypes.add(type);\n\n widgets.push(sourceWidgetToDescriptor(widget, type));\n });\n\n if (errors.length > 0) return { success: false, errors };\n\n return {\n success: true,\n value: {\n sourcePackage,\n packageKey,\n packageId,\n owner: resolvedOwner,\n version: sourcePackage.version,\n widgets,\n },\n errors: [],\n };\n}\n\nexport function buildWidgetPackagePublishManifest(\n validated: ValidatedWidgetPackageBuild,\n options: {\n readonly cssUrls?: readonly string[];\n } = {},\n): WidgetPackagePublishManifest {\n return {\n manifestVersion: WIDGET_PACKAGE_MANIFEST_VERSION,\n runtime: \"remote-dom\",\n packageId: validated.packageId,\n source: validated.owner,\n version: validated.version,\n // Published manifests name package-local artifacts. Catalog producers\n // resolve these paths to absolute URLs before returning the descriptor to\n // a host, where portal-core performs its absolute-URL ingress validation.\n workerEntryUrl: toWidgetPackageArtifactPath(\"widget.js\"),\n cssUrls: mergeCssUrls(validated.sourcePackage.cssUrls, options.cssUrls),\n assetUrls: [],\n widgets: validated.widgets.map(({ name: _name, ...widget }) => widget),\n };\n}\n\nfunction sourceWidgetToDescriptor(\n widget: SourceWidgetMetadata,\n type: string,\n): WidgetDescriptorMetadata {\n const displayName = widget.displayName ?? widget.name;\n\n return {\n type,\n name: widget.name,\n displayName,\n description: widget.description ?? `Custom widget ${displayName}`,\n icon: widget.icon ?? DEFAULT_WIDGET_ICON,\n category: widget.category ?? DEFAULT_WIDGET_CATEGORY,\n propertySchema: normalizePropertySchema(widget.propertySchema, type),\n defaultProps: widget.defaultProps ?? {},\n container: normalizeContainer(widget.container),\n minSdkVersion: widget.minSdkVersion ?? DEFAULT_MIN_SDK_VERSION,\n resizable: normalizeResizable(widget.resizable),\n capabilities: normalizeCapabilities(widget.capabilities ?? []),\n };\n}\n\nfunction normalizeCapabilities(\n capabilities: readonly WidgetCapabilityMetadata[],\n): readonly Required<WidgetCapabilityMetadata>[] {\n return capabilities.map((capability) => ({\n name: capability.name,\n version: capability.version ?? \"1\",\n }));\n}\n\nfunction validationFailure(\n error: WidgetPackageValidationError,\n): WidgetPackageValidationResult {\n return { success: false, errors: [error] };\n}\n\nfunction validateSourcePackageShape(\n value: unknown,\n): WidgetPackageValidationError[] {\n if (!isRecord(value)) {\n return [\n {\n code: \"INVALID_SOURCE_PACKAGE\",\n message: \"Widget source package must be a JSON object.\",\n },\n ];\n }\n\n const errors: WidgetPackageValidationError[] = [];\n requireStringField(value, \"packageId\", \"packageId\", errors);\n requireStringField(value, \"version\", \"version\", errors);\n validateOptionalStringField(value, \"scope\", \"scope\", errors);\n validateOptionalStringField(\n value,\n \"packageStableId\",\n \"packageStableId\",\n errors,\n );\n validateOptionalStringField(value, \"packageType\", \"packageType\", errors);\n\n if (Object.prototype.hasOwnProperty.call(value, \"navigationOrigins\")) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: \"navigationOrigins\",\n message:\n \"navigationOrigins has been removed. Declare the externalNavigation capability and call allowAnchorUrl(url) for each external link.\",\n });\n }\n\n if (value.cssUrls !== undefined) {\n if (!Array.isArray(value.cssUrls)) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: \"cssUrls\",\n message:\n \"Widget package cssUrls must be an array of strings when present.\",\n });\n } else {\n value.cssUrls.forEach((cssUrl, index) => {\n validateCssUrl(cssUrl, `cssUrls[${index}]`, errors);\n });\n }\n }\n\n if (!Array.isArray(value.widgets)) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: \"widgets\",\n message: \"Widget package widgets must be an array.\",\n });\n return errors;\n }\n\n value.widgets.forEach((widget, index) => {\n const widgetPath = `widgets[${index}]`;\n if (!isRecord(widget)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: widgetPath,\n message: \"Widget metadata must be a JSON object.\",\n });\n return;\n }\n\n requireStringField(widget, \"name\", `${widgetPath}.name`, errors, {\n code: \"INVALID_WIDGET_NAME\",\n message: \"Widget name must be a string and cannot be empty.\",\n });\n validateOptionalStringField(\n widget,\n \"displayName\",\n `${widgetPath}.displayName`,\n errors,\n { requireNonEmpty: true },\n );\n validateOptionalStringField(\n widget,\n \"description\",\n `${widgetPath}.description`,\n errors,\n { requireNonEmpty: true },\n );\n validateOptionalStringField(widget, \"icon\", `${widgetPath}.icon`, errors, {\n requireNonEmpty: true,\n });\n validateOptionalStringField(\n widget,\n \"category\",\n `${widgetPath}.category`,\n errors,\n { requireNonEmpty: true },\n );\n validateOptionalStringField(\n widget,\n \"minSdkVersion\",\n `${widgetPath}.minSdkVersion`,\n errors,\n { requireNonEmpty: true },\n );\n validateOptionalJsonRecordField(\n widget,\n \"propertySchema\",\n `${widgetPath}.propertySchema`,\n errors,\n );\n validateOptionalJsonRecordField(\n widget,\n \"defaultProps\",\n `${widgetPath}.defaultProps`,\n errors,\n );\n validateOptionalCapabilities(\n widget,\n \"capabilities\",\n `${widgetPath}.capabilities`,\n errors,\n );\n });\n\n return errors;\n}\n\nfunction requireStringField(\n record: Record<string, unknown>,\n key: string,\n path: string,\n errors: WidgetPackageValidationError[],\n override?: Pick<WidgetPackageValidationError, \"code\" | \"message\">,\n): void {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) return;\n\n errors.push({\n code: override?.code ?? \"INVALID_SOURCE_PACKAGE\",\n path,\n message:\n override?.message ?? `${path} must be a string and cannot be empty.`,\n });\n}\n\nfunction validateOptionalStringField(\n record: Record<string, unknown>,\n key: string,\n path: string,\n errors: WidgetPackageValidationError[],\n options: { readonly requireNonEmpty?: boolean } = {},\n): void {\n const value = record[key];\n if (value === undefined) return;\n if (typeof value === \"string\") {\n if (!options.requireNonEmpty || value.trim().length > 0) return;\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path,\n message: `${path} must be a non-empty string when present.`,\n });\n return;\n }\n\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path,\n message: `${path} must be a string when present.`,\n });\n}\n\nfunction validateCssUrl(\n value: unknown,\n cssUrlPath: string,\n errors: WidgetPackageValidationError[],\n): void {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: cssUrlPath,\n message: \"Widget package cssUrls entries must be non-empty strings.\",\n });\n return;\n }\n\n if (!isWidgetPackageCssArtifactPath(value)) {\n errors.push({\n code: \"INVALID_SOURCE_PACKAGE\",\n path: cssUrlPath,\n message:\n \"Widget package cssUrls entries must be top-level generated CSS artifact filenames matching [A-Za-z0-9._~-]+.css. Self-host external CSS or fonts via @font-face in widget CSS so the build can isolate them.\",\n });\n }\n}\n\nfunction validateOptionalJsonRecordField(\n record: Record<string, unknown>,\n key: string,\n path: string,\n errors: WidgetPackageValidationError[],\n): void {\n const value = record[key];\n if (value === undefined) return;\n if (isRecord(value) && isJsonValue(value)) return;\n\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path,\n message: `${path} must be a JSON object when present.`,\n });\n}\n\nfunction validateOptionalCapabilities(\n record: Record<string, unknown>,\n key: string,\n path: string,\n errors: WidgetPackageValidationError[],\n): void {\n const value = record[key];\n if (value === undefined) return;\n if (!Array.isArray(value)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path,\n message: `${path} must be an array when present.`,\n });\n return;\n }\n\n const names = new Set<string>();\n value.forEach((candidate, index) => {\n const capabilityPath = `${path}[${index}]`;\n if (!isRecord(candidate)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: capabilityPath,\n message: `${capabilityPath} must be a JSON object.`,\n });\n return;\n }\n\n const name = candidate.name;\n if (!isCanonicalMetadataString(name)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: `${capabilityPath}.name`,\n message: `${capabilityPath}.name must be a non-empty string without surrounding whitespace or control characters.`,\n });\n return;\n }\n\n const version = candidate.version;\n if (version !== undefined && !isCanonicalMetadataString(version)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: `${capabilityPath}.version`,\n message: `${capabilityPath}.version must be a non-empty string without surrounding whitespace or control characters when present.`,\n });\n }\n\n if (names.has(name)) {\n errors.push({\n code: \"INVALID_WIDGET_METADATA\",\n path: `${capabilityPath}.name`,\n message: `${path} must not contain duplicate capability name ${JSON.stringify(name)}.`,\n });\n return;\n }\n names.add(name);\n });\n}\n\nfunction isCanonicalMetadataString(value: unknown): value is string {\n return (\n typeof value === \"string\" &&\n value.length > 0 &&\n value === value.trim() &&\n !/\\p{Cc}/u.test(value)\n );\n}\n\nfunction mergeCssUrls(\n sourceCssUrls: readonly string[] | undefined,\n generatedCssUrls: readonly string[] | undefined,\n): WidgetPackageArtifactPath[] {\n const generatedCssUrlSet = new Set(generatedCssUrls ?? []);\n generatedCssUrls?.forEach((cssUrl, index) => {\n validateGeneratedCssArtifactUrl(cssUrl, `generated cssUrls[${index}]`);\n });\n sourceCssUrls?.forEach((cssUrl, index) => {\n validateGeneratedCssArtifactUrl(cssUrl, `cssUrls[${index}]`);\n if (generatedCssUrlSet.has(cssUrl)) return;\n\n throw new Error(\n `cssUrls[${index}] URL ${JSON.stringify(cssUrl)} must match a generated top-level CSS artifact. ` +\n \"Import the CSS from the widget package bundle or remove it from cssUrls.\",\n );\n });\n\n return Array.from(\n new Set([...(sourceCssUrls ?? []), ...(generatedCssUrls ?? [])]),\n ).map(toWidgetPackageArtifactPath);\n}\n\nfunction toWidgetPackageArtifactPath(value: string): WidgetPackageArtifactPath {\n return value as WidgetPackageArtifactPath;\n}\n\nfunction validateGeneratedCssArtifactUrl(\n value: string,\n cssUrlPath: string,\n): void {\n if (value.trim().length === 0) {\n throw new Error(`${cssUrlPath} must be a non-empty string.`);\n }\n\n if (!isWidgetPackageCssArtifactPath(value)) {\n throw new Error(\n `${cssUrlPath} must be a top-level generated CSS artifact filename matching [A-Za-z0-9._~-]+.css. Self-host external CSS or fonts via @font-face in widget CSS so the build can isolate them.`,\n );\n }\n}\n\nfunction normalizePropertySchema(\n value: JsonObject | undefined,\n widgetType: string,\n): JsonObject {\n return { ...(value ?? {}), widgetType };\n}\n\nfunction normalizeContainer(value: unknown): WidgetRuntimeContainer {\n if (\n value === \"inline\" ||\n value === \"block\" ||\n value === \"card\" ||\n value === \"fullscreen\"\n ) {\n return value;\n }\n\n return DEFAULT_WIDGET_CONTAINER;\n}\n\nfunction normalizeResizable(value: unknown): WidgetRuntimeResizable {\n if (typeof value === \"boolean\") return value;\n if (value === \"horizontal\" || value === \"vertical\" || value === \"both\") {\n return value;\n }\n if (!isRecord(value)) return false;\n\n const horizontal = value.horizontal === true;\n const vertical = value.vertical === true;\n\n if (horizontal && vertical) return \"both\";\n if (horizontal) return \"horizontal\";\n if (vertical) return \"vertical\";\n return false;\n}\n\nfunction resolvePackageKey(\n sourcePackage: SourceWidgetPackageMetadata,\n owner: WidgetPackageOwnerKind,\n): string {\n const packageStableId = readNonEmptyTrimmedString(\n sourcePackage.packageStableId,\n );\n if (packageStableId) {\n return prefixPackageStableIdWithNonOwnerScope(\n packageStableId,\n sourcePackage.scope,\n );\n }\n\n return stripOwnerScopeFromPackageId(\n sourcePackage.packageId,\n sourcePackage.scope,\n owner,\n );\n}\n\nfunction prefixPackageStableIdWithNonOwnerScope(\n packageStableId: string,\n sourceScope: string | undefined,\n): string {\n const sourceScopeText = readNonEmptyTrimmedString(sourceScope);\n if (!sourceScopeText || isWidgetPackageOwnerKind(sourceScopeText)) {\n return packageStableId;\n }\n\n const sourceScopePrefix = `${sourceScopeText}.`;\n if (packageStableId.startsWith(sourceScopePrefix)) return packageStableId;\n return `${sourceScopeText}.${packageStableId}`;\n}\n\nfunction stripOwnerScopeFromPackageId(\n packageId: string,\n sourceScope: string | undefined,\n owner: WidgetPackageOwnerKind,\n): string {\n const ownerPrefix = `${owner}.`;\n if (\n packageId.startsWith(ownerPrefix) &&\n packageId.length > ownerPrefix.length\n ) {\n return packageId.slice(ownerPrefix.length);\n }\n\n const sourceScopeText = readNonEmptyTrimmedString(sourceScope);\n if (\n isWidgetPackageOwnerKind(sourceScopeText) &&\n packageId.startsWith(`${sourceScopeText}.`) &&\n packageId.length > sourceScopeText.length + 1\n ) {\n return packageId.slice(sourceScopeText.length + 1);\n }\n\n return packageId;\n}\n\nfunction readNonEmptyTrimmedString(\n value: string | undefined,\n): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction isWidgetPackageOwnerKind(\n value: string | undefined,\n): value is WidgetPackageOwnerKind {\n return value === \"company\" || value === \"droplet\";\n}\n\nfunction isUrlSafeDottedIdentifier(value: string): boolean {\n return URL_SAFE_DOTTED_IDENTIFIER_PATTERN.test(value);\n}\n\nfunction isUrlSafeWidgetName(value: string): boolean {\n return URL_SAFE_WIDGET_NAME_PATTERN.test(value);\n}\n\nfunction isUrlSafeSemver(value: string): boolean {\n return SEMVER_URL_SAFE_PATTERN.test(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { RemoteDomWidgetPackageDescriptor } from \"@fluid-app/portal-core/remote-dom-widget-package\";\nimport { WidgetToolingError } from \"./errors.js\";\nimport {\n validateSingleSourceWidgetPackage,\n type ValidatedWidgetPackageBuild,\n type WidgetPackageOwnerKind,\n} from \"./internal/widget-package-validation.js\";\n\nexport interface CreateWidgetPackageDevelopmentDescriptorOptions {\n readonly sourceModule: Readonly<Record<string, unknown>>;\n readonly owner: WidgetPackageOwnerKind;\n readonly origin: string;\n readonly workerEntryPath?: string;\n readonly defaultCssPath?: string;\n}\n\nexport function createWidgetPackageDevelopmentDescriptor(\n options: CreateWidgetPackageDevelopmentDescriptorOptions,\n): RemoteDomWidgetPackageDescriptor {\n const validation = validateSingleSourceWidgetPackage(\n readSourcePackages(options.sourceModule),\n { owner: options.owner },\n );\n if (!validation.success || !validation.value) {\n throw new WidgetToolingError(\n \"VALIDATION_FAILED\",\n validation.errors.map((error) => error.message).join(\"\\n\") ||\n \"Widget package validation failed.\",\n { diagnostics: validation.errors },\n );\n }\n\n return validatedPackageToDescriptor(validation.value, options);\n}\n\nfunction validatedPackageToDescriptor(\n validated: ValidatedWidgetPackageBuild,\n options: CreateWidgetPackageDevelopmentDescriptorOptions,\n): RemoteDomWidgetPackageDescriptor {\n const cssUrls = validated.sourcePackage.cssUrls ?? [];\n const workerEntryPath = options.workerEntryPath ?? \"/__runtime-entry__\";\n const defaultCssPath = options.defaultCssPath ?? \"/styles.css\";\n\n return {\n manifestVersion: 1,\n runtime: \"remote-dom\",\n packageId: validated.packageId,\n source: validated.owner,\n version: validated.version,\n workerEntryUrl: new URL(workerEntryPath, options.origin).href,\n cssUrls:\n cssUrls.length > 0\n ? cssUrls.map((url) => toDevelopmentCssUrl(url, options.origin))\n : [toDevelopmentCssUrl(defaultCssPath, options.origin)],\n assetUrls: [],\n widgets: validated.widgets.map(({ name: _name, ...widget }) => widget),\n };\n}\n\nfunction readSourcePackages(\n sourceModule: Readonly<Record<string, unknown>>,\n): readonly unknown[] {\n const packages = sourceModule[\"widgetPackages\"];\n if (Array.isArray(packages) && packages.length > 0) return packages;\n\n const widgetPackage = sourceModule[\"widgetPackage\"];\n if (widgetPackage !== undefined) return [widgetPackage];\n\n const defaultPackage = sourceModule[\"default\"];\n return defaultPackage === undefined ? [] : [defaultPackage];\n}\n\nfunction toDevelopmentCssUrl(url: string, origin: string): string {\n const { href } = new URL(url, origin);\n return href.includes(\"?\") ? `${href}&direct` : `${href}?direct`;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { RemoteDomWidgetPackageDescriptor } from \"@fluid-app/portal-core/remote-dom-widget-package\";\nimport { createWidgetPackageDevelopmentDescriptor } from \"./development-descriptor.js\";\nimport { WidgetToolingError } from \"./errors.js\";\nimport type { WidgetPackageOwnerKind } from \"./internal/widget-package-validation.js\";\nimport type { Plugin, UserConfig, ViteDevServer } from \"vite\";\n\n/**\n * Layout of the project these dev routes serve.\n *\n * Defaults describe a standalone widget project, which is the only layout that\n * existed when these routes were written. A portal project keeps its package\n * source at `src/widgets.config.ts`, owns it as `company` rather than\n * `droplet`, and has no `startWidgetPackage()` module of its own — so it\n * supplies a generated entry via `entryModulePath`.\n */\nexport interface FluidWidgetDevPluginOptions {\n /** Module the worker bootstrap imports. Must call `startWidgetPackage()`. */\n readonly entryModulePath?: string;\n /** Module exporting `widgetPackage` / `widgetPackages`. */\n readonly configModulePath?: string;\n /** Who owns the published package. */\n readonly owner?: WidgetPackageOwnerKind;\n /**\n * Treat \"the project declares no widget packages\" as an empty catalog rather\n * than an error. A standalone widget project with no package is broken, but a\n * portal that has not been given a custom widget yet is perfectly normal — and\n * its preview polls this route continuously, so erroring would be constant\n * noise for the expected case.\n */\n readonly allowNoPackages?: boolean;\n}\n\n/**\n * Creates the Vite plugin that serves a widget package descriptor and worker entry.\n *\n * @param options - Source layout and ownership overrides. The defaults match the standalone widget template.\n * @returns A serve-only Vite plugin for Fluid widget development.\n */\nexport function fluidWidgetDevPlugin(\n options: FluidWidgetDevPluginOptions = {},\n): Plugin {\n const entryModulePath = options.entryModulePath ?? WIDGET_ENTRY_MODULE_PATH;\n const configModulePath =\n options.configModulePath ?? WIDGET_CONFIG_MODULE_PATH;\n const owner = options.owner ?? \"droplet\";\n\n return {\n name: \"fluid-widget-dev-routes\",\n apply: \"serve\",\n config: createWidgetDevServerConfig,\n configureServer(server) {\n server.middlewares.use(async (request, response, next): Promise<void> => {\n const pathname = (request.url ?? \"\").split(\"?\")[0] ?? \"\";\n\n if (\n pathname === \"/__runtime-entry__\" ||\n pathname === \"/__runtime-entry__/\"\n ) {\n if (handleOptions(request, response)) return;\n const origin = getRequestOrigin(request);\n sendJavaScript(\n request,\n response,\n buildRuntimeEntryBootstrapScript(\n entryModulePath,\n origin,\n await resolveWorkerSdkUrl(server, origin),\n ),\n );\n return;\n }\n\n if (\n pathname === \"/__widget-packages__\" ||\n pathname === \"/__widget-packages__/\"\n ) {\n await sendWidgetPackages(server, request, response, {\n configModulePath,\n owner,\n allowNoPackages: options.allowNoPackages === true,\n });\n return;\n }\n\n next();\n });\n },\n };\n}\n\n/**\n * Widget projects intentionally have no HTML entrypoint, so Vite cannot\n * discover the worker's dependency graph during its normal startup scan.\n * Without an explicit entry, the first live-preview request discovers and\n * optimizes the portal worker after the server reports ready. Vite reloads\n * the worker mid-mount, closing its message thread and stranding the preview\n * in a permanent error state.\n *\n * Pre-optimizing the worker entry makes the initial graph stable before a\n * preview can connect. Vite follows this entry's imports, so React and the\n * Remote DOM worker runtime are optimized in the same startup pass.\n */\nexport function createWidgetDevServerConfig(): UserConfig {\n return {\n optimizeDeps: {\n // The SDK worker entry drags the whole guard subgraph into this same\n // optimization pass, so naming `@fluid-app/widget-runtime/worker`\n // here adds nothing — and cannot work: see the resolve.dedupe note\n // below. Vite answers an unresolvable entry with \"Failed to resolve\n // dependency … present in optimizeDeps.include\" and pre-warms nothing.\n include: [\"@fluid-app/portal-sdk/widgets/worker\"],\n },\n resolve: {\n // One module instance per worker realm (INV-1): a second copy of the\n // SDK worker subgraph gives the network guard two instances (the\n // MIST-PW-01 lockdown failure), and a second copy of react breaks\n // hooks. The Mist renderer dedupes on its side\n // (apps/mist-desktop/vite.renderer.config.ts); the worker's dev server\n // needs the same guarantee.\n //\n // Every entry MUST be resolvable from the project root, which is what\n // dedupe anchors resolution to. `@fluid-app/widget-runtime` is not: a\n // scaffolded widget project depends on it only through\n // `@fluid-app/portal-sdk`, and under pnpm's strict layout it exists\n // solely inside portal-sdk's private node_modules. Listing it made\n // Vite fail to resolve the package and took `/__widget-packages__`\n // down with \"Cannot find module '@fluid-app/widget-runtime/worker'\",\n // i.e. every preview reported \"Widget package failed validation\".\n // Deduping portal-sdk covers the same subgraph, since the guard ships\n // inside its worker entry.\n dedupe: [\"@fluid-app/portal-sdk\", \"react\", \"react-dom\"],\n },\n ssr: {\n // `/__widget-packages__` reads the package source with `ssrLoadModule`.\n // Left external, Vite hands `@fluid-app/portal-sdk` to Node, which loads\n // its TypeScript source directly — and that source uses extensionless\n // relative imports, legal for a bundler and fatal under Node ESM:\n //\n // Cannot find module .../remote/worker/widget-package\n // imported from .../widgets/worker.ts\n //\n // The file is present; Node just will not resolve it without the\n // extension. `noExternal` keeps the SDK inside Vite's graph, where\n // extensionless resolution works.\n //\n // The standalone widget template sets this in its own vite.config. It\n // lives here as well so any host of these routes gets it — a portal\n // project has no reason to know that serving widget descriptors imposes\n // an SSR requirement, and existing portals cannot be retro-edited.\n noExternal: [\"@fluid-app/portal-sdk\"],\n },\n };\n}\n\n/** Source-relative path of a widget project's entry module. The dev\n * scaffold always places it here (see the widget template) — this is\n * the one thing the bootstrap script below needs from the plugin\n * that isn't itself part of the race/preamble fix. */\nconst WIDGET_ENTRY_MODULE_PATH = \"/src/index.ts\";\n\n/** Source-relative path of a standalone widget project's package source. */\nconst WIDGET_CONFIG_MODULE_PATH = \"/fluid.widget.config.ts\";\n\n/** Bare specifier of the SDK worker module the bootstrap prepares. */\nconst WORKER_SDK_SPECIFIER = \"@fluid-app/portal-sdk/widgets/worker\";\n\n/**\n * Resolves the bootstrap's SDK worker import to the same module URL the\n * widget entry's rewritten bare import uses.\n *\n * The bootstrap used to import the hardcoded alias\n * `/@id/@fluid-app/portal-sdk/widgets/worker`. Vite serves the optimized\n * module body inline at that URL while the entry's rewritten import uses the\n * canonical `/node_modules/.vite/deps/...?v=<hash>` URL — same bytes, two\n * resolved URLs, two records in the worker's ES module map. The network\n * guard's re-entry check is module-instance-local, so the second evaluation\n * threw on every dev preview load (MIST-PW-01). Resolving server-side at\n * request time keeps both imports on one module record.\n *\n * Falls back to the `/@id/` alias when resolution fails — no worse than the\n * previous behavior, and the widget-runtime duplicate-install tripwire names\n * the condition if the split ever regresses.\n */\nexport async function resolveWorkerSdkUrl(\n server: ViteDevServer,\n origin: string,\n): Promise<string> {\n const fallback = new URL(`/@id/${WORKER_SDK_SPECIFIER}`, origin).toString();\n try {\n const resolved = await server.pluginContainer.resolveId(\n WORKER_SDK_SPECIFIER,\n undefined,\n { ssr: false },\n );\n if (!resolved?.id) return fallback;\n const url = moduleIdToUrl(resolved.id, server.config.root);\n return url ? new URL(url, origin).toString() : fallback;\n } catch {\n return fallback;\n }\n}\n\n/**\n * Mirrors Vite import-analysis URL normalization for the id shapes the\n * resolver produces here: a file under the served root (the optimized-deps\n * dir lives at `<root>/node_modules/.vite`) becomes a root-relative URL; any\n * other absolute file path is served through `/@fs/`. Ids and root arrive\n * posix-normalized from Vite, Windows drive letters included.\n */\nfunction moduleIdToUrl(id: string, root: string): string | undefined {\n const rootPrefix = root.endsWith(\"/\") ? root : `${root}/`;\n if (id.startsWith(rootPrefix)) return `/${id.slice(rootPrefix.length)}`;\n if (id.startsWith(\"/\") || /^[A-Za-z]:\\//.test(id))\n return `/@fs/${id.replace(/^\\//, \"\")}`;\n return undefined;\n}\n\n/**\n * Builds the `/__runtime-entry__` worker bootstrap. Runtime-verified\n * against a real widget dev server + `@fluid-app/widget-runtime` host\n * in a Playwright harness (styled Leaderboard widget rendering,\n * mutation records flowing, `mounted.ready` resolving) — every piece\n * below exists to fix something that reproduced in that harness:\n *\n * 1. **Message-buffer race (the silent-mount killer).** The host\n * (widget-runtime) posts the \"mount\" message immediately after\n * `new Worker(...)`. A production-built worker bundle evaluates\n * synchronously and never races that message. In dev, though, the\n * worker's module graph loads asynchronously over many HTTP\n * requests (this bootstrap script, then the entry module, then\n * everything it imports, each a separate fetch) — so the \"mount\"\n * message can be dispatched and consumed by the Worker's default\n * (listener-less) handling before the widget entry's own\n * `message` listener, wired up deep inside the awaited import\n * below, is ever attached. The message is dropped silently, with\n * no error anywhere — the old `void import(\"/src/index.ts\")` also\n * swallowed the import's own rejections, compounding the silence.\n * Traced live: host→worker \"mount\" posts, zero worker→host replies\n * until this buffer-and-replay was added; after it, mutation\n * records flow and `mounted.ready` resolves. Fix: buffer every\n * message from the instant the worker boots (before anything else\n * runs), then replay the buffer, in order, once the entry module\n * has finished importing and has had the chance to attach its\n * real listener.\n * 2. **React-refresh preamble.** `@vitejs/plugin-react` injects a\n * preamble into every dev-transformed `.tsx` module referencing\n * `window.$RefreshReg$` / `$RefreshSig$`. A Worker global scope has\n * no `window` and no preamble, so importing a react-based widget\n * entry throws `window is not defined`, and — once `window` is\n * aliased to `globalThis` — throws again on the bare\n * `$RefreshSig$` alias. Installing the canonical preamble\n * (`RefreshRuntime.injectIntoGlobalHook` + no-op `$RefreshReg$` /\n * `$RefreshSig$`) before the entry import fixes both. The\n * `window = globalThis` alias was checked against widget-runtime's\n * worker lockdown / scope detection (which is\n * `globalThis.postMessage`-based) — no conflict. `/@react-refresh`\n * is `@vitejs/plugin-react`'s stable virtual module id, but a\n * widget project isn't guaranteed to use the react plugin, so the\n * whole block is try/catch-guarded — a project with no\n * `/@react-refresh` module (no react plugin) boots straight\n * through to the entry import unaffected.\n * 3. **`await import`, not `void import`.** A genuine failure to\n * import the entry module (syntax error, missing dependency, …)\n * must reject the worker's module evaluation loudly, not vanish\n * the way a fire-and-forget `void import` did.\n * 4. **Absolute dev-server imports.** Mist and portal previews load the\n * worker from another origin, so the host wraps this entry in a blob URL.\n * Root-relative specifiers inside a blob module resolve against the host\n * page (or fail to resolve at all), not this Vite server. Anchoring both\n * imports to the request origin keeps the entire dev module graph on the\n * widget server.\n *\n * Callers obtain `workerSdkUrl` from `resolveWorkerSdkUrl`, which owns the\n * `/@id/` fallback. The parameter is deliberately required: defaulting to the\n * alias here would let a caller silently reintroduce the two-module-record\n * split of MIST-PW-01.\n *\n * Dev-only: this only ever serves from `configureServer` (the\n * plugin's `apply: \"serve\"` gate), never a built/published package.\n */\nexport function buildRuntimeEntryBootstrapScript(\n entryPath: string,\n origin: string,\n workerSdkUrl: string,\n): string {\n const refreshRuntimeUrl = new URL(\"/@react-refresh\", origin).toString();\n const entryUrl = new URL(entryPath, origin).toString();\n\n return [\n \"// Dev-only worker bootstrap — see buildRuntimeEntryBootstrapScript\",\n \"// in packages/cli/widget-tooling/src/dev-routes.ts for why each piece\",\n \"// here exists (message-buffer race, react-refresh preamble,\",\n \"// await-not-void import).\",\n \"const __q = [];\",\n \"const __buf = (e) => { __q.push(e.data); };\",\n 'self.addEventListener(\"message\", __buf);',\n 'if (typeof window === \"undefined\") { globalThis.window = globalThis; }',\n `const { prepareRemoteDomWidgetWorker } = await import(${JSON.stringify(workerSdkUrl)});`,\n \"prepareRemoteDomWidgetWorker();\",\n \"try {\",\n ` const { default: RefreshRuntime } = await import(${JSON.stringify(refreshRuntimeUrl)});`,\n \" RefreshRuntime.injectIntoGlobalHook(window);\",\n \" window.$RefreshReg$ = () => {};\",\n \" window.$RefreshSig$ = () => (type) => type;\",\n \" window.__vite_plugin_react_preamble_installed__ = true;\",\n \"} catch {\",\n \" // No @vitejs/plugin-react in this widget project (no\",\n \" // /@react-refresh virtual module) — nothing to preinstall.\",\n \"}\",\n `await import(${JSON.stringify(entryUrl)});`,\n 'self.removeEventListener(\"message\", __buf);',\n \"for (const data of __q) {\",\n ' self.dispatchEvent(new MessageEvent(\"message\", { data }));',\n \"}\",\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * The shared development descriptor workflow appends Vite's `?direct` query\n * to CSS URLs so preview hosts receive real CSS instead of JS style modules.\n * Published descriptors use a separate build path and never receive it.\n */\nexport function createDevWidgetPackageDescriptors(\n configModule: Readonly<Record<string, unknown>>,\n origin: string,\n owner: WidgetPackageOwnerKind = \"droplet\",\n): readonly RemoteDomWidgetPackageDescriptor[] {\n return [\n createWidgetPackageDevelopmentDescriptor({\n sourceModule: configModule,\n owner,\n origin,\n workerEntryPath: \"/__runtime-entry__\",\n defaultCssPath: \"/styles.css\",\n }),\n ];\n}\n\n/**\n * True when validation failed *only* because the project declares no widget\n * package. Checked against the typed diagnostics rather than message text, and\n * deliberately narrow: a config that declares a package and gets it wrong must\n * still be reported.\n */\nfunction isNoSourcePackageError(error: unknown): boolean {\n if (!(error instanceof WidgetToolingError)) return false;\n const diagnostics = error.diagnostics ?? [];\n return (\n diagnostics.length > 0 &&\n diagnostics.every((diagnostic) => diagnostic.code === \"NO_SOURCE_PACKAGE\")\n );\n}\n\nasync function sendWidgetPackages(\n server: ViteDevServer,\n request: IncomingMessage,\n response: ServerResponse,\n options: {\n readonly configModulePath: string;\n readonly owner: WidgetPackageOwnerKind;\n readonly allowNoPackages: boolean;\n },\n): Promise<void> {\n if (handleOptions(request, response)) return;\n\n try {\n const configModule = (await server.ssrLoadModule(\n options.configModulePath,\n )) as Record<string, unknown>;\n sendJson(\n response,\n createDevWidgetPackageDescriptors(\n configModule,\n getRequestOrigin(request),\n options.owner,\n ),\n );\n } catch (error) {\n // \"This project declares no widget package\" is an expected state for a\n // portal that has not been given a custom widget yet — serve an empty\n // catalog so the preview falls back to built-in widgets. Every other\n // failure (a broken config, a bad manifest) still surfaces loudly.\n if (options.allowNoPackages && isNoSourcePackageError(error)) {\n sendJson(response, []);\n return;\n }\n server.config.logger.error(\n `[fluid] Failed to load widget packages: ${String(error)}`,\n );\n sendJson(response, { error: String(error) }, 500);\n }\n}\n\nfunction sendJavaScript(\n request: IncomingMessage,\n response: ServerResponse,\n source: string,\n): void {\n if (handleOptions(request, response)) return;\n setCorsHeaders(response);\n response.setHeader(\"Content-Type\", \"text/javascript\");\n response.statusCode = 200;\n response.end(source);\n}\n\nfunction sendJson(\n response: ServerResponse,\n body: unknown,\n statusCode = 200,\n): void {\n setCorsHeaders(response);\n response.setHeader(\"Content-Type\", \"application/json\");\n response.statusCode = statusCode;\n response.end(JSON.stringify(body, null, 2));\n}\n\nexport function handleOptions(\n request: IncomingMessage,\n response: ServerResponse,\n): boolean {\n if (request.method !== \"OPTIONS\") return false;\n setCorsHeaders(response);\n response.statusCode = 204;\n response.end();\n return true;\n}\n\nexport function setCorsHeaders(response: ServerResponse): void {\n response.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n response.setHeader(\"Access-Control-Allow-Methods\", \"GET, HEAD, OPTIONS\");\n response.setHeader(\n \"Access-Control-Allow-Headers\",\n \"Content-Type, Authorization\",\n );\n}\n\nfunction getRequestOrigin(request: IncomingMessage): string {\n const host = readHeader(request.headers.host);\n if (!host) throw new Error(\"Widget dev request is missing the Host header.\");\n\n const forwardedProtocol = readHeader(request.headers[\"x-forwarded-proto\"]);\n const protocol = forwardedProtocol === \"https\" ? \"https\" : \"http\";\n return `${protocol}://${host}`;\n}\n\nfunction readHeader(\n value: string | readonly string[] | undefined,\n): string | undefined {\n const candidate = Array.isArray(value) ? value[0] : value;\n return typeof candidate === \"string\" && candidate.trim().length > 0\n ? candidate.trim()\n : undefined;\n}\n","/**\n * How this package runs the helper scripts it generates.\n *\n * Building a widget package writes two scripts to disk and runs them: a config\n * extractor (under `tsx`) and a Vite build. Both used to assume the same thing —\n * that `process.execPath` is Node and that `tsx` is resolvable from this\n * module. Both assumptions hold for a CLI and neither holds in an Electron main\n * process, where `process.execPath` is the Electron binary. Spawning it without\n * `ELECTRON_RUN_AS_NODE` starts a second copy of the app instead of running the\n * script, and `tsx` is not in a packaged app's dependency closure at all.\n *\n * So the host says how to run a script rather than this package guessing. The\n * default reproduces the old behaviour exactly, which is why both CLIs are\n * unchanged by this.\n */\n\nimport { createRequire } from \"node:module\";\n\nexport interface WidgetToolingNodeRuntime {\n /**\n * Executable that runs a Node script.\n *\n * Defaults to `process.execPath`. An Electron host passes its resolved system\n * Node, or its own binary together with `ELECTRON_RUN_AS_NODE` in `env`.\n */\n readonly execPath?: string;\n /**\n * Extra environment for spawned scripts — the place `ELECTRON_RUN_AS_NODE: \"1\"`\n * goes when `execPath` is an Electron binary.\n */\n readonly env?: Readonly<Record<string, string>>;\n /**\n * Absolute path to `tsx`'s CLI entry.\n *\n * Injectable because a host that bundles this package cannot necessarily\n * resolve `tsx` from here — it is a dependency of this package, not of the\n * app that embedded it.\n */\n readonly tsxCliPath?: string;\n}\n\n/** The executable to spawn, and the env to spawn it with. */\nexport function resolveSpawnTarget(runtime?: WidgetToolingNodeRuntime): {\n readonly execPath: string;\n readonly env: Readonly<Record<string, string>>;\n} {\n return {\n execPath: runtime?.execPath ?? process.execPath,\n env: runtime?.env ?? {},\n };\n}\n\n/**\n * Resolves `tsx`'s CLI, preferring an injected path.\n *\n * Deliberately a function rather than a module-scope constant. It used to be\n * `const TSX_CLI_PATH = require.resolve(\"tsx/cli\")`, which runs on IMPORT — so a\n * host that merely imported this package, and never published anything, crashed\n * at startup if `tsx` was absent. Resolving on use means a missing `tsx` is a\n * publish-time error the caller can report, not a boot failure.\n */\nexport function resolveTsxCliPath(runtime?: WidgetToolingNodeRuntime): string {\n if (runtime?.tsxCliPath) return runtime.tsxCliPath;\n const require = createRequire(import.meta.url);\n return require.resolve(\"tsx/cli\");\n}\n","import { execa } from \"execa\";\nimport fs from \"fs-extra\";\nimport path from \"node:path\";\nimport { type Result, success, failure } from \"@fluid-app/fluid-cli\";\nimport {\n resolveSpawnTarget,\n resolveTsxCliPath,\n type WidgetToolingNodeRuntime,\n} from \"../node-runtime.js\";\n\nconst WIDGET_CONFIG_PATH = \"src/widgets.config.ts\";\n/** Long enough for a cold tsx start on a slow machine, short enough to fail. */\nconst CONFIG_EVAL_TIMEOUT_MS = 60_000;\nconst SOURCE_PACKAGE_EXTRACT_FILENAME = \"extract-widget-packages.ts\";\nconst SOURCE_PACKAGE_OUTPUT_FILENAME = \"source-widget-packages.json\";\nconst SOURCE_PACKAGE_OUTPUT_SENTINEL = \"fluid-widget-source-packages:v1\";\n\nexport interface WidgetSourceConfig {\n readonly path: string;\n readonly relativePath: string;\n}\n\nexport interface WidgetSourceConfigLoadError {\n readonly code: \"CONFIG_LOAD_FAILED\" | \"INVALID_FORMAT\";\n readonly message: string;\n readonly details?: string;\n}\n\nexport async function resolvePortalWidgetSourceConfig(\n projectDir: string,\n): Promise<WidgetSourceConfig | undefined> {\n const candidate = path.join(projectDir, WIDGET_CONFIG_PATH);\n return (await fs.pathExists(candidate))\n ? { path: candidate, relativePath: WIDGET_CONFIG_PATH }\n : undefined;\n}\n\nexport async function loadSourceWidgetPackages(\n projectDir: string,\n nodeRuntime?: WidgetToolingNodeRuntime,\n): Promise<Result<unknown[], WidgetSourceConfigLoadError>> {\n const config = await resolvePortalWidgetSourceConfig(projectDir);\n if (!config) return success([]);\n\n let tempDir: string | undefined;\n\n try {\n tempDir = await createTempDirectory(projectDir);\n const extractFile = path.join(tempDir, SOURCE_PACKAGE_EXTRACT_FILENAME);\n const outputFile = path.join(tempDir, SOURCE_PACKAGE_OUTPUT_FILENAME);\n\n await fs.writeFile(\n extractFile,\n createSourcePackageExtractorScript({\n projectDir,\n configPath: config.path,\n }),\n { encoding: \"utf-8\", flag: \"wx\" },\n );\n\n const spawn = resolveSpawnTarget(nodeRuntime);\n await execa(\n spawn.execPath,\n [resolveTsxCliPath(nodeRuntime), extractFile, outputFile],\n {\n cwd: projectDir,\n stdio: \"pipe\",\n env: {\n ...process.env,\n ...spawn.env,\n NODE_ENV: \"production\",\n },\n // `widgets.config.ts` is project code: it is imported and evaluated\n // here, so anything it does at module scope — an await that never\n // settles, a server it starts — runs with no deadline of its own. A\n // caller that awaits this inside a publish would wait forever, and the\n // publish path this feeds serializes on it, so one bad config would\n // wedge publishing for the whole app until it restarts.\n timeout: CONFIG_EVAL_TIMEOUT_MS,\n killSignal: \"SIGKILL\",\n },\n );\n\n const outputResult = await readSourcePackageExtractorOutput(outputFile);\n if (!outputResult.success) return outputResult;\n\n const parsed = outputResult.value;\n if (parsed.length === 0) return success([]);\n\n return success(parsed);\n } catch (err) {\n const error = err as { stderr?: string; message?: string };\n return failure({\n code: \"CONFIG_LOAD_FAILED\",\n message: `Failed to load widget packages from ${config.relativePath}`,\n details: error.stderr ?? error.message ?? String(err),\n });\n } finally {\n if (tempDir) await fs.remove(tempDir).catch(() => {});\n }\n}\n\nasync function createTempDirectory(projectDir: string): Promise<string> {\n const projectTmpDir = path.join(projectDir, \".fluid\", \"tmp\");\n try {\n await fs.ensureDir(projectTmpDir);\n return await fs.mkdtemp(path.join(projectTmpDir, \"widget-packages-\"));\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Unable to create project-local temporary directory at ${projectTmpDir}: ${message}`,\n );\n }\n}\n\nasync function readSourcePackageExtractorOutput(\n outputFile: string,\n): Promise<Result<unknown[], WidgetSourceConfigLoadError>> {\n let output: string;\n try {\n output = await fs.readFile(outputFile, \"utf-8\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return failure({\n code: \"CONFIG_LOAD_FAILED\",\n message: \"Widget package extractor did not write an output file\",\n details: message,\n });\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(output);\n } catch {\n return failure({\n code: \"INVALID_FORMAT\",\n message: \"Failed to parse widget package output file as JSON\",\n details: `Output was: ${output.slice(0, 200)}`,\n });\n }\n\n if (!isRecord(parsed) || parsed.sentinel !== SOURCE_PACKAGE_OUTPUT_SENTINEL) {\n return failure({\n code: \"INVALID_FORMAT\",\n message: \"Widget package extractor output file had an invalid sentinel\",\n });\n }\n\n if (!Array.isArray(parsed.data)) {\n return failure({\n code: \"INVALID_FORMAT\",\n message: \"Extracted widget package output is not an array\",\n details: `Expected an array, got: ${typeof parsed.data}`,\n });\n }\n\n return success(parsed.data);\n}\n\nfunction createSourcePackageExtractorScript(options: {\n readonly projectDir: string;\n readonly configPath: string;\n}): string {\n return `\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createServer, normalizePath } from \"vite\";\n\nconst SOURCE_PACKAGE_MARKER = \"__fluidSourceWidgetPackage\";\nconst OUTPUT_SENTINEL = ${JSON.stringify(SOURCE_PACKAGE_OUTPUT_SENTINEL)};\nconst projectRoot = ${JSON.stringify(options.projectDir)};\nconst widgetConfigPath = ${JSON.stringify(options.configPath)};\nconst outputPath = process.argv[2];\nif (!outputPath) throw new Error(\"Missing widget package extractor output path.\");\n\nfunction toViteModuleId(modulePath) {\n const relativePath = path.relative(projectRoot, modulePath);\n if (!relativePath.startsWith(\"..\") && !path.isAbsolute(relativePath)) {\n return \"/\" + normalizePath(relativePath);\n }\n return normalizePath(modulePath);\n}\n\nconst server = await createServer({\n root: projectRoot,\n mode: \"production\",\n server: { middlewareMode: true },\n appType: \"custom\",\n logLevel: \"error\",\n clearScreen: false,\n resolve: {\n conditions: [\"module\", \"browser\", \"development|production\"],\n },\n ssr: {\n noExternal: [\"@fluid-app/portal-sdk\"],\n resolve: {\n conditions: [\"module\", \"node\", \"development|production\"],\n },\n },\n});\n\ntry {\n const widgetConfig = await server.ssrLoadModule(toViteModuleId(widgetConfigPath));\n\n function isSourceWidgetPackage(value) {\n return Boolean(value && typeof value === \"object\" && value[SOURCE_PACKAGE_MARKER] === true);\n }\n\n function collectSourceWidgetPackages(mod) {\n const candidates = [\n mod.widgetPackage,\n ...(Array.isArray(mod.widgetPackages) ? mod.widgetPackages : []),\n mod.default,\n ];\n const byPackageId = new Map();\n for (const candidate of candidates) {\n if (!isSourceWidgetPackage(candidate)) continue;\n if (!byPackageId.has(candidate.packageId)) byPackageId.set(candidate.packageId, candidate);\n }\n return Array.from(byPackageId.values());\n }\n\n function serializeWidget(widget) {\n if (!widget || typeof widget !== \"object\" || Array.isArray(widget)) {\n return widget;\n }\n const { component, ...metadata } = widget;\n return metadata;\n }\n\n function serializePackage(sourcePackage) {\n return {\n manifestVersion: sourcePackage.manifestVersion,\n scope: sourcePackage.scope,\n packageStableId: sourcePackage.packageStableId,\n packageId: sourcePackage.packageId,\n packageType: sourcePackage.packageType,\n version: sourcePackage.version,\n cssUrls: sourcePackage.cssUrls,\n ...(Object.prototype.hasOwnProperty.call(sourcePackage, \"navigationOrigins\")\n ? { navigationOrigins: sourcePackage.navigationOrigins }\n : {}),\n widgets: Array.isArray(sourcePackage.widgets)\n ? sourcePackage.widgets.map(serializeWidget)\n : sourcePackage.widgets,\n };\n }\n\n await fs.writeFile(\n outputPath,\n JSON.stringify({\n sentinel: OUTPUT_SENTINEL,\n data: collectSourceWidgetPackages(widgetConfig).map(serializePackage),\n }),\n \"utf-8\",\n );\n} finally {\n await server.close();\n}\n`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { execa } from \"execa\";\nimport {\n resolveSpawnTarget,\n type WidgetToolingNodeRuntime,\n} from \"../node-runtime.js\";\nimport fs from \"fs-extra\";\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { pathToFileURL } from \"node:url\";\nimport { type Result, success, failure } from \"@fluid-app/fluid-cli\";\nimport {\n loadSourceWidgetPackages,\n resolvePortalWidgetSourceConfig,\n} from \"./widget-package-config.js\";\nimport {\n buildWidgetPackagePublishManifest,\n validateSingleSourceWidgetPackage,\n type ValidatedWidgetPackageBuild,\n type WidgetPackageOwnerKind,\n} from \"./widget-package-validation.js\";\nimport {\n collectWidgetPackageArtifacts,\n createPublishManifestMetadata,\n isWidgetPackageCssArtifactPath,\n} from \"./widget-package-artifacts.js\";\n\nconst DEFAULT_PUBLISH_DIR = \".fluid/widget-dist\";\nconst DEFAULT_RUNTIME_VERSION = \"1\";\nconst TEMP_BUILD_DIR = \".fluid/widget-build\";\nconst TEMP_CLI_DIR = \".fluid/tmp\";\nconst PROJECT_VITE_CONFIG_CANDIDATES = [\n \"vite.config.ts\",\n \"vite.config.mts\",\n \"vite.config.js\",\n \"vite.config.mjs\",\n] as const;\nconst BLOCKED_FLUID_PROJECT_PLUGIN_NAMES = [\n \"fluid-portal-dev\",\n \"fluid-backend-dev\",\n] as const;\nconst require = createRequire(import.meta.url);\n\nexport interface BuildSharedWidgetPackageOptions {\n readonly projectDir: string;\n readonly publishDir?: string;\n readonly owner?: WidgetPackageOwnerKind;\n readonly cliVersion: string;\n /** How to run the generated helper scripts — see WidgetToolingNodeRuntime. */\n readonly nodeRuntime?: WidgetToolingNodeRuntime;\n /**\n * Stamp this version into the manifests instead of the config's.\n *\n * A company has ONE widget package that several projects publish into, so the\n * version is really a property of that shared package — not of any single\n * project's source file. Two projects both declaring \"0.5.0\" is not a\n * mistake either of them can see, and the server refuses the second one.\n * The caller resolves the version against what is actually published; this\n * is where that answer lands.\n */\n readonly versionOverride?: string;\n}\n\nexport interface SharedWidgetPackageBuildResult {\n readonly publishDir: string;\n readonly packageId: string;\n readonly version: string;\n readonly manifestPath: string;\n readonly publishManifestPath: string;\n readonly widgetScriptPath: string;\n}\n\nexport interface SharedWidgetPackageBuildError {\n readonly code:\n | \"CONFIG_LOAD_FAILED\"\n | \"VALIDATION_FAILED\"\n | \"INVALID_PUBLISH_DIR\"\n | \"WRITE_FAILED\";\n readonly message: string;\n readonly details?: string;\n}\n\nexport interface ValidateSharedWidgetPackagePublishDirOptions {\n readonly optionName?: string;\n}\n\nexport function validateSharedWidgetPackagePublishDir(\n projectDir: string,\n publishDir: string = DEFAULT_PUBLISH_DIR,\n options: ValidateSharedWidgetPackagePublishDirOptions = {},\n): void {\n const label = options.optionName ?? \"publishDir\";\n\n if (path.isAbsolute(publishDir)) {\n throw new Error(`${label} must be relative to the project directory.`);\n }\n\n const normalizedPublishDir = normalizePublishDirForValidation(publishDir);\n if (\n normalizedPublishDir === \".fluid\" ||\n !normalizedPublishDir.startsWith(\".fluid/\")\n ) {\n throw new Error(`${label} must be a relative path under .fluid/.`);\n }\n\n if (isPathWithinReservedDir(normalizedPublishDir, TEMP_BUILD_DIR)) {\n throw new Error(\n `${label} must not be ${TEMP_BUILD_DIR} because it is reserved for temporary builder output.`,\n );\n }\n\n if (isPathWithinReservedDir(normalizedPublishDir, TEMP_CLI_DIR)) {\n throw new Error(\n `${label} must not be ${TEMP_CLI_DIR} because it is reserved for Fluid CLI temporary files.`,\n );\n }\n\n const resolvedProjectDir = path.resolve(projectDir);\n const resolvedPublishDir = path.resolve(resolvedProjectDir, publishDir);\n const relative = path.relative(resolvedProjectDir, resolvedPublishDir);\n\n if (\n relative === \"\" ||\n relative.startsWith(\"..\") ||\n path.isAbsolute(relative)\n ) {\n throw new Error(`${label} must stay inside the project directory.`);\n }\n}\n\n/**\n * Restamps each loaded source package with `version`.\n *\n * Object spread carries own enumerable SYMBOL keys as well as string ones,\n * which matters here: `defineWidgetPackage` marks its result with a symbol that\n * validation uses to recognise a real source package. A copy that dropped it\n * would fail validation with a message about a missing package rather than\n * about the version.\n */\nfunction withVersionOverride(\n sourcePackages: readonly unknown[],\n version: string,\n): readonly unknown[] {\n return sourcePackages.map((sourcePackage) =>\n typeof sourcePackage === \"object\" && sourcePackage !== null\n ? { ...sourcePackage, version }\n : sourcePackage,\n );\n}\n\nexport async function buildSharedWidgetPackage(\n options: BuildSharedWidgetPackageOptions,\n): Promise<\n Result<SharedWidgetPackageBuildResult, SharedWidgetPackageBuildError>\n> {\n const publishDirInput = options.publishDir ?? DEFAULT_PUBLISH_DIR;\n try {\n await validateWidgetPackageOutputPaths(options.projectDir, publishDirInput);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n return failure({\n code: \"INVALID_PUBLISH_DIR\",\n message: \"Unsafe widget package publish directory\",\n details: error.message,\n });\n }\n\n const sourcePackageResult = await loadSourceWidgetPackages(\n options.projectDir,\n options.nodeRuntime,\n );\n if (!sourcePackageResult.success) {\n return failure({\n code: \"CONFIG_LOAD_FAILED\",\n message: sourcePackageResult.error.message,\n details: sourcePackageResult.error.details,\n });\n }\n\n // Applied BEFORE validation, so an overridden version is held to exactly the\n // same SemVer rules as one written in the config — the override is not a way\n // to smuggle an unpublishable version past the checks.\n const sourcePackages = options.versionOverride\n ? withVersionOverride(sourcePackageResult.value, options.versionOverride)\n : sourcePackageResult.value;\n\n const validation = validateSingleSourceWidgetPackage(sourcePackages, {\n owner: options.owner,\n });\n if (!validation.success || !validation.value) {\n return failure({\n code: \"VALIDATION_FAILED\",\n message: validation.errors.map((error) => error.message).join(\"\\n\"),\n });\n }\n\n try {\n await validateWidgetPackageOutputPaths(options.projectDir, publishDirInput);\n\n const publishDir = path.resolve(options.projectDir, publishDirInput);\n const widgetScriptPath = path.join(publishDir, \"widget.js\");\n await fs.emptyDir(publishDir);\n\n const tempDir = path.resolve(options.projectDir, TEMP_BUILD_DIR);\n await fs.emptyDir(tempDir);\n let buildFailure: { readonly error: unknown } | undefined;\n try {\n await buildWidgetScriptBundle({\n projectDir: options.projectDir,\n tempDir,\n publishDir,\n validated: validation.value,\n ...(options.nodeRuntime ? { nodeRuntime: options.nodeRuntime } : {}),\n });\n } catch (error) {\n buildFailure = { error };\n }\n\n try {\n await fs.remove(tempDir);\n } catch {\n const cleanupFailure = new Error(\n \"Failed to remove reserved temporary build directory.\",\n );\n if (buildFailure) {\n const primaryError =\n buildFailure.error instanceof Error\n ? buildFailure.error\n : new Error(String(buildFailure.error));\n throw new AggregateError(\n [primaryError, cleanupFailure],\n `${primaryError.message}\\n${cleanupFailure.message}`,\n );\n }\n throw cleanupFailure;\n }\n\n if (buildFailure) {\n throw buildFailure.error;\n }\n\n const cssUrls = await collectCssUrls(publishDir);\n const descriptor = buildWidgetPackagePublishManifest(validation.value, {\n cssUrls,\n });\n const manifestContent = stableStringify(descriptor);\n const publishPackageId = descriptor.packageId;\n\n const manifestPath = path.join(publishDir, \"manifest.json\");\n const publishManifestPath = path.join(publishDir, \"publish-manifest.json\");\n\n await fs.writeFile(manifestPath, manifestContent, \"utf-8\");\n\n const artifacts = await collectWidgetPackageArtifacts(publishDir);\n const publishManifest = createPublishManifestMetadata({\n packageId: publishPackageId,\n version: validation.value.version,\n cliVersion: options.cliVersion,\n runtimeVersion: DEFAULT_RUNTIME_VERSION,\n manifestContent,\n artifacts,\n });\n await fs.writeFile(\n publishManifestPath,\n stableStringify(publishManifest),\n \"utf-8\",\n );\n\n return success({\n publishDir,\n packageId: validation.value.packageId,\n version: validation.value.version,\n manifestPath,\n publishManifestPath,\n widgetScriptPath,\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n const isPublishDirValidationError =\n /^(publishDir|reserved temporary build directory) /.test(error.message);\n return failure({\n code: isPublishDirValidationError\n ? \"INVALID_PUBLISH_DIR\"\n : \"WRITE_FAILED\",\n message: isPublishDirValidationError\n ? \"Unsafe widget package publish directory\"\n : \"Failed to build shared widget package artifacts\",\n details: error.message,\n });\n }\n}\n\nexport function createWidgetPackageEntrySource(options: {\n readonly configImportPath: string;\n readonly cssImportPath?: string;\n readonly validated: ValidatedWidgetPackageBuild;\n}): string {\n return `import { createElement } from \"react\";\nimport { prepareRemoteDomWidgetWorker, startWidgetPackage } from \"@fluid-app/portal-sdk/widgets/worker\";\n${options.cssImportPath ? `import ${JSON.stringify(options.cssImportPath)};` : \"\"}\n\nprepareRemoteDomWidgetWorker();\nconst widgetConfig = await import(${JSON.stringify(options.configImportPath)});\nconst SOURCE_PACKAGE_MARKER = \"__fluidSourceWidgetPackage\";\nconst descriptors = ${JSON.stringify(options.validated.widgets, null, 2)};\n\nfunction isSourceWidgetPackage(value) {\n return Boolean(value && typeof value === \"object\" && value[SOURCE_PACKAGE_MARKER] === true);\n}\n\nfunction collectSourceWidgetPackages(mod) {\n return [\n mod.widgetPackage,\n ...(Array.isArray(mod.widgetPackages) ? mod.widgetPackages : []),\n mod.default,\n ].filter(isSourceWidgetPackage);\n}\n\nconst sourcePackage = collectSourceWidgetPackages(widgetConfig)[0];\nif (!sourcePackage) {\n throw new Error(\"No Fluid source widget package found while loading widget package worker bundle.\");\n}\n\nconst componentsByName = new Map(\n sourcePackage.widgets.map((widget) => [widget.name, widget.component]),\n);\n\nconst widgets = descriptors.map((descriptor) => {\n const component = componentsByName.get(descriptor.name);\n if (typeof component !== \"function\") {\n throw new Error(\"Widget package is missing Remote DOM component for \" + descriptor.name + \".\");\n }\n return {\n ...descriptor,\n component: (props) => createElement(component, props),\n };\n});\n\nstartWidgetPackage({ widgets });\n`;\n}\n\nasync function buildWidgetScriptBundle(options: {\n readonly projectDir: string;\n readonly tempDir: string;\n readonly publishDir: string;\n readonly validated: ValidatedWidgetPackageBuild;\n readonly nodeRuntime?: WidgetToolingNodeRuntime;\n}): Promise<void> {\n const sourceConfig = await resolvePortalWidgetSourceConfig(\n options.projectDir,\n );\n if (!sourceConfig) {\n throw new Error(\"No portal widget source config found.\");\n }\n\n const entryPath = path.join(options.tempDir, \"widget-entry.ts\");\n const viteConfigPath = path.join(options.tempDir, \"vite.config.mjs\");\n const rootStylesPath = path.join(options.projectDir, \"styles.css\");\n await fs.writeFile(\n entryPath,\n createWidgetPackageEntrySource({\n configImportPath: pathToFileURL(sourceConfig.path).href,\n cssImportPath: (await fs.pathExists(rootStylesPath))\n ? pathToFileURL(rootStylesPath).href\n : undefined,\n validated: options.validated,\n }),\n \"utf-8\",\n );\n await fs.writeFile(\n viteConfigPath,\n createViteConfigSource({\n entryPath,\n publishDir: options.publishDir,\n projectConfigPath: await resolveProjectViteConfigPath(options.projectDir),\n }),\n \"utf-8\",\n );\n\n const viteCliPath = resolveViteCliPath(options.projectDir);\n const spawn = resolveSpawnTarget(options.nodeRuntime);\n await execa(\n spawn.execPath,\n [viteCliPath, \"build\", \"--config\", viteConfigPath],\n {\n cwd: options.projectDir,\n stdio: \"pipe\",\n env: {\n ...process.env,\n ...spawn.env,\n NODE_ENV: \"production\",\n },\n },\n );\n}\n\nexport function resolveViteCliPath(projectDir: string): string {\n const projectRequire = createRequire(path.join(projectDir, \"package.json\"));\n const projectViteCliPath = resolveViteCliPathFromRequire(projectRequire);\n if (projectViteCliPath) return projectViteCliPath;\n\n const cliViteCliPath = resolveViteCliPathFromRequire(require);\n if (cliViteCliPath) return cliViteCliPath;\n\n throw new Error(\n \"Unable to resolve Vite for the portal project. Install the project dependencies and ensure vite is available before building widget packages.\",\n );\n}\n\nexport async function resolveProjectViteConfigPath(\n projectDir: string,\n): Promise<string | undefined> {\n for (const fileName of PROJECT_VITE_CONFIG_CANDIDATES) {\n const candidate = path.join(projectDir, fileName);\n if (await fs.pathExists(candidate)) return candidate;\n }\n\n return undefined;\n}\n\nexport function createViteConfigSource(options: {\n readonly entryPath: string;\n readonly publishDir: string;\n readonly projectConfigPath?: string;\n}): string {\n const widgetConfigSource = createWidgetViteConfigObjectSource({\n ...options,\n disableConfigFileLookup: !options.projectConfigPath,\n });\n\n if (!options.projectConfigPath) {\n return `import { defineConfig } from \"vite\";\n\nexport default defineConfig(${widgetConfigSource});\n`;\n }\n\n return `import { defineConfig, loadConfigFromFile, mergeConfig } from \"vite\";\n\nconst projectConfigPath = ${JSON.stringify(options.projectConfigPath)};\nconst widgetConfig = ${widgetConfigSource};\nconst fluidWidgetDefineInvariants = {\n \"process.env.NODE_ENV\": JSON.stringify(\"production\"),\n};\nconst blockedFluidPluginNames = new Set(${JSON.stringify(BLOCKED_FLUID_PROJECT_PLUGIN_NAMES)});\n\nfunction isAllowedProjectPlugin(plugin) {\n return !plugin || typeof plugin !== \"object\" || !blockedFluidPluginNames.has(plugin.name);\n}\n\nfunction sanitizeProjectPlugins(pluginOption) {\n if (!Array.isArray(pluginOption)) {\n return isAllowedProjectPlugin(pluginOption) ? pluginOption : [];\n }\n\n return pluginOption\n .map((plugin) => Array.isArray(plugin) ? sanitizeProjectPlugins(plugin) : plugin)\n .filter(isAllowedProjectPlugin);\n}\n\nfunction copyProjectConfigValue(source, target, key) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n}\n\nfunction sanitizeProjectConfig(config) {\n if (!config || typeof config !== \"object\") return {};\n\n const sanitized = {};\n if (Object.prototype.hasOwnProperty.call(config, \"plugins\")) {\n sanitized.plugins = sanitizeProjectPlugins(config.plugins);\n }\n copyProjectConfigValue(config, sanitized, \"resolve\");\n copyProjectConfigValue(config, sanitized, \"define\");\n copyProjectConfigValue(config, sanitized, \"css\");\n copyProjectConfigValue(config, sanitized, \"esbuild\");\n copyProjectConfigValue(config, sanitized, \"json\");\n copyProjectConfigValue(config, sanitized, \"assetsInclude\");\n copyProjectConfigValue(config, sanitized, \"envDir\");\n copyProjectConfigValue(config, sanitized, \"envPrefix\");\n return sanitized;\n}\n\nfunction copyConfigDefineValue(value) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? { ...value }\n : {};\n}\n\nfunction mergeFluidWidgetDefineInvariants(mergedConfig, safeProjectConfig, widgetConfig) {\n mergedConfig.define = {\n ...copyConfigDefineValue(safeProjectConfig.define),\n ...copyConfigDefineValue(mergedConfig.define),\n ...copyConfigDefineValue(widgetConfig.define),\n ...fluidWidgetDefineInvariants,\n };\n return mergedConfig;\n}\n\nexport default defineConfig(async (configEnv) => {\n const projectConfig = await loadConfigFromFile(configEnv, projectConfigPath);\n const safeProjectConfig = sanitizeProjectConfig(projectConfig?.config ?? {});\n return mergeFluidWidgetDefineInvariants(mergeConfig(safeProjectConfig, widgetConfig), safeProjectConfig, widgetConfig);\n});\n`;\n}\n\nfunction createWidgetViteConfigObjectSource(options: {\n readonly entryPath: string;\n readonly publishDir: string;\n readonly disableConfigFileLookup: boolean;\n}): string {\n const configFileSource = options.disableConfigFileLookup\n ? \" configFile: false,\\n\"\n : \"\";\n return `(() => {\n const fluidWidgetDefineInvariants = {\n \"process.env.NODE_ENV\": JSON.stringify(\"production\"),\n };\n\n function createFluidWidgetBuildInvariants() {\n return {\n copyPublicDir: false,\n emptyOutDir: false,\n outDir: ${JSON.stringify(options.publishDir)},\n sourcemap: false,\n target: \"esnext\",\n cssCodeSplit: false,\n lib: {\n entry: ${JSON.stringify(options.entryPath)},\n formats: [\"es\"],\n fileName: () => \"widget.js\",\n cssFileName: \"widget\",\n },\n rollupOptions: {\n output: {\n inlineDynamicImports: true,\n hoistTransitiveImports: false,\n },\n },\n };\n }\n\n function fluidWidgetBuildInvariantsPlugin() {\n return {\n name: \"fluid-widget-build-invariants\",\n enforce: \"post\",\n config() {\n return { build: createFluidWidgetBuildInvariants() };\n },\n configResolved(config) {\n config.define = {\n ...(config.define ?? {}),\n ...fluidWidgetDefineInvariants,\n };\n Object.assign(config.build, createFluidWidgetBuildInvariants());\n },\n };\n }\n\n return {\n${configFileSource} publicDir: false,\n define: fluidWidgetDefineInvariants,\n resolve: {\n conditions: [\n \"module\",\n \"browser\",\n \"development|production\",\n ],\n },\n plugins: [fluidWidgetBuildInvariantsPlugin()],\n build: createFluidWidgetBuildInvariants(),\n };\n})()`;\n}\n\nasync function validateWidgetPackageOutputPaths(\n projectDir: string,\n publishDir: string,\n): Promise<void> {\n validateSharedWidgetPackagePublishDir(projectDir, publishDir);\n await rejectSymlinkedPathSegments({\n projectDir,\n relativePath: publishDir,\n label: \"publishDir\",\n });\n await rejectSymlinkedPathSegments({\n projectDir,\n relativePath: TEMP_BUILD_DIR,\n label: \"reserved temporary build directory\",\n });\n}\n\nasync function collectCssUrls(publishDir: string): Promise<string[]> {\n const entries = await fs.readdir(publishDir, { withFileTypes: true });\n return entries\n .filter(\n (entry) => entry.isFile() && isWidgetPackageCssArtifactPath(entry.name),\n )\n .map((entry) => entry.name)\n .sort();\n}\n\nasync function rejectSymlinkedPathSegments(options: {\n readonly projectDir: string;\n readonly relativePath: string;\n readonly label: string;\n}): Promise<void> {\n const resolvedProjectDir = path.resolve(options.projectDir);\n const resolvedTargetPath = path.resolve(\n resolvedProjectDir,\n options.relativePath,\n );\n const relative = path.relative(resolvedProjectDir, resolvedTargetPath);\n const segments = relative.split(path.sep).filter(Boolean);\n let currentPath = resolvedProjectDir;\n\n for (const segment of segments) {\n currentPath = path.join(currentPath, segment);\n let stat: fs.Stats;\n try {\n stat = await fs.lstat(currentPath);\n } catch (err) {\n if (isNodeError(err) && err.code === \"ENOENT\") return;\n throw err;\n }\n\n if (stat.isSymbolicLink()) {\n throw new Error(`${options.label} must not include symbolic links.`);\n }\n }\n}\n\nfunction normalizePublishDirForValidation(value: string): string {\n return toPosixPath(path.normalize(value)).replace(/\\/+$/, \"\") || \".\";\n}\n\nfunction isPathWithinReservedDir(value: string, reservedDir: string): boolean {\n return value === reservedDir || value.startsWith(`${reservedDir}/`);\n}\n\nfunction toPosixPath(value: string): string {\n return value.split(path.sep).join(\"/\");\n}\n\nfunction stableStringify(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nfunction resolveViteCliPathFromRequire(\n moduleRequire: NodeJS.Require,\n): string | undefined {\n try {\n const packageJsonPath = moduleRequire.resolve(\"vite/package.json\");\n const packageJson = moduleRequire(packageJsonPath) as { bin?: unknown };\n const binPath = getViteBinPath(packageJson.bin);\n if (!binPath) return undefined;\n\n return path.resolve(path.dirname(packageJsonPath), binPath);\n } catch (err) {\n if (isModuleResolutionError(err)) return undefined;\n throw err;\n }\n}\n\nfunction getViteBinPath(bin: unknown): string | undefined {\n if (typeof bin === \"string\") return bin;\n if (!isRecord(bin)) return undefined;\n\n const viteBin = bin.vite;\n return typeof viteBin === \"string\" ? viteBin : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeError(value: unknown): value is NodeJS.ErrnoException {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"code\" in value &&\n typeof value.code === \"string\"\n );\n}\n\nfunction isModuleResolutionError(value: unknown): boolean {\n return (\n isNodeError(value) &&\n (value.code === \"MODULE_NOT_FOUND\" || value.code === \"ERR_MODULE_NOT_FOUND\")\n );\n}\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\nimport {\n collectWidgetPackageArtifacts,\n computeArtifactMetadata,\n sha256,\n type ArtifactMetadata,\n type PublishManifestMetadata,\n} from \"./widget-package-artifacts.js\";\nimport type { WidgetPackagePublishRequest } from \"./widget-package-upload.js\";\nimport type { WidgetPackageOwnerKind } from \"./widget-package-validation.js\";\n\nexport async function createWidgetPackagePublishRequest(options: {\n readonly publishDir: string;\n readonly manifestPath: string;\n readonly publishManifestPath: string;\n readonly owner: WidgetPackageOwnerKind;\n}): Promise<WidgetPackagePublishRequest> {\n const manifestContent = await fs.readFile(options.manifestPath);\n const manifest = parseJsonRecord(\n manifestContent.toString(\"utf-8\"),\n options.manifestPath,\n );\n const publishManifest = await readPublishManifest(\n options.publishManifestPath,\n );\n assertManifestIdentityMatches(\n manifest,\n publishManifest,\n options.manifestPath,\n );\n assertMetadataMatches({\n label: \"manifestHash\",\n path: \"manifest.json\",\n expected: publishManifest.manifestHash,\n actual: sha256(manifestContent),\n });\n const collectedArtifacts = await collectWidgetPackageArtifacts(\n options.publishDir,\n );\n assertArtifactInventoryMatches(publishManifest.artifacts, collectedArtifacts);\n const artifacts = await readUploadArtifacts(\n options.publishDir,\n publishManifest.artifacts,\n );\n\n return {\n version: publishManifest.version,\n packageKey: stripOwnerPrefix(publishManifest.packageId, options.owner),\n builderVersion: publishManifest.builderVersion,\n cliVersion: publishManifest.cliVersion,\n runtimeVersion: publishManifest.runtimeVersion,\n manifestHash: publishManifest.manifestHash,\n manifest,\n artifacts,\n };\n}\nasync function readJsonRecord(\n filePath: string,\n): Promise<Record<string, unknown>> {\n return parseJsonRecord(await fs.readFile(filePath, \"utf-8\"), filePath);\n}\n\nfunction parseJsonRecord(\n content: string,\n filePath: string,\n): Record<string, unknown> {\n const value = JSON.parse(content) as unknown;\n if (!isRecord(value) || Array.isArray(value)) {\n throw new Error(`${path.basename(filePath)} must contain a JSON object.`);\n }\n return value;\n}\n\nasync function readPublishManifest(\n filePath: string,\n): Promise<PublishManifestMetadata> {\n const record = await readJsonRecord(filePath);\n const artifactsValue = record[\"artifacts\"];\n if (!Array.isArray(artifactsValue)) {\n throw new Error(\"publish-manifest.json must include an artifacts array.\");\n }\n\n return {\n packageId: readRequiredString(record, \"packageId\", filePath),\n version: readRequiredString(record, \"version\", filePath),\n builderVersion: readRequiredString(record, \"builderVersion\", filePath),\n cliVersion: readRequiredString(record, \"cliVersion\", filePath),\n runtimeVersion: readRequiredString(record, \"runtimeVersion\", filePath),\n manifestHash: readRequiredString(record, \"manifestHash\", filePath),\n artifacts: artifactsValue.map((artifact, index) =>\n readArtifactMetadata(artifact, index),\n ),\n };\n}\n\nfunction readArtifactMetadata(value: unknown, index: number): ArtifactMetadata {\n if (!isRecord(value) || Array.isArray(value)) {\n throw new Error(\n `publish-manifest.json artifacts[${index}] must be a JSON object.`,\n );\n }\n\n return {\n path: readRequiredString(value, \"path\", \"publish-manifest.json\"),\n sha256: readRequiredString(value, \"sha256\", \"publish-manifest.json\"),\n bytes: readRequiredNumber(value, \"bytes\", \"publish-manifest.json\"),\n contentType: readRequiredString(\n value,\n \"contentType\",\n \"publish-manifest.json\",\n ),\n };\n}\n\nasync function readUploadArtifacts(\n publishDir: string,\n artifacts: readonly ArtifactMetadata[],\n): Promise<WidgetPackagePublishRequest[\"artifacts\"]> {\n const resolvedPublishDir = path.resolve(publishDir);\n\n return Promise.all(\n artifacts.map(async (artifact) => {\n const artifactPath = resolveArtifactPath(\n resolvedPublishDir,\n artifact.path,\n );\n const actual = await computeArtifactMetadata(\n artifactPath,\n resolvedPublishDir,\n );\n assertArtifactMetadataMatches(artifact, actual);\n\n return {\n ...actual,\n body: await fs.readFile(artifactPath),\n };\n }),\n );\n}\n\nfunction assertManifestIdentityMatches(\n manifest: Record<string, unknown>,\n publishManifest: PublishManifestMetadata,\n manifestPath: string,\n): void {\n assertMetadataMatches({\n label: \"packageId\",\n path: \"manifest.json\",\n expected: publishManifest.packageId,\n actual: readRequiredString(manifest, \"packageId\", manifestPath),\n });\n assertMetadataMatches({\n label: \"version\",\n path: \"manifest.json\",\n expected: publishManifest.version,\n actual: readRequiredString(manifest, \"version\", manifestPath),\n });\n}\n\nfunction assertArtifactInventoryMatches(\n expected: readonly ArtifactMetadata[],\n actual: readonly ArtifactMetadata[],\n): void {\n const expectedByPath = new Map<string, ArtifactMetadata>();\n for (const artifact of expected) {\n if (expectedByPath.has(artifact.path)) {\n throw new Error(\n `publish-manifest.json artifacts include duplicate path ${JSON.stringify(artifact.path)}. ` +\n \"Rebuild the widget package before publishing.\",\n );\n }\n expectedByPath.set(artifact.path, artifact);\n }\n\n const actualPaths = new Set<string>();\n for (const actualArtifact of actual) {\n actualPaths.add(actualArtifact.path);\n const expectedArtifact = expectedByPath.get(actualArtifact.path);\n if (!expectedArtifact) {\n throw new Error(\n `publish-manifest.json artifacts omit ${JSON.stringify(actualArtifact.path)}. ` +\n \"Rebuild the widget package before publishing.\",\n );\n }\n assertArtifactMetadataMatches(expectedArtifact, actualArtifact);\n }\n\n for (const expectedArtifact of expected) {\n if (actualPaths.has(expectedArtifact.path)) continue;\n throw new Error(\n `publish-manifest.json artifacts include ${JSON.stringify(expectedArtifact.path)}, but that file is not present on disk. ` +\n \"Rebuild the widget package before publishing.\",\n );\n }\n}\n\nfunction assertArtifactMetadataMatches(\n expected: ArtifactMetadata,\n actual: ArtifactMetadata,\n): void {\n assertMetadataMatches({\n label: \"path\",\n path: expected.path,\n expected: expected.path,\n actual: actual.path,\n });\n assertMetadataMatches({\n label: \"sha256\",\n path: expected.path,\n expected: expected.sha256,\n actual: actual.sha256,\n });\n assertMetadataMatches({\n label: \"bytes\",\n path: expected.path,\n expected: expected.bytes,\n actual: actual.bytes,\n });\n assertMetadataMatches({\n label: \"contentType\",\n path: expected.path,\n expected: expected.contentType,\n actual: actual.contentType,\n });\n}\n\nfunction assertMetadataMatches(options: {\n readonly label: string;\n readonly path: string;\n readonly expected: string | number;\n readonly actual: string | number;\n}): void {\n if (options.expected === options.actual) return;\n\n throw new Error(\n `publish-manifest.json ${options.label} for ${JSON.stringify(options.path)} does not match the file on disk. ` +\n `Recorded ${JSON.stringify(options.expected)}, computed ${JSON.stringify(options.actual)}. ` +\n \"Rebuild the widget package before publishing.\",\n );\n}\n\nfunction resolveArtifactPath(publishDir: string, artifactPath: string): string {\n const resolved = path.resolve(publishDir, artifactPath);\n const relative = path.relative(publishDir, resolved);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new Error(\n `Artifact path ${JSON.stringify(artifactPath)} escapes the publish directory.`,\n );\n }\n return resolved;\n}\n\nfunction stripOwnerPrefix(\n packageId: string,\n owner: WidgetPackageOwnerKind,\n): string {\n const prefix = `${owner}.`;\n if (packageId.startsWith(prefix) && packageId.length > prefix.length) {\n return packageId.slice(prefix.length);\n }\n return packageId;\n}\n\nfunction readRequiredString(\n record: Record<string, unknown>,\n key: string,\n filePath: string,\n): string {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) return value;\n throw new Error(`${path.basename(filePath)} must include string ${key}.`);\n}\n\nfunction readRequiredNumber(\n record: Record<string, unknown>,\n key: string,\n filePath: string,\n): number {\n const value = record[key];\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n throw new Error(`${path.basename(filePath)} must include number ${key}.`);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n","/**\n * Shared widget package publish/upload helpers.\n *\n * These utilities cover the two owner scopes currently supported by the\n * portal widget package upload API: marketplace droplets and company-owned\n * Fluid OS packages. They intentionally do not register CLI commands; command\n * implementations can compose the typed payload builders, session/complete\n * requests, signed URL uploads, and dry-run orchestration exposed here.\n */\n\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport {\n fluidOsV0CompleteWidgetPackageVersionUpload,\n fluidOsV0CreateWidgetPackageVersion,\n} from \"@fluid-app/fluidos-api-client/sdk\";\nimport type {\n FluidOsV0CompleteWidgetPackageVersionUploadData,\n FluidOsV0CreateWidgetPackageVersionData,\n} from \"@fluid-app/fluidos-api-client/types\";\nimport type { ArtifactMetadata } from \"./widget-package-artifacts.js\";\n\nexport type WidgetPackageUploadOwner =\n | { readonly kind: \"droplet\"; readonly uuid: string }\n | { readonly kind: \"company\" };\n\nexport type WidgetPackageArtifactMetadata = ArtifactMetadata;\n\nexport interface WidgetPackageUploadArtifact extends WidgetPackageArtifactMetadata {\n readonly body: BodyInit;\n}\n\nexport interface WidgetPackageSessionRequest {\n readonly version: string;\n readonly packageKey: string;\n readonly builderVersion: string;\n readonly cliVersion: string;\n readonly runtimeVersion: string;\n readonly manifestHash: string;\n readonly manifest: Record<string, unknown>;\n readonly artifacts: readonly WidgetPackageArtifactMetadata[];\n}\n\nexport interface WidgetPackagePublishRequest extends Omit<\n WidgetPackageSessionRequest,\n \"artifacts\"\n> {\n readonly artifacts: readonly WidgetPackageUploadArtifact[];\n}\n\nexport type WidgetPackageArtifactPayload = ArtifactMetadata;\n\nexport interface WidgetPackageUploadSessionPayload {\n readonly version: string;\n readonly package_key: string;\n readonly builder_version: string;\n readonly cli_version: string;\n readonly runtime_version: string;\n readonly manifest_hash: string;\n readonly manifest: Record<string, unknown>;\n readonly artifacts: readonly WidgetPackageArtifactPayload[];\n}\n\nexport interface WidgetPackageCompleteUploadPayload {\n readonly package_key: string;\n readonly artifacts: readonly WidgetPackageArtifactPayload[];\n}\n\nexport interface WidgetPackageSignedUpload {\n readonly path: string;\n readonly url: string;\n readonly contentType: string;\n readonly headers: Readonly<Record<string, string>>;\n}\n\nexport interface WidgetPackageUploadSession {\n readonly version: string;\n readonly uploads: readonly WidgetPackageSignedUpload[];\n readonly raw: unknown;\n}\n\nexport interface WidgetPackageArtifactUploadResult {\n readonly path: string;\n readonly status: number;\n readonly contentType: string;\n}\n\nexport interface WidgetPackageCompleteResult {\n readonly version: string;\n readonly status?: string;\n readonly packageKey?: string;\n readonly raw: unknown;\n}\n\nexport interface WidgetPackagePublishResult {\n readonly dryRun: boolean;\n readonly sessionPayload: WidgetPackageUploadSessionPayload;\n readonly session?: WidgetPackageUploadSession;\n readonly uploadedArtifacts?: readonly WidgetPackageArtifactUploadResult[];\n readonly complete?: WidgetPackageCompleteResult;\n}\n\ninterface BasePublishWidgetPackageVersionOptions {\n readonly owner: WidgetPackageUploadOwner;\n readonly request: WidgetPackagePublishRequest;\n readonly fetchImpl?: WidgetPackageUploadFetch;\n}\n\nexport interface DryRunPublishWidgetPackageVersionOptions extends BasePublishWidgetPackageVersionOptions {\n readonly client?: FluidOsHeyApiClient;\n readonly dryRun: true;\n}\n\nexport interface PublishWidgetPackageVersionUploadOptions extends BasePublishWidgetPackageVersionOptions {\n readonly client: FluidOsHeyApiClient;\n readonly dryRun?: boolean;\n}\n\nexport type PublishWidgetPackageVersionOptions =\n | DryRunPublishWidgetPackageVersionOptions\n | PublishWidgetPackageVersionUploadOptions;\n\ntype FluidOsCreateWidgetPackageVersionPayload =\n FluidOsV0CreateWidgetPackageVersionData[\"body\"];\n\ntype FluidOsCompleteWidgetPackageVersionUploadPayload =\n FluidOsV0CompleteWidgetPackageVersionUploadData[\"body\"];\n\nexport type WidgetPackageUploadFetch = (\n input: string | URL,\n init: RequestInit,\n) => Promise<Response>;\n\nexport class WidgetPackageUploadError extends Error {\n public readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = \"WidgetPackageUploadError\";\n this.code = code;\n }\n}\n\nexport function buildWidgetPackageArtifactPayload(\n artifact: WidgetPackageArtifactMetadata,\n): WidgetPackageArtifactPayload {\n return {\n path: artifact.path,\n sha256: artifact.sha256,\n bytes: artifact.bytes,\n contentType: artifact.contentType,\n };\n}\n\nexport function buildWidgetPackageUploadSessionPayload(\n request: WidgetPackageSessionRequest,\n): WidgetPackageUploadSessionPayload {\n return {\n version: request.version,\n package_key: request.packageKey,\n builder_version: request.builderVersion,\n cli_version: request.cliVersion,\n runtime_version: request.runtimeVersion,\n manifest_hash: request.manifestHash,\n manifest: request.manifest,\n artifacts: request.artifacts.map(buildWidgetPackageArtifactPayload),\n };\n}\n\nexport function buildWidgetPackageCompleteUploadPayload(\n packageKey: string,\n artifacts: readonly WidgetPackageArtifactMetadata[],\n): WidgetPackageCompleteUploadPayload {\n return {\n package_key: packageKey,\n artifacts: artifacts.map(buildWidgetPackageArtifactPayload),\n };\n}\n\nexport function getWidgetPackageUploadSessionRoute(\n owner: WidgetPackageUploadOwner,\n): string {\n switch (owner.kind) {\n case \"droplet\":\n return `/api/droplets/${encodeURIComponent(owner.uuid)}/widget_package_versions`;\n case \"company\":\n return \"/api/company/fluid_os/widget_package_versions\";\n }\n}\n\nexport function getWidgetPackageCompleteUploadRoute(\n owner: WidgetPackageUploadOwner,\n version: string,\n): string {\n switch (owner.kind) {\n case \"droplet\":\n return `/api/droplets/${encodeURIComponent(owner.uuid)}/widget_package_versions/${encodeURIComponent(version)}/complete_upload`;\n case \"company\":\n return `/api/company/fluid_os/widget_package_versions/${encodeURIComponent(version)}/complete_upload`;\n }\n}\n\nexport async function requestWidgetPackageUploadSession(\n client: FluidOsHeyApiClient,\n owner: WidgetPackageUploadOwner,\n request: WidgetPackageSessionRequest,\n): Promise<WidgetPackageUploadSession> {\n const payload = buildWidgetPackageUploadSessionPayload(request);\n\n try {\n const response =\n owner.kind === \"company\"\n ? await fluidOsV0CreateWidgetPackageVersion({\n body: payload as FluidOsCreateWidgetPackageVersionPayload,\n client,\n })\n : await client.post({\n body: payload,\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: getWidgetPackageUploadSessionRoute(owner),\n });\n return normalizeWidgetPackageUploadSession(\n response,\n request.version,\n request.artifacts,\n );\n } catch (err) {\n if (err instanceof WidgetPackageUploadError) {\n throw err;\n }\n\n throw new WidgetPackageUploadError(\n \"SESSION_REQUEST_FAILED\",\n `Failed to create widget package upload session: ${formatUnknownError(err)}`,\n );\n }\n}\n\nexport async function uploadWidgetPackageArtifacts(\n session: WidgetPackageUploadSession,\n artifacts: readonly WidgetPackageUploadArtifact[],\n fetchImpl: WidgetPackageUploadFetch = fetch,\n): Promise<WidgetPackageArtifactUploadResult[]> {\n const uploadsByPath = new Map(\n session.uploads.map((upload) => [upload.path, upload] as const),\n );\n const results: WidgetPackageArtifactUploadResult[] = [];\n\n for (const artifact of artifacts) {\n const upload = uploadsByPath.get(artifact.path);\n if (!upload) {\n throw new WidgetPackageUploadError(\n \"MISSING_SIGNED_URL\",\n `Upload session did not include a signed URL for artifact \"${artifact.path}\".`,\n );\n }\n\n if (upload.contentType !== artifact.contentType) {\n throw new WidgetPackageUploadError(\n \"CONTENT_TYPE_MISMATCH\",\n `Upload session expected artifact \"${artifact.path}\" to use content type \"${upload.contentType}\", but local artifact uses \"${artifact.contentType}\".`,\n );\n }\n\n let response: Response;\n try {\n response = await fetchImpl(upload.url, {\n method: \"PUT\",\n headers: mergeUploadHeaders(upload.headers, upload.contentType),\n body: artifact.body,\n });\n } catch (err) {\n throw new WidgetPackageUploadError(\n \"ARTIFACT_UPLOAD_FAILED\",\n `Failed to upload artifact \"${artifact.path}\": ${formatUnknownError(err)}`,\n );\n }\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n const details = body.trim() ? `: ${body.trim().slice(0, 500)}` : \"\";\n throw new WidgetPackageUploadError(\n \"ARTIFACT_UPLOAD_FAILED\",\n `Failed to upload artifact \"${artifact.path}\": PUT returned HTTP ${response.status}${details}`,\n );\n }\n\n results.push({\n path: artifact.path,\n status: response.status,\n contentType: upload.contentType,\n });\n }\n\n return results;\n}\n\nexport async function completeWidgetPackageUpload(\n client: FluidOsHeyApiClient,\n owner: WidgetPackageUploadOwner,\n version: string,\n packageKey: string,\n artifacts: readonly WidgetPackageArtifactMetadata[],\n): Promise<WidgetPackageCompleteResult> {\n const payload = buildWidgetPackageCompleteUploadPayload(\n packageKey,\n artifacts,\n );\n\n try {\n const response =\n owner.kind === \"company\"\n ? await fluidOsV0CompleteWidgetPackageVersionUpload({\n body: payload as FluidOsCompleteWidgetPackageVersionUploadPayload,\n client,\n path: { version },\n })\n : await client.post({\n body: payload,\n responseStyle: \"data\",\n security: [{ scheme: \"bearer\", type: \"http\" }],\n url: getWidgetPackageCompleteUploadRoute(owner, version),\n });\n return normalizeWidgetPackageCompleteResponse(response, version);\n } catch (err) {\n if (err instanceof WidgetPackageUploadError) {\n throw err;\n }\n\n throw new WidgetPackageUploadError(\n \"COMPLETE_UPLOAD_FAILED\",\n `Failed to complete widget package upload: ${formatUnknownError(err)}`,\n );\n }\n}\n\nexport async function publishWidgetPackageVersion(\n options: PublishWidgetPackageVersionOptions,\n): Promise<WidgetPackagePublishResult> {\n const sessionPayload = buildWidgetPackageUploadSessionPayload(\n options.request,\n );\n\n if (options.dryRun) {\n return { dryRun: true, sessionPayload };\n }\n\n if (!options.client) {\n throw new Error(\"A FluidOS API client is required when dryRun is false.\");\n }\n\n const session = await requestWidgetPackageUploadSession(\n options.client,\n options.owner,\n options.request,\n );\n const uploadedArtifacts = await uploadWidgetPackageArtifacts(\n session,\n options.request.artifacts,\n options.fetchImpl,\n );\n const complete = await completeWidgetPackageUpload(\n options.client,\n options.owner,\n session.version,\n options.request.packageKey,\n options.request.artifacts,\n );\n\n return {\n dryRun: false,\n sessionPayload,\n session,\n uploadedArtifacts,\n complete,\n };\n}\n\nexport function normalizeWidgetPackageUploadSession(\n response: unknown,\n requestedVersion: string,\n requestedArtifacts: readonly WidgetPackageArtifactMetadata[],\n): WidgetPackageUploadSession {\n const record = requireRecord(\n response,\n \"INVALID_SESSION_RESPONSE\",\n \"Upload session response must be a JSON object.\",\n );\n requireFiniteNumberProperty(record, \"version_id\", \"INVALID_SESSION_RESPONSE\");\n requireStringProperty(\n record,\n \"artifact_base_url\",\n \"INVALID_SESSION_RESPONSE\",\n );\n\n const uploadValues = record[\"uploads\"];\n if (!Array.isArray(uploadValues)) {\n throw new WidgetPackageUploadError(\n \"INVALID_SESSION_RESPONSE\",\n 'Upload session response must contain an \"uploads\" array.',\n );\n }\n\n const requestedArtifactsByPath = new Map(\n requestedArtifacts.map((artifact) => [artifact.path, artifact] as const),\n );\n const seenUploadPaths = new Set<string>();\n const uploads = uploadValues.map((value, index) => {\n const upload = requireRecord(\n value,\n \"INVALID_SESSION_RESPONSE\",\n `Upload session uploads[${index}] must be a JSON object.`,\n );\n const path = requireStringProperty(\n upload,\n \"path\",\n \"INVALID_SESSION_RESPONSE\",\n );\n const url = requireStringProperty(\n upload,\n \"upload_url\",\n \"INVALID_SESSION_RESPONSE\",\n );\n requireStringProperty(upload, \"public_url\", \"INVALID_SESSION_RESPONSE\");\n\n const requestedArtifact = requestedArtifactsByPath.get(path);\n if (!requestedArtifact) {\n throw new WidgetPackageUploadError(\n \"INVALID_SESSION_RESPONSE\",\n `Upload session response included unexpected artifact \"${path}\".`,\n );\n }\n if (seenUploadPaths.has(path)) {\n throw new WidgetPackageUploadError(\n \"INVALID_SESSION_RESPONSE\",\n `Upload session response included duplicate artifact \"${path}\".`,\n );\n }\n seenUploadPaths.add(path);\n\n return {\n path,\n url,\n contentType: requestedArtifact.contentType,\n headers: {},\n };\n });\n const missingUploadPaths = requestedArtifacts\n .map((artifact) => artifact.path)\n .filter((artifactPath) => !seenUploadPaths.has(artifactPath));\n\n if (missingUploadPaths.length > 0) {\n throw new WidgetPackageUploadError(\n \"INVALID_SESSION_RESPONSE\",\n `Upload session response is missing signed URLs for artifact(s): ${missingUploadPaths.join(\", \")}.`,\n );\n }\n\n return { version: requestedVersion, uploads, raw: response };\n}\n\nexport function normalizeWidgetPackageCompleteResponse(\n response: unknown,\n requestedVersion: string,\n): WidgetPackageCompleteResult {\n const record = requireRecord(\n response,\n \"INVALID_COMPLETE_RESPONSE\",\n \"Complete upload response must be a JSON object.\",\n );\n const responseVersion = requireStringProperty(\n record,\n \"version\",\n \"INVALID_COMPLETE_RESPONSE\",\n );\n\n if (responseVersion !== requestedVersion) {\n throw new WidgetPackageUploadError(\n \"INVALID_COMPLETE_RESPONSE\",\n `Complete upload response version \"${responseVersion}\" did not match requested version \"${requestedVersion}\".`,\n );\n }\n\n const packageKey = requireStringProperty(\n record,\n \"packageId\",\n \"INVALID_COMPLETE_RESPONSE\",\n );\n const status = requireStringProperty(\n record,\n \"status\",\n \"INVALID_COMPLETE_RESPONSE\",\n );\n requireStringProperty(record, \"scriptUrl\", \"INVALID_COMPLETE_RESPONSE\");\n requireStringProperty(record, \"manifestUrl\", \"INVALID_COMPLETE_RESPONSE\");\n requireStringArrayProperty(record, \"cssUrls\", \"INVALID_COMPLETE_RESPONSE\");\n\n return {\n version: responseVersion,\n status,\n packageKey,\n raw: response,\n };\n}\n\nfunction normalizeHeaderName(name: string): string {\n return name.toLowerCase();\n}\n\nfunction mergeUploadHeaders(\n headers: Readonly<Record<string, string>>,\n contentType: string,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(headers)) {\n if (normalizeHeaderName(key) === \"content-type\") continue;\n merged[key] = value;\n }\n\n merged[\"Content-Type\"] = contentType;\n return merged;\n}\n\nfunction requireRecord(\n value: unknown,\n code: string,\n message: string,\n): Record<string, unknown> {\n if (!isRecord(value) || Array.isArray(value)) {\n throw new WidgetPackageUploadError(code, message);\n }\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction requireStringProperty(\n record: Record<string, unknown>,\n key: string,\n code: string,\n): string {\n const value = record[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n throw new WidgetPackageUploadError(\n code,\n `Response field \"${key}\" must be a non-empty string.`,\n );\n}\n\nfunction requireFiniteNumberProperty(\n record: Record<string, unknown>,\n key: string,\n code: string,\n): number {\n const value = record[key];\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n throw new WidgetPackageUploadError(\n code,\n `Response field \"${key}\" must be a finite number.`,\n );\n}\n\nfunction requireStringArrayProperty(\n record: Record<string, unknown>,\n key: string,\n code: string,\n): readonly string[] {\n const value = record[key];\n if (\n Array.isArray(value) &&\n value.every((entry) => typeof entry === \"string\" && entry.trim().length > 0)\n ) {\n return value;\n }\n throw new WidgetPackageUploadError(\n code,\n `Response field \"${key}\" must be an array of non-empty strings.`,\n );\n}\n\nfunction formatUnknownError(err: unknown): string {\n const base = err instanceof Error ? err.message : String(err);\n\n if (isRecord(err) && \"data\" in err) {\n return `${base} — ${safeStringify(err.data)}`;\n }\n\n return base;\n}\n\nfunction safeStringify(value: unknown): string {\n const seen = new WeakSet<object>();\n\n try {\n const serialized = JSON.stringify(value, (_key, item: unknown) => {\n if (typeof item === \"bigint\") return `${item}n`;\n if (typeof item !== \"object\" || item === null) return item;\n if (seen.has(item)) return \"[Circular]\";\n seen.add(item);\n return item;\n });\n return serialized ?? String(value);\n } catch {\n return \"[unserializable error data]\";\n }\n}\n","import type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport { WidgetToolingError, type WidgetToolingErrorCode } from \"./errors.js\";\nimport type { WidgetToolingNodeRuntime } from \"./node-runtime.js\";\nimport {\n buildSharedWidgetPackage,\n type SharedWidgetPackageBuildResult,\n} from \"./internal/widget-package-builder.js\";\nimport {\n loadSourceWidgetPackages,\n resolvePortalWidgetSourceConfig,\n} from \"./internal/widget-package-config.js\";\nimport { createWidgetPackagePublishRequest } from \"./internal/widget-package-publish-request.js\";\nimport {\n publishWidgetPackageVersion,\n WidgetPackageUploadError,\n type WidgetPackagePublishRequest,\n type WidgetPackagePublishResult,\n type WidgetPackageUploadFetch,\n type WidgetPackageUploadOwner,\n} from \"./internal/widget-package-upload.js\";\nimport {\n validateSingleSourceWidgetPackage,\n type SourceWidgetMetadata,\n type SourceWidgetPackageMetadata,\n type ValidatedWidgetPackageBuild,\n type WidgetPackageOwnerKind,\n type WidgetPackageValidationError,\n type WidgetPackageValidationErrorCode,\n} from \"./internal/widget-package-validation.js\";\n\nexport type {\n SourceWidgetMetadata,\n SourceWidgetPackageMetadata,\n ValidatedWidgetPackageBuild,\n WidgetPackageOwnerKind,\n WidgetPackageValidationError,\n WidgetPackageValidationErrorCode,\n};\n\nexport type WidgetPackageOwner = WidgetPackageUploadOwner;\nexport type WidgetPackageBuildResult = SharedWidgetPackageBuildResult;\nexport type WidgetPackagePublishWorkflowRequest = WidgetPackagePublishRequest;\nexport type WidgetPackagePublishWorkflowResult = WidgetPackagePublishResult;\n\nexport interface LoadAndValidateWidgetPackageOptions {\n readonly projectDir: string;\n readonly owner: WidgetPackageOwnerKind;\n /** How to run the generated helper scripts — see WidgetToolingNodeRuntime. */\n readonly nodeRuntime?: WidgetToolingNodeRuntime;\n}\n\nexport interface LoadedWidgetPackage {\n readonly projectDir: string;\n readonly sourceConfigPath: string;\n readonly validated: ValidatedWidgetPackageBuild;\n}\n\nexport async function loadAndValidateWidgetPackage(\n options: LoadAndValidateWidgetPackageOptions,\n): Promise<LoadedWidgetPackage> {\n const sourceConfig = await resolvePortalWidgetSourceConfig(\n options.projectDir,\n );\n const loadResult = await loadSourceWidgetPackages(\n options.projectDir,\n options.nodeRuntime,\n );\n if (!loadResult.success) {\n throw new WidgetToolingError(\n \"CONFIG_LOAD_FAILED\",\n loadResult.error.message,\n { details: loadResult.error.details },\n );\n }\n\n const validation = validateSingleSourceWidgetPackage(loadResult.value, {\n owner: options.owner,\n });\n if (!validation.success || !validation.value) {\n throw new WidgetToolingError(\n \"VALIDATION_FAILED\",\n validation.errors.map((error) => error.message).join(\"\\n\") ||\n \"Widget package validation failed.\",\n { diagnostics: validation.errors },\n );\n }\n\n return {\n projectDir: options.projectDir,\n sourceConfigPath: sourceConfig?.relativePath ?? \"src/widgets.config.ts\",\n validated: validation.value,\n };\n}\n\nexport interface BuildWidgetPackageOptions {\n readonly projectDir: string;\n readonly outDir?: string;\n readonly owner: WidgetPackageOwnerKind;\n readonly cliVersion: string;\n /** Publish as this version instead of the config's — see\n * `BuildSharedWidgetPackageOptions.versionOverride`. */\n readonly version?: string;\n /** How to run the generated helper scripts — see WidgetToolingNodeRuntime. */\n readonly nodeRuntime?: WidgetToolingNodeRuntime;\n}\n\nexport async function buildWidgetPackage(\n options: BuildWidgetPackageOptions,\n): Promise<WidgetPackageBuildResult> {\n const result = await buildSharedWidgetPackage({\n projectDir: options.projectDir,\n publishDir: options.outDir,\n owner: options.owner,\n cliVersion: options.cliVersion,\n ...(options.version ? { versionOverride: options.version } : {}),\n ...(options.nodeRuntime ? { nodeRuntime: options.nodeRuntime } : {}),\n });\n if (result.success) return result.value;\n\n const code: WidgetToolingErrorCode =\n result.error.code === \"CONFIG_LOAD_FAILED\"\n ? \"CONFIG_LOAD_FAILED\"\n : result.error.code === \"VALIDATION_FAILED\"\n ? \"VALIDATION_FAILED\"\n : result.error.code === \"INVALID_PUBLISH_DIR\"\n ? \"INVALID_OUTPUT_DIR\"\n : \"BUILD_FAILED\";\n throw new WidgetToolingError(code, result.error.message, {\n details: result.error.details,\n });\n}\n\ninterface BasePublishWidgetPackageOptions extends BuildWidgetPackageOptions {\n readonly owner: WidgetPackageOwnerKind;\n readonly uploadOwner: WidgetPackageOwner;\n readonly fetchImpl?: WidgetPackageUploadFetch;\n}\n\nexport interface DryRunPublishWidgetPackageOptions extends BasePublishWidgetPackageOptions {\n readonly dryRun: true;\n readonly client?: never;\n}\n\nexport interface UploadWidgetPackageOptions extends BasePublishWidgetPackageOptions {\n readonly dryRun?: false;\n readonly client: FluidOsHeyApiClient;\n}\n\nexport type PublishWidgetPackageOptions =\n | DryRunPublishWidgetPackageOptions\n | UploadWidgetPackageOptions;\n\nexport interface PublishedWidgetPackage {\n readonly build: WidgetPackageBuildResult;\n readonly request: WidgetPackagePublishRequest;\n readonly publish: WidgetPackagePublishResult;\n}\n\nexport async function publishWidgetPackage(\n options: PublishWidgetPackageOptions,\n): Promise<PublishedWidgetPackage> {\n if (options.owner !== options.uploadOwner.kind) {\n throw new WidgetToolingError(\n \"OWNER_MISMATCH\",\n `Widget package build owner \"${options.owner}\" must match upload owner kind \"${options.uploadOwner.kind}\".`,\n );\n }\n\n if (!options.dryRun && !options.client) {\n throw new WidgetToolingError(\n \"CLIENT_REQUIRED\",\n \"A FluidOS API client is required when dryRun is false.\",\n );\n }\n\n const build = await buildWidgetPackage(options);\n\n let request: WidgetPackagePublishRequest;\n try {\n request = await createWidgetPackagePublishRequest({\n publishDir: build.publishDir,\n manifestPath: build.manifestPath,\n publishManifestPath: build.publishManifestPath,\n owner: options.owner,\n });\n } catch (error) {\n throw new WidgetToolingError(\n \"ARTIFACT_VERIFICATION_FAILED\",\n error instanceof Error\n ? error.message\n : \"Failed to verify widget package artifacts.\",\n { cause: error },\n );\n }\n\n try {\n const publish = options.dryRun\n ? await publishWidgetPackageVersion({\n owner: options.uploadOwner,\n request,\n dryRun: true,\n fetchImpl: options.fetchImpl,\n })\n : await publishWidgetPackageVersion({\n client: options.client,\n owner: options.uploadOwner,\n request,\n fetchImpl: options.fetchImpl,\n });\n\n return { build, request, publish };\n } catch (error) {\n if (error instanceof WidgetToolingError) throw error;\n if (error instanceof WidgetPackageUploadError) {\n throw new WidgetToolingError(\n toPublicUploadErrorCode(error.code),\n error.message,\n { cause: error },\n );\n }\n throw new WidgetToolingError(\n \"PUBLISH_FAILED\",\n error instanceof Error\n ? error.message\n : \"Failed to publish widget package.\",\n { cause: error },\n );\n }\n}\n\nfunction toPublicUploadErrorCode(code: string): WidgetToolingErrorCode {\n switch (code) {\n case \"SESSION_REQUEST_FAILED\":\n case \"INVALID_SESSION_RESPONSE\":\n case \"MISSING_SIGNED_URL\":\n case \"CONTENT_TYPE_MISMATCH\":\n case \"ARTIFACT_UPLOAD_FAILED\":\n case \"COMPLETE_UPLOAD_FAILED\":\n case \"INVALID_COMPLETE_RESPONSE\":\n return code;\n default:\n return \"PUBLISH_FAILED\";\n }\n}\n","/**\n * Reads the company's existing widget package key.\n *\n * A company has exactly ONE widget package. Its key is fixed by whichever\n * project publishes first, and every portal project in that company must\n * publish into it. Publishing under any other key is rejected server-side with\n *\n * 422 Package key does not match this widget package\n *\n * which names no key and offers no way to find one. `packageStableId` is not the\n * client's to choose once a company has published; the scaffold writing a guess\n * (`portal-widgets`) is the bug.\n *\n * The key IS discoverable — this route returns it for the ordinary CLI token.\n * `/api/app/widget-packages` is the one that 404s, because it is portal-session\n * scoped, which is what makes this look unreachable from a terminal.\n *\n * Deliberately read-only. The key is NOT injected into the build, because a\n * widget's type is `company.<key>.<Name>` and those types are written into\n * screen JSON. Publishing under a key the project's config does not declare\n * would leave every screen referencing a type that no longer exists — the exact\n * silent breakage this milestone is trying to remove. The config has to be\n * corrected; this module exists so the CLI can say what to correct it to.\n */\n\nimport type { FluidOsHeyApiClient } from \"@fluid-app/fluidos-api-client\";\nimport { fluidOsV0ListWidgetPackages } from \"@fluid-app/fluidos-api-client/sdk\";\nimport { resolvePortalWidgetSourceConfig } from \"./internal/widget-package-config.js\";\nimport { collectScreenWidgetTypes } from \"./screen-widget-types.js\";\n\n/** Strips the owner scope so the result can be compared to `packageStableId`. */\nconst COMPANY_PACKAGE_ID_PREFIX = \"company.\";\n\nexport interface CompanyWidgetPackage {\n /** Bare key, comparable to `packageStableId` (no `company.` prefix). */\n readonly key: string;\n readonly version: string;\n /**\n * Fully-qualified widget types this package publishes — `company.<key>.<Name>`,\n * the same strings screen JSON stores. Empty when the response carried no\n * usable manifest, which is a \"cannot tell\", not \"publishes nothing\".\n */\n readonly widgetTypes: readonly string[];\n}\n\n/**\n * Returns every company-scoped widget package the API reports.\n *\n * An empty array is a normal, expected answer: the first publish defines the\n * key, so any configured value is valid until one exists.\n *\n * Never throws for the caller's benefit — a deploy must not be blocked because\n * a preflight lookup failed. An unreachable or unexpected response resolves to\n * an empty array, which degrades to today's behaviour (publish, and let the\n * server reject it) rather than inventing a reason to stop.\n */\nexport async function readCompanyWidgetPackages(\n client: FluidOsHeyApiClient,\n): Promise<CompanyWidgetPackage[]> {\n return (await readCompanyWidgetCatalog(client)) ?? [];\n}\n\n/**\n * The same read, keeping \"the company has published nothing\" apart from \"the\n * lookup did not answer\" — `[]` versus `null`.\n *\n * {@link readCompanyWidgetPackages} folds the two together because a preflight\n * treats both as \"proceed\". A caller deciding whether to START a publish cannot:\n * an empty catalog means publish, and a failed lookup that reads as empty would\n * publish on every attempt, consuming an irreversible version of a package the\n * whole company shares each time.\n */\nexport async function readCompanyWidgetCatalog(\n client: FluidOsHeyApiClient,\n): Promise<CompanyWidgetPackage[] | null> {\n let response: unknown;\n try {\n response = await fluidOsV0ListWidgetPackages({ client });\n } catch {\n return null;\n }\n\n if (!isRecord(response) || !Array.isArray(response.packages)) return null;\n\n const packages: CompanyWidgetPackage[] = [];\n for (const candidate of response.packages) {\n if (!isRecord(candidate)) continue;\n const packageId = candidate.packageId;\n const version = candidate.version;\n if (typeof packageId !== \"string\" || packageId.length === 0) continue;\n if (!packageId.startsWith(COMPANY_PACKAGE_ID_PREFIX)) continue;\n\n const key = packageId.slice(COMPANY_PACKAGE_ID_PREFIX.length);\n if (key.length === 0) continue;\n\n packages.push({\n key,\n version: typeof version === \"string\" ? version : \"unknown\",\n widgetTypes: readWidgetTypes(candidate),\n });\n }\n\n return packages;\n}\n\n/**\n * The types a catalog entry publishes.\n *\n * `type` is the fully-qualified name the publish manifest wrote\n * (`${packageId}.${widget.name}`) — the exact string a screen stores.\n *\n * Read from BOTH the entry itself and a nested `manifest`, because the two\n * disagree and only one of them is real. The generated OpenAPI types describe\n * `FluidOSWidgetPackageCatalogEntry` as carrying an opaque `manifest` object\n * with no top-level `widgets`; the live route returns the manifest FLATTENED\n * onto the entry — `packageId`, `version`, `runtime`, `widgets`, `workerEntryUrl`\n * — and no `manifest` key at all. Verified against\n * `GET /api/company/fluid_os/widget_packages`.\n *\n * Trusting the generated shape found nothing, which does not fail loudly: it\n * looks exactly like a company that has published no widgets. Reading both\n * costs one property access and survives whichever way the route settles.\n */\nfunction readWidgetTypes(entry: Readonly<Record<string, unknown>>): string[] {\n const nested = isRecord(entry.manifest) ? entry.manifest.widgets : undefined;\n const types = new Set<string>();\n for (const source of [entry.widgets, nested]) {\n if (!Array.isArray(source)) continue;\n for (const widget of source) {\n if (!isRecord(widget)) continue;\n if (typeof widget.type === \"string\" && widget.type.length > 0) {\n types.add(widget.type);\n }\n }\n }\n return [...types];\n}\n\n/**\n * Widget types this project's screens reference that this project could publish\n * but has not — the reason to publish widgets before pushing content.\n *\n * A screen node whose type is not in the catalog renders nothing at all: `null`\n * and a `console.warn`. No placeholder, no error, just a gap. Publishing the\n * portal while that is true ships the gap, and the author has no way to tell\n * from the screen that anything is wrong.\n *\n * Every uncertainty answers \"nothing missing\", which is the opposite bias from\n * {@link preflightCompanyPackage} and deliberately so. That one guards a publish\n * the user already asked for, so proceeding costs nothing. This one DECIDES\n * whether to publish, and every company shares one widget package whose versions\n * cannot be rolled back — so a wrong \"missing\" spends a version on EVERY press\n * of the button, and keeps spending one for as long as the type stays missing.\n * A wrong \"nothing missing\" only leaves today's behaviour in place.\n *\n * The test for \"could publish\" is the project's own declared widget list, not\n * its package key. A key match alone says a type is in our namespace; only the\n * list says a publish would actually supply it. Those differ exactly when a\n * screen outlives the widget it points at — a rename or a deletion in\n * `src/widgets.config.ts` — and that gap is unbounded: the publish succeeds,\n * the catalog still lacks the type, and the next press publishes again.\n *\n * Concretely, it answers empty when:\n *\n * - the catalog lookup did not answer, as distinct from answering \"none\"\n * - the project has no `src/widgets.config.ts`, so it has nothing to publish\n * - this project's own package could not be read, so nothing can be attributed\n * - no referenced type is one this project declares\n * - this project's own catalog entry exists but reported no types at all, which\n * cannot be told apart from a response that withheld them\n *\n * Droplet-owned types are excluded rather than reported: they belong to another\n * publisher, and no publish this project can run would supply them. So is\n * anything this project does not itself declare.\n */\nexport async function findUnpublishedWidgetTypes(options: {\n readonly projectDir: string;\n readonly client: FluidOsHeyApiClient;\n /**\n * What this project would publish: its package id and the fully-qualified\n * types it declares.\n *\n * Both halves are load-bearing. The id picks this project's entry out of a\n * catalog that may hold several packages. The type list is what makes\n * \"missing\" mean \"a publish would fix this\" rather than merely \"absent\" —\n * without it a screen still pointing at a renamed or deleted widget is\n * attributed here, published for, and still missing afterwards, on every\n * press.\n *\n * Injected rather than read here because resolving it means evaluating\n * `src/widgets.config.ts` in a spawned process — the same reason\n * {@link preflightCompanyPackage} takes `readConfiguredPackage`. It is called\n * only once a referenced type is absent from the catalog, so the ordinary\n * \"everything is published\" press never pays for it.\n *\n * Absent or unable to answer, nothing is reported. There is no sound\n * substitute: the catalog's own keys are not one, because a company can hold\n * more than one package.\n */\n readonly readConfiguredPackage?: (\n projectDir: string,\n ) => Promise<ConfiguredWidgetPackageTypes | null>;\n}): Promise<string[]> {\n const referenced = (\n await collectScreenWidgetTypes(options.projectDir)\n ).filter((type) => type.startsWith(COMPANY_PACKAGE_ID_PREFIX));\n if (referenced.length === 0) return [];\n\n if (!(await resolvePortalWidgetSourceConfig(options.projectDir))) return [];\n\n const catalog = await readCompanyWidgetCatalog(options.client);\n if (!catalog) return [];\n\n // Cheap pre-filter against every package the company publishes, purely to\n // decide whether the expensive step below is worth taking. It cannot decide\n // ownership — another package's entry may well contain a type of ours' name\n // — so its answer is only ever \"there is something to look into\".\n const anythingAbsent = referenced.some(\n (type) => !catalog.some((entry) => entry.widgetTypes.includes(type)),\n );\n if (!anythingAbsent) return [];\n\n let own: ConfiguredWidgetPackageTypes | null = null;\n try {\n own = (await options.readConfiguredPackage?.(options.projectDir)) ?? null;\n } catch {\n // Unreadable config is the build's failure to report, with far better\n // diagnostics than this has.\n own = null;\n }\n if (!own) return [];\n\n // Ownership decided BEFORE anything else, including the never-published case.\n // A first publish is not a licence to claim a foreign type: a screen copied\n // from another project, or a `packageStableId` renamed before the first\n // publish, would otherwise spend a version on a widget this package does not\n // contain.\n const declared = new Set(own.widgetTypes);\n const ours = referenced.filter((type) => declared.has(type));\n if (ours.length === 0) return [];\n\n const ownKey = own.packageId.replace(/^company\\./u, \"\");\n const entry = catalog.find((candidate) => candidate.key === ownKey) ?? null;\n\n // Never published under this key — every declared type a screen uses is\n // genuinely absent, and this publish is the one that creates them.\n if (!entry) return ours;\n\n // Per-entry rather than aggregate. Another package answering does not mean\n // OURS did: if this project's entry carries no readable type list — the shape\n // drift this module already survived once — its published widgets read as\n // absent and a full publish runs on every press for as long as that lasts.\n if (entry.widgetTypes.length === 0) return [];\n\n const published = new Set(entry.widgetTypes);\n return ours.filter((type) => !published.has(type));\n}\n\n/** What a project's `src/widgets.config.ts` would publish. */\nexport interface ConfiguredWidgetPackageTypes {\n readonly packageId: string;\n /** Fully-qualified `company.<key>.<Name>` types the project declares. */\n readonly widgetTypes: readonly string[];\n}\n\n/**\n * The company's widget package, or `null` when it has never published.\n *\n * A company is expected to have exactly one. This returns the first, and exists\n * for callers that only need \"what is this company's key\" — a preflight must use\n * {@link readCompanyWidgetPackages} and reconcile against the configured key\n * instead, or a second package would make it report a confident, wrong answer.\n */\nexport async function readCompanyWidgetPackage(\n client: FluidOsHeyApiClient,\n): Promise<CompanyWidgetPackage | null> {\n return (await readCompanyWidgetPackages(client))[0] ?? null;\n}\n\n/**\n * The message shown when the project's key disagrees with the company's.\n *\n * Names the actual key and the exact edit, because the failure it replaces gave\n * neither — and because the fix is one line the author can apply immediately.\n */\nexport function formatPackageKeyMismatch(options: {\n readonly configuredKey: string;\n readonly companyKey: string;\n readonly companyVersion: string;\n}): string {\n return [\n `This company already has a widget package: \"${options.companyKey}\" (published v${options.companyVersion}).`,\n \"\",\n `A company has one widget package, and every portal project publishes into it, so`,\n `\"${options.configuredKey}\" would be rejected.`,\n \"\",\n \"Fix — in src/widgets.config.ts:\",\n ` packageStableId: \"${options.companyKey}\",`,\n \"\",\n \"This must be corrected in the file rather than applied at publish time:\",\n \"widget types are `company.<key>.<Name>` and are written into your screen\",\n \"JSON, so publishing under a different key would leave those screens\",\n \"pointing at types that do not exist.\",\n ].join(\"\\n\");\n}\n\n/** What the project's own `src/widgets.config.ts` declares. */\nexport interface ConfiguredWidgetPackage {\n readonly packageId: string;\n readonly version: string;\n}\n\nexport interface CompanyPackagePreflight {\n /** Set when the deploy must not proceed; the text explains the one-line fix. */\n readonly mismatch?: string;\n /** Set when the configured version would collide; publish as this instead. */\n readonly versionOverride?: string;\n /** The version that would have collided, for reporting the substitution. */\n readonly configuredVersion?: string;\n}\n\n/**\n * One round trip against the company's widget package, answering both questions\n * a publish has to settle before it builds anything: is this the right package,\n * and is this version free?\n *\n * Shared so `fluid portal deploy` and any host that drives it reach the same\n * verdict for the same reason.\n *\n * Proceeds on every uncertainty — the company has never published (its first\n * publish defines both key and version), the lookup failed, or the local config\n * could not be read. A preflight exists to replace a confusing failure with a\n * clear one, not to invent new reasons to stop; when it cannot tell, the server\n * still decides.\n */\nexport async function preflightCompanyPackage(options: {\n readonly projectDir: string;\n readonly client: FluidOsHeyApiClient;\n /** Injected so callers bundle their own loader; avoids a cycle back into the build path. */\n readonly readConfiguredPackage: (\n projectDir: string,\n ) => Promise<ConfiguredWidgetPackage | null>;\n}): Promise<CompanyPackagePreflight> {\n let configured: ConfiguredWidgetPackage | null;\n try {\n configured = await options.readConfiguredPackage(options.projectDir);\n } catch {\n // A config that cannot load is the build's error to report, with better\n // diagnostics than this preflight could produce.\n return {};\n }\n if (!configured) return {};\n\n const companyPackages = await readCompanyWidgetPackages(options.client);\n if (companyPackages.length === 0) return {};\n\n const configuredKey = configured.packageId.replace(/^company\\./u, \"\");\n // Reconcile against EVERY company package, not just the first. Taking the\n // first and comparing meant a second company-scoped package (or a paginated\n // response) could produce a confident, wrong refusal — naming a key the\n // project never configured, with a \"fix it in src/widgets.config.ts\"\n // instruction pointing at the wrong value. That is worse than the 422 this\n // replaces, because it looks authoritative, and worse still now that the\n // mismatch is routed to an agent told to apply the edit and change nothing\n // else. A mismatch is only reported when NONE of them matches.\n const companyPackage =\n companyPackages.find((candidate) => candidate.key === configuredKey) ??\n null;\n if (!companyPackage) {\n const first = companyPackages[0]!;\n return {\n mismatch: formatPackageKeyMismatch({\n configuredKey,\n companyKey: first.key,\n companyVersion: first.version,\n }),\n };\n }\n\n const versionOverride = resolvePublishVersion({\n configuredVersion: configured.version,\n publishedVersion: companyPackage.version,\n });\n if (!versionOverride) return {};\n\n return { versionOverride, configuredVersion: configured.version };\n}\n\n/**\n * Returns the version to publish as, or `null` to publish the configured one.\n *\n * A company has ONE widget package and several projects publish into it, so the\n * version belongs to that shared package rather than to any project's source\n * file. Nothing tells a project what the others have already released, so two\n * of them declaring `0.5.0` is inevitable — and republishing a version that\n * exists is refused with `422 Package version already exists`, whose only fix\n * is editing a SemVer string in a TypeScript file. For an author who never\n * opens a terminal that is the end of the road, and it happens on EVERY publish\n * after the first, not in some corner case.\n *\n * So a configured version at or below what is published becomes the next patch\n * after the published one. A configured version ABOVE it is honoured exactly —\n * that is a deliberate minor or major bump and the whole reason to keep the\n * field.\n *\n * Returns `null` on any version this cannot reason about — a prerelease, build\n * metadata, anything not a plain numeric triple. Guessing a successor for those\n * would be worse than letting the server answer.\n */\nexport function resolvePublishVersion(options: {\n readonly configuredVersion: string;\n readonly publishedVersion: string;\n}): string | null {\n const configured = parseVersionTriple(options.configuredVersion);\n const published = parseVersionTriple(options.publishedVersion);\n if (!configured || !published) return null;\n if (compareVersionTriples(configured, published) > 0) return null;\n\n const [major, minor, patch] = published;\n return `${major}.${minor}.${patch + 1}`;\n}\n\ntype VersionTriple = readonly [number, number, number];\n\nfunction parseVersionTriple(version: string): VersionTriple | null {\n const match = /^(\\d+)\\.(\\d+)\\.(\\d+)$/u.exec(version.trim());\n if (!match) return null;\n const [major, minor, patch] = [\n Number(match[1]),\n Number(match[2]),\n Number(match[3]),\n ];\n if (!Number.isSafeInteger(major)) return null;\n if (!Number.isSafeInteger(minor)) return null;\n if (!Number.isSafeInteger(patch)) return null;\n return [major, minor, patch];\n}\n\nfunction compareVersionTriples(a: VersionTriple, b: VersionTriple): number {\n for (let i = 0; i < 3; i++) {\n const left = a[i] ?? 0;\n const right = b[i] ?? 0;\n if (left !== right) return left - right;\n }\n return 0;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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"}