@burdenoff/microfe-cosmicintersection 2026.805.1 → 2026.827.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cosmicintersection/api/cosmicApi.d.ts +84 -2
- package/dist/cosmicintersection/api/cosmicApi.d.ts.map +1 -1
- package/dist/cosmicintersection/api/cosmicApi.js +135 -79
- package/dist/cosmicintersection/api/cosmicApi.js.map +1 -1
- package/dist/cosmicintersection/components/LineageGraph.d.ts +6 -1
- package/dist/cosmicintersection/components/LineageGraph.d.ts.map +1 -1
- package/dist/cosmicintersection/components/LineageGraph.js.map +1 -1
- package/dist/cosmicintersection/components/StepDAG.d.ts.map +1 -1
- package/dist/cosmicintersection/components/StepDAG.js +22 -18
- package/dist/cosmicintersection/components/StepDAG.js.map +1 -1
- package/dist/cosmicintersection/pages/collections/CollectionsPage.d.ts.map +1 -1
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js +52 -38
- package/dist/cosmicintersection/pages/collections/CollectionsPage.js.map +1 -1
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.d.ts.map +1 -1
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js +212 -164
- package/dist/cosmicintersection/pages/datasets/DatasetDetailPage.js.map +1 -1
- package/dist/cosmicintersection/pages/runs/RunDetailPage.d.ts.map +1 -1
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js +252 -118
- package/dist/cosmicintersection/pages/runs/RunDetailPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cosmicApi.js","names":[],"sources":["../../../src/cosmicintersection/api/cosmicApi.ts"],"sourcesContent":["/**\n * cosmicApi — hand-written typed data layer for the CosmicIntersection MFE.\n *\n * Mirrors the pattern in microfe-eventfullymanaged's eventApi.ts: inline `gql`\n * documents + `@apollo/client/react` hooks, with hand-written response/variables\n * types that track the wspace-cosmicintersection-svc subgraph SDL exactly. The\n * Apollo client is provided by the HOST app shell via React context (integrated\n * mode) — this module never constructs a client. Every `cos*` operation runs on\n * the workspace gateway (the default client in context).\n *\n * Scalar mapping: BigInt -> string, JSON -> Record<string, unknown>,\n * DateTime -> string (ISO).\n */\nimport { gql, type ErrorLike } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\n\nimport { notify } from '../lib/toast';\n\n/**\n * Shared mutation error sink. The gateway client runs with `errorPolicy: 'all'`,\n * so in-band GraphQL errors also invoke `onError`; wiring this on every write\n * mutation guarantees a failure is always surfaced to the user even if a caller\n * forgets to inspect the resolved result.\n */\nconst onMutationError = (error: ErrorLike): void => {\n notify.error('Something went wrong', error.message || 'Please try again.');\n};\n\n// ============================================================================\n// ENUMS (string-literal unions — exact SDL values)\n// ============================================================================\n\nexport type CosDatasetStatus = 'DRAFT' | 'INGESTING' | 'AVAILABLE' | 'DEPRECATED' | 'ARCHIVED';\nexport type CosAccessLevel = 'PUBLIC' | 'WORKSPACE' | 'RESTRICTED' | 'EMBARGOED';\nexport type CosSourceType =\n | 'TELESCOPE'\n | 'SATELLITE'\n | 'GROUND_SENSOR'\n | 'ARCHIVE'\n | 'API'\n | 'STREAM'\n | 'FILE_DROP'\n | 'SIMULATION';\nexport type CosSourceStatus =\n 'CONFIGURING' | 'CONNECTED' | 'SYNCING' | 'DEGRADED' | 'ERROR' | 'DISABLED';\nexport type CosFieldType =\n | 'STRING'\n | 'INTEGER'\n | 'FLOAT'\n | 'BOOLEAN'\n | 'TIMESTAMP'\n | 'COORDINATE'\n | 'SPECTRUM'\n | 'GEOMETRY'\n | 'IMAGE_REF'\n | 'JSON';\nexport type CosPipelineStatus = 'DRAFT' | 'ACTIVE' | 'PAUSED' | 'ARCHIVED';\nexport type CosPipelineTrigger = 'MANUAL' | 'SCHEDULED' | 'ON_INGEST' | 'WEBHOOK';\nexport type CosRunStatus = 'QUEUED' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'CANCELLED';\nexport type CosStepKind = 'INGEST' | 'CALIBRATE' | 'TRANSFORM' | 'ANALYZE' | 'EXPORT' | 'NOTIFY';\nexport type CosNotebookStatus = 'DRAFT' | 'RUNNING' | 'PUBLISHED' | 'ARCHIVED';\nexport type CosAnalysisStatus = 'PENDING' | 'RUNNING' | 'COMPLETED' | 'FAILED';\nexport type CosReleaseStatus = 'DRAFT' | 'UNDER_REVIEW' | 'PUBLISHED' | 'RETRACTED';\nexport type CosGrantStatus = 'PENDING' | 'ACTIVE' | 'EXPIRED' | 'REVOKED';\n\n// ============================================================================\n// ENTITY TYPES\n// ============================================================================\n\n/** Federated wspace-files File stub — only `{ id }` is resolvable in this subgraph. */\nexport interface CosFileRef {\n id: string;\n}\n\nexport interface CosSchemaField {\n id: string;\n workspaceId: string;\n datasetId: string;\n name: string;\n fieldType: CosFieldType;\n unit?: string | null;\n description?: string | null;\n nullable: boolean;\n position: number;\n provenance?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CosDataset {\n id: string;\n workspaceId: string;\n name: string;\n description?: string | null;\n status: CosDatasetStatus;\n accessLevel: CosAccessLevel;\n format?: string | null;\n sourceId?: string | null;\n collectionId?: string | null;\n /** BigInt returned as a numeric string. */\n rowCount: string;\n /** BigInt returned as a numeric string. */\n sizeBytes: string;\n version: number;\n lineageCaptured: boolean;\n coverage?: Record<string, unknown> | null;\n ingestedAt?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relations — only present when the operation selects them (detail queries).\n source?: CosSource | null;\n collection?: CosCollection | null;\n file?: CosFileRef | null;\n schemaFields?: CosSchemaField[];\n}\n\nexport interface CosSource {\n id: string;\n workspaceId: string;\n name: string;\n description?: string | null;\n type: CosSourceType;\n status: CosSourceStatus;\n endpoint?: string | null;\n config?: Record<string, unknown> | null;\n lastSyncedAt?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relation — present only on detail queries.\n datasets?: CosDataset[];\n}\n\nexport interface CosCollection {\n id: string;\n workspaceId: string;\n name: string;\n slug?: string | null;\n description?: string | null;\n isPublic: boolean;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relation — present only on detail queries.\n datasets?: CosDataset[];\n}\n\nexport interface CosPipeline {\n id: string;\n workspaceId: string;\n name: string;\n description?: string | null;\n status: CosPipelineStatus;\n trigger: CosPipelineTrigger;\n schedule?: string | null;\n definition?: Record<string, unknown> | null;\n version: number;\n lastRunAt?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relation — present only on detail queries.\n runs?: CosPipelineRun[];\n}\n\nexport interface CosPipelineRun {\n id: string;\n workspaceId: string;\n pipelineId: string;\n runNumber: number;\n status: CosRunStatus;\n datasetId?: string | null;\n params?: Record<string, unknown> | null;\n metrics?: Record<string, unknown> | null;\n triggeredBy?: string | null;\n startedAt?: string | null;\n finishedAt?: string | null;\n durationMs?: number | null;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n // Relations — present only on detail queries.\n pipeline?: CosPipeline | null;\n steps?: CosPipelineStep[];\n}\n\nexport interface CosPipelineStep {\n id: string;\n workspaceId: string;\n runId: string;\n name: string;\n kind: CosStepKind;\n position: number;\n status: CosRunStatus;\n inputs?: Record<string, unknown> | null;\n outputs?: Record<string, unknown> | null;\n logsRef?: string | null;\n startedAt?: string | null;\n finishedAt?: string | null;\n durationMs?: number | null;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CosNotebook {\n id: string;\n workspaceId: string;\n title: string;\n description?: string | null;\n status: CosNotebookStatus;\n runtime?: string | null;\n environment?: Record<string, unknown> | null;\n datasetIds: string[];\n isShared: boolean;\n shareSlug?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relations — present only on detail queries.\n file?: CosFileRef | null;\n analyses?: CosAnalysis[];\n releases?: CosRelease[];\n}\n\nexport interface CosAnalysis {\n id: string;\n workspaceId: string;\n title: string;\n status: CosAnalysisStatus;\n method?: string | null;\n aiAssisted: boolean;\n notebookId?: string | null;\n datasetId?: string | null;\n results?: Record<string, unknown> | null;\n outputFile?: CosFileRef | null;\n startedAt?: string | null;\n finishedAt?: string | null;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CosRelease {\n id: string;\n workspaceId: string;\n title: string;\n version: string;\n status: CosReleaseStatus;\n abstract?: string | null;\n authors: string[];\n datasetIds: string[];\n notebookId?: string | null;\n doi?: string | null;\n license?: string | null;\n publishedAt?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CosDataAccessGrant {\n id: string;\n workspaceId: string;\n datasetId: string;\n granteeId: string;\n status: CosGrantStatus;\n scopes: string[];\n reason?: string | null;\n grantedAt?: string | null;\n expiresAt?: string | null;\n revokedAt?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n// ============================================================================\n// PAGINATION / CONNECTIONS\n// ============================================================================\n\nexport interface CosPageInfo {\n hasMore: boolean;\n cursor?: string | null;\n}\n\nexport interface CosConnection<T> {\n items: T[];\n pageInfo: CosPageInfo;\n}\n\n/** Offset-based pagination input (PaginationInput in the SDL; limit defaults to 50). */\nexport interface CosPaginationInput {\n limit?: number;\n offset?: number;\n cursor?: string;\n}\n\n// ============================================================================\n// INPUT TYPES\n// ============================================================================\n\nexport interface CosCreateDatasetInput {\n name: string;\n description?: string;\n status?: CosDatasetStatus;\n accessLevel?: CosAccessLevel;\n format?: string;\n sourceId?: string;\n collectionId?: string;\n fileId?: string;\n coverage?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosUpdateDatasetInput {\n name?: string;\n description?: string;\n accessLevel?: CosAccessLevel;\n format?: string;\n collectionId?: string;\n coverage?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosAddSchemaFieldInput {\n datasetId: string;\n name: string;\n fieldType?: CosFieldType;\n unit?: string;\n description?: string;\n nullable?: boolean;\n position?: number;\n provenance?: string;\n}\n\nexport interface CosCreateSourceInput {\n name: string;\n type?: CosSourceType;\n status?: CosSourceStatus;\n description?: string;\n endpoint?: string;\n credentialRef?: string;\n config?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosUpdateSourceInput {\n name?: string;\n type?: CosSourceType;\n status?: CosSourceStatus;\n description?: string;\n endpoint?: string;\n credentialRef?: string;\n config?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosCreateCollectionInput {\n name: string;\n slug?: string;\n description?: string;\n isPublic?: boolean;\n tags?: string[];\n}\n\n/** All fields optional — only the provided keys are updated (CosUpdateCollectionInput in the SDL). */\nexport interface CosUpdateCollectionInput {\n name?: string;\n slug?: string;\n description?: string;\n isPublic?: boolean;\n tags?: string[];\n}\n\nexport interface CosCreatePipelineInput {\n name: string;\n description?: string;\n trigger?: CosPipelineTrigger;\n schedule?: string;\n definition?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosUpdatePipelineInput {\n name?: string;\n description?: string;\n status?: CosPipelineStatus;\n trigger?: CosPipelineTrigger;\n schedule?: string;\n definition?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosStartRunInput {\n pipelineId: string;\n datasetId?: string;\n params?: Record<string, unknown>;\n}\n\nexport interface CosAddRunStepInput {\n runId: string;\n name: string;\n kind?: CosStepKind;\n inputs?: Record<string, unknown>;\n position?: number;\n}\n\nexport interface CosCreateNotebookInput {\n title: string;\n description?: string;\n runtime?: string;\n environment?: Record<string, unknown>;\n datasetIds?: string[];\n fileId?: string;\n tags?: string[];\n}\n\nexport interface CosUpdateNotebookInput {\n title?: string;\n description?: string;\n status?: CosNotebookStatus;\n runtime?: string;\n environment?: Record<string, unknown>;\n datasetIds?: string[];\n isShared?: boolean;\n shareSlug?: string;\n tags?: string[];\n}\n\nexport interface CosRunAnalysisInput {\n title: string;\n method?: string;\n aiAssisted?: boolean;\n notebookId?: string;\n datasetId?: string;\n}\n\nexport interface CosCreateReleaseInput {\n title: string;\n version?: string;\n abstract?: string;\n authors?: string[];\n datasetIds?: string[];\n notebookId?: string;\n license?: string;\n}\n\nexport interface CosGrantAccessInput {\n datasetId: string;\n granteeId: string;\n scopes?: string[];\n reason?: string;\n expiresAt?: string;\n}\n\n// ============================================================================\n// GQL DOCUMENTS — QUERIES\n// ============================================================================\n\nexport const COS_HEALTH_QUERY = gql`\n query CosHealth {\n cosHealth\n }\n`;\n\nexport const COS_DATASETS_QUERY = gql`\n query CosListDatasets(\n $q: String\n $accessLevel: CosAccessLevel\n $format: String\n $collectionId: ID\n $sourceId: ID\n $status: CosDatasetStatus\n $pagination: PaginationInput\n ) {\n cosListDatasets(\n q: $q\n accessLevel: $accessLevel\n format: $format\n collectionId: $collectionId\n sourceId: $sourceId\n status: $status\n pagination: $pagination\n ) {\n items {\n id\n workspaceId\n name\n description\n status\n accessLevel\n format\n sourceId\n collectionId\n rowCount\n sizeBytes\n version\n lineageCaptured\n ingestedAt\n tags\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_DATASET_QUERY = gql`\n query CosDataset($id: ID!) {\n cosDataset(id: $id) {\n id\n workspaceId\n name\n description\n status\n accessLevel\n format\n sourceId\n collectionId\n rowCount\n sizeBytes\n version\n lineageCaptured\n coverage\n ingestedAt\n tags\n createdAt\n updatedAt\n file {\n id\n }\n source {\n id\n name\n type\n status\n }\n collection {\n id\n name\n slug\n }\n schemaFields {\n id\n datasetId\n name\n fieldType\n unit\n description\n nullable\n position\n provenance\n createdAt\n updatedAt\n }\n }\n }\n`;\n\nexport const COS_SOURCES_QUERY = gql`\n query CosListSources(\n $type: CosSourceType\n $status: CosSourceStatus\n $pagination: PaginationInput\n ) {\n cosListSources(type: $type, status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n name\n description\n type\n status\n endpoint\n config\n lastSyncedAt\n tags\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_SOURCE_QUERY = gql`\n query CosSource($id: ID!) {\n cosSource(id: $id) {\n id\n workspaceId\n name\n description\n type\n status\n endpoint\n config\n lastSyncedAt\n tags\n createdAt\n updatedAt\n datasets {\n id\n name\n status\n accessLevel\n rowCount\n updatedAt\n }\n }\n }\n`;\n\nexport const COS_COLLECTIONS_QUERY = gql`\n query CosListCollections {\n cosListCollections {\n id\n workspaceId\n name\n slug\n description\n isPublic\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_COLLECTION_QUERY = gql`\n query CosCollection($id: ID!) {\n cosCollection(id: $id) {\n id\n workspaceId\n name\n slug\n description\n isPublic\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_SCHEMA_FIELDS_QUERY = gql`\n query CosListSchemaFields($datasetId: ID!) {\n cosListSchemaFields(datasetId: $datasetId) {\n id\n workspaceId\n datasetId\n name\n fieldType\n unit\n description\n nullable\n position\n provenance\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_PIPELINES_QUERY = gql`\n query CosListPipelines($status: CosPipelineStatus, $pagination: PaginationInput) {\n cosListPipelines(status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n name\n description\n status\n trigger\n schedule\n version\n lastRunAt\n tags\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_PIPELINE_QUERY = gql`\n query CosPipeline($id: ID!) {\n cosPipeline(id: $id) {\n id\n workspaceId\n name\n description\n status\n trigger\n schedule\n definition\n version\n lastRunAt\n tags\n createdAt\n updatedAt\n runs {\n id\n runNumber\n status\n datasetId\n startedAt\n finishedAt\n durationMs\n createdAt\n }\n }\n }\n`;\n\nexport const COS_RUNS_QUERY = gql`\n query CosListRuns($pipelineId: ID, $status: CosRunStatus, $pagination: PaginationInput) {\n cosListRuns(pipelineId: $pipelineId, status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n pipelineId\n runNumber\n status\n datasetId\n triggeredBy\n startedAt\n finishedAt\n durationMs\n errorMessage\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_RUN_QUERY = gql`\n query CosRun($id: ID!) {\n cosRun(id: $id) {\n id\n workspaceId\n pipelineId\n runNumber\n status\n datasetId\n params\n metrics\n triggeredBy\n startedAt\n finishedAt\n durationMs\n errorMessage\n createdAt\n updatedAt\n pipeline {\n id\n name\n status\n }\n steps {\n id\n runId\n name\n kind\n position\n status\n startedAt\n finishedAt\n durationMs\n errorMessage\n }\n }\n }\n`;\n\nexport const COS_RUN_STEPS_QUERY = gql`\n query CosListRunSteps($runId: ID!) {\n cosListRunSteps(runId: $runId) {\n id\n workspaceId\n runId\n name\n kind\n position\n status\n inputs\n outputs\n logsRef\n startedAt\n finishedAt\n durationMs\n errorMessage\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_NOTEBOOKS_QUERY = gql`\n query CosListNotebooks($status: CosNotebookStatus, $pagination: PaginationInput) {\n cosListNotebooks(status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n title\n description\n status\n runtime\n datasetIds\n isShared\n shareSlug\n tags\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_NOTEBOOK_QUERY = gql`\n query CosNotebook($id: ID!) {\n cosNotebook(id: $id) {\n id\n workspaceId\n title\n description\n status\n runtime\n environment\n datasetIds\n isShared\n shareSlug\n tags\n createdAt\n updatedAt\n file {\n id\n }\n analyses {\n id\n title\n status\n aiAssisted\n method\n createdAt\n }\n releases {\n id\n title\n version\n status\n publishedAt\n }\n }\n }\n`;\n\nexport const COS_ANALYSES_QUERY = gql`\n query CosListAnalyses($datasetId: ID, $notebookId: ID, $status: CosAnalysisStatus) {\n cosListAnalyses(datasetId: $datasetId, notebookId: $notebookId, status: $status) {\n id\n workspaceId\n title\n status\n method\n aiAssisted\n notebookId\n datasetId\n results\n outputFile {\n id\n }\n startedAt\n finishedAt\n errorMessage\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_RELEASES_QUERY = gql`\n query CosListReleases($status: CosReleaseStatus, $pagination: PaginationInput) {\n cosListReleases(status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n title\n version\n status\n abstract\n authors\n datasetIds\n notebookId\n doi\n license\n publishedAt\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_ACCESS_GRANTS_QUERY = gql`\n query CosListAccessGrants($datasetId: ID, $status: CosGrantStatus) {\n cosListAccessGrants(datasetId: $datasetId, status: $status) {\n id\n workspaceId\n datasetId\n granteeId\n status\n scopes\n reason\n grantedAt\n expiresAt\n revokedAt\n createdAt\n updatedAt\n }\n }\n`;\n\n// ============================================================================\n// PLATFORM REUSE — activity feed (wspace-activity-svc, federated on the\n// workspace supergraph). The cos mutation-audit plugin already writes these\n// ActivityLog rows via be-sdk `trackOperation`; this is the read surface,\n// scoped to a single cos entity by `resourceId`. Only scalar fields are\n// selected so no cross-subgraph entity resolution is required.\n// ============================================================================\n\nexport const COS_ACTIVITY_BY_RESOURCE_QUERY = gql`\n query CosResourceActivity($filter: ActivityLogFilter) {\n getActivities(filter: $filter) {\n id\n action\n description\n resourceType\n resourceId\n userId\n timestamp\n }\n }\n`;\n\n// ============================================================================\n// GQL DOCUMENTS — MUTATIONS\n// ============================================================================\n\nexport const COS_CREATE_DATASET_MUTATION = gql`\n mutation CosCreateDataset($input: CosCreateDatasetInput!) {\n cosCreateDataset(input: $input) {\n id\n name\n status\n accessLevel\n sourceId\n collectionId\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_DATASET_MUTATION = gql`\n mutation CosUpdateDataset($id: ID!, $input: CosUpdateDatasetInput!) {\n cosUpdateDataset(id: $id, input: $input) {\n id\n name\n description\n status\n accessLevel\n format\n collectionId\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_PUBLISH_DATASET_MUTATION = gql`\n mutation CosPublishDataset($id: ID!) {\n cosPublishDataset(id: $id) {\n id\n status\n ingestedAt\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_DATASET_MUTATION = gql`\n mutation CosArchiveDataset($id: ID!) {\n cosArchiveDataset(id: $id)\n }\n`;\n\nexport const COS_ADD_SCHEMA_FIELD_MUTATION = gql`\n mutation CosAddSchemaField($input: CosAddSchemaFieldInput!) {\n cosAddSchemaField(input: $input) {\n id\n workspaceId\n datasetId\n name\n fieldType\n unit\n description\n nullable\n position\n provenance\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_CREATE_SOURCE_MUTATION = gql`\n mutation CosCreateSource($input: CosCreateSourceInput!) {\n cosCreateSource(input: $input) {\n id\n name\n type\n status\n endpoint\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_SOURCE_MUTATION = gql`\n mutation CosUpdateSource($id: ID!, $input: CosUpdateSourceInput!) {\n cosUpdateSource(id: $id, input: $input) {\n id\n name\n description\n type\n status\n endpoint\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_MARK_SOURCE_SYNCED_MUTATION = gql`\n mutation CosMarkSourceSynced($id: ID!) {\n cosMarkSourceSynced(id: $id) {\n id\n status\n lastSyncedAt\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_SOURCE_MUTATION = gql`\n mutation CosArchiveSource($id: ID!) {\n cosArchiveSource(id: $id)\n }\n`;\n\nexport const COS_CREATE_COLLECTION_MUTATION = gql`\n mutation CosCreateCollection($input: CosCreateCollectionInput!) {\n cosCreateCollection(input: $input) {\n id\n name\n slug\n description\n isPublic\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_COLLECTION_MUTATION = gql`\n mutation CosUpdateCollection($id: ID!, $input: CosUpdateCollectionInput!) {\n cosUpdateCollection(id: $id, input: $input) {\n id\n name\n slug\n description\n isPublic\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_COLLECTION_MUTATION = gql`\n mutation CosArchiveCollection($id: ID!) {\n cosArchiveCollection(id: $id)\n }\n`;\n\nexport const COS_CREATE_PIPELINE_MUTATION = gql`\n mutation CosCreatePipeline($input: CosCreatePipelineInput!) {\n cosCreatePipeline(input: $input) {\n id\n name\n status\n trigger\n schedule\n version\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_PIPELINE_MUTATION = gql`\n mutation CosUpdatePipeline($id: ID!, $input: CosUpdatePipelineInput!) {\n cosUpdatePipeline(id: $id, input: $input) {\n id\n name\n description\n status\n trigger\n schedule\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_PIPELINE_MUTATION = gql`\n mutation CosArchivePipeline($id: ID!) {\n cosArchivePipeline(id: $id)\n }\n`;\n\nexport const COS_START_RUN_MUTATION = gql`\n mutation CosStartRun($input: CosStartRunInput!) {\n cosStartRun(input: $input) {\n id\n pipelineId\n runNumber\n status\n datasetId\n startedAt\n createdAt\n }\n }\n`;\n\nexport const COS_TRANSITION_RUN_MUTATION = gql`\n mutation CosTransitionRun($id: ID!, $status: CosRunStatus!) {\n cosTransitionRun(id: $id, status: $status) {\n id\n status\n startedAt\n finishedAt\n durationMs\n updatedAt\n }\n }\n`;\n\nexport const COS_ADD_RUN_STEP_MUTATION = gql`\n mutation CosAddRunStep($input: CosAddRunStepInput!) {\n cosAddRunStep(input: $input) {\n id\n runId\n name\n kind\n position\n status\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_CREATE_NOTEBOOK_MUTATION = gql`\n mutation CosCreateNotebook($input: CosCreateNotebookInput!) {\n cosCreateNotebook(input: $input) {\n id\n title\n status\n runtime\n datasetIds\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_NOTEBOOK_MUTATION = gql`\n mutation CosUpdateNotebook($id: ID!, $input: CosUpdateNotebookInput!) {\n cosUpdateNotebook(id: $id, input: $input) {\n id\n title\n description\n status\n runtime\n datasetIds\n isShared\n shareSlug\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_NOTEBOOK_MUTATION = gql`\n mutation CosArchiveNotebook($id: ID!) {\n cosArchiveNotebook(id: $id)\n }\n`;\n\nexport const COS_RUN_ANALYSIS_MUTATION = gql`\n mutation CosRunAnalysis($input: CosRunAnalysisInput!) {\n cosRunAnalysis(input: $input) {\n id\n title\n status\n method\n aiAssisted\n notebookId\n datasetId\n startedAt\n createdAt\n }\n }\n`;\n\nexport const COS_COMPLETE_ANALYSIS_MUTATION = gql`\n mutation CosCompleteAnalysis(\n $id: ID!\n $status: CosAnalysisStatus!\n $results: JSON\n $outputFileId: ID\n ) {\n cosCompleteAnalysis(id: $id, status: $status, results: $results, outputFileId: $outputFileId) {\n id\n status\n results\n finishedAt\n errorMessage\n outputFile {\n id\n }\n updatedAt\n }\n }\n`;\n\nexport const COS_CREATE_RELEASE_MUTATION = gql`\n mutation CosCreateRelease($input: CosCreateReleaseInput!) {\n cosCreateRelease(input: $input) {\n id\n title\n version\n status\n authors\n datasetIds\n notebookId\n license\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_PUBLISH_RELEASE_MUTATION = gql`\n mutation CosPublishRelease($id: ID!, $doi: String) {\n cosPublishRelease(id: $id, doi: $doi) {\n id\n status\n doi\n publishedAt\n updatedAt\n }\n }\n`;\n\nexport const COS_GRANT_ACCESS_MUTATION = gql`\n mutation CosGrantAccess($input: CosGrantAccessInput!) {\n cosGrantAccess(input: $input) {\n id\n datasetId\n granteeId\n status\n scopes\n reason\n grantedAt\n expiresAt\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_REVOKE_ACCESS_MUTATION = gql`\n mutation CosRevokeAccess($id: ID!) {\n cosRevokeAccess(id: $id) {\n id\n status\n revokedAt\n updatedAt\n }\n }\n`;\n\n// ============================================================================\n// RESPONSE / VARIABLES TYPES\n// ============================================================================\n\nexport interface CosHealthQueryData {\n cosHealth: string;\n}\n\nexport interface CosDatasetsQueryData {\n cosListDatasets: CosConnection<CosDataset>;\n}\nexport interface CosDatasetsQueryVars {\n /** Full-text search across dataset name/description/tags (backend `q` arg). */\n q?: string;\n accessLevel?: CosAccessLevel;\n format?: string;\n collectionId?: string;\n sourceId?: string;\n status?: CosDatasetStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosDatasetQueryData {\n cosDataset: CosDataset | null;\n}\n\nexport interface CosSourcesQueryData {\n cosListSources: CosConnection<CosSource>;\n}\nexport interface CosSourcesQueryVars {\n type?: CosSourceType;\n status?: CosSourceStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosSourceQueryData {\n cosSource: CosSource | null;\n}\n\nexport interface CosCollectionsQueryData {\n cosListCollections: CosCollection[];\n}\n\nexport interface CosCollectionQueryData {\n cosCollection: CosCollection | null;\n}\n\nexport interface CosSchemaFieldsQueryData {\n cosListSchemaFields: CosSchemaField[];\n}\n\nexport interface CosPipelinesQueryData {\n cosListPipelines: CosConnection<CosPipeline>;\n}\nexport interface CosPipelinesQueryVars {\n status?: CosPipelineStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosPipelineQueryData {\n cosPipeline: CosPipeline | null;\n}\n\nexport interface CosRunsQueryData {\n cosListRuns: CosConnection<CosPipelineRun>;\n}\nexport interface CosRunsQueryVars {\n pipelineId?: string;\n status?: CosRunStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosRunQueryData {\n cosRun: CosPipelineRun | null;\n}\n\nexport interface CosRunStepsQueryData {\n cosListRunSteps: CosPipelineStep[];\n}\n\nexport interface CosNotebooksQueryData {\n cosListNotebooks: CosConnection<CosNotebook>;\n}\nexport interface CosNotebooksQueryVars {\n status?: CosNotebookStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosNotebookQueryData {\n cosNotebook: CosNotebook | null;\n}\n\nexport interface CosAnalysesQueryData {\n cosListAnalyses: CosAnalysis[];\n}\nexport interface CosAnalysesQueryVars {\n datasetId?: string;\n notebookId?: string;\n status?: CosAnalysisStatus;\n}\n\nexport interface CosReleasesQueryData {\n cosListReleases: CosConnection<CosRelease>;\n}\nexport interface CosReleasesQueryVars {\n status?: CosReleaseStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosAccessGrantsQueryData {\n cosListAccessGrants: CosDataAccessGrant[];\n}\nexport interface CosAccessGrantsQueryVars {\n datasetId?: string;\n status?: CosGrantStatus;\n}\n\n/** A single platform activity record (subset of wspace-activity-svc ActivityLog). */\nexport interface CosActivityEntry {\n id: string;\n action: string;\n description?: string | null;\n resourceType?: string | null;\n resourceId?: string | null;\n userId: string;\n timestamp: string;\n}\n\nexport interface CosActivityQueryData {\n getActivities: CosActivityEntry[];\n}\n\n/** Mirrors ActivityLogFilter — only the fields the cos activity panel needs. */\nexport interface CosActivityFilter {\n workspaceId?: string;\n resourceId?: string;\n resourceType?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface CosActivityQueryVars {\n filter?: CosActivityFilter;\n}\n\n// ============================================================================\n// QUERY HOOKS\n// ============================================================================\n\nexport const useCosHealthQuery = () => useQuery<CosHealthQueryData>(COS_HEALTH_QUERY);\n\nexport const useCosDatasetsQuery = (variables: CosDatasetsQueryVars = {}) =>\n useQuery<CosDatasetsQueryData, CosDatasetsQueryVars>(COS_DATASETS_QUERY, { variables });\n\nexport const useCosDatasetQuery = (id: string) =>\n useQuery<CosDatasetQueryData, { id: string }>(COS_DATASET_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosSourcesQuery = (variables: CosSourcesQueryVars = {}) =>\n useQuery<CosSourcesQueryData, CosSourcesQueryVars>(COS_SOURCES_QUERY, { variables });\n\nexport const useCosSourceQuery = (id: string) =>\n useQuery<CosSourceQueryData, { id: string }>(COS_SOURCE_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosCollectionsQuery = () =>\n useQuery<CosCollectionsQueryData>(COS_COLLECTIONS_QUERY);\n\nexport const useCosCollectionQuery = (id: string) =>\n useQuery<CosCollectionQueryData, { id: string }>(COS_COLLECTION_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosSchemaFieldsQuery = (datasetId: string) =>\n useQuery<CosSchemaFieldsQueryData, { datasetId: string }>(COS_SCHEMA_FIELDS_QUERY, {\n variables: { datasetId },\n skip: !datasetId,\n });\n\nexport const useCosPipelinesQuery = (variables: CosPipelinesQueryVars = {}) =>\n useQuery<CosPipelinesQueryData, CosPipelinesQueryVars>(COS_PIPELINES_QUERY, { variables });\n\nexport const useCosPipelineQuery = (id: string) =>\n useQuery<CosPipelineQueryData, { id: string }>(COS_PIPELINE_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosRunsQuery = (variables: CosRunsQueryVars = {}) =>\n useQuery<CosRunsQueryData, CosRunsQueryVars>(COS_RUNS_QUERY, { variables });\n\nexport const useCosRunQuery = (id: string) =>\n useQuery<CosRunQueryData, { id: string }>(COS_RUN_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosRunStepsQuery = (runId: string) =>\n useQuery<CosRunStepsQueryData, { runId: string }>(COS_RUN_STEPS_QUERY, {\n variables: { runId },\n skip: !runId,\n });\n\nexport const useCosNotebooksQuery = (variables: CosNotebooksQueryVars = {}) =>\n useQuery<CosNotebooksQueryData, CosNotebooksQueryVars>(COS_NOTEBOOKS_QUERY, { variables });\n\nexport const useCosNotebookQuery = (id: string) =>\n useQuery<CosNotebookQueryData, { id: string }>(COS_NOTEBOOK_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosAnalysesQuery = (variables: CosAnalysesQueryVars = {}) =>\n useQuery<CosAnalysesQueryData, CosAnalysesQueryVars>(COS_ANALYSES_QUERY, { variables });\n\nexport const useCosReleasesQuery = (variables: CosReleasesQueryVars = {}) =>\n useQuery<CosReleasesQueryData, CosReleasesQueryVars>(COS_RELEASES_QUERY, { variables });\n\nexport const useCosAccessGrantsQuery = (variables: CosAccessGrantsQueryVars = {}) =>\n useQuery<CosAccessGrantsQueryData, CosAccessGrantsQueryVars>(COS_ACCESS_GRANTS_QUERY, {\n variables,\n });\n\n/**\n * Resource-scoped platform activity for a single cos entity. RBAC on\n * `getActivities` scopes on `filter.workspaceId`, so both a workspaceId and the\n * entity's resourceId are required — the query is skipped until both are known.\n */\nexport const useCosResourceActivityQuery = (params: {\n workspaceId?: string;\n resourceId: string;\n resourceType?: string;\n limit?: number;\n}) => {\n const { workspaceId, resourceId, resourceType, limit = 20 } = params;\n return useQuery<CosActivityQueryData, CosActivityQueryVars>(COS_ACTIVITY_BY_RESOURCE_QUERY, {\n variables: { filter: { workspaceId, resourceId, resourceType, limit } },\n skip: !workspaceId || !resourceId,\n fetchPolicy: 'cache-and-network',\n });\n};\n\n// ============================================================================\n// MUTATION HOOKS\n// ============================================================================\n\nexport const useCosCreateDatasetMutation = () =>\n useMutation<{ cosCreateDataset: CosDataset }, { input: CosCreateDatasetInput }>(\n COS_CREATE_DATASET_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_DATASETS_QUERY }],\n }\n );\n\nexport const useCosUpdateDatasetMutation = () =>\n useMutation<{ cosUpdateDataset: CosDataset }, { id: string; input: CosUpdateDatasetInput }>(\n COS_UPDATE_DATASET_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_DATASETS_QUERY }],\n }\n );\n\nexport const useCosPublishDatasetMutation = () =>\n useMutation<{ cosPublishDataset: CosDataset }, { id: string }>(COS_PUBLISH_DATASET_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_DATASETS_QUERY }],\n });\n\nexport const useCosArchiveDatasetMutation = () =>\n useMutation<{ cosArchiveDataset: boolean }, { id: string }>(COS_ARCHIVE_DATASET_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_DATASETS_QUERY }],\n });\n\nexport const useCosAddSchemaFieldMutation = () =>\n useMutation<{ cosAddSchemaField: CosSchemaField }, { input: CosAddSchemaFieldInput }>(\n COS_ADD_SCHEMA_FIELD_MUTATION,\n { errorPolicy: 'all', onError: onMutationError }\n );\n\nexport const useCosCreateSourceMutation = () =>\n useMutation<{ cosCreateSource: CosSource }, { input: CosCreateSourceInput }>(\n COS_CREATE_SOURCE_MUTATION,\n { errorPolicy: 'all', onError: onMutationError, refetchQueries: [{ query: COS_SOURCES_QUERY }] }\n );\n\nexport const useCosUpdateSourceMutation = () =>\n useMutation<{ cosUpdateSource: CosSource }, { id: string; input: CosUpdateSourceInput }>(\n COS_UPDATE_SOURCE_MUTATION,\n { errorPolicy: 'all', onError: onMutationError, refetchQueries: [{ query: COS_SOURCES_QUERY }] }\n );\n\nexport const useCosMarkSourceSyncedMutation = () =>\n useMutation<{ cosMarkSourceSynced: CosSource }, { id: string }>(COS_MARK_SOURCE_SYNCED_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_SOURCES_QUERY }],\n });\n\nexport const useCosArchiveSourceMutation = () =>\n useMutation<{ cosArchiveSource: boolean }, { id: string }>(COS_ARCHIVE_SOURCE_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_SOURCES_QUERY }],\n });\n\nexport const useCosCreateCollectionMutation = () =>\n useMutation<{ cosCreateCollection: CosCollection }, { input: CosCreateCollectionInput }>(\n COS_CREATE_COLLECTION_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_COLLECTIONS_QUERY }],\n }\n );\n\nexport const useCosUpdateCollectionMutation = () =>\n useMutation<\n { cosUpdateCollection: CosCollection },\n { id: string; input: CosUpdateCollectionInput }\n >(COS_UPDATE_COLLECTION_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_COLLECTIONS_QUERY }],\n });\n\nexport const useCosArchiveCollectionMutation = () =>\n useMutation<{ cosArchiveCollection: boolean }, { id: string }>(COS_ARCHIVE_COLLECTION_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_COLLECTIONS_QUERY }],\n });\n\nexport const useCosCreatePipelineMutation = () =>\n useMutation<{ cosCreatePipeline: CosPipeline }, { input: CosCreatePipelineInput }>(\n COS_CREATE_PIPELINE_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_PIPELINES_QUERY }],\n }\n );\n\nexport const useCosUpdatePipelineMutation = () =>\n useMutation<{ cosUpdatePipeline: CosPipeline }, { id: string; input: CosUpdatePipelineInput }>(\n COS_UPDATE_PIPELINE_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_PIPELINES_QUERY }],\n }\n );\n\nexport const useCosArchivePipelineMutation = () =>\n useMutation<{ cosArchivePipeline: boolean }, { id: string }>(COS_ARCHIVE_PIPELINE_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_PIPELINES_QUERY }],\n });\n\nexport const useCosStartRunMutation = () =>\n useMutation<{ cosStartRun: CosPipelineRun }, { input: CosStartRunInput }>(\n COS_START_RUN_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_RUNS_QUERY }],\n }\n );\n\nexport const useCosTransitionRunMutation = () =>\n useMutation<{ cosTransitionRun: CosPipelineRun }, { id: string; status: CosRunStatus }>(\n COS_TRANSITION_RUN_MUTATION,\n { errorPolicy: 'all', onError: onMutationError, refetchQueries: [{ query: COS_RUNS_QUERY }] }\n );\n\nexport const useCosAddRunStepMutation = () =>\n useMutation<{ cosAddRunStep: CosPipelineStep }, { input: CosAddRunStepInput }>(\n COS_ADD_RUN_STEP_MUTATION,\n { errorPolicy: 'all', onError: onMutationError }\n );\n\nexport const useCosCreateNotebookMutation = () =>\n useMutation<{ cosCreateNotebook: CosNotebook }, { input: CosCreateNotebookInput }>(\n COS_CREATE_NOTEBOOK_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_NOTEBOOKS_QUERY }],\n }\n );\n\nexport const useCosUpdateNotebookMutation = () =>\n useMutation<{ cosUpdateNotebook: CosNotebook }, { id: string; input: CosUpdateNotebookInput }>(\n COS_UPDATE_NOTEBOOK_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_NOTEBOOKS_QUERY }],\n }\n );\n\nexport const useCosArchiveNotebookMutation = () =>\n useMutation<{ cosArchiveNotebook: boolean }, { id: string }>(COS_ARCHIVE_NOTEBOOK_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_NOTEBOOKS_QUERY }],\n });\n\nexport const useCosRunAnalysisMutation = () =>\n useMutation<{ cosRunAnalysis: CosAnalysis }, { input: CosRunAnalysisInput }>(\n COS_RUN_ANALYSIS_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_ANALYSES_QUERY }],\n }\n );\n\nexport const useCosCompleteAnalysisMutation = () =>\n useMutation<\n { cosCompleteAnalysis: CosAnalysis },\n {\n id: string;\n status: Extract<CosAnalysisStatus, 'COMPLETED' | 'FAILED'>;\n results?: Record<string, unknown>;\n outputFileId?: string;\n }\n >(COS_COMPLETE_ANALYSIS_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_ANALYSES_QUERY }],\n });\n\nexport const useCosCreateReleaseMutation = () =>\n useMutation<{ cosCreateRelease: CosRelease }, { input: CosCreateReleaseInput }>(\n COS_CREATE_RELEASE_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_RELEASES_QUERY }],\n }\n );\n\nexport const useCosPublishReleaseMutation = () =>\n useMutation<{ cosPublishRelease: CosRelease }, { id: string; doi?: string }>(\n COS_PUBLISH_RELEASE_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_RELEASES_QUERY }],\n }\n );\n\nexport const useCosGrantAccessMutation = () =>\n useMutation<{ cosGrantAccess: CosDataAccessGrant }, { input: CosGrantAccessInput }>(\n COS_GRANT_ACCESS_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_ACCESS_GRANTS_QUERY }],\n }\n );\n\nexport const useCosRevokeAccessMutation = () =>\n useMutation<{ cosRevokeAccess: CosDataAccessGrant }, { id: string }>(COS_REVOKE_ACCESS_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_ACCESS_GRANTS_QUERY }],\n });\n"],"mappings":";;;;AAwBA,IAAM,KAAmB,MAA2B;CAClD,EAAO,MAAM,wBAAwB,EAAM,WAAW,mBAAmB;AAC3E;AAibgC,CAAG;;;;;AAMnC,IAAa,IAAqB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CxB,IAAoB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDvB,IAAoB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BvB,IAAmB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;GA2BtB,IAAwB,CAAG;;;;;;;;;;;;;;GAgB3B,IAAuB,CAAG;;;;;;;;;;;;;;;AAgBA,CAAG;;;;;;;;;;;;;;;;;;AAmB1C,IAAa,IAAsB,CAAG;;;;;;;;;;;;;;;;;;;;;;;GAyBzB,IAAqB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BxB,IAAiB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;GA0BpB,KAAgB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCnB,KAAsB,CAAG;;;;;;;;;;;;;;;;;;;;;GAuBzB,IAAsB,CAAG;;;;;;;;;;;;;;;;;;;;;;;GAyBzB,IAAqB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCxB,IAAqB,CAAG;;;;;;;;;;;;;;;;;;;;;;GAwBxB,IAAqB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;GA2BxB,IAA0B,CAAG;;;;;;;;;;;;;;;;;GA2B7B,IAAiC,CAAG;;;;;;;;;;;;GAkBpC,IAA8B,CAAG;;;;;;;;;;;;;;GAgBjC,IAA8B,CAAG;;;;;;;;;;;;;;GAgBjC,IAA+B,CAAG;;;;;;;;;GAWlC,IAA+B,CAAG;;;;GAMlC,IAAgC,CAAG;;;;;;;;;;;;;;;;;GAmBnC,IAA6B,CAAG;;;;;;;;;;;;;GAehC,IAA6B,CAAG;;;;;;;;;;;;;GAehC,IAAkC,CAAG;;;;;;;;;GAWrC,IAA8B,CAAG;;;;GAMjC,IAAiC,CAAG;;;;;;;;;;;;;GAepC,IAAiC,CAAG;;;;;;;;;;;;GAcpC,IAAkC,CAAG;;;;GAMrC,IAA+B,CAAG;;;;;;;;;;;;;;GAgBlC,IAA+B,CAAG;;;;;;;;;;;;;GAelC,IAAgC,CAAG;;;;GAMnC,IAAyB,CAAG;;;;;;;;;;;;GAc5B,IAA8B,CAAG;;;;;;;;;;;GAajC,IAA4B,CAAG;;;;;;;;;;;;;GAe/B,IAA+B,CAAG;;;;;;;;;;;;;GAelC,IAA+B,CAAG;;;;;;;;;;;;;;;GAiBlC,IAAgC,CAAG;;;;GAMnC,IAA4B,CAAG;;;;;;;;;;;;;;GAgB/B,IAAiC,CAAG;;;;;;;;;;;;;;;;;;;GAqBpC,IAA8B,CAAG;;;;;;;;;;;;;;;GAiBjC,IAA+B,CAAG;;;;;;;;;;GAYlC,IAA4B,CAAG;;;;;;;;;;;;;;;GAiB/B,IAA6B,CAAG;;;;;;;;;GAkKhC,KAAuB,IAAkC,CAAC,MACrE,EAAqD,GAAoB,EAAE,aAAU,CAAC,GAE3E,KAAsB,MACjC,EAA8C,GAAmB;CAC/D,WAAW,EAAE,MAAG;CAChB,MAAM,CAAC;AACT,CAAC,GAEU,KAAsB,IAAiC,CAAC,MACnE,EAAmD,GAAmB,EAAE,aAAU,CAAC,GAExE,KAAqB,MAChC,EAA6C,GAAkB;CAC7D,WAAW,EAAE,MAAG;CAChB,MAAM,CAAC;AACT,CAAC,GAEU,UACX,EAAkC,CAAqB,GAE5C,KAAyB,MACpC,EAAiD,GAAsB;CACrE,WAAW,EAAE,MAAG;CAChB,MAAM,CAAC;AACT,CAAC,GAQU,MAAwB,IAAmC,CAAC,MACvE,EAAuD,GAAqB,EAAE,aAAU,CAAC,GAE9E,MAAuB,MAClC,EAA+C,GAAoB;CACjE,WAAW,EAAE,MAAG;CAChB,MAAM,CAAC;AACT,CAAC,GAEU,MAAmB,IAA8B,CAAC,MAC7D,EAA6C,GAAgB,EAAE,aAAU,CAAC,GAE/D,MAAkB,MAC7B,EAA0C,IAAe;CACvD,WAAW,EAAE,MAAG;CAChB,MAAM,CAAC;AACT,CAAC,GAEU,MAAuB,MAClC,EAAkD,IAAqB;CACrE,WAAW,EAAE,SAAM;CACnB,MAAM,CAAC;AACT,CAAC,GAEU,MAAwB,IAAmC,CAAC,MACvE,EAAuD,GAAqB,EAAE,aAAU,CAAC,GAE9E,MAAuB,MAClC,EAA+C,GAAoB;CACjE,WAAW,EAAE,MAAG;CAChB,MAAM,CAAC;AACT,CAAC,GAEU,MAAuB,IAAkC,CAAC,MACrE,EAAqD,GAAoB,EAAE,aAAU,CAAC,GAE3E,MAAuB,IAAkC,CAAC,MACrE,EAAqD,GAAoB,EAAE,aAAU,CAAC,GAE3E,MAA2B,IAAsC,CAAC,MAC7E,EAA6D,GAAyB,EACpF,aACF,CAAC,GAOU,MAA+B,MAKtC;CACJ,IAAM,EAAE,gBAAa,eAAY,iBAAc,WAAQ,OAAO;CAC9D,OAAO,EAAqD,GAAgC;EAC1F,WAAW,EAAE,QAAQ;GAAE;GAAa;GAAY;GAAc;EAAM,EAAE;EACtE,MAAM,CAAC,KAAe,CAAC;EACvB,aAAa;CACf,CAAC;AACH,GAMa,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAmB,CAAC;AAChD,CACF,GAEW,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAmB,CAAC;AAChD,CACF,GAEW,WACX,EAA+D,GAA8B;CAC3F,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAmB,CAAC;AAChD,CAAC,GAEU,WACX,EAA4D,GAA8B;CACxF,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAmB,CAAC;AAChD,CAAC,GAEU,WACX,EACE,GACA;CAAE,aAAa;CAAO,SAAS;AAAgB,CACjD,GAEW,WACX,EACE,GACA;CAAE,aAAa;CAAO,SAAS;CAAiB,gBAAgB,CAAC,EAAE,OAAO,EAAkB,CAAC;AAAE,CACjG,GAEW,WACX,EACE,GACA;CAAE,aAAa;CAAO,SAAS;CAAiB,gBAAgB,CAAC,EAAE,OAAO,EAAkB,CAAC;AAAE,CACjG,GAEW,WACX,EAAgE,GAAiC;CAC/F,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAkB,CAAC;AAC/C,CAAC,GAEU,WACX,EAA2D,GAA6B;CACtF,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAkB,CAAC;AAC/C,CAAC,GAEU,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAsB,CAAC;AACnD,CACF,GAEW,WACX,EAGE,GAAgC;CAChC,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAsB,CAAC;AACnD,CAAC,GAEU,WACX,EAA+D,GAAiC;CAC9F,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAsB,CAAC;AACnD,CAAC,GAEU,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAoB,CAAC;AACjD,CACF,GAEW,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAoB,CAAC;AACjD,CACF,GAEW,WACX,EAA6D,GAA+B;CAC1F,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAoB,CAAC;AACjD,CAAC,GAEU,UACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAe,CAAC;AAC5C,CACF,GAEW,WACX,EACE,GACA;CAAE,aAAa;CAAO,SAAS;CAAiB,gBAAgB,CAAC,EAAE,OAAO,EAAe,CAAC;AAAE,CAC9F,GAEW,WACX,EACE,GACA;CAAE,aAAa;CAAO,SAAS;AAAgB,CACjD,GAEW,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAoB,CAAC;AACjD,CACF,GAEW,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAoB,CAAC;AACjD,CACF,GAEW,WACX,EAA6D,GAA+B;CAC1F,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAoB,CAAC;AACjD,CAAC,GAEU,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAmB,CAAC;AAChD,CACF,GAEW,WACX,EAQE,GAAgC;CAChC,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAmB,CAAC;AAChD,CAAC,GAEU,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAmB,CAAC;AAChD,CACF,GAEW,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAmB,CAAC;AAChD,CACF,GAEW,WACX,EACE,GACA;CACE,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAwB,CAAC;AACrD,CACF,GAEW,WACX,EAAqE,GAA4B;CAC/F,aAAa;CACb,SAAS;CACT,gBAAgB,CAAC,EAAE,OAAO,EAAwB,CAAC;AACrD,CAAC"}
|
|
1
|
+
{"version":3,"file":"cosmicApi.js","names":[],"sources":["../../../src/cosmicintersection/api/cosmicApi.ts"],"sourcesContent":["/**\n * cosmicApi — hand-written typed data layer for the CosmicIntersection MFE.\n *\n * Mirrors the pattern in microfe-eventfullymanaged's eventApi.ts: inline `gql`\n * documents + `@apollo/client/react` hooks, with hand-written response/variables\n * types that track the wspace-cosmicintersection-svc subgraph SDL exactly. The\n * Apollo client is provided by the HOST app shell via React context (integrated\n * mode) — this module never constructs a client. Every `cos*` operation runs on\n * the workspace gateway (the default client in context).\n *\n * Scalar mapping: BigInt -> string, JSON -> Record<string, unknown>,\n * DateTime -> string (ISO).\n */\nimport { gql, type ErrorLike } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\n\nimport { notify } from '../lib/toast';\n\n/**\n * Shared mutation error sink. The gateway client runs with `errorPolicy: 'all'`,\n * so in-band GraphQL errors also invoke `onError`; wiring this on every write\n * mutation guarantees a failure is always surfaced to the user even if a caller\n * forgets to inspect the resolved result.\n */\nconst onMutationError = (error: ErrorLike): void => {\n notify.error('Something went wrong', error.message || 'Please try again.');\n};\n\n// ============================================================================\n// ENUMS (string-literal unions — exact SDL values)\n// ============================================================================\n\nexport type CosDatasetStatus = 'DRAFT' | 'INGESTING' | 'AVAILABLE' | 'DEPRECATED' | 'ARCHIVED';\nexport type CosAccessLevel = 'PUBLIC' | 'WORKSPACE' | 'RESTRICTED' | 'EMBARGOED';\nexport type CosSourceType =\n | 'TELESCOPE'\n | 'SATELLITE'\n | 'GROUND_SENSOR'\n | 'ARCHIVE'\n | 'API'\n | 'STREAM'\n | 'FILE_DROP'\n | 'SIMULATION';\nexport type CosSourceStatus =\n 'CONFIGURING' | 'CONNECTED' | 'SYNCING' | 'DEGRADED' | 'ERROR' | 'DISABLED';\nexport type CosFieldType =\n | 'STRING'\n | 'INTEGER'\n | 'FLOAT'\n | 'BOOLEAN'\n | 'TIMESTAMP'\n | 'COORDINATE'\n | 'SPECTRUM'\n | 'GEOMETRY'\n | 'IMAGE_REF'\n | 'JSON';\nexport type CosPipelineStatus = 'DRAFT' | 'ACTIVE' | 'PAUSED' | 'ARCHIVED';\nexport type CosPipelineTrigger = 'MANUAL' | 'SCHEDULED' | 'ON_INGEST' | 'WEBHOOK';\nexport type CosRunStatus = 'QUEUED' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'CANCELLED';\n/**\n * Full SDL vocabulary. The four geospatial kinds are recognised values a step\n * can already carry (BOFF-4355) — only RASTER_CALC has an execution backend, so\n * they are readable/renderable but are deliberately not offered as authoring\n * options in the add-step form.\n */\nexport type CosStepKind =\n | 'INGEST'\n | 'CALIBRATE'\n | 'TRANSFORM'\n | 'ANALYZE'\n | 'EXPORT'\n | 'NOTIFY'\n | 'RASTER_CALC'\n | 'REPROJECT'\n | 'TILE'\n | 'ZONAL_STATS';\nexport type CosNotebookStatus = 'DRAFT' | 'RUNNING' | 'PUBLISHED' | 'ARCHIVED';\nexport type CosAnalysisStatus = 'PENDING' | 'RUNNING' | 'COMPLETED' | 'FAILED';\nexport type CosReleaseStatus = 'DRAFT' | 'UNDER_REVIEW' | 'PUBLISHED' | 'RETRACTED';\nexport type CosGrantStatus = 'PENDING' | 'ACTIVE' | 'EXPIRED' | 'REVOKED';\n\n// ============================================================================\n// ENTITY TYPES\n// ============================================================================\n\n/** Federated wspace-files File stub — only `{ id }` is resolvable in this subgraph. */\nexport interface CosFileRef {\n id: string;\n}\n\n/** An entity selected id-only, where the operation needs its existence, not its body. */\nexport interface CosIdRef {\n id: string;\n}\n\n/**\n * Per-parent cap the subgraph applies to every relation field\n * (`capPerGroup(rows, key, DEFAULT_LIMIT)` in wspace-cosmicintersection-svc's\n * dataloaders — DEFAULT_LIMIT is 50).\n *\n * A relation array of exactly this length means \"at least this many\", NOT an\n * exact total: render it as `50+`, never as a precise count.\n */\nexport const COS_RELATION_PAGE_SIZE = 50;\n\nexport interface CosSchemaField {\n id: string;\n workspaceId: string;\n datasetId: string;\n name: string;\n fieldType: CosFieldType;\n unit?: string | null;\n description?: string | null;\n nullable: boolean;\n position: number;\n provenance?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CosDataset {\n id: string;\n workspaceId: string;\n name: string;\n description?: string | null;\n status: CosDatasetStatus;\n accessLevel: CosAccessLevel;\n format?: string | null;\n sourceId?: string | null;\n collectionId?: string | null;\n /** BigInt returned as a numeric string. */\n rowCount: string;\n /** BigInt returned as a numeric string. */\n sizeBytes: string;\n version: number;\n lineageCaptured: boolean;\n coverage?: Record<string, unknown> | null;\n ingestedAt?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relations — only present when the operation selects them (detail queries).\n source?: CosSource | null;\n collection?: CosCollection | null;\n file?: CosFileRef | null;\n schemaFields?: CosSchemaField[];\n}\n\nexport interface CosSource {\n id: string;\n workspaceId: string;\n name: string;\n description?: string | null;\n type: CosSourceType;\n status: CosSourceStatus;\n endpoint?: string | null;\n config?: Record<string, unknown> | null;\n lastSyncedAt?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relation — present only on detail queries.\n datasets?: CosDataset[];\n}\n\nexport interface CosCollection {\n id: string;\n workspaceId: string;\n name: string;\n slug?: string | null;\n description?: string | null;\n isPublic: boolean;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relation — present only on detail queries.\n datasets?: CosDataset[];\n}\n\nexport interface CosPipeline {\n id: string;\n workspaceId: string;\n name: string;\n description?: string | null;\n status: CosPipelineStatus;\n trigger: CosPipelineTrigger;\n schedule?: string | null;\n definition?: Record<string, unknown> | null;\n version: number;\n lastRunAt?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relation — present only on detail queries.\n runs?: CosPipelineRun[];\n}\n\nexport interface CosPipelineRun {\n id: string;\n workspaceId: string;\n pipelineId: string;\n runNumber: number;\n status: CosRunStatus;\n datasetId?: string | null;\n params?: Record<string, unknown> | null;\n metrics?: Record<string, unknown> | null;\n triggeredBy?: string | null;\n startedAt?: string | null;\n finishedAt?: string | null;\n durationMs?: number | null;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n // Relations — present only on detail queries.\n pipeline?: CosPipeline | null;\n steps?: CosPipelineStep[];\n}\n\nexport interface CosPipelineStep {\n id: string;\n workspaceId: string;\n runId: string;\n name: string;\n kind: CosStepKind;\n position: number;\n status: CosRunStatus;\n inputs?: Record<string, unknown> | null;\n outputs?: Record<string, unknown> | null;\n logsRef?: string | null;\n startedAt?: string | null;\n finishedAt?: string | null;\n durationMs?: number | null;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CosNotebook {\n id: string;\n workspaceId: string;\n title: string;\n description?: string | null;\n status: CosNotebookStatus;\n runtime?: string | null;\n environment?: Record<string, unknown> | null;\n datasetIds: string[];\n isShared: boolean;\n shareSlug?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n // Relations — present only on detail queries.\n file?: CosFileRef | null;\n analyses?: CosAnalysis[];\n releases?: CosRelease[];\n}\n\nexport interface CosAnalysis {\n id: string;\n workspaceId: string;\n title: string;\n status: CosAnalysisStatus;\n method?: string | null;\n aiAssisted: boolean;\n notebookId?: string | null;\n datasetId?: string | null;\n results?: Record<string, unknown> | null;\n outputFile?: CosFileRef | null;\n startedAt?: string | null;\n finishedAt?: string | null;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CosRelease {\n id: string;\n workspaceId: string;\n title: string;\n version: string;\n status: CosReleaseStatus;\n abstract?: string | null;\n authors: string[];\n datasetIds: string[];\n notebookId?: string | null;\n doi?: string | null;\n license?: string | null;\n publishedAt?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CosDataAccessGrant {\n id: string;\n workspaceId: string;\n datasetId: string;\n granteeId: string;\n status: CosGrantStatus;\n scopes: string[];\n reason?: string | null;\n grantedAt?: string | null;\n expiresAt?: string | null;\n revokedAt?: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n// ============================================================================\n// PAGINATION / CONNECTIONS\n// ============================================================================\n\nexport interface CosPageInfo {\n hasMore: boolean;\n cursor?: string | null;\n}\n\nexport interface CosConnection<T> {\n items: T[];\n pageInfo: CosPageInfo;\n}\n\n/** Offset-based pagination input (PaginationInput in the SDL; limit defaults to 50). */\nexport interface CosPaginationInput {\n limit?: number;\n offset?: number;\n cursor?: string;\n}\n\n// ============================================================================\n// INPUT TYPES\n// ============================================================================\n\nexport interface CosCreateDatasetInput {\n name: string;\n description?: string;\n status?: CosDatasetStatus;\n accessLevel?: CosAccessLevel;\n format?: string;\n sourceId?: string;\n collectionId?: string;\n fileId?: string;\n coverage?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosUpdateDatasetInput {\n name?: string;\n description?: string;\n accessLevel?: CosAccessLevel;\n format?: string;\n collectionId?: string;\n coverage?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosAddSchemaFieldInput {\n datasetId: string;\n name: string;\n fieldType?: CosFieldType;\n unit?: string;\n description?: string;\n nullable?: boolean;\n position?: number;\n provenance?: string;\n}\n\nexport interface CosCreateSourceInput {\n name: string;\n type?: CosSourceType;\n status?: CosSourceStatus;\n description?: string;\n endpoint?: string;\n credentialRef?: string;\n config?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosUpdateSourceInput {\n name?: string;\n type?: CosSourceType;\n status?: CosSourceStatus;\n description?: string;\n endpoint?: string;\n credentialRef?: string;\n config?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosCreateCollectionInput {\n name: string;\n slug?: string;\n description?: string;\n isPublic?: boolean;\n tags?: string[];\n}\n\n/** All fields optional — only the provided keys are updated (CosUpdateCollectionInput in the SDL). */\nexport interface CosUpdateCollectionInput {\n name?: string;\n slug?: string;\n description?: string;\n isPublic?: boolean;\n tags?: string[];\n}\n\nexport interface CosCreatePipelineInput {\n name: string;\n description?: string;\n trigger?: CosPipelineTrigger;\n schedule?: string;\n definition?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosUpdatePipelineInput {\n name?: string;\n description?: string;\n status?: CosPipelineStatus;\n trigger?: CosPipelineTrigger;\n schedule?: string;\n definition?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface CosStartRunInput {\n pipelineId: string;\n datasetId?: string;\n params?: Record<string, unknown>;\n}\n\nexport interface CosAddRunStepInput {\n runId: string;\n name: string;\n kind?: CosStepKind;\n inputs?: Record<string, unknown>;\n position?: number;\n}\n\nexport interface CosCreateNotebookInput {\n title: string;\n description?: string;\n runtime?: string;\n environment?: Record<string, unknown>;\n datasetIds?: string[];\n fileId?: string;\n tags?: string[];\n}\n\nexport interface CosUpdateNotebookInput {\n title?: string;\n description?: string;\n status?: CosNotebookStatus;\n runtime?: string;\n environment?: Record<string, unknown>;\n datasetIds?: string[];\n isShared?: boolean;\n shareSlug?: string;\n tags?: string[];\n}\n\nexport interface CosRunAnalysisInput {\n title: string;\n method?: string;\n aiAssisted?: boolean;\n notebookId?: string;\n datasetId?: string;\n}\n\nexport interface CosCreateReleaseInput {\n title: string;\n version?: string;\n abstract?: string;\n authors?: string[];\n datasetIds?: string[];\n notebookId?: string;\n license?: string;\n}\n\nexport interface CosGrantAccessInput {\n datasetId: string;\n granteeId: string;\n scopes?: string[];\n reason?: string;\n expiresAt?: string;\n}\n\n// ============================================================================\n// GQL DOCUMENTS — QUERIES\n// ============================================================================\n\nexport const COS_HEALTH_QUERY = gql`\n query CosHealth {\n cosHealth\n }\n`;\n\nexport const COS_DATASETS_QUERY = gql`\n query CosListDatasets(\n $q: String\n $accessLevel: CosAccessLevel\n $format: String\n $collectionId: ID\n $sourceId: ID\n $status: CosDatasetStatus\n $pagination: PaginationInput\n ) {\n cosListDatasets(\n q: $q\n accessLevel: $accessLevel\n format: $format\n collectionId: $collectionId\n sourceId: $sourceId\n status: $status\n pagination: $pagination\n ) {\n items {\n id\n workspaceId\n name\n description\n status\n accessLevel\n format\n sourceId\n collectionId\n rowCount\n sizeBytes\n version\n lineageCaptured\n ingestedAt\n tags\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_DATASET_QUERY = gql`\n query CosDataset($id: ID!) {\n cosDataset(id: $id) {\n id\n workspaceId\n name\n description\n status\n accessLevel\n format\n sourceId\n collectionId\n rowCount\n sizeBytes\n version\n lineageCaptured\n coverage\n ingestedAt\n tags\n createdAt\n updatedAt\n file {\n id\n }\n source {\n id\n name\n type\n status\n }\n collection {\n id\n name\n slug\n }\n schemaFields {\n id\n datasetId\n name\n fieldType\n unit\n description\n nullable\n position\n provenance\n createdAt\n updatedAt\n }\n }\n }\n`;\n\nexport const COS_SOURCES_QUERY = gql`\n query CosListSources(\n $type: CosSourceType\n $status: CosSourceStatus\n $pagination: PaginationInput\n ) {\n cosListSources(type: $type, status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n name\n description\n type\n status\n endpoint\n config\n lastSyncedAt\n tags\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_SOURCE_QUERY = gql`\n query CosSource($id: ID!) {\n cosSource(id: $id) {\n id\n workspaceId\n name\n description\n type\n status\n endpoint\n config\n lastSyncedAt\n tags\n createdAt\n updatedAt\n datasets {\n id\n name\n status\n accessLevel\n rowCount\n updatedAt\n }\n }\n }\n`;\n\n/**\n * `datasets` is selected id-only so each card can show how many datasets the\n * collection holds. The subgraph resolves it through `collectionDatasetsLoader`\n * (one batched query for the whole page) and filters to the datasets THIS actor\n * may read, so the length is the caller's visible count — capped at\n * `COS_RELATION_PAGE_SIZE`.\n */\nexport const COS_COLLECTIONS_QUERY = gql`\n query CosListCollections {\n cosListCollections {\n id\n workspaceId\n name\n slug\n description\n isPublic\n tags\n createdAt\n updatedAt\n datasets {\n id\n }\n }\n }\n`;\n\nexport const COS_COLLECTION_QUERY = gql`\n query CosCollection($id: ID!) {\n cosCollection(id: $id) {\n id\n workspaceId\n name\n slug\n description\n isPublic\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_SCHEMA_FIELDS_QUERY = gql`\n query CosListSchemaFields($datasetId: ID!) {\n cosListSchemaFields(datasetId: $datasetId) {\n id\n workspaceId\n datasetId\n name\n fieldType\n unit\n description\n nullable\n position\n provenance\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_PIPELINES_QUERY = gql`\n query CosListPipelines($status: CosPipelineStatus, $pagination: PaginationInput) {\n cosListPipelines(status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n name\n description\n status\n trigger\n schedule\n version\n lastRunAt\n tags\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_PIPELINE_QUERY = gql`\n query CosPipeline($id: ID!) {\n cosPipeline(id: $id) {\n id\n workspaceId\n name\n description\n status\n trigger\n schedule\n definition\n version\n lastRunAt\n tags\n createdAt\n updatedAt\n runs {\n id\n runNumber\n status\n datasetId\n startedAt\n finishedAt\n durationMs\n createdAt\n }\n }\n }\n`;\n\nexport const COS_RUNS_QUERY = gql`\n query CosListRuns($pipelineId: ID, $status: CosRunStatus, $pagination: PaginationInput) {\n cosListRuns(pipelineId: $pipelineId, status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n pipelineId\n runNumber\n status\n datasetId\n triggeredBy\n startedAt\n finishedAt\n durationMs\n errorMessage\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_RUN_QUERY = gql`\n query CosRun($id: ID!) {\n cosRun(id: $id) {\n id\n workspaceId\n pipelineId\n runNumber\n status\n datasetId\n params\n metrics\n triggeredBy\n startedAt\n finishedAt\n durationMs\n errorMessage\n createdAt\n updatedAt\n pipeline {\n id\n name\n status\n trigger\n schedule\n }\n steps {\n id\n runId\n name\n kind\n position\n status\n startedAt\n finishedAt\n durationMs\n errorMessage\n }\n }\n }\n`;\n\n/**\n * Other FAILED runs of the same pipeline, newest first, each with its steps so\n * the caller can name the step that broke. `steps` resolves through\n * `pipelineRunStepsLoader`, so the whole list costs one extra batched query.\n */\nexport const COS_PIPELINE_FAILED_RUNS_QUERY = gql`\n query CosPipelineFailedRuns($pipelineId: ID!, $pagination: PaginationInput) {\n cosListRuns(pipelineId: $pipelineId, status: FAILED, pagination: $pagination) {\n items {\n id\n workspaceId\n pipelineId\n runNumber\n status\n errorMessage\n startedAt\n finishedAt\n createdAt\n updatedAt\n steps {\n id\n runId\n name\n kind\n position\n status\n errorMessage\n }\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\n/**\n * Minimal dataset lookup — resolves an id held on another entity (e.g.\n * `CosPipelineRun.datasetId`, which the SDL exposes as a bare ID with no\n * relation field) to something a human can read. Returns null when the caller\n * has no read access to that dataset, so callers must fall back to the id.\n */\nexport const COS_DATASET_SUMMARY_QUERY = gql`\n query CosDatasetSummary($id: ID!) {\n cosDataset(id: $id) {\n id\n name\n status\n accessLevel\n }\n }\n`;\n\nexport const COS_RUN_STEPS_QUERY = gql`\n query CosListRunSteps($runId: ID!) {\n cosListRunSteps(runId: $runId) {\n id\n workspaceId\n runId\n name\n kind\n position\n status\n inputs\n outputs\n logsRef\n startedAt\n finishedAt\n durationMs\n errorMessage\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_NOTEBOOKS_QUERY = gql`\n query CosListNotebooks($status: CosNotebookStatus, $pagination: PaginationInput) {\n cosListNotebooks(status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n title\n description\n status\n runtime\n datasetIds\n isShared\n shareSlug\n tags\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_NOTEBOOK_QUERY = gql`\n query CosNotebook($id: ID!) {\n cosNotebook(id: $id) {\n id\n workspaceId\n title\n description\n status\n runtime\n environment\n datasetIds\n isShared\n shareSlug\n tags\n createdAt\n updatedAt\n file {\n id\n }\n analyses {\n id\n title\n status\n aiAssisted\n method\n createdAt\n }\n releases {\n id\n title\n version\n status\n publishedAt\n }\n }\n }\n`;\n\nexport const COS_ANALYSES_QUERY = gql`\n query CosListAnalyses($datasetId: ID, $notebookId: ID, $status: CosAnalysisStatus) {\n cosListAnalyses(datasetId: $datasetId, notebookId: $notebookId, status: $status) {\n id\n workspaceId\n title\n status\n method\n aiAssisted\n notebookId\n datasetId\n results\n outputFile {\n id\n }\n startedAt\n finishedAt\n errorMessage\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_RELEASES_QUERY = gql`\n query CosListReleases($status: CosReleaseStatus, $pagination: PaginationInput) {\n cosListReleases(status: $status, pagination: $pagination) {\n items {\n id\n workspaceId\n title\n version\n status\n abstract\n authors\n datasetIds\n notebookId\n doi\n license\n publishedAt\n createdAt\n updatedAt\n }\n pageInfo {\n hasMore\n cursor\n }\n }\n }\n`;\n\nexport const COS_ACCESS_GRANTS_QUERY = gql`\n query CosListAccessGrants($datasetId: ID, $status: CosGrantStatus) {\n cosListAccessGrants(datasetId: $datasetId, status: $status) {\n id\n workspaceId\n datasetId\n granteeId\n status\n scopes\n reason\n grantedAt\n expiresAt\n revokedAt\n createdAt\n updatedAt\n }\n }\n`;\n\n// ============================================================================\n// PLATFORM REUSE — activity feed (wspace-activity-svc, federated on the\n// workspace supergraph). The cos mutation-audit plugin already writes these\n// ActivityLog rows via be-sdk `trackOperation`; this is the read surface,\n// scoped to a single cos entity by `resourceId`. Only scalar fields are\n// selected so no cross-subgraph entity resolution is required.\n// ============================================================================\n\nexport const COS_ACTIVITY_BY_RESOURCE_QUERY = gql`\n query CosResourceActivity($filter: ActivityLogFilter) {\n getActivities(filter: $filter) {\n id\n action\n description\n resourceType\n resourceId\n userId\n timestamp\n }\n }\n`;\n\n// ============================================================================\n// GQL DOCUMENTS — MUTATIONS\n// ============================================================================\n\nexport const COS_CREATE_DATASET_MUTATION = gql`\n mutation CosCreateDataset($input: CosCreateDatasetInput!) {\n cosCreateDataset(input: $input) {\n id\n name\n status\n accessLevel\n sourceId\n collectionId\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_DATASET_MUTATION = gql`\n mutation CosUpdateDataset($id: ID!, $input: CosUpdateDatasetInput!) {\n cosUpdateDataset(id: $id, input: $input) {\n id\n name\n description\n status\n accessLevel\n format\n collectionId\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_PUBLISH_DATASET_MUTATION = gql`\n mutation CosPublishDataset($id: ID!) {\n cosPublishDataset(id: $id) {\n id\n status\n ingestedAt\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_DATASET_MUTATION = gql`\n mutation CosArchiveDataset($id: ID!) {\n cosArchiveDataset(id: $id)\n }\n`;\n\nexport const COS_ADD_SCHEMA_FIELD_MUTATION = gql`\n mutation CosAddSchemaField($input: CosAddSchemaFieldInput!) {\n cosAddSchemaField(input: $input) {\n id\n workspaceId\n datasetId\n name\n fieldType\n unit\n description\n nullable\n position\n provenance\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_CREATE_SOURCE_MUTATION = gql`\n mutation CosCreateSource($input: CosCreateSourceInput!) {\n cosCreateSource(input: $input) {\n id\n name\n type\n status\n endpoint\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_SOURCE_MUTATION = gql`\n mutation CosUpdateSource($id: ID!, $input: CosUpdateSourceInput!) {\n cosUpdateSource(id: $id, input: $input) {\n id\n name\n description\n type\n status\n endpoint\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_MARK_SOURCE_SYNCED_MUTATION = gql`\n mutation CosMarkSourceSynced($id: ID!) {\n cosMarkSourceSynced(id: $id) {\n id\n status\n lastSyncedAt\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_SOURCE_MUTATION = gql`\n mutation CosArchiveSource($id: ID!) {\n cosArchiveSource(id: $id)\n }\n`;\n\nexport const COS_CREATE_COLLECTION_MUTATION = gql`\n mutation CosCreateCollection($input: CosCreateCollectionInput!) {\n cosCreateCollection(input: $input) {\n id\n name\n slug\n description\n isPublic\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_COLLECTION_MUTATION = gql`\n mutation CosUpdateCollection($id: ID!, $input: CosUpdateCollectionInput!) {\n cosUpdateCollection(id: $id, input: $input) {\n id\n name\n slug\n description\n isPublic\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_COLLECTION_MUTATION = gql`\n mutation CosArchiveCollection($id: ID!) {\n cosArchiveCollection(id: $id)\n }\n`;\n\nexport const COS_CREATE_PIPELINE_MUTATION = gql`\n mutation CosCreatePipeline($input: CosCreatePipelineInput!) {\n cosCreatePipeline(input: $input) {\n id\n name\n status\n trigger\n schedule\n version\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_PIPELINE_MUTATION = gql`\n mutation CosUpdatePipeline($id: ID!, $input: CosUpdatePipelineInput!) {\n cosUpdatePipeline(id: $id, input: $input) {\n id\n name\n description\n status\n trigger\n schedule\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_PIPELINE_MUTATION = gql`\n mutation CosArchivePipeline($id: ID!) {\n cosArchivePipeline(id: $id)\n }\n`;\n\nexport const COS_START_RUN_MUTATION = gql`\n mutation CosStartRun($input: CosStartRunInput!) {\n cosStartRun(input: $input) {\n id\n pipelineId\n runNumber\n status\n datasetId\n startedAt\n createdAt\n }\n }\n`;\n\nexport const COS_TRANSITION_RUN_MUTATION = gql`\n mutation CosTransitionRun($id: ID!, $status: CosRunStatus!) {\n cosTransitionRun(id: $id, status: $status) {\n id\n status\n startedAt\n finishedAt\n durationMs\n updatedAt\n }\n }\n`;\n\nexport const COS_ADD_RUN_STEP_MUTATION = gql`\n mutation CosAddRunStep($input: CosAddRunStepInput!) {\n cosAddRunStep(input: $input) {\n id\n runId\n name\n kind\n position\n status\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_CREATE_NOTEBOOK_MUTATION = gql`\n mutation CosCreateNotebook($input: CosCreateNotebookInput!) {\n cosCreateNotebook(input: $input) {\n id\n title\n status\n runtime\n datasetIds\n tags\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_UPDATE_NOTEBOOK_MUTATION = gql`\n mutation CosUpdateNotebook($id: ID!, $input: CosUpdateNotebookInput!) {\n cosUpdateNotebook(id: $id, input: $input) {\n id\n title\n description\n status\n runtime\n datasetIds\n isShared\n shareSlug\n tags\n updatedAt\n }\n }\n`;\n\nexport const COS_ARCHIVE_NOTEBOOK_MUTATION = gql`\n mutation CosArchiveNotebook($id: ID!) {\n cosArchiveNotebook(id: $id)\n }\n`;\n\nexport const COS_RUN_ANALYSIS_MUTATION = gql`\n mutation CosRunAnalysis($input: CosRunAnalysisInput!) {\n cosRunAnalysis(input: $input) {\n id\n title\n status\n method\n aiAssisted\n notebookId\n datasetId\n startedAt\n createdAt\n }\n }\n`;\n\nexport const COS_COMPLETE_ANALYSIS_MUTATION = gql`\n mutation CosCompleteAnalysis(\n $id: ID!\n $status: CosAnalysisStatus!\n $results: JSON\n $outputFileId: ID\n ) {\n cosCompleteAnalysis(id: $id, status: $status, results: $results, outputFileId: $outputFileId) {\n id\n status\n results\n finishedAt\n errorMessage\n outputFile {\n id\n }\n updatedAt\n }\n }\n`;\n\nexport const COS_CREATE_RELEASE_MUTATION = gql`\n mutation CosCreateRelease($input: CosCreateReleaseInput!) {\n cosCreateRelease(input: $input) {\n id\n title\n version\n status\n authors\n datasetIds\n notebookId\n license\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_PUBLISH_RELEASE_MUTATION = gql`\n mutation CosPublishRelease($id: ID!, $doi: String) {\n cosPublishRelease(id: $id, doi: $doi) {\n id\n status\n doi\n publishedAt\n updatedAt\n }\n }\n`;\n\nexport const COS_GRANT_ACCESS_MUTATION = gql`\n mutation CosGrantAccess($input: CosGrantAccessInput!) {\n cosGrantAccess(input: $input) {\n id\n datasetId\n granteeId\n status\n scopes\n reason\n grantedAt\n expiresAt\n createdAt\n updatedAt\n }\n }\n`;\n\nexport const COS_REVOKE_ACCESS_MUTATION = gql`\n mutation CosRevokeAccess($id: ID!) {\n cosRevokeAccess(id: $id) {\n id\n status\n revokedAt\n updatedAt\n }\n }\n`;\n\n// ============================================================================\n// RESPONSE / VARIABLES TYPES\n// ============================================================================\n\nexport interface CosHealthQueryData {\n cosHealth: string;\n}\n\nexport interface CosDatasetsQueryData {\n cosListDatasets: CosConnection<CosDataset>;\n}\nexport interface CosDatasetsQueryVars {\n /** Full-text search across dataset name/description/tags (backend `q` arg). */\n q?: string;\n accessLevel?: CosAccessLevel;\n format?: string;\n collectionId?: string;\n sourceId?: string;\n status?: CosDatasetStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosDatasetQueryData {\n cosDataset: CosDataset | null;\n}\n\nexport interface CosSourcesQueryData {\n cosListSources: CosConnection<CosSource>;\n}\nexport interface CosSourcesQueryVars {\n type?: CosSourceType;\n status?: CosSourceStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosSourceQueryData {\n cosSource: CosSource | null;\n}\n\n/**\n * Row shape of `cosListCollections` — same as `CosCollection` except `datasets`\n * is the id-only selection COS_COLLECTIONS_QUERY makes, so the list page can\n * size each collection without over-fetching dataset bodies.\n */\nexport interface CosCollectionListItem extends Omit<CosCollection, 'datasets'> {\n datasets: CosIdRef[];\n}\n\nexport interface CosCollectionsQueryData {\n cosListCollections: CosCollectionListItem[];\n}\n\nexport interface CosCollectionQueryData {\n cosCollection: CosCollection | null;\n}\n\nexport interface CosSchemaFieldsQueryData {\n cosListSchemaFields: CosSchemaField[];\n}\n\nexport interface CosPipelinesQueryData {\n cosListPipelines: CosConnection<CosPipeline>;\n}\nexport interface CosPipelinesQueryVars {\n status?: CosPipelineStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosPipelineQueryData {\n cosPipeline: CosPipeline | null;\n}\n\nexport interface CosRunsQueryData {\n cosListRuns: CosConnection<CosPipelineRun>;\n}\nexport interface CosRunsQueryVars {\n pipelineId?: string;\n status?: CosRunStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosRunQueryData {\n cosRun: CosPipelineRun | null;\n}\n\nexport interface CosRunStepsQueryData {\n cosListRunSteps: CosPipelineStep[];\n}\n\n/** Row of COS_PIPELINE_FAILED_RUNS_QUERY — `steps` is always selected. */\nexport interface CosFailedRunListItem extends Omit<CosPipelineRun, 'steps'> {\n steps: CosPipelineStep[];\n}\n\nexport interface CosPipelineFailedRunsQueryData {\n cosListRuns: CosConnection<CosFailedRunListItem>;\n}\nexport interface CosPipelineFailedRunsQueryVars {\n pipelineId: string;\n pagination?: CosPaginationInput;\n}\n\n/** Just enough of a dataset to render its name in place of a bare id. */\nexport interface CosDatasetSummary {\n id: string;\n name: string;\n status: CosDatasetStatus;\n accessLevel: CosAccessLevel;\n}\n\nexport interface CosDatasetSummaryQueryData {\n cosDataset: CosDatasetSummary | null;\n}\n\nexport interface CosNotebooksQueryData {\n cosListNotebooks: CosConnection<CosNotebook>;\n}\nexport interface CosNotebooksQueryVars {\n status?: CosNotebookStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosNotebookQueryData {\n cosNotebook: CosNotebook | null;\n}\n\nexport interface CosAnalysesQueryData {\n cosListAnalyses: CosAnalysis[];\n}\nexport interface CosAnalysesQueryVars {\n datasetId?: string;\n notebookId?: string;\n status?: CosAnalysisStatus;\n}\n\nexport interface CosReleasesQueryData {\n cosListReleases: CosConnection<CosRelease>;\n}\nexport interface CosReleasesQueryVars {\n status?: CosReleaseStatus;\n pagination?: CosPaginationInput;\n}\n\nexport interface CosAccessGrantsQueryData {\n cosListAccessGrants: CosDataAccessGrant[];\n}\nexport interface CosAccessGrantsQueryVars {\n datasetId?: string;\n status?: CosGrantStatus;\n}\n\n/** A single platform activity record (subset of wspace-activity-svc ActivityLog). */\nexport interface CosActivityEntry {\n id: string;\n action: string;\n description?: string | null;\n resourceType?: string | null;\n resourceId?: string | null;\n userId: string;\n timestamp: string;\n}\n\nexport interface CosActivityQueryData {\n getActivities: CosActivityEntry[];\n}\n\n/** Mirrors ActivityLogFilter — only the fields the cos activity panel needs. */\nexport interface CosActivityFilter {\n workspaceId?: string;\n resourceId?: string;\n resourceType?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface CosActivityQueryVars {\n filter?: CosActivityFilter;\n}\n\n// ============================================================================\n// QUERY HOOKS\n// ============================================================================\n\nexport const useCosHealthQuery = () => useQuery<CosHealthQueryData>(COS_HEALTH_QUERY);\n\nexport const useCosDatasetsQuery = (variables: CosDatasetsQueryVars = {}) =>\n useQuery<CosDatasetsQueryData, CosDatasetsQueryVars>(COS_DATASETS_QUERY, { variables });\n\nexport const useCosDatasetQuery = (id: string) =>\n useQuery<CosDatasetQueryData, { id: string }>(COS_DATASET_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosSourcesQuery = (variables: CosSourcesQueryVars = {}) =>\n useQuery<CosSourcesQueryData, CosSourcesQueryVars>(COS_SOURCES_QUERY, { variables });\n\nexport const useCosSourceQuery = (id: string) =>\n useQuery<CosSourceQueryData, { id: string }>(COS_SOURCE_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosCollectionsQuery = () =>\n useQuery<CosCollectionsQueryData>(COS_COLLECTIONS_QUERY);\n\nexport const useCosCollectionQuery = (id: string) =>\n useQuery<CosCollectionQueryData, { id: string }>(COS_COLLECTION_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosSchemaFieldsQuery = (datasetId: string) =>\n useQuery<CosSchemaFieldsQueryData, { datasetId: string }>(COS_SCHEMA_FIELDS_QUERY, {\n variables: { datasetId },\n skip: !datasetId,\n });\n\nexport const useCosPipelinesQuery = (variables: CosPipelinesQueryVars = {}) =>\n useQuery<CosPipelinesQueryData, CosPipelinesQueryVars>(COS_PIPELINES_QUERY, { variables });\n\nexport const useCosPipelineQuery = (id: string) =>\n useQuery<CosPipelineQueryData, { id: string }>(COS_PIPELINE_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosRunsQuery = (variables: CosRunsQueryVars = {}) =>\n useQuery<CosRunsQueryData, CosRunsQueryVars>(COS_RUNS_QUERY, { variables });\n\nexport const useCosRunQuery = (id: string) =>\n useQuery<CosRunQueryData, { id: string }>(COS_RUN_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosRunStepsQuery = (runId: string) =>\n useQuery<CosRunStepsQueryData, { runId: string }>(COS_RUN_STEPS_QUERY, {\n variables: { runId },\n skip: !runId,\n });\n\n/**\n * Failed runs of one pipeline. Skipped until a pipelineId is known so the run\n * detail page can call it unconditionally while its own query is still loading.\n */\nexport const useCosPipelineFailedRunsQuery = (\n pipelineId: string | undefined,\n options: { limit?: number; skip?: boolean } = {}\n) =>\n useQuery<CosPipelineFailedRunsQueryData, CosPipelineFailedRunsQueryVars>(\n COS_PIPELINE_FAILED_RUNS_QUERY,\n {\n variables: {\n pipelineId: pipelineId ?? '',\n pagination: { limit: options.limit ?? 20, offset: 0 },\n },\n skip: !pipelineId || options.skip === true,\n }\n );\n\n/** Resolves a dataset id to its name. Returns null data when unreadable. */\nexport const useCosDatasetSummaryQuery = (id: string | null | undefined) =>\n useQuery<CosDatasetSummaryQueryData, { id: string }>(COS_DATASET_SUMMARY_QUERY, {\n variables: { id: id ?? '' },\n skip: !id,\n });\n\nexport const useCosNotebooksQuery = (variables: CosNotebooksQueryVars = {}) =>\n useQuery<CosNotebooksQueryData, CosNotebooksQueryVars>(COS_NOTEBOOKS_QUERY, { variables });\n\nexport const useCosNotebookQuery = (id: string) =>\n useQuery<CosNotebookQueryData, { id: string }>(COS_NOTEBOOK_QUERY, {\n variables: { id },\n skip: !id,\n });\n\nexport const useCosAnalysesQuery = (variables: CosAnalysesQueryVars = {}) =>\n useQuery<CosAnalysesQueryData, CosAnalysesQueryVars>(COS_ANALYSES_QUERY, { variables });\n\nexport const useCosReleasesQuery = (variables: CosReleasesQueryVars = {}) =>\n useQuery<CosReleasesQueryData, CosReleasesQueryVars>(COS_RELEASES_QUERY, { variables });\n\nexport const useCosAccessGrantsQuery = (variables: CosAccessGrantsQueryVars = {}) =>\n useQuery<CosAccessGrantsQueryData, CosAccessGrantsQueryVars>(COS_ACCESS_GRANTS_QUERY, {\n variables,\n });\n\n/**\n * Resource-scoped platform activity for a single cos entity. RBAC on\n * `getActivities` scopes on `filter.workspaceId`, so both a workspaceId and the\n * entity's resourceId are required — the query is skipped until both are known.\n */\nexport const useCosResourceActivityQuery = (params: {\n workspaceId?: string;\n resourceId: string;\n resourceType?: string;\n limit?: number;\n}) => {\n const { workspaceId, resourceId, resourceType, limit = 20 } = params;\n return useQuery<CosActivityQueryData, CosActivityQueryVars>(COS_ACTIVITY_BY_RESOURCE_QUERY, {\n variables: { filter: { workspaceId, resourceId, resourceType, limit } },\n skip: !workspaceId || !resourceId,\n fetchPolicy: 'cache-and-network',\n });\n};\n\n// ============================================================================\n// MUTATION HOOKS\n// ============================================================================\n\nexport const useCosCreateDatasetMutation = () =>\n useMutation<{ cosCreateDataset: CosDataset }, { input: CosCreateDatasetInput }>(\n COS_CREATE_DATASET_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_DATASETS_QUERY }],\n }\n );\n\nexport const useCosUpdateDatasetMutation = () =>\n useMutation<{ cosUpdateDataset: CosDataset }, { id: string; input: CosUpdateDatasetInput }>(\n COS_UPDATE_DATASET_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_DATASETS_QUERY }],\n }\n );\n\nexport const useCosPublishDatasetMutation = () =>\n useMutation<{ cosPublishDataset: CosDataset }, { id: string }>(COS_PUBLISH_DATASET_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_DATASETS_QUERY }],\n });\n\nexport const useCosArchiveDatasetMutation = () =>\n useMutation<{ cosArchiveDataset: boolean }, { id: string }>(COS_ARCHIVE_DATASET_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_DATASETS_QUERY }],\n });\n\nexport const useCosAddSchemaFieldMutation = () =>\n useMutation<{ cosAddSchemaField: CosSchemaField }, { input: CosAddSchemaFieldInput }>(\n COS_ADD_SCHEMA_FIELD_MUTATION,\n { errorPolicy: 'all', onError: onMutationError }\n );\n\nexport const useCosCreateSourceMutation = () =>\n useMutation<{ cosCreateSource: CosSource }, { input: CosCreateSourceInput }>(\n COS_CREATE_SOURCE_MUTATION,\n { errorPolicy: 'all', onError: onMutationError, refetchQueries: [{ query: COS_SOURCES_QUERY }] }\n );\n\nexport const useCosUpdateSourceMutation = () =>\n useMutation<{ cosUpdateSource: CosSource }, { id: string; input: CosUpdateSourceInput }>(\n COS_UPDATE_SOURCE_MUTATION,\n { errorPolicy: 'all', onError: onMutationError, refetchQueries: [{ query: COS_SOURCES_QUERY }] }\n );\n\nexport const useCosMarkSourceSyncedMutation = () =>\n useMutation<{ cosMarkSourceSynced: CosSource }, { id: string }>(COS_MARK_SOURCE_SYNCED_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_SOURCES_QUERY }],\n });\n\nexport const useCosArchiveSourceMutation = () =>\n useMutation<{ cosArchiveSource: boolean }, { id: string }>(COS_ARCHIVE_SOURCE_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_SOURCES_QUERY }],\n });\n\nexport const useCosCreateCollectionMutation = () =>\n useMutation<{ cosCreateCollection: CosCollection }, { input: CosCreateCollectionInput }>(\n COS_CREATE_COLLECTION_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_COLLECTIONS_QUERY }],\n }\n );\n\nexport const useCosUpdateCollectionMutation = () =>\n useMutation<\n { cosUpdateCollection: CosCollection },\n { id: string; input: CosUpdateCollectionInput }\n >(COS_UPDATE_COLLECTION_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_COLLECTIONS_QUERY }],\n });\n\nexport const useCosArchiveCollectionMutation = () =>\n useMutation<{ cosArchiveCollection: boolean }, { id: string }>(COS_ARCHIVE_COLLECTION_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_COLLECTIONS_QUERY }],\n });\n\nexport const useCosCreatePipelineMutation = () =>\n useMutation<{ cosCreatePipeline: CosPipeline }, { input: CosCreatePipelineInput }>(\n COS_CREATE_PIPELINE_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_PIPELINES_QUERY }],\n }\n );\n\nexport const useCosUpdatePipelineMutation = () =>\n useMutation<{ cosUpdatePipeline: CosPipeline }, { id: string; input: CosUpdatePipelineInput }>(\n COS_UPDATE_PIPELINE_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_PIPELINES_QUERY }],\n }\n );\n\nexport const useCosArchivePipelineMutation = () =>\n useMutation<{ cosArchivePipeline: boolean }, { id: string }>(COS_ARCHIVE_PIPELINE_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_PIPELINES_QUERY }],\n });\n\nexport const useCosStartRunMutation = () =>\n useMutation<{ cosStartRun: CosPipelineRun }, { input: CosStartRunInput }>(\n COS_START_RUN_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_RUNS_QUERY }],\n }\n );\n\nexport const useCosTransitionRunMutation = () =>\n useMutation<{ cosTransitionRun: CosPipelineRun }, { id: string; status: CosRunStatus }>(\n COS_TRANSITION_RUN_MUTATION,\n { errorPolicy: 'all', onError: onMutationError, refetchQueries: [{ query: COS_RUNS_QUERY }] }\n );\n\nexport const useCosAddRunStepMutation = () =>\n useMutation<{ cosAddRunStep: CosPipelineStep }, { input: CosAddRunStepInput }>(\n COS_ADD_RUN_STEP_MUTATION,\n { errorPolicy: 'all', onError: onMutationError }\n );\n\nexport const useCosCreateNotebookMutation = () =>\n useMutation<{ cosCreateNotebook: CosNotebook }, { input: CosCreateNotebookInput }>(\n COS_CREATE_NOTEBOOK_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_NOTEBOOKS_QUERY }],\n }\n );\n\nexport const useCosUpdateNotebookMutation = () =>\n useMutation<{ cosUpdateNotebook: CosNotebook }, { id: string; input: CosUpdateNotebookInput }>(\n COS_UPDATE_NOTEBOOK_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_NOTEBOOKS_QUERY }],\n }\n );\n\nexport const useCosArchiveNotebookMutation = () =>\n useMutation<{ cosArchiveNotebook: boolean }, { id: string }>(COS_ARCHIVE_NOTEBOOK_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_NOTEBOOKS_QUERY }],\n });\n\nexport const useCosRunAnalysisMutation = () =>\n useMutation<{ cosRunAnalysis: CosAnalysis }, { input: CosRunAnalysisInput }>(\n COS_RUN_ANALYSIS_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_ANALYSES_QUERY }],\n }\n );\n\nexport const useCosCompleteAnalysisMutation = () =>\n useMutation<\n { cosCompleteAnalysis: CosAnalysis },\n {\n id: string;\n status: Extract<CosAnalysisStatus, 'COMPLETED' | 'FAILED'>;\n results?: Record<string, unknown>;\n outputFileId?: string;\n }\n >(COS_COMPLETE_ANALYSIS_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_ANALYSES_QUERY }],\n });\n\nexport const useCosCreateReleaseMutation = () =>\n useMutation<{ cosCreateRelease: CosRelease }, { input: CosCreateReleaseInput }>(\n COS_CREATE_RELEASE_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_RELEASES_QUERY }],\n }\n );\n\nexport const useCosPublishReleaseMutation = () =>\n useMutation<{ cosPublishRelease: CosRelease }, { id: string; doi?: string }>(\n COS_PUBLISH_RELEASE_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_RELEASES_QUERY }],\n }\n );\n\nexport const useCosGrantAccessMutation = () =>\n useMutation<{ cosGrantAccess: CosDataAccessGrant }, { input: CosGrantAccessInput }>(\n COS_GRANT_ACCESS_MUTATION,\n {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_ACCESS_GRANTS_QUERY }],\n }\n );\n\nexport const useCosRevokeAccessMutation = () =>\n useMutation<{ cosRevokeAccess: CosDataAccessGrant }, { id: string }>(COS_REVOKE_ACCESS_MUTATION, {\n errorPolicy: 'all',\n onError: onMutationError,\n refetchQueries: [{ query: COS_ACCESS_GRANTS_QUERY }],\n });\n"],"mappings":"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"}
|
|
@@ -29,7 +29,12 @@ export interface LineageModel {
|
|
|
29
29
|
export interface LineageDataPools {
|
|
30
30
|
datasetsById: Map<string, CosDataset>;
|
|
31
31
|
sourcesById: Map<string, CosSource>;
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Only the collection's display name is read, so this accepts any collection
|
|
34
|
+
* shape carrying it — including the id-only-`datasets` rows the collections
|
|
35
|
+
* list query returns.
|
|
36
|
+
*/
|
|
37
|
+
collectionsById: Map<string, Pick<CosCollection, 'id' | 'name'>>;
|
|
33
38
|
runs: CosPipelineRun[];
|
|
34
39
|
notebooks: CosNotebook[];
|
|
35
40
|
analyses: CosAnalysis[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineageGraph.d.ts","sourceRoot":"","sources":["../../../src/cosmicintersection/components/LineageGraph.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,SAAS,EACV,MAAM,kBAAkB,CAAC;AAO1B,MAAM,MAAM,eAAe,GACzB,QAAQ,GAAG,YAAY,GAAG,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;AAEpF,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"LineageGraph.d.ts","sourceRoot":"","sources":["../../../src/cosmicintersection/components/LineageGraph.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,SAAS,EACV,MAAM,kBAAkB,CAAC;AAO1B,MAAM,MAAM,eAAe,GACzB,QAAQ,GAAG,YAAY,GAAG,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;AAEpF,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC;;;;OAIG;IACH,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC;IACjE,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAC1C;AA+MD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,YAAY,CAS5F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,YAAY,CAyC5F;AAsJD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,IAAa,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,iBAAiB,kDAsL9F;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineageGraph.js","names":[],"sources":["../../../src/cosmicintersection/components/LineageGraph.tsx"],"sourcesContent":["/**\n * LineageGraph — a reusable, dependency-free provenance DAG for CosmicIntersection.\n *\n * Renders a typed, left-to-right lineage graph (Source → Dataset → Pipeline Run →\n * Notebook / Analysis → Release) as custom inline SVG edges + absolutely-positioned\n * token-styled node cards. No graph library — the layout is a simple column/row\n * solver, edges are cubic-bezier `<path>`s. Every colour comes from fe-libs semantic\n * tokens (bg-*, text-*, border-*, status-*, accent-*) so it renders in every theme.\n *\n * The graph MODEL is derived client-side from existing cos entities by the pure\n * `buildDatasetLineage` / `buildReleaseLineage` builders exported below — the\n * component itself never fetches. Nodes with a `route` are clickable and call\n * `onNavigate` (basePath-relative), matching the rest of the MFE's navigation.\n *\n * Modes:\n * - `full` — page mode (larger cards, legend, dotted canvas). See mockup 20.\n * - `compact` — detail-panel mini map (smaller cards, no legend). See mockup 03.\n */\nimport { useId, useMemo } from 'react';\nimport {\n Boxes,\n Cog,\n Database,\n LineChart,\n NotebookText,\n Radar,\n Tag,\n type LucideIcon,\n} from 'lucide-react';\n\nimport type {\n CosAnalysis,\n CosCollection,\n CosDataset,\n CosNotebook,\n CosPipeline,\n CosPipelineRun,\n CosRelease,\n CosSource,\n} from '../api/cosmicApi';\nimport { cn } from '../utils/cn';\n\n// ============================================================================\n// MODEL\n// ============================================================================\n\nexport type LineageNodeType =\n 'source' | 'collection' | 'dataset' | 'run' | 'notebook' | 'analysis' | 'release';\n\nexport interface LineageNode {\n /** Stable, unique within a model (e.g. `ds:<uuid>`). */\n id: string;\n type: LineageNodeType;\n title: string;\n /** Overrides the default type label (e.g. \"Pipeline Run #340\"). */\n typeLabel?: string;\n /** Small third line — status, version, DOI hint (hidden in compact mode). */\n subtitle?: string;\n /** basePath-relative route; when set (and `onNavigate` given) the node is clickable. */\n route?: string;\n /** Semantic column / layer index, 0 = leftmost (upstream). */\n column: number;\n /** Highlight the graph root (the entity the lineage was requested for). */\n emphasis?: boolean;\n}\n\nexport interface LineageEdge {\n from: string;\n to: string;\n}\n\nexport interface LineageModel {\n nodes: LineageNode[];\n edges: LineageEdge[];\n}\n\n/** Data pools the builders read from — resolved maps + already-filtered lists. */\nexport interface LineageDataPools {\n datasetsById: Map<string, CosDataset>;\n sourcesById: Map<string, CosSource>;\n collectionsById: Map<string, CosCollection>;\n runs: CosPipelineRun[];\n notebooks: CosNotebook[];\n analyses: CosAnalysis[];\n releases: CosRelease[];\n pipelinesById?: Map<string, CosPipeline>;\n}\n\n// ============================================================================\n// BUILDERS (pure — no hooks, no fetching)\n// ============================================================================\n\nconst COLUMN: Record<LineageNodeType, number> = {\n source: 0,\n collection: 0,\n dataset: 1,\n run: 2,\n notebook: 3,\n analysis: 4,\n release: 5,\n};\n\nfunction humanEnum(value: string): string {\n const lower = value.replace(/_/g, ' ').toLowerCase();\n return lower.charAt(0).toUpperCase() + lower.slice(1);\n}\n\n/** Incrementally assembles a de-duplicated node/edge model. */\nclass LineageBuilder {\n private readonly nodes = new Map<string, LineageNode>();\n private readonly edgeKeys = new Set<string>();\n private readonly edges: LineageEdge[] = [];\n\n addNode(node: LineageNode): void {\n const existing = this.nodes.get(node.id);\n if (!existing) {\n this.nodes.set(node.id, node);\n return;\n }\n // Preserve an emphasis flag once set (root wins over a later plain add).\n if (node.emphasis && !existing.emphasis) {\n this.nodes.set(node.id, { ...existing, emphasis: true });\n }\n }\n\n link(from: string, to: string): void {\n if (from === to) {\n return;\n }\n // Only connect endpoints that actually exist in the graph.\n if (!this.nodes.has(from) || !this.nodes.has(to)) {\n return;\n }\n const key = `${from}»${to}`;\n if (this.edgeKeys.has(key)) {\n return;\n }\n this.edgeKeys.add(key);\n this.edges.push({ from, to });\n }\n\n has(id: string): boolean {\n return this.nodes.has(id);\n }\n\n build(): LineageModel {\n return { nodes: [...this.nodes.values()], edges: this.edges };\n }\n}\n\nconst nid = {\n source: (id: string) => `src:${id}`,\n collection: (id: string) => `col:${id}`,\n dataset: (id: string) => `ds:${id}`,\n run: (id: string) => `run:${id}`,\n notebook: (id: string) => `nb:${id}`,\n analysis: (id: string) => `an:${id}`,\n release: (id: string) => `rel:${id}`,\n};\n\n/** Add a dataset node plus its upstream source/collection to the builder. */\nfunction addDatasetUpstream(\n builder: LineageBuilder,\n dataset: CosDataset,\n pools: LineageDataPools,\n emphasis: boolean\n): void {\n builder.addNode({\n id: nid.dataset(dataset.id),\n type: 'dataset',\n title: dataset.name,\n subtitle: humanEnum(dataset.status),\n route: `datasets/${dataset.id}`,\n column: COLUMN.dataset,\n emphasis,\n });\n\n if (dataset.sourceId) {\n const source = pools.sourcesById.get(dataset.sourceId);\n builder.addNode({\n id: nid.source(dataset.sourceId),\n type: 'source',\n title: source?.name ?? 'Linked source',\n subtitle: source ? humanEnum(source.type) : undefined,\n route: `sources/${dataset.sourceId}`,\n column: COLUMN.source,\n });\n builder.link(nid.source(dataset.sourceId), nid.dataset(dataset.id));\n }\n\n if (dataset.collectionId) {\n const collection = pools.collectionsById.get(dataset.collectionId);\n builder.addNode({\n id: nid.collection(dataset.collectionId),\n type: 'collection',\n title: collection?.name ?? 'Collection',\n route: `collections/${dataset.collectionId}`,\n column: COLUMN.collection,\n });\n builder.link(nid.collection(dataset.collectionId), nid.dataset(dataset.id));\n }\n}\n\n/** Add the downstream fan for a dataset: runs, notebooks, analyses, releases. */\nfunction addDatasetDownstream(\n builder: LineageBuilder,\n dataset: CosDataset,\n pools: LineageDataPools\n): void {\n const datasetNode = nid.dataset(dataset.id);\n\n for (const run of pools.runs) {\n if (run.datasetId !== dataset.id) {\n continue;\n }\n const pipelineName = run.pipelineId\n ? pools.pipelinesById?.get(run.pipelineId)?.name\n : undefined;\n builder.addNode({\n id: nid.run(run.id),\n type: 'run',\n typeLabel: `Pipeline Run #${run.runNumber}`,\n title: pipelineName ?? `Run #${run.runNumber}`,\n subtitle: humanEnum(run.status),\n route: `runs/${run.id}`,\n column: COLUMN.run,\n });\n builder.link(datasetNode, nid.run(run.id));\n }\n\n for (const notebook of pools.notebooks) {\n if (!notebook.datasetIds.includes(dataset.id)) {\n continue;\n }\n builder.addNode({\n id: nid.notebook(notebook.id),\n type: 'notebook',\n title: notebook.title,\n subtitle: humanEnum(notebook.status),\n route: `notebooks/${notebook.id}`,\n column: COLUMN.notebook,\n });\n builder.link(datasetNode, nid.notebook(notebook.id));\n }\n\n for (const analysis of pools.analyses) {\n const linkedToNotebook =\n analysis.notebookId != null && builder.has(nid.notebook(analysis.notebookId));\n if (analysis.datasetId !== dataset.id && !linkedToNotebook) {\n continue;\n }\n builder.addNode({\n id: nid.analysis(analysis.id),\n type: 'analysis',\n title: analysis.title,\n subtitle: humanEnum(analysis.status),\n // No per-analysis detail route exists — land on the analyses list.\n route: 'analyses',\n column: COLUMN.analysis,\n });\n if (linkedToNotebook && analysis.notebookId != null) {\n builder.link(nid.notebook(analysis.notebookId), nid.analysis(analysis.id));\n } else {\n builder.link(datasetNode, nid.analysis(analysis.id));\n }\n }\n\n for (const release of pools.releases) {\n if (!release.datasetIds.includes(dataset.id)) {\n continue;\n }\n addReleaseNode(builder, release);\n builder.link(datasetNode, nid.release(release.id));\n if (release.notebookId != null && builder.has(nid.notebook(release.notebookId))) {\n builder.link(nid.notebook(release.notebookId), nid.release(release.id));\n }\n }\n}\n\nfunction addReleaseNode(builder: LineageBuilder, release: CosRelease, emphasis = false): void {\n const doiSuffix = release.doi ? ' · DOI' : '';\n builder.addNode({\n id: nid.release(release.id),\n type: 'release',\n title: release.title,\n subtitle: `v${release.version}${doiSuffix}`,\n // No per-release detail route exists — land on the releases list.\n route: 'releases',\n column: COLUMN.release,\n emphasis,\n });\n}\n\n/**\n * Provenance for a single dataset: its upstream (source + collection) and its\n * full downstream fan (runs, notebooks, analyses, releases). The dataset is the\n * emphasised root.\n */\nexport function buildDatasetLineage(datasetId: string, pools: LineageDataPools): LineageModel {\n const builder = new LineageBuilder();\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n return builder.build();\n }\n addDatasetUpstream(builder, dataset, pools, true);\n addDatasetDownstream(builder, dataset, pools);\n return builder.build();\n}\n\n/**\n * Provenance for a release: the release plus its input datasets and notebook,\n * each expanded UPSTREAM (source/collection for datasets; the notebook's own\n * datasets). The release is the emphasised root.\n */\nexport function buildReleaseLineage(releaseId: string, pools: LineageDataPools): LineageModel {\n const builder = new LineageBuilder();\n const release = pools.releases.find((item) => item.id === releaseId);\n if (!release) {\n return builder.build();\n }\n\n addReleaseNode(builder, release, true);\n\n for (const datasetId of release.datasetIds) {\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n continue;\n }\n addDatasetUpstream(builder, dataset, pools, false);\n builder.link(nid.dataset(dataset.id), nid.release(release.id));\n }\n\n if (release.notebookId != null) {\n const notebook = pools.notebooks.find((item) => item.id === release.notebookId);\n builder.addNode({\n id: nid.notebook(release.notebookId),\n type: 'notebook',\n title: notebook?.title ?? 'Notebook',\n subtitle: notebook ? humanEnum(notebook.status) : undefined,\n route: `notebooks/${release.notebookId}`,\n column: COLUMN.notebook,\n });\n builder.link(nid.notebook(release.notebookId), nid.release(release.id));\n\n for (const datasetId of notebook?.datasetIds ?? []) {\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n continue;\n }\n addDatasetUpstream(builder, dataset, pools, false);\n builder.link(nid.dataset(dataset.id), nid.notebook(release.notebookId));\n }\n }\n\n return builder.build();\n}\n\n// ============================================================================\n// PRESENTATION\n// ============================================================================\n\ninterface NodeMeta {\n label: string;\n Icon: LucideIcon;\n /** Icon-chip classes (semantic accent tokens only). */\n chip: string;\n /** Card border colour class. */\n border: string;\n}\n\nconst NODE_META: Record<LineageNodeType, NodeMeta> = {\n source: {\n label: 'Source',\n Icon: Radar,\n chip: 'bg-accent-blue-subtle text-accent-blue',\n border: 'border-accent-blue',\n },\n collection: {\n label: 'Collection',\n Icon: Boxes,\n chip: 'bg-accent-teal-subtle text-accent-teal',\n border: 'border-accent-teal',\n },\n dataset: {\n label: 'Dataset',\n Icon: Database,\n chip: 'bg-accent-indigo-subtle text-accent-indigo',\n border: 'border-accent-indigo',\n },\n run: {\n label: 'Pipeline Run',\n Icon: Cog,\n chip: 'bg-accent-purple-subtle text-accent-purple',\n border: 'border-accent-purple',\n },\n notebook: {\n label: 'Notebook',\n Icon: NotebookText,\n chip: 'bg-accent-teal-subtle text-accent-teal',\n border: 'border-accent-teal',\n },\n analysis: {\n label: 'Analysis',\n Icon: LineChart,\n chip: 'bg-accent-purple-subtle text-accent-purple',\n border: 'border-accent-purple',\n },\n release: {\n label: 'Release',\n Icon: Tag,\n chip: 'bg-status-success-bg-subtle text-status-success-text',\n border: 'border-status-success-border',\n },\n};\n\ninterface Dims {\n nodeW: number;\n nodeH: number;\n colGap: number;\n rowGap: number;\n pad: number;\n iconSize: string;\n showSubtitle: boolean;\n}\n\nconst DIMS: Record<'full' | 'compact', Dims> = {\n full: {\n nodeW: 190,\n nodeH: 78,\n colGap: 74,\n rowGap: 30,\n pad: 32,\n iconSize: 'size-8',\n showSubtitle: true,\n },\n compact: {\n nodeW: 150,\n nodeH: 54,\n colGap: 46,\n rowGap: 18,\n pad: 18,\n iconSize: 'size-6',\n showSubtitle: false,\n },\n};\n\ninterface Positioned {\n node: LineageNode;\n x: number;\n y: number;\n}\n\ninterface Layout {\n positions: Map<string, Positioned>;\n width: number;\n height: number;\n}\n\nfunction computeLayout(model: LineageModel, dims: Dims): Layout {\n const positions = new Map<string, Positioned>();\n if (model.nodes.length === 0) {\n return { positions, width: dims.pad * 2, height: dims.pad * 2 };\n }\n\n // Present columns, remapped to contiguous indices so empty layers collapse.\n const presentCols = [...new Set(model.nodes.map((n) => n.column))].sort((a, b) => a - b);\n const colOrder = new Map(presentCols.map((c, i) => [c, i]));\n\n const byColumn = new Map<number, LineageNode[]>();\n for (const node of model.nodes) {\n const list = byColumn.get(node.column);\n if (list) {\n list.push(node);\n } else {\n byColumn.set(node.column, [node]);\n }\n }\n\n let contentH = dims.nodeH;\n for (const list of byColumn.values()) {\n const h = list.length * dims.nodeH + (list.length - 1) * dims.rowGap;\n contentH = Math.max(contentH, h);\n }\n\n for (const col of presentCols) {\n const list = byColumn.get(col) ?? [];\n const colH = list.length * dims.nodeH + (list.length - 1) * dims.rowGap;\n const startY = dims.pad + (contentH - colH) / 2;\n const x = dims.pad + (colOrder.get(col) ?? 0) * (dims.nodeW + dims.colGap);\n list.forEach((node, i) => {\n positions.set(node.id, { node, x, y: startY + i * (dims.nodeH + dims.rowGap) });\n });\n }\n\n const width =\n dims.pad * 2 + presentCols.length * dims.nodeW + (presentCols.length - 1) * dims.colGap;\n const height = dims.pad * 2 + contentH;\n return { positions, width, height };\n}\n\nfunction edgePath(x1: number, y1: number, x2: number, y2: number): string {\n const dx = Math.max(24, (x2 - x1) * 0.5);\n return `M ${x1} ${y1} C ${x1 + dx} ${y1}, ${x2 - dx} ${y2}, ${x2} ${y2}`;\n}\n\nexport interface LineageGraphProps {\n model: LineageModel;\n mode?: 'full' | 'compact';\n onNavigate?: (route: string) => void;\n className?: string;\n}\n\nexport function LineageGraph({ model, mode = 'full', onNavigate, className }: LineageGraphProps) {\n const markerId = `cos-lineage-arrow-${useId().replace(/:/g, '')}`;\n const dims = DIMS[mode];\n\n const layout = useMemo(() => computeLayout(model, dims), [model, dims]);\n\n const legendTypes = useMemo(() => {\n const seen = new Set<LineageNodeType>();\n const ordered: LineageNodeType[] = [];\n for (const node of [...model.nodes].sort((a, b) => a.column - b.column)) {\n if (!seen.has(node.type)) {\n seen.add(node.type);\n ordered.push(node.type);\n }\n }\n return ordered;\n }, [model.nodes]);\n\n if (model.nodes.length === 0) {\n return null;\n }\n\n return (\n <div className={cn('flex flex-col gap-3', className)}>\n {mode === 'full' && legendTypes.length > 0 ? (\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n {legendTypes.map((type) => {\n const meta = NODE_META[type];\n return (\n <span\n key={type}\n className=\"inline-flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n className={cn(\n 'flex size-5 items-center justify-center rounded-button',\n meta.chip\n )}\n >\n <meta.Icon className=\"size-3\" aria-hidden=\"true\" />\n </span>\n {meta.label}\n </span>\n );\n })}\n </div>\n ) : null}\n\n <div\n className={cn(\n 'overflow-x-auto rounded-card border border-border-seam bg-bg-canvas',\n mode === 'full' ? 'p-1' : 'p-0.5'\n )}\n >\n <div\n className=\"relative\"\n style={{\n width: layout.width,\n height: layout.height,\n minWidth: '100%',\n backgroundImage: 'radial-gradient(var(--color-border-subtle) 1px, transparent 1px)',\n backgroundSize: mode === 'full' ? '20px 20px' : '16px 16px',\n }}\n >\n {/* Edges (behind the node cards). */}\n <svg\n className=\"pointer-events-none absolute inset-0 text-border-strong\"\n width={layout.width}\n height={layout.height}\n viewBox={`0 0 ${layout.width} ${layout.height}`}\n aria-hidden=\"true\"\n >\n <defs>\n <marker\n id={markerId}\n viewBox=\"0 0 8 8\"\n refX=\"6.5\"\n refY=\"4\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M1 1 L7 4 L1 7 z\" fill=\"currentColor\" />\n </marker>\n </defs>\n {model.edges.map((edge) => {\n const from = layout.positions.get(edge.from);\n const to = layout.positions.get(edge.to);\n if (!from || !to) {\n return null;\n }\n const x1 = from.x + dims.nodeW;\n const y1 = from.y + dims.nodeH / 2;\n const x2 = to.x;\n const y2 = to.y + dims.nodeH / 2;\n return (\n <path\n key={`${edge.from}»${edge.to}`}\n d={edgePath(x1, y1, x2, y2)}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={mode === 'full' ? 1.5 : 1.25}\n strokeLinecap=\"round\"\n markerEnd={`url(#${markerId})`}\n opacity={0.7}\n />\n );\n })}\n </svg>\n\n {/* Node cards. */}\n {[...layout.positions.values()].map(({ node, x, y }) => {\n const meta = NODE_META[node.type];\n const clickable = Boolean(node.route && onNavigate);\n const content = (\n <div\n className={cn(\n 'flex h-full w-full items-center gap-2.5 rounded-card border bg-bg-elevated px-3 shadow-sm transition-shadow',\n meta.border,\n clickable && 'group-hover:shadow-md',\n node.emphasis && 'ring-1 ring-border-strong'\n )}\n >\n <span\n className={cn(\n 'flex shrink-0 items-center justify-center rounded-button',\n dims.iconSize,\n meta.chip\n )}\n aria-hidden=\"true\"\n >\n <meta.Icon className={mode === 'full' ? 'size-4' : 'size-3.5'} />\n </span>\n <span className=\"flex min-w-0 flex-1 flex-col text-left\">\n <span className=\"truncate text-[10px] font-medium uppercase tracking-wide text-text-tertiary\">\n {node.typeLabel ?? meta.label}\n </span>\n <span\n className={cn(\n 'truncate font-semibold text-text-primary',\n mode === 'full' ? 'text-sm' : 'text-xs'\n )}\n >\n {node.title}\n </span>\n {dims.showSubtitle && node.subtitle ? (\n <span className=\"truncate text-[11px] text-text-secondary\">\n {node.subtitle}\n </span>\n ) : null}\n </span>\n </div>\n );\n\n const style = { left: x, top: y, width: dims.nodeW, height: dims.nodeH } as const;\n\n if (clickable && node.route) {\n const route = node.route;\n return (\n <button\n key={node.id}\n type=\"button\"\n onClick={() => onNavigate?.(route)}\n className=\"group absolute rounded-card focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n style={style}\n title={`${node.typeLabel ?? meta.label}: ${node.title}`}\n >\n {content}\n </button>\n );\n }\n\n return (\n <div key={node.id} className=\"absolute\" style={style}>\n {content}\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n}\n\nexport default LineageGraph;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LineageGraph.js","names":[],"sources":["../../../src/cosmicintersection/components/LineageGraph.tsx"],"sourcesContent":["/**\n * LineageGraph — a reusable, dependency-free provenance DAG for CosmicIntersection.\n *\n * Renders a typed, left-to-right lineage graph (Source → Dataset → Pipeline Run →\n * Notebook / Analysis → Release) as custom inline SVG edges + absolutely-positioned\n * token-styled node cards. No graph library — the layout is a simple column/row\n * solver, edges are cubic-bezier `<path>`s. Every colour comes from fe-libs semantic\n * tokens (bg-*, text-*, border-*, status-*, accent-*) so it renders in every theme.\n *\n * The graph MODEL is derived client-side from existing cos entities by the pure\n * `buildDatasetLineage` / `buildReleaseLineage` builders exported below — the\n * component itself never fetches. Nodes with a `route` are clickable and call\n * `onNavigate` (basePath-relative), matching the rest of the MFE's navigation.\n *\n * Modes:\n * - `full` — page mode (larger cards, legend, dotted canvas). See mockup 20.\n * - `compact` — detail-panel mini map (smaller cards, no legend). See mockup 03.\n */\nimport { useId, useMemo } from 'react';\nimport {\n Boxes,\n Cog,\n Database,\n LineChart,\n NotebookText,\n Radar,\n Tag,\n type LucideIcon,\n} from 'lucide-react';\n\nimport type {\n CosAnalysis,\n CosCollection,\n CosDataset,\n CosNotebook,\n CosPipeline,\n CosPipelineRun,\n CosRelease,\n CosSource,\n} from '../api/cosmicApi';\nimport { cn } from '../utils/cn';\n\n// ============================================================================\n// MODEL\n// ============================================================================\n\nexport type LineageNodeType =\n 'source' | 'collection' | 'dataset' | 'run' | 'notebook' | 'analysis' | 'release';\n\nexport interface LineageNode {\n /** Stable, unique within a model (e.g. `ds:<uuid>`). */\n id: string;\n type: LineageNodeType;\n title: string;\n /** Overrides the default type label (e.g. \"Pipeline Run #340\"). */\n typeLabel?: string;\n /** Small third line — status, version, DOI hint (hidden in compact mode). */\n subtitle?: string;\n /** basePath-relative route; when set (and `onNavigate` given) the node is clickable. */\n route?: string;\n /** Semantic column / layer index, 0 = leftmost (upstream). */\n column: number;\n /** Highlight the graph root (the entity the lineage was requested for). */\n emphasis?: boolean;\n}\n\nexport interface LineageEdge {\n from: string;\n to: string;\n}\n\nexport interface LineageModel {\n nodes: LineageNode[];\n edges: LineageEdge[];\n}\n\n/** Data pools the builders read from — resolved maps + already-filtered lists. */\nexport interface LineageDataPools {\n datasetsById: Map<string, CosDataset>;\n sourcesById: Map<string, CosSource>;\n /**\n * Only the collection's display name is read, so this accepts any collection\n * shape carrying it — including the id-only-`datasets` rows the collections\n * list query returns.\n */\n collectionsById: Map<string, Pick<CosCollection, 'id' | 'name'>>;\n runs: CosPipelineRun[];\n notebooks: CosNotebook[];\n analyses: CosAnalysis[];\n releases: CosRelease[];\n pipelinesById?: Map<string, CosPipeline>;\n}\n\n// ============================================================================\n// BUILDERS (pure — no hooks, no fetching)\n// ============================================================================\n\nconst COLUMN: Record<LineageNodeType, number> = {\n source: 0,\n collection: 0,\n dataset: 1,\n run: 2,\n notebook: 3,\n analysis: 4,\n release: 5,\n};\n\nfunction humanEnum(value: string): string {\n const lower = value.replace(/_/g, ' ').toLowerCase();\n return lower.charAt(0).toUpperCase() + lower.slice(1);\n}\n\n/** Incrementally assembles a de-duplicated node/edge model. */\nclass LineageBuilder {\n private readonly nodes = new Map<string, LineageNode>();\n private readonly edgeKeys = new Set<string>();\n private readonly edges: LineageEdge[] = [];\n\n addNode(node: LineageNode): void {\n const existing = this.nodes.get(node.id);\n if (!existing) {\n this.nodes.set(node.id, node);\n return;\n }\n // Preserve an emphasis flag once set (root wins over a later plain add).\n if (node.emphasis && !existing.emphasis) {\n this.nodes.set(node.id, { ...existing, emphasis: true });\n }\n }\n\n link(from: string, to: string): void {\n if (from === to) {\n return;\n }\n // Only connect endpoints that actually exist in the graph.\n if (!this.nodes.has(from) || !this.nodes.has(to)) {\n return;\n }\n const key = `${from}»${to}`;\n if (this.edgeKeys.has(key)) {\n return;\n }\n this.edgeKeys.add(key);\n this.edges.push({ from, to });\n }\n\n has(id: string): boolean {\n return this.nodes.has(id);\n }\n\n build(): LineageModel {\n return { nodes: [...this.nodes.values()], edges: this.edges };\n }\n}\n\nconst nid = {\n source: (id: string) => `src:${id}`,\n collection: (id: string) => `col:${id}`,\n dataset: (id: string) => `ds:${id}`,\n run: (id: string) => `run:${id}`,\n notebook: (id: string) => `nb:${id}`,\n analysis: (id: string) => `an:${id}`,\n release: (id: string) => `rel:${id}`,\n};\n\n/** Add a dataset node plus its upstream source/collection to the builder. */\nfunction addDatasetUpstream(\n builder: LineageBuilder,\n dataset: CosDataset,\n pools: LineageDataPools,\n emphasis: boolean\n): void {\n builder.addNode({\n id: nid.dataset(dataset.id),\n type: 'dataset',\n title: dataset.name,\n subtitle: humanEnum(dataset.status),\n route: `datasets/${dataset.id}`,\n column: COLUMN.dataset,\n emphasis,\n });\n\n if (dataset.sourceId) {\n const source = pools.sourcesById.get(dataset.sourceId);\n builder.addNode({\n id: nid.source(dataset.sourceId),\n type: 'source',\n title: source?.name ?? 'Linked source',\n subtitle: source ? humanEnum(source.type) : undefined,\n route: `sources/${dataset.sourceId}`,\n column: COLUMN.source,\n });\n builder.link(nid.source(dataset.sourceId), nid.dataset(dataset.id));\n }\n\n if (dataset.collectionId) {\n const collection = pools.collectionsById.get(dataset.collectionId);\n builder.addNode({\n id: nid.collection(dataset.collectionId),\n type: 'collection',\n title: collection?.name ?? 'Collection',\n route: `collections/${dataset.collectionId}`,\n column: COLUMN.collection,\n });\n builder.link(nid.collection(dataset.collectionId), nid.dataset(dataset.id));\n }\n}\n\n/** Add the downstream fan for a dataset: runs, notebooks, analyses, releases. */\nfunction addDatasetDownstream(\n builder: LineageBuilder,\n dataset: CosDataset,\n pools: LineageDataPools\n): void {\n const datasetNode = nid.dataset(dataset.id);\n\n for (const run of pools.runs) {\n if (run.datasetId !== dataset.id) {\n continue;\n }\n const pipelineName = run.pipelineId\n ? pools.pipelinesById?.get(run.pipelineId)?.name\n : undefined;\n builder.addNode({\n id: nid.run(run.id),\n type: 'run',\n typeLabel: `Pipeline Run #${run.runNumber}`,\n title: pipelineName ?? `Run #${run.runNumber}`,\n subtitle: humanEnum(run.status),\n route: `runs/${run.id}`,\n column: COLUMN.run,\n });\n builder.link(datasetNode, nid.run(run.id));\n }\n\n for (const notebook of pools.notebooks) {\n if (!notebook.datasetIds.includes(dataset.id)) {\n continue;\n }\n builder.addNode({\n id: nid.notebook(notebook.id),\n type: 'notebook',\n title: notebook.title,\n subtitle: humanEnum(notebook.status),\n route: `notebooks/${notebook.id}`,\n column: COLUMN.notebook,\n });\n builder.link(datasetNode, nid.notebook(notebook.id));\n }\n\n for (const analysis of pools.analyses) {\n const linkedToNotebook =\n analysis.notebookId != null && builder.has(nid.notebook(analysis.notebookId));\n if (analysis.datasetId !== dataset.id && !linkedToNotebook) {\n continue;\n }\n builder.addNode({\n id: nid.analysis(analysis.id),\n type: 'analysis',\n title: analysis.title,\n subtitle: humanEnum(analysis.status),\n // No per-analysis detail route exists — land on the analyses list.\n route: 'analyses',\n column: COLUMN.analysis,\n });\n if (linkedToNotebook && analysis.notebookId != null) {\n builder.link(nid.notebook(analysis.notebookId), nid.analysis(analysis.id));\n } else {\n builder.link(datasetNode, nid.analysis(analysis.id));\n }\n }\n\n for (const release of pools.releases) {\n if (!release.datasetIds.includes(dataset.id)) {\n continue;\n }\n addReleaseNode(builder, release);\n builder.link(datasetNode, nid.release(release.id));\n if (release.notebookId != null && builder.has(nid.notebook(release.notebookId))) {\n builder.link(nid.notebook(release.notebookId), nid.release(release.id));\n }\n }\n}\n\nfunction addReleaseNode(builder: LineageBuilder, release: CosRelease, emphasis = false): void {\n const doiSuffix = release.doi ? ' · DOI' : '';\n builder.addNode({\n id: nid.release(release.id),\n type: 'release',\n title: release.title,\n subtitle: `v${release.version}${doiSuffix}`,\n // No per-release detail route exists — land on the releases list.\n route: 'releases',\n column: COLUMN.release,\n emphasis,\n });\n}\n\n/**\n * Provenance for a single dataset: its upstream (source + collection) and its\n * full downstream fan (runs, notebooks, analyses, releases). The dataset is the\n * emphasised root.\n */\nexport function buildDatasetLineage(datasetId: string, pools: LineageDataPools): LineageModel {\n const builder = new LineageBuilder();\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n return builder.build();\n }\n addDatasetUpstream(builder, dataset, pools, true);\n addDatasetDownstream(builder, dataset, pools);\n return builder.build();\n}\n\n/**\n * Provenance for a release: the release plus its input datasets and notebook,\n * each expanded UPSTREAM (source/collection for datasets; the notebook's own\n * datasets). The release is the emphasised root.\n */\nexport function buildReleaseLineage(releaseId: string, pools: LineageDataPools): LineageModel {\n const builder = new LineageBuilder();\n const release = pools.releases.find((item) => item.id === releaseId);\n if (!release) {\n return builder.build();\n }\n\n addReleaseNode(builder, release, true);\n\n for (const datasetId of release.datasetIds) {\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n continue;\n }\n addDatasetUpstream(builder, dataset, pools, false);\n builder.link(nid.dataset(dataset.id), nid.release(release.id));\n }\n\n if (release.notebookId != null) {\n const notebook = pools.notebooks.find((item) => item.id === release.notebookId);\n builder.addNode({\n id: nid.notebook(release.notebookId),\n type: 'notebook',\n title: notebook?.title ?? 'Notebook',\n subtitle: notebook ? humanEnum(notebook.status) : undefined,\n route: `notebooks/${release.notebookId}`,\n column: COLUMN.notebook,\n });\n builder.link(nid.notebook(release.notebookId), nid.release(release.id));\n\n for (const datasetId of notebook?.datasetIds ?? []) {\n const dataset = pools.datasetsById.get(datasetId);\n if (!dataset) {\n continue;\n }\n addDatasetUpstream(builder, dataset, pools, false);\n builder.link(nid.dataset(dataset.id), nid.notebook(release.notebookId));\n }\n }\n\n return builder.build();\n}\n\n// ============================================================================\n// PRESENTATION\n// ============================================================================\n\ninterface NodeMeta {\n label: string;\n Icon: LucideIcon;\n /** Icon-chip classes (semantic accent tokens only). */\n chip: string;\n /** Card border colour class. */\n border: string;\n}\n\nconst NODE_META: Record<LineageNodeType, NodeMeta> = {\n source: {\n label: 'Source',\n Icon: Radar,\n chip: 'bg-accent-blue-subtle text-accent-blue',\n border: 'border-accent-blue',\n },\n collection: {\n label: 'Collection',\n Icon: Boxes,\n chip: 'bg-accent-teal-subtle text-accent-teal',\n border: 'border-accent-teal',\n },\n dataset: {\n label: 'Dataset',\n Icon: Database,\n chip: 'bg-accent-indigo-subtle text-accent-indigo',\n border: 'border-accent-indigo',\n },\n run: {\n label: 'Pipeline Run',\n Icon: Cog,\n chip: 'bg-accent-purple-subtle text-accent-purple',\n border: 'border-accent-purple',\n },\n notebook: {\n label: 'Notebook',\n Icon: NotebookText,\n chip: 'bg-accent-teal-subtle text-accent-teal',\n border: 'border-accent-teal',\n },\n analysis: {\n label: 'Analysis',\n Icon: LineChart,\n chip: 'bg-accent-purple-subtle text-accent-purple',\n border: 'border-accent-purple',\n },\n release: {\n label: 'Release',\n Icon: Tag,\n chip: 'bg-status-success-bg-subtle text-status-success-text',\n border: 'border-status-success-border',\n },\n};\n\ninterface Dims {\n nodeW: number;\n nodeH: number;\n colGap: number;\n rowGap: number;\n pad: number;\n iconSize: string;\n showSubtitle: boolean;\n}\n\nconst DIMS: Record<'full' | 'compact', Dims> = {\n full: {\n nodeW: 190,\n nodeH: 78,\n colGap: 74,\n rowGap: 30,\n pad: 32,\n iconSize: 'size-8',\n showSubtitle: true,\n },\n compact: {\n nodeW: 150,\n nodeH: 54,\n colGap: 46,\n rowGap: 18,\n pad: 18,\n iconSize: 'size-6',\n showSubtitle: false,\n },\n};\n\ninterface Positioned {\n node: LineageNode;\n x: number;\n y: number;\n}\n\ninterface Layout {\n positions: Map<string, Positioned>;\n width: number;\n height: number;\n}\n\nfunction computeLayout(model: LineageModel, dims: Dims): Layout {\n const positions = new Map<string, Positioned>();\n if (model.nodes.length === 0) {\n return { positions, width: dims.pad * 2, height: dims.pad * 2 };\n }\n\n // Present columns, remapped to contiguous indices so empty layers collapse.\n const presentCols = [...new Set(model.nodes.map((n) => n.column))].sort((a, b) => a - b);\n const colOrder = new Map(presentCols.map((c, i) => [c, i]));\n\n const byColumn = new Map<number, LineageNode[]>();\n for (const node of model.nodes) {\n const list = byColumn.get(node.column);\n if (list) {\n list.push(node);\n } else {\n byColumn.set(node.column, [node]);\n }\n }\n\n let contentH = dims.nodeH;\n for (const list of byColumn.values()) {\n const h = list.length * dims.nodeH + (list.length - 1) * dims.rowGap;\n contentH = Math.max(contentH, h);\n }\n\n for (const col of presentCols) {\n const list = byColumn.get(col) ?? [];\n const colH = list.length * dims.nodeH + (list.length - 1) * dims.rowGap;\n const startY = dims.pad + (contentH - colH) / 2;\n const x = dims.pad + (colOrder.get(col) ?? 0) * (dims.nodeW + dims.colGap);\n list.forEach((node, i) => {\n positions.set(node.id, { node, x, y: startY + i * (dims.nodeH + dims.rowGap) });\n });\n }\n\n const width =\n dims.pad * 2 + presentCols.length * dims.nodeW + (presentCols.length - 1) * dims.colGap;\n const height = dims.pad * 2 + contentH;\n return { positions, width, height };\n}\n\nfunction edgePath(x1: number, y1: number, x2: number, y2: number): string {\n const dx = Math.max(24, (x2 - x1) * 0.5);\n return `M ${x1} ${y1} C ${x1 + dx} ${y1}, ${x2 - dx} ${y2}, ${x2} ${y2}`;\n}\n\nexport interface LineageGraphProps {\n model: LineageModel;\n mode?: 'full' | 'compact';\n onNavigate?: (route: string) => void;\n className?: string;\n}\n\nexport function LineageGraph({ model, mode = 'full', onNavigate, className }: LineageGraphProps) {\n const markerId = `cos-lineage-arrow-${useId().replace(/:/g, '')}`;\n const dims = DIMS[mode];\n\n const layout = useMemo(() => computeLayout(model, dims), [model, dims]);\n\n const legendTypes = useMemo(() => {\n const seen = new Set<LineageNodeType>();\n const ordered: LineageNodeType[] = [];\n for (const node of [...model.nodes].sort((a, b) => a.column - b.column)) {\n if (!seen.has(node.type)) {\n seen.add(node.type);\n ordered.push(node.type);\n }\n }\n return ordered;\n }, [model.nodes]);\n\n if (model.nodes.length === 0) {\n return null;\n }\n\n return (\n <div className={cn('flex flex-col gap-3', className)}>\n {mode === 'full' && legendTypes.length > 0 ? (\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n {legendTypes.map((type) => {\n const meta = NODE_META[type];\n return (\n <span\n key={type}\n className=\"inline-flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n className={cn(\n 'flex size-5 items-center justify-center rounded-button',\n meta.chip\n )}\n >\n <meta.Icon className=\"size-3\" aria-hidden=\"true\" />\n </span>\n {meta.label}\n </span>\n );\n })}\n </div>\n ) : null}\n\n <div\n className={cn(\n 'overflow-x-auto rounded-card border border-border-seam bg-bg-canvas',\n mode === 'full' ? 'p-1' : 'p-0.5'\n )}\n >\n <div\n className=\"relative\"\n style={{\n width: layout.width,\n height: layout.height,\n minWidth: '100%',\n backgroundImage: 'radial-gradient(var(--color-border-subtle) 1px, transparent 1px)',\n backgroundSize: mode === 'full' ? '20px 20px' : '16px 16px',\n }}\n >\n {/* Edges (behind the node cards). */}\n <svg\n className=\"pointer-events-none absolute inset-0 text-border-strong\"\n width={layout.width}\n height={layout.height}\n viewBox={`0 0 ${layout.width} ${layout.height}`}\n aria-hidden=\"true\"\n >\n <defs>\n <marker\n id={markerId}\n viewBox=\"0 0 8 8\"\n refX=\"6.5\"\n refY=\"4\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M1 1 L7 4 L1 7 z\" fill=\"currentColor\" />\n </marker>\n </defs>\n {model.edges.map((edge) => {\n const from = layout.positions.get(edge.from);\n const to = layout.positions.get(edge.to);\n if (!from || !to) {\n return null;\n }\n const x1 = from.x + dims.nodeW;\n const y1 = from.y + dims.nodeH / 2;\n const x2 = to.x;\n const y2 = to.y + dims.nodeH / 2;\n return (\n <path\n key={`${edge.from}»${edge.to}`}\n d={edgePath(x1, y1, x2, y2)}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={mode === 'full' ? 1.5 : 1.25}\n strokeLinecap=\"round\"\n markerEnd={`url(#${markerId})`}\n opacity={0.7}\n />\n );\n })}\n </svg>\n\n {/* Node cards. */}\n {[...layout.positions.values()].map(({ node, x, y }) => {\n const meta = NODE_META[node.type];\n const clickable = Boolean(node.route && onNavigate);\n const content = (\n <div\n className={cn(\n 'flex h-full w-full items-center gap-2.5 rounded-card border bg-bg-elevated px-3 shadow-sm transition-shadow',\n meta.border,\n clickable && 'group-hover:shadow-md',\n node.emphasis && 'ring-1 ring-border-strong'\n )}\n >\n <span\n className={cn(\n 'flex shrink-0 items-center justify-center rounded-button',\n dims.iconSize,\n meta.chip\n )}\n aria-hidden=\"true\"\n >\n <meta.Icon className={mode === 'full' ? 'size-4' : 'size-3.5'} />\n </span>\n <span className=\"flex min-w-0 flex-1 flex-col text-left\">\n <span className=\"truncate text-[10px] font-medium uppercase tracking-wide text-text-tertiary\">\n {node.typeLabel ?? meta.label}\n </span>\n <span\n className={cn(\n 'truncate font-semibold text-text-primary',\n mode === 'full' ? 'text-sm' : 'text-xs'\n )}\n >\n {node.title}\n </span>\n {dims.showSubtitle && node.subtitle ? (\n <span className=\"truncate text-[11px] text-text-secondary\">\n {node.subtitle}\n </span>\n ) : null}\n </span>\n </div>\n );\n\n const style = { left: x, top: y, width: dims.nodeW, height: dims.nodeH } as const;\n\n if (clickable && node.route) {\n const route = node.route;\n return (\n <button\n key={node.id}\n type=\"button\"\n onClick={() => onNavigate?.(route)}\n className=\"group absolute rounded-card focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n style={style}\n title={`${node.typeLabel ?? meta.label}: ${node.title}`}\n >\n {content}\n </button>\n );\n }\n\n return (\n <div key={node.id} className=\"absolute\" style={style}>\n {content}\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n}\n\nexport default LineageGraph;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StepDAG.d.ts","sourceRoot":"","sources":["../../../src/cosmicintersection/components/StepDAG.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"StepDAG.d.ts","sourceRoot":"","sources":["../../../src/cosmicintersection/components/StepDAG.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGlE,MAAM,WAAW,WAAW;IAC1B,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,yDAAyD;IACzD,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoHD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,YAAY,kDAkBzD;AAED,eAAe,OAAO,CAAC"}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { formatEnumLabel as e } from "./StatusBadge.js";
|
|
2
2
|
import { Fragment as t } from "react";
|
|
3
3
|
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
4
|
-
import { Bell as i,
|
|
4
|
+
import { Bell as i, Boxes as a, Calculator as o, Database as s, Gauge as c, Globe2 as l, Grid3x3 as u, Shuffle as d, SlidersHorizontal as f, Upload as p } from "lucide-react";
|
|
5
5
|
//#region src/cosmicintersection/components/StepDAG.tsx
|
|
6
|
-
var
|
|
7
|
-
INGEST: { icon:
|
|
8
|
-
CALIBRATE: { icon:
|
|
9
|
-
TRANSFORM: { icon:
|
|
10
|
-
ANALYZE: { icon:
|
|
11
|
-
EXPORT: { icon:
|
|
12
|
-
NOTIFY: { icon: i }
|
|
13
|
-
|
|
6
|
+
var m = {
|
|
7
|
+
INGEST: { icon: s },
|
|
8
|
+
CALIBRATE: { icon: f },
|
|
9
|
+
TRANSFORM: { icon: d },
|
|
10
|
+
ANALYZE: { icon: c },
|
|
11
|
+
EXPORT: { icon: p },
|
|
12
|
+
NOTIFY: { icon: i },
|
|
13
|
+
RASTER_CALC: { icon: o },
|
|
14
|
+
REPROJECT: { icon: l },
|
|
15
|
+
TILE: { icon: u },
|
|
16
|
+
ZONAL_STATS: { icon: a }
|
|
17
|
+
}, h = { icon: a }, g = {
|
|
14
18
|
border: "border-border-default",
|
|
15
19
|
icon: "bg-bg-sunken text-text-secondary",
|
|
16
20
|
ring: ""
|
|
17
|
-
},
|
|
21
|
+
}, _ = {
|
|
18
22
|
SUCCEEDED: {
|
|
19
23
|
border: "border-status-success-border",
|
|
20
24
|
icon: "bg-status-success-bg-subtle text-status-success-text",
|
|
@@ -35,9 +39,9 @@ var u = {
|
|
|
35
39
|
icon: "bg-status-info-bg-subtle text-status-info-text",
|
|
36
40
|
ring: ""
|
|
37
41
|
},
|
|
38
|
-
CANCELLED:
|
|
42
|
+
CANCELLED: g
|
|
39
43
|
};
|
|
40
|
-
function
|
|
44
|
+
function v() {
|
|
41
45
|
return /* @__PURE__ */ n("span", {
|
|
42
46
|
"aria-hidden": "true",
|
|
43
47
|
className: "flex shrink-0 items-center justify-center text-border-strong",
|
|
@@ -58,8 +62,8 @@ function p() {
|
|
|
58
62
|
})
|
|
59
63
|
});
|
|
60
64
|
}
|
|
61
|
-
function
|
|
62
|
-
let a =
|
|
65
|
+
function y({ step: t, index: i }) {
|
|
66
|
+
let a = (m[t.kind] ?? h).icon, o = t.status && _[t.status] || g, s = e(t.kind), c = !!(t.name && t.name.trim() && t.name.trim().toLowerCase() !== s.toLowerCase());
|
|
63
67
|
return /* @__PURE__ */ r("div", {
|
|
64
68
|
role: "listitem",
|
|
65
69
|
className: `flex w-full items-center gap-3 rounded-card border bg-bg-elevated px-3.5 py-3 md:w-auto md:min-w-[8.5rem] ${o.border} ${o.ring}`,
|
|
@@ -87,18 +91,18 @@ function m({ step: t, index: i }) {
|
|
|
87
91
|
})]
|
|
88
92
|
});
|
|
89
93
|
}
|
|
90
|
-
function
|
|
94
|
+
function b({ steps: e, className: i }) {
|
|
91
95
|
return e.length === 0 ? null : /* @__PURE__ */ n("div", {
|
|
92
96
|
role: "list",
|
|
93
97
|
"aria-label": "Pipeline step flow",
|
|
94
98
|
className: `flex flex-col items-stretch gap-2 md:flex-row md:flex-wrap md:items-center ${i ?? ""}`,
|
|
95
|
-
children: e.map((i, a) => /* @__PURE__ */ r(t, { children: [/* @__PURE__ */ n(
|
|
99
|
+
children: e.map((i, a) => /* @__PURE__ */ r(t, { children: [/* @__PURE__ */ n(y, {
|
|
96
100
|
step: i,
|
|
97
101
|
index: a
|
|
98
|
-
}), a < e.length - 1 ? /* @__PURE__ */ n(
|
|
102
|
+
}), a < e.length - 1 ? /* @__PURE__ */ n(v, {}) : null] }, `${i.kind}-${a}`))
|
|
99
103
|
});
|
|
100
104
|
}
|
|
101
105
|
//#endregion
|
|
102
|
-
export {
|
|
106
|
+
export { b as default };
|
|
103
107
|
|
|
104
108
|
//# sourceMappingURL=StepDAG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StepDAG.js","names":[],"sources":["../../../src/cosmicintersection/components/StepDAG.tsx"],"sourcesContent":["/**\n * StepDAG — a lightweight, dependency-free step-flow visualization.\n *\n * Renders an ordered list of pipeline steps as connected rounded nodes: each\n * node shows a per-kind icon + label (and an optional custom step name), and an\n * optional run status tint. Nodes are joined by custom inline-SVG arrow\n * connectors — horizontal on md+ screens, vertical (stacked) on small screens\n * so it never forces a horizontal-scroll.\n *\n * Colour comes only from the semantic token families (bg-bg-*, text-text-*,\n * border-border-*, status-*) — never a raw palette colour — matching mockups\n * 11 & 14.\n */\nimport { Fragment } from 'react';\nimport type { LucideIcon } from 'lucide-react';\nimport {
|
|
1
|
+
{"version":3,"file":"StepDAG.js","names":[],"sources":["../../../src/cosmicintersection/components/StepDAG.tsx"],"sourcesContent":["/**\n * StepDAG — a lightweight, dependency-free step-flow visualization.\n *\n * Renders an ordered list of pipeline steps as connected rounded nodes: each\n * node shows a per-kind icon + label (and an optional custom step name), and an\n * optional run status tint. Nodes are joined by custom inline-SVG arrow\n * connectors — horizontal on md+ screens, vertical (stacked) on small screens\n * so it never forces a horizontal-scroll.\n *\n * Colour comes only from the semantic token families (bg-bg-*, text-text-*,\n * border-border-*, status-*) — never a raw palette colour — matching mockups\n * 11 & 14.\n */\nimport { Fragment } from 'react';\nimport type { LucideIcon } from 'lucide-react';\nimport {\n Bell,\n Boxes,\n Calculator,\n Database,\n Gauge,\n Globe2,\n Grid3x3,\n Shuffle,\n SlidersHorizontal,\n Upload,\n} from 'lucide-react';\n\nimport type { CosRunStatus, CosStepKind } from '../api/cosmicApi';\nimport { formatEnumLabel } from './StatusBadge';\n\nexport interface StepDAGStep {\n /** Optional human-authored step name; shown under the kind label when it differs. */\n name?: string | null;\n kind: CosStepKind;\n /** Optional run status — tints the node when present. */\n status?: CosRunStatus | null;\n}\n\nexport interface StepDAGProps {\n steps: StepDAGStep[];\n className?: string;\n}\n\nconst KIND_META: Record<CosStepKind, { icon: LucideIcon }> = {\n INGEST: { icon: Database },\n CALIBRATE: { icon: SlidersHorizontal },\n TRANSFORM: { icon: Shuffle },\n ANALYZE: { icon: Gauge },\n EXPORT: { icon: Upload },\n NOTIFY: { icon: Bell },\n // Geospatial kinds (BOFF-4355) — a step can already carry these, so they get\n // a real icon rather than falling through to the generic one.\n RASTER_CALC: { icon: Calculator },\n REPROJECT: { icon: Globe2 },\n TILE: { icon: Grid3x3 },\n ZONAL_STATS: { icon: Boxes },\n};\n\n/** Guards against a kind the subgraph adds before this map catches up. */\nconst FALLBACK_KIND_META: { icon: LucideIcon } = { icon: Boxes };\n\ninterface Accent {\n /** Node border. */\n border: string;\n /** Icon chip background + text. */\n icon: string;\n /** Optional focus ring (used to flag an in-flight node). */\n ring: string;\n}\n\nconst DEFAULT_ACCENT: Accent = {\n border: 'border-border-default',\n icon: 'bg-bg-sunken text-text-secondary',\n ring: '',\n};\n\nconst STATUS_ACCENT: Partial<Record<CosRunStatus, Accent>> = {\n SUCCEEDED: {\n border: 'border-status-success-border',\n icon: 'bg-status-success-bg-subtle text-status-success-text',\n ring: '',\n },\n RUNNING: {\n border: 'border-status-warning-border',\n icon: 'bg-status-warning-bg-subtle text-status-warning-text',\n ring: 'ring-2 ring-status-warning-border',\n },\n FAILED: {\n border: 'border-status-error-border',\n icon: 'bg-status-error-bg-subtle text-status-error-text',\n ring: '',\n },\n QUEUED: {\n border: 'border-status-info-border',\n icon: 'bg-status-info-bg-subtle text-status-info-text',\n ring: '',\n },\n CANCELLED: DEFAULT_ACCENT,\n};\n\n/** Custom inline-SVG connector: a line + arrowhead. Points right on md+, down below. */\nfunction StepConnector() {\n return (\n <span\n aria-hidden=\"true\"\n className=\"flex shrink-0 items-center justify-center text-border-strong\"\n >\n <svg\n viewBox=\"0 0 40 12\"\n className=\"h-4 w-6 rotate-90 md:h-3 md:w-9 md:rotate-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.75}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"2\" y1=\"6\" x2=\"33\" y2=\"6\" />\n <path d=\"M28 2 L34 6 L28 10\" />\n </svg>\n </span>\n );\n}\n\nfunction StepNode({ step, index }: { step: StepDAGStep; index: number }) {\n const meta = KIND_META[step.kind] ?? FALLBACK_KIND_META;\n const Icon = meta.icon;\n const accent = (step.status && STATUS_ACCENT[step.status]) || DEFAULT_ACCENT;\n const label = formatEnumLabel(step.kind);\n const showName = Boolean(\n step.name && step.name.trim() && step.name.trim().toLowerCase() !== label.toLowerCase()\n );\n\n return (\n <div\n role=\"listitem\"\n className={`flex w-full items-center gap-3 rounded-card border bg-bg-elevated px-3.5 py-3 md:w-auto md:min-w-[8.5rem] ${accent.border} ${accent.ring}`}\n >\n <span\n className={`flex size-9 shrink-0 items-center justify-center rounded-lg ${accent.icon}`}\n >\n <Icon className=\"size-4\" aria-hidden=\"true\" />\n </span>\n <span className=\"flex min-w-0 flex-col\">\n <span className=\"flex items-baseline gap-1.5\">\n <span className=\"text-[0.65rem] font-semibold tabular-nums text-text-secondary\">\n {index + 1}\n </span>\n <span className=\"truncate text-sm font-medium text-text-primary\">{label}</span>\n </span>\n {showName ? (\n <span className=\"truncate text-xs text-text-secondary\">{step.name}</span>\n ) : null}\n </span>\n </div>\n );\n}\n\n/**\n * Horizontal (md+) / vertical (mobile) step-flow diagram. Presentational only —\n * callers decide where the step list comes from (pipeline definition or a run).\n */\nexport function StepDAG({ steps, className }: StepDAGProps) {\n if (steps.length === 0) {\n return null;\n }\n return (\n <div\n role=\"list\"\n aria-label=\"Pipeline step flow\"\n className={`flex flex-col items-stretch gap-2 md:flex-row md:flex-wrap md:items-center ${className ?? ''}`}\n >\n {steps.map((step, index) => (\n <Fragment key={`${step.kind}-${index}`}>\n <StepNode step={step} index={index} />\n {index < steps.length - 1 ? <StepConnector /> : null}\n </Fragment>\n ))}\n </div>\n );\n}\n\nexport default StepDAG;\n"],"mappings":";;;;;AA4CA,IAAM,IAAuD;CAC3D,QAAQ,EAAE,MAAM,EAAS;CACzB,WAAW,EAAE,MAAM,EAAkB;CACrC,WAAW,EAAE,MAAM,EAAQ;CAC3B,SAAS,EAAE,MAAM,EAAM;CACvB,QAAQ,EAAE,MAAM,EAAO;CACvB,QAAQ,EAAE,MAAM,EAAK;CAGrB,aAAa,EAAE,MAAM,EAAW;CAChC,WAAW,EAAE,MAAM,EAAO;CAC1B,MAAM,EAAE,MAAM,EAAQ;CACtB,aAAa,EAAE,MAAM,EAAM;AAC7B,GAGM,IAA2C,EAAE,MAAM,EAAM,GAWzD,IAAyB;CAC7B,QAAQ;CACR,MAAM;CACN,MAAM;AACR,GAEM,IAAuD;CAC3D,WAAW;EACT,QAAQ;EACR,MAAM;EACN,MAAM;CACR;CACA,SAAS;EACP,QAAQ;EACR,MAAM;EACN,MAAM;CACR;CACA,QAAQ;EACN,QAAQ;EACR,MAAM;EACN,MAAM;CACR;CACA,QAAQ;EACN,QAAQ;EACR,MAAM;EACN,MAAM;CACR;CACA,WAAW;AACb;AAGA,SAAS,IAAgB;CACvB,OACE,kBAAC,QAAD;EACE,eAAY;EACZ,WAAU;YAEV,kBAAC,OAAD;GACE,SAAQ;GACR,WAAU;GACV,MAAK;GACL,QAAO;GACP,aAAa;GACb,eAAc;GACd,gBAAe;aAPjB,CASE,kBAAC,QAAD;IAAM,IAAG;IAAI,IAAG;IAAI,IAAG;IAAK,IAAG;GAAK,CAAA,GACpC,kBAAC,QAAD,EAAM,GAAE,qBAAsB,CAAA,CAC3B;;CACD,CAAA;AAEV;AAEA,SAAS,EAAS,EAAE,SAAM,YAA+C;CAEvE,IAAM,KADO,EAAU,EAAK,SAAS,GACnB,MACZ,IAAU,EAAK,UAAU,EAAc,EAAK,WAAY,GACxD,IAAQ,EAAgB,EAAK,IAAI,GACjC,IAAW,GACf,EAAK,QAAQ,EAAK,KAAK,KAAK,KAAK,EAAK,KAAK,KAAK,EAAE,YAAY,MAAM,EAAM,YAAY;CAGxF,OACE,kBAAC,OAAD;EACE,MAAK;EACL,WAAW,6GAA6G,EAAO,OAAO,GAAG,EAAO;YAFlJ,CAIE,kBAAC,QAAD;GACE,WAAW,+DAA+D,EAAO;aAEjF,kBAAC,GAAD;IAAM,WAAU;IAAS,eAAY;GAAQ,CAAA;EACzC,CAAA,GACN,kBAAC,QAAD;GAAM,WAAU;aAAhB,CACE,kBAAC,QAAD;IAAM,WAAU;cAAhB,CACE,kBAAC,QAAD;KAAM,WAAU;eACb,IAAQ;IACL,CAAA,GACN,kBAAC,QAAD;KAAM,WAAU;eAAkD;IAAY,CAAA,CAC1E;OACL,IACC,kBAAC,QAAD;IAAM,WAAU;cAAwC,EAAK;GAAW,CAAA,IACtE,IACA;IACH;;AAET;AAMA,SAAgB,EAAQ,EAAE,UAAO,gBAA2B;CAI1D,OAHI,EAAM,WAAW,IACZ,OAGP,kBAAC,OAAD;EACE,MAAK;EACL,cAAW;EACX,WAAW,8EAA8E,KAAa;YAErG,EAAM,KAAK,GAAM,MAChB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;GAAgB;GAAa;EAAQ,CAAA,GACpC,IAAQ,EAAM,SAAS,IAAI,kBAAC,GAAD,CAAgB,CAAA,IAAI,IACxC,EAAA,GAHK,GAAG,EAAK,KAAK,GAAG,GAGrB,CACX;CACE,CAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionsPage.d.ts","sourceRoot":"","sources":["../../../../src/cosmicintersection/pages/collections/CollectionsPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CollectionsPage.d.ts","sourceRoot":"","sources":["../../../../src/cosmicintersection/pages/collections/CollectionsPage.tsx"],"names":[],"mappings":"AA4BA,MAAM,CAAC,OAAO,UAAU,eAAe,4CAiItC"}
|