11/** @file Type definitions common between all backends. */
22import { z } from 'zod'
33import { getText , resolveDictionary , type Replacements , type TextId } from '../text.js'
4- import * as array from '../utilities/data/array.js'
54import * as dateTime from '../utilities/data/dateTime.js'
65import * as newtype from '../utilities/data/newtype.js'
76import * as permissions from '../utilities/permissions.js'
8- import * as uniqueString from '../utilities/uniqueString.js'
97import { getFileDetailsPath } from './Backend/remoteBackendPaths.js'
108import {
119 DatalinkId ,
@@ -18,7 +16,6 @@ import {
1816 Path ,
1917 ProjectId ,
2018 SecretId ,
21- UpAssetId ,
2219 VirtualParentsPath ,
2320 type Address ,
2421 type AssetId ,
@@ -515,9 +512,13 @@ export enum Plan {
515512 enterprise = 'enterprise' ,
516513}
517514
518- export const PLANS = Object . values ( Plan )
515+ export const PLANS : readonly Plan [ ] = Object . values ( Plan )
519516
520- export const isPlan = array . includesPredicate ( PLANS )
517+ /** Whether a given value is a {@link Plan}. */
518+ export function isPlan ( value : unknown ) : value is Plan {
519+ const plans : readonly unknown [ ] = PLANS
520+ return plans . includes ( value )
521+ }
521522
522523/** Metadata for a payment checkout session. */
523524export interface CheckoutSession {
@@ -628,8 +629,8 @@ export interface CreateCustomerPortalSessionResponse {
628629export interface PathResolveResponse extends Omit < AnyRealAsset , 'type' | 'ensoPath' > { }
629630
630631/** Response from "assets/${assetId}" endpoint. */
631- export type AssetDetailsResponse < Id extends RealAssetId > =
632- | ( Omit < Asset < RealAssetTypeId < Id > > , 'ensoPath' > & { readonly metadataId : MetadataId } )
632+ export type AssetDetailsResponse < Id extends AssetId > =
633+ | ( Omit < Asset < AssetTypeFromId < Id > > , 'ensoPath' > & { readonly metadataId : MetadataId } )
633634 | null
634635
635636/** Whether the user is on a plan with multiple seats (i.e. a plan that supports multiple users). */
@@ -856,16 +857,13 @@ export enum AssetType {
856857 secret = 'secret' ,
857858 datalink = 'datalink' ,
858859 directory = 'directory' ,
859- /** A special {@link AssetType} representing a button that navigates to the parent directory. */
860- specialUp = 'specialUp' ,
861860}
862861
863862export const ASSET_TYPE_TO_TEXT_ID : Readonly < Record < AssetType , TextId > > = {
864863 [ AssetType . directory ] : 'directoryAssetType' ,
865864 [ AssetType . project ] : 'projectAssetType' ,
866865 [ AssetType . file ] : 'fileAssetType' ,
867866 [ AssetType . secret ] : 'secretAssetType' ,
868- [ AssetType . specialUp ] : 'specialUpAssetType' ,
869867 [ AssetType . datalink ] : 'datalinkAssetType' ,
870868} satisfies { [ Type in AssetType ] : `${Type } AssetType` }
871869
@@ -885,26 +883,21 @@ export type RealAssetType =
885883 | AssetType . directory
886884
887885/** The corresponding ID newtype for each {@link AssetType}. */
888- export interface IdType extends RealAssetIdType , SpecialAssetIdType { }
889- export type RealAssetId = ProjectId | FileId | DatalinkId | SecretId | DirectoryId
890- export interface RealAssetIdType {
886+ export interface IdType {
891887 readonly [ AssetType . project ] : ProjectId
892888 readonly [ AssetType . file ] : FileId
893889 readonly [ AssetType . datalink ] : DatalinkId
894890 readonly [ AssetType . secret ] : SecretId
895891 readonly [ AssetType . directory ] : DirectoryId
896892}
897893
898- export type RealAssetTypeId < Id extends RealAssetId > =
894+ type AssetTypeFromId < Id extends AssetId > =
899895 Id extends ProjectId ? AssetType . project
900896 : Id extends FileId ? AssetType . file
901897 : Id extends DatalinkId ? AssetType . datalink
902898 : Id extends SecretId ? AssetType . secret
903- : AssetType . directory
904-
905- export interface SpecialAssetIdType {
906- readonly [ AssetType . specialUp ] : UpAssetId
907- }
899+ : Id extends DirectoryId ? AssetType . directory
900+ : never
908901
909902/**
910903 * Integers (starting from 0) corresponding to the order in which each asset type should appear
@@ -916,7 +909,6 @@ export const ASSET_TYPE_ORDER: Readonly<Record<AssetType, number>> = {
916909 [ AssetType . file ] : - 2 ,
917910 [ AssetType . datalink ] : - 3 ,
918911 [ AssetType . secret ] : - 4 ,
919- [ AssetType . specialUp ] : 1 ,
920912}
921913
922914/** A state associated with a credential. */
@@ -975,89 +967,26 @@ export type DatalinkAsset = Asset<AssetType.datalink>
975967/** A convenience alias for {@link Asset}<{@link AssetType.secret}>. */
976968export type SecretAsset = Asset < AssetType . secret >
977969
978- /** A convenience alias for {@link Asset}<{@link AssetType.specialUp}>. */
979- export type SpecialUpAsset = Asset < AssetType . specialUp >
980-
981- const PLACEHOLDER_SIGNATURE = Symbol ( 'placeholder' )
982-
983- /** Creates a new placeholder id. */
984- function createPlaceholderId ( from ?: string ) : string {
985- const id = new String ( from ?? uniqueString . uniqueString ( ) )
986-
987- Object . defineProperty ( id , PLACEHOLDER_SIGNATURE , {
988- value : true ,
989- enumerable : false ,
990- configurable : false ,
991- writable : false ,
992- } )
993-
994- return id as string
995- }
996-
997- /** Whether a given {@link AssetId} is a placeholder id. */
998- export function isPlaceholderId ( id : AssetId ) {
999- return typeof id !== 'string' && PLACEHOLDER_SIGNATURE in id
1000- }
1001-
1002970/** Whether a given asset represents a credential. */
1003971export function isAssetCredential (
1004972 asset : Asset ,
1005973) : asset is SecretAsset & { credentialMetadata : CredentialMetadata } {
1006974 return asset . type === 'secret' && asset . credentialMetadata !== undefined
1007975}
1008976
1009- /** Extract the file extension from a file name. */
1010- function fileExtension ( fileNameOrPath : string ) {
1011- return fileNameOrPath . match ( / [ . ] ( [ ^ . ] + ?) $ / ) ?. [ 1 ] ?? ''
1012- }
1013-
1014977/** Whether an asset can be downloaded. */
1015978export function isDownloadableAsset ( type : AssetType | undefined ) {
1016979 return type !== AssetType . secret
1017980}
1018981
1019- /** Creates a {@link FileAsset} using the given values. */
1020- export function createPlaceholderFileAsset ( title : string , parentId : DirectoryId ) : FileAsset {
1021- return {
1022- type : AssetType . file ,
1023- id : FileId ( createPlaceholderId ( ) ) ,
1024- title,
1025- parentId,
1026- permissions : [ ] ,
1027- modifiedAt : dateTime . toRfc3339 ( new Date ( ) ) ,
1028- projectState : null ,
1029- extension : fileExtension ( title ) ,
1030- parentsPath : ParentsPath ( '' ) ,
1031- virtualParentsPath : VirtualParentsPath ( '' ) ,
1032- ensoPath : EnsoPath ( '' ) ,
1033- }
1034- }
1035-
1036- /** Creates a {@link ProjectAsset} using the given values. */
1037- export function createPlaceholderProjectAsset ( title : string , parentId : DirectoryId ) : ProjectAsset {
1038- return {
1039- type : AssetType . project ,
1040- id : ProjectId ( createPlaceholderId ( ) ) ,
1041- title,
1042- parentId,
1043- permissions : [ ] ,
1044- modifiedAt : dateTime . toRfc3339 ( new Date ( ) ) ,
1045- projectState : { type : ProjectState . new } ,
1046- extension : null ,
1047- parentsPath : ParentsPath ( '' ) ,
1048- virtualParentsPath : VirtualParentsPath ( '' ) ,
1049- ensoPath : EnsoPath ( '' ) ,
1050- }
1051- }
1052-
1053982/** Any object with a `type` field matching the given `AssetType`. */
1054983interface HasType < Type extends AssetType > {
1055984 readonly type : Type
1056985}
1057986
1058987/** A union of all possible {@link Asset} variants. */
1059988export type AnyAsset < Type extends AssetType = AssetType > = Extract <
1060- DatalinkAsset | DirectoryAsset | FileAsset | ProjectAsset | SecretAsset | SpecialUpAsset ,
989+ DatalinkAsset | DirectoryAsset | FileAsset | ProjectAsset | SecretAsset ,
1061990 HasType < Type >
1062991>
1063992
@@ -1081,44 +1010,6 @@ export function extractTypeFromId(id: AssetId): AnyAsset extends infer T ?
10811010 } as never
10821011}
10831012
1084- /** Creates a new placeholder asset id for the given asset type. */
1085- export function createPlaceholderAssetId < Type extends AssetType > (
1086- type : Type ,
1087- id ?: string ,
1088- ) : IdType [ Type ] {
1089- // This is required so that TypeScript can check the `switch` for exhaustiveness.
1090- const assetType : AssetType = type
1091- id = createPlaceholderId ( id )
1092- let result : AssetId
1093- switch ( assetType ) {
1094- case AssetType . directory : {
1095- result = DirectoryId ( `directory-${ id } ` )
1096- break
1097- }
1098- case AssetType . project : {
1099- result = ProjectId ( id )
1100- break
1101- }
1102- case AssetType . file : {
1103- result = FileId ( id )
1104- break
1105- }
1106- case AssetType . datalink : {
1107- result = DatalinkId ( id )
1108- break
1109- }
1110- case AssetType . secret : {
1111- result = SecretId ( id )
1112- break
1113- }
1114- case AssetType . specialUp : {
1115- result = UpAssetId ( id )
1116- break
1117- }
1118- }
1119- return result as IdType [ Type ]
1120- }
1121-
11221013/** A type guard that returns whether an {@link Asset} is a {@link ProjectAsset}. */
11231014export const assetIsProject = assetIsType ( AssetType . project )
11241015/** A type guard that returns whether an {@link Asset} is a {@link DirectoryAsset}. */
@@ -1917,7 +1808,7 @@ export default abstract class Backend {
19171808 */
19181809 abstract getProjectDetails ( projectId : ProjectId , getPresignedUrl ?: boolean ) : Promise < Project >
19191810 /** Return asset details. */
1920- abstract getAssetDetails < Id extends RealAssetId > (
1811+ abstract getAssetDetails < Id extends AssetId > (
19211812 assetId : Id ,
19221813 rootPath : Path | undefined ,
19231814 ) : Promise < AssetDetailsResponse < Id > >
0 commit comments