@attlaz/client 1.112.0 → 1.114.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,24 +1,23 @@
1
- import { Adapter } from '../Adapter/Adapter.js';
2
- import { AdapterConnection } from '../Adapter/AdapterConnection.js';
3
1
  import { ApiRecord } from '../ApiRecord.js';
4
- import { CodeSource } from '../Deployment/CodeSource.js';
5
- import { CodeSourceAccount } from '../Deployment/CodeSourceAccount.js';
6
- import { EntityType } from '../EntityType.js';
7
- import { Flow } from '../../Flow/Model/Flow.js';
8
- import { FlowRun } from '../../Flow/Model/FlowRun.js';
9
- import { Channel } from '../Messaging/Channel/Channel.js';
10
- import { Subscriber } from '../Messaging/Subscriber.js';
11
- import { CodeDeploy } from '../Project/CodeDeploy.js';
12
- import { Project } from '../Project/Project.js';
13
- import { ProjectEnvironment } from '../Project/ProjectEnvironment.js';
14
- import { Trigger } from '../Trigger/Trigger.js';
15
- import { Workspace } from '../Workspace/Workspace.js';
16
- import { WorkspaceMember } from '../Workspace/WorkspaceMember.js';
2
+ /**
3
+ * One row of a search response.
4
+ *
5
+ * The search index is a display projection: `label` and `description` are stored in the index and
6
+ * are everything the result list renders. Navigation is resolved on click from `entityId` and
7
+ * `type`, so no entity is loaded for the results the user never clicks.
8
+ *
9
+ * `type` is deliberately a plain string rather than {@link EntityType}: an entity type this client
10
+ * does not know about must still be shown. Parsing it into the enum here used to throw, and a
11
+ * throw in a parser makes the row disappear from the collection with no error the user can see —
12
+ * every multi-word type was silently missing from search for over a year that way. Map it to
13
+ * `EntityType` where navigation is decided, and let an unrecognised type render as a result that
14
+ * cannot be opened.
15
+ */
17
16
  export declare class SearchResult {
18
- type: EntityType;
17
+ type: string;
18
+ entityId: string;
19
19
  label: string;
20
20
  description: string;
21
- entity: Workspace | WorkspaceMember | Project | ProjectEnvironment | Flow | FlowRun | Trigger | Channel | Subscriber | Adapter | AdapterConnection | CodeSourceAccount | CodeSource | CodeDeploy;
22
21
  score: number;
23
22
  static parse(rawResult: ApiRecord): SearchResult;
24
23
  }
@@ -1,94 +1,30 @@
1
- import { Adapter } from '../Adapter/Adapter.js';
2
- import { AdapterConnection } from '../Adapter/AdapterConnection.js';
3
- import { CodeSource } from '../Deployment/CodeSource.js';
4
- import { CodeSourceAccount } from '../Deployment/CodeSourceAccount.js';
5
- import { EntityType } from '../EntityType.js';
6
- import { Flow } from '../../Flow/Model/Flow.js';
7
- import { FlowRun } from '../../Flow/Model/FlowRun.js';
8
- import { Channel } from '../Messaging/Channel/Channel.js';
9
- import { Subscriber } from '../Messaging/Subscriber.js';
10
- import { CodeDeploy } from '../Project/CodeDeploy.js';
11
- import { Project } from '../Project/Project.js';
12
- import { ProjectEnvironment } from '../Project/ProjectEnvironment.js';
13
- import { Trigger } from '../Trigger/Trigger.js';
14
- import { Workspace } from '../Workspace/Workspace.js';
15
- import { WorkspaceMember } from '../Workspace/WorkspaceMember.js';
1
+ /**
2
+ * One row of a search response.
3
+ *
4
+ * The search index is a display projection: `label` and `description` are stored in the index and
5
+ * are everything the result list renders. Navigation is resolved on click from `entityId` and
6
+ * `type`, so no entity is loaded for the results the user never clicks.
7
+ *
8
+ * `type` is deliberately a plain string rather than {@link EntityType}: an entity type this client
9
+ * does not know about must still be shown. Parsing it into the enum here used to throw, and a
10
+ * throw in a parser makes the row disappear from the collection with no error the user can see —
11
+ * every multi-word type was silently missing from search for over a year that way. Map it to
12
+ * `EntityType` where navigation is decided, and let an unrecognised type render as a result that
13
+ * cannot be opened.
14
+ */
16
15
  export class SearchResult {
17
16
  type;
17
+ entityId;
18
18
  label;
19
19
  description;
20
- entity;
21
20
  score;
22
21
  static parse(rawResult) {
23
22
  const searchResult = new SearchResult();
24
- searchResult.type = EntityType.fromString(rawResult.entity_type);
25
- // searchResult.entity = rawResult.entity;
23
+ searchResult.type = rawResult.entity_type;
24
+ searchResult.entityId = rawResult.entity;
26
25
  searchResult.label = rawResult.label;
27
26
  searchResult.description = rawResult.description;
28
27
  searchResult.score = rawResult.score;
29
- const rawEntity = rawResult.entity;
30
- switch (searchResult.type) {
31
- case EntityType.Organisation:
32
- // TODO: implement
33
- searchResult.entity = rawEntity;
34
- break;
35
- case EntityType.Workspace:
36
- searchResult.entity = Workspace.parse(rawEntity);
37
- break;
38
- case EntityType.Project:
39
- searchResult.entity = Project.parse(rawEntity);
40
- break;
41
- case EntityType.ProjectEnvironment:
42
- searchResult.entity = ProjectEnvironment.parse(rawEntity);
43
- break;
44
- case EntityType.Flow:
45
- searchResult.entity = Flow.parse(rawEntity);
46
- break;
47
- case EntityType.FlowRun:
48
- searchResult.entity = FlowRun.parse(rawEntity);
49
- break;
50
- case EntityType.WorkspaceMember:
51
- searchResult.entity = WorkspaceMember.parse(rawEntity);
52
- break;
53
- case EntityType.Adapter:
54
- searchResult.entity = Adapter.parse(rawEntity);
55
- break;
56
- case EntityType.AdapterConnection:
57
- searchResult.entity = AdapterConnection.parse(rawEntity);
58
- break;
59
- case EntityType.Channel:
60
- searchResult.entity = Channel.parse(rawEntity);
61
- break;
62
- case EntityType.ChannelSubscriber:
63
- searchResult.entity = Subscriber.parseRaw(rawEntity);
64
- break;
65
- case EntityType.Trigger:
66
- searchResult.entity = Trigger.parse(rawEntity);
67
- break;
68
- case EntityType.CodeSourceAccount:
69
- searchResult.entity = CodeSourceAccount.parse(rawEntity);
70
- break;
71
- case EntityType.CodeSource:
72
- searchResult.entity = CodeSource.parse(rawEntity);
73
- break;
74
- case EntityType.CodeSourceDeploy:
75
- searchResult.entity = CodeDeploy.parse(rawEntity);
76
- break;
77
- case EntityType.StorageBucket:
78
- // TODO: implement
79
- searchResult.entity = rawEntity;
80
- break;
81
- case EntityType.LogStream:
82
- // TODO: implement
83
- searchResult.entity = rawEntity;
84
- break;
85
- case EntityType.RunnerPool:
86
- // TODO: implement
87
- searchResult.entity = rawEntity;
88
- break;
89
- default:
90
- throw new Error('Unknown search result type "' + searchResult.type + '"');
91
- }
92
28
  return searchResult;
93
29
  }
94
30
  }
@@ -20,6 +20,11 @@ export declare class StorageEndpoint extends Endpoint {
20
20
  * JSON envelope would either inflate it (base64) or destroy it (a UTF-8 decode replaces every
21
21
  * invalid sequence, so bytes do not survive the round trip).
22
22
  */
23
+ /**
24
+ * Whether an item exists, without transferring it. Backed by HEAD, so a content-addressed check
25
+ * ("do I already have these bytes?") costs headers rather than the whole object.
26
+ */
27
+ hasItem(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItemKey: string): Promise<boolean>;
23
28
  getItemBytes(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItemKey: string): Promise<Buffer>;
24
29
  /**
25
30
  * Store raw bytes. Metadata travels as headers, since the body is the value.
@@ -3,6 +3,8 @@ import { StorageInformation } from '../Model/Storage/StorageInformation.js';
3
3
  import { StorageItem } from '../Model/Storage/StorageItem.js';
4
4
  import { StorageItemInformation } from '../Model/Storage/StorageItemInformation.js';
5
5
  import { QueryString } from '../Http/Data/QueryString.js';
6
+ import { ClientError } from '../Http/ClientError.js';
7
+ import { HttpStatus } from '../Http/HttpStatus.js';
6
8
  import { Endpoint } from './Endpoint.js';
7
9
  export class StorageEndpoint extends Endpoint {
8
10
  async getInformation(projectEnvironmentId, storageType) {
@@ -98,6 +100,23 @@ export class StorageEndpoint extends Endpoint {
98
100
  * JSON envelope would either inflate it (base64) or destroy it (a UTF-8 decode replaces every
99
101
  * invalid sequence, so bytes do not survive the round trip).
100
102
  */
103
+ /**
104
+ * Whether an item exists, without transferring it. Backed by HEAD, so a content-addressed check
105
+ * ("do I already have these bytes?") costs headers rather than the whole object.
106
+ */
107
+ async hasItem(projectEnvironmentId, storageType, bucketKey, storageItemKey) {
108
+ const cmd = path('/projectenvironments/:projectEnvironmentId/storage/:storageType/:bucketKey/items/:key', { projectEnvironmentId, storageType, bucketKey, key: storageItemKey });
109
+ try {
110
+ await this.requestBytes(cmd, null, 'HEAD');
111
+ return true;
112
+ }
113
+ catch (error) {
114
+ if (ClientError.statusOf(error) === HttpStatus.HTTP_NOTFOUND) {
115
+ return false;
116
+ }
117
+ throw error;
118
+ }
119
+ }
101
120
  async getItemBytes(projectEnvironmentId, storageType, bucketKey, storageItemKey) {
102
121
  const cmd = path('/projectenvironments/:projectEnvironmentId/storage/:storageType/:bucketKey/items/:key', { projectEnvironmentId, storageType, bucketKey, key: storageItemKey });
103
122
  return await this.requestBytes(cmd);
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "1.111.0";
1
+ export declare const VERSION = "1.113.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = "1.111.0";
1
+ export const VERSION = "1.113.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@attlaz/client",
3
- "version": "1.112.0",
3
+ "version": "1.114.0",
4
4
  "description": "Javascript Client to access Attlaz API",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -53,7 +53,7 @@
53
53
  "registry": "https://registry.npmjs.org"
54
54
  },
55
55
  "devDependencies": {
56
- "@types/node": "^26.2.0",
56
+ "@types/node": "^26.4.0",
57
57
  "@typescript-eslint/eslint-plugin": "^8.59.3",
58
58
  "@typescript-eslint/parser": "^8.59.3",
59
59
  "eslint": "^9.39.5",
@@ -65,7 +65,7 @@
65
65
  "eslint-plugin-promise": "^7.3.0",
66
66
  "rimraf": "^6.1.3",
67
67
  "typescript": "^6.0.3",
68
- "vitest": "^4.1.10"
68
+ "vitest": "^4.1.11"
69
69
  },
70
70
  "directories": {
71
71
  "test": "test"