@thatopen/services 0.3.15 → 0.4.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.
- package/README.md +62 -62
- package/dist/built-in/index.d.ts +165 -2
- package/dist/cli.js +27 -13
- package/dist/core/client.d.ts +1 -0
- package/dist/core/platform-client.d.ts +7 -0
- package/dist/index.cjs.js +2 -2
- package/dist/index.es.js +396 -374
- package/dist/vite-env.d.ts +1 -1
- package/docs/builtin/paths.json +94 -86
- package/docs/cli/create.md +29 -29
- package/docs/cli/local-server.md +38 -38
- package/docs/cli/login.md +32 -32
- package/docs/cli/publish.md +31 -31
- package/docs/cli/run.md +26 -26
- package/docs/cli/serve.md +43 -43
- package/docs/cli/swap.md +30 -30
- package/package.json +4 -4
- package/resources/AGENTS.md +40 -40
- package/src/built-in/CDEManager/example.ts +214 -214
- package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -226
- package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -186
- package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -295
- package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -210
- package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -230
- package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -230
- package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -166
- package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -177
- package/src/built-in/ClashesManager/example.ts +283 -283
- package/src/built-in/UIManager/src/app/example.ts +97 -97
- package/src/built-in/UIManager/src/app/examples/AppState/example.ts +140 -140
- package/src/built-in/UIManager/src/app/examples/Banner/example.ts +159 -159
- package/src/built-in/UIManager/src/app/examples/Contexts/example.ts +123 -123
- package/src/built-in/UIManager/src/app/examples/FileDrop/example.ts +124 -124
- package/src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts +90 -90
- package/src/built-in/UIManager/src/app/examples/Modal/example.ts +163 -163
- package/src/built-in/UIManager/src/app/examples/Notifications/example.ts +133 -133
- package/src/built-in/UIManager/src/app/examples/ProjectFileStorage/example.ts +150 -0
- package/src/built-in/UIManager/src/app/examples/Sidebar/example.ts +102 -102
- package/src/built-in/UIManager/src/clashes-panel/example.ts +183 -160
- package/src/built-in/UIManager/src/models-list/example.ts +122 -122
- package/src/built-in/UIManager/src/topics-panel/example.ts +170 -0
- package/src/built-in/index.ts +1048 -881
- package/src/cli/templates/app/index.html +35 -35
- package/src/cli/templates/app/package.json +32 -32
- package/src/cli/templates/app/src/bim-components/CloudRunner/index.ts +95 -95
- package/src/cli/templates/app/src/bim-components/CloudRunner/src/index.ts +1 -1
- package/src/cli/templates/app/src/bim-components/CloudRunner/src/types.ts +5 -5
- package/src/cli/templates/app/src/bim-components/index.ts +1 -1
- package/src/cli/templates/app/src/globals.ts +1 -1
- package/src/cli/templates/app/src/ui-components/app-info-section/index.ts +26 -26
- package/src/cli/templates/app/src/ui-components/app-info-section/src/index.ts +1 -1
- package/src/cli/templates/app/src/ui-components/app-info-section/src/types.ts +15 -15
- package/src/cli/templates/app/src/ui-components/cloud-runner-section/index.ts +37 -37
- package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/index.ts +1 -1
- package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/types.ts +14 -14
- package/src/cli/templates/app/src/ui-components/index.ts +2 -2
- package/src/cli/templates/app/tsconfig.json +16 -16
- package/src/cli/templates/app/vite.config.js +57 -57
- package/src/cli/templates/cloud-component/README.md +205 -205
- package/src/cli/templates/cloud-component/_thatopen +5 -5
- package/src/cli/templates/cloud-component/declarations.json +4 -4
- package/src/cli/templates/cloud-component/package.json +21 -21
- package/src/cli/templates/cloud-component/src/main.ts +70 -70
- package/src/cli/templates/cloud-component/tsconfig.json +16 -16
- package/src/cli/templates/cloud-component/vite.config.js +46 -46
- package/src/cli/templates/shared/AGENTS.md +8 -8
- package/src/cli/templates/shared/CLAUDE.md +1 -1
- package/src/cli/templates/shared/_gitignore +5 -5
package/README.md
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
# @thatopen/services
|
|
2
|
-
|
|
3
|
-
Client library and CLI for building BIM apps and cloud components on [That Open Platform](https://platform.thatopen.com). Apps run inside the platform's browser environment; cloud components run server-side and can be triggered from any app.
|
|
4
|
-
|
|
5
|
-
> **Using an AI assistant?** Point it at this single file and it can take you from nothing to a running app:
|
|
6
|
-
> → [`docs/ai-quickstart.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/ai-quickstart.md)
|
|
7
|
-
|
|
8
|
-
## Quick Start
|
|
9
|
-
|
|
10
|
-
### 1. Install the CLI
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npm install -g @thatopen/services@latest
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### 2. Choose a project type
|
|
17
|
-
|
|
18
|
-
| Type | Template | Use when |
|
|
19
|
-
|------|----------|----------|
|
|
20
|
-
| **App** | `app` | You're building a BIM app that runs in the platform's browser UI |
|
|
21
|
-
| **Cloud component** | `cloud-component` | You're building server-side logic triggered by an app |
|
|
22
|
-
|
|
23
|
-
### 3. Scaffold
|
|
24
|
-
|
|
25
|
-
See the full command reference here:
|
|
26
|
-
→ [`docs/cli/create.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/create.md)
|
|
27
|
-
|
|
28
|
-
To use beta engine libraries instead of the stable ones, see:
|
|
29
|
-
→ [`docs/cli/swap.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/swap.md)
|
|
30
|
-
|
|
31
|
-
### 4. Next steps
|
|
32
|
-
|
|
33
|
-
Once scaffolded, open `AGENTS.md` in the scaffolded project root — it has everything needed to start building.
|
|
34
|
-
|
|
35
|
-
## Beta engine libraries (Founding Members)
|
|
36
|
-
|
|
37
|
-
Founding Members get early access to the private beta engine libraries (`@thatopen-platform/*-beta`). The CLI configures access automatically — no npm account or manual token needed.
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
thatopen login --token <your-token> # API token from the dashboard → Data → API Tokens
|
|
41
|
-
thatopen create my-app --beta # new project on the beta libraries
|
|
42
|
-
# or, in an existing project:
|
|
43
|
-
thatopen swap --beta # toggle the current project to beta
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
On `--beta`, the CLI fetches your read-only beta npm credentials and writes them to the project's `.npmrc`, so `npm install` resolves the private packages. The `.npmrc` is gitignored — it carries a credential, so don't commit or share it. Access is tied to your membership; non-Founding accounts get a clear message and the project is still created.
|
|
47
|
-
|
|
48
|
-
## What's in this repository
|
|
49
|
-
|
|
50
|
-
- **Library** — `EngineServicesClient` and `PlatformClient` for interacting with the That Open API (files, folders, apps, cloud components, executions, permissions).
|
|
51
|
-
- **CLI** — `thatopen` command for scaffolding and publishing.
|
|
52
|
-
- **Built-in component types** — TypeScript stubs for platform-hosted components.
|
|
53
|
-
|
|
54
|
-
## Docs
|
|
55
|
-
|
|
56
|
-
Full reference for all CLI commands and flags:
|
|
57
|
-
→ [`docs/cli/paths.json`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/paths.json)
|
|
58
|
-
|
|
59
|
-
## Contributing
|
|
60
|
-
|
|
61
|
-
See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, build commands, and publishing workflow.
|
|
62
|
-
|
|
1
|
+
# @thatopen/services
|
|
2
|
+
|
|
3
|
+
Client library and CLI for building BIM apps and cloud components on [That Open Platform](https://platform.thatopen.com). Apps run inside the platform's browser environment; cloud components run server-side and can be triggered from any app.
|
|
4
|
+
|
|
5
|
+
> **Using an AI assistant?** Point it at this single file and it can take you from nothing to a running app:
|
|
6
|
+
> → [`docs/ai-quickstart.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/ai-quickstart.md)
|
|
7
|
+
|
|
8
|
+
## Quick Start
|
|
9
|
+
|
|
10
|
+
### 1. Install the CLI
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g @thatopen/services@latest
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 2. Choose a project type
|
|
17
|
+
|
|
18
|
+
| Type | Template | Use when |
|
|
19
|
+
|------|----------|----------|
|
|
20
|
+
| **App** | `app` | You're building a BIM app that runs in the platform's browser UI |
|
|
21
|
+
| **Cloud component** | `cloud-component` | You're building server-side logic triggered by an app |
|
|
22
|
+
|
|
23
|
+
### 3. Scaffold
|
|
24
|
+
|
|
25
|
+
See the full command reference here:
|
|
26
|
+
→ [`docs/cli/create.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/create.md)
|
|
27
|
+
|
|
28
|
+
To use beta engine libraries instead of the stable ones, see:
|
|
29
|
+
→ [`docs/cli/swap.md`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/swap.md)
|
|
30
|
+
|
|
31
|
+
### 4. Next steps
|
|
32
|
+
|
|
33
|
+
Once scaffolded, open `AGENTS.md` in the scaffolded project root — it has everything needed to start building.
|
|
34
|
+
|
|
35
|
+
## Beta engine libraries (Founding Members)
|
|
36
|
+
|
|
37
|
+
Founding Members get early access to the private beta engine libraries (`@thatopen-platform/*-beta`). The CLI configures access automatically — no npm account or manual token needed.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
thatopen login --token <your-token> # API token from the dashboard → Data → API Tokens
|
|
41
|
+
thatopen create my-app --beta # new project on the beta libraries
|
|
42
|
+
# or, in an existing project:
|
|
43
|
+
thatopen swap --beta # toggle the current project to beta
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
On `--beta`, the CLI fetches your read-only beta npm credentials and writes them to the project's `.npmrc`, so `npm install` resolves the private packages. The `.npmrc` is gitignored — it carries a credential, so don't commit or share it. Access is tied to your membership; non-Founding accounts get a clear message and the project is still created.
|
|
47
|
+
|
|
48
|
+
## What's in this repository
|
|
49
|
+
|
|
50
|
+
- **Library** — `EngineServicesClient` and `PlatformClient` for interacting with the That Open API (files, folders, apps, cloud components, executions, permissions).
|
|
51
|
+
- **CLI** — `thatopen` command for scaffolding and publishing.
|
|
52
|
+
- **Built-in component types** — TypeScript stubs for platform-hosted components.
|
|
53
|
+
|
|
54
|
+
## Docs
|
|
55
|
+
|
|
56
|
+
Full reference for all CLI commands and flags:
|
|
57
|
+
→ [`docs/cli/paths.json`](https://raw.githubusercontent.com/ThatOpen/engine_services/main/docs/cli/paths.json)
|
|
58
|
+
|
|
59
|
+
## Contributing
|
|
60
|
+
|
|
61
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, build commands, and publishing workflow.
|
|
62
|
+
|
package/dist/built-in/index.d.ts
CHANGED
|
@@ -370,6 +370,11 @@ declare class _CDEManager extends OBC.Component implements OBC.Transitionable<CD
|
|
|
370
370
|
success: boolean;
|
|
371
371
|
error?: string;
|
|
372
372
|
}>;
|
|
373
|
+
/** Fires when `_derivedFileIds` finishes a (re)sync — consumers that filter
|
|
374
|
+
* or resolve by source↔derived link (e.g. `top-files-panel` hiding an
|
|
375
|
+
* already-linked `.frag` row) should reload on this, since it can complete
|
|
376
|
+
* after `onFilesChanged` already fired with the (still unsynced) list. */
|
|
377
|
+
readonly onDerivedFileIdsChanged: OBC.Event<Record<string, string>>;
|
|
373
378
|
readonly conversionProgress: Map<string, number>;
|
|
374
379
|
enabled: boolean;
|
|
375
380
|
projectName: string;
|
|
@@ -390,6 +395,14 @@ declare class _CDEManager extends OBC.Component implements OBC.Transitionable<CD
|
|
|
390
395
|
}[];
|
|
391
396
|
get viewableExtensions(): Set<string>;
|
|
392
397
|
private _files;
|
|
398
|
+
/** ifcFileId → its linked derivedFileId (FRAG today; other source formats
|
|
399
|
+
* once they get a converter too), read from each IFC's own version
|
|
400
|
+
* metadata. Kept as an in-memory cache — synced by `_syncDerivedFileIds`
|
|
401
|
+
* whenever `_files` is (re)set, or right after a conversion succeeds —
|
|
402
|
+
* rather than fetched live per call, so `resolveViewFile` can stay a plain
|
|
403
|
+
* synchronous lookup (same contract as before, no ripple into
|
|
404
|
+
* `sendMachineEvent`'s callers). */
|
|
405
|
+
private _derivedFileIds;
|
|
393
406
|
private _folders;
|
|
394
407
|
private _fileHistory;
|
|
395
408
|
private _metadataSchema;
|
|
@@ -423,6 +436,8 @@ declare class _CDEManager extends OBC.Component implements OBC.Transitionable<CD
|
|
|
423
436
|
get machineState(): CDEMachineState;
|
|
424
437
|
get files(): CDEFile[];
|
|
425
438
|
set files(value: CDEFile[]);
|
|
439
|
+
/** ifcFileId → derivedFileId — see `_derivedFileIds`. */
|
|
440
|
+
get derivedFileIds(): Record<string, string>;
|
|
426
441
|
get folders(): ItemFolder[];
|
|
427
442
|
set folders(value: ItemFolder[]);
|
|
428
443
|
get showArchived(): boolean;
|
|
@@ -463,10 +478,12 @@ declare class _CDEManager extends OBC.Component implements OBC.Transitionable<CD
|
|
|
463
478
|
loadUserConfig(): Promise<{
|
|
464
479
|
visibleColumns?: string[];
|
|
465
480
|
metadataViews?: CDEMetadataView[];
|
|
481
|
+
hideDerivedFiles?: boolean;
|
|
466
482
|
} | null>;
|
|
467
483
|
saveUserConfig(config: {
|
|
468
484
|
visibleColumns?: string[];
|
|
469
485
|
metadataViews?: CDEMetadataView[];
|
|
486
|
+
hideDerivedFiles?: boolean;
|
|
470
487
|
}): Promise<string | undefined>;
|
|
471
488
|
loadMetadataSchema(): Promise<void>;
|
|
472
489
|
initMetadataViews(views: CDEMetadataView[], activeId: string | null): void;
|
|
@@ -481,7 +498,23 @@ declare class _CDEManager extends OBC.Component implements OBC.Transitionable<CD
|
|
|
481
498
|
file: CDEFile;
|
|
482
499
|
existing: CDEFile;
|
|
483
500
|
}[];
|
|
501
|
+
/** Which file to actually load when the user views `file` — its linked FRAG
|
|
502
|
+
* if it has one, else the IFC itself. Reads `_derivedFileIds` (the IFC's
|
|
503
|
+
* own version metadata, kept in sync — see `_syncDerivedFileIds`), NOT a
|
|
504
|
+
* name+folder match anymore. Stays synchronous: `_derivedFileIds` is a
|
|
505
|
+
* pre-synced in-memory cache, so this is a plain lookup, keeping the
|
|
506
|
+
* contract every existing caller (`sendMachineEvent`'s `VIEW` case,
|
|
507
|
+
* `top-files-panel`'s "add to view" actions) already relies on. */
|
|
484
508
|
resolveViewFile(file: CDEFile): CDEFile;
|
|
509
|
+
/** Populates `_derivedFileIds` from every IFC's own version metadata — the
|
|
510
|
+
* source of truth for the IFC↔FRAG link (same mechanism as `models-list`'s
|
|
511
|
+
* `_syncDerivedFileIds`). Reads the unified `derivedFileId` key, falling
|
|
512
|
+
* back to the legacy `fragmentsFileId` key that `IfcFragmenter` still
|
|
513
|
+
* stamps until it's updated (see issue #3, Task 3). Called whenever
|
|
514
|
+
* `_files` is (re)set and right after a conversion succeeds — never
|
|
515
|
+
* cached indefinitely, so a reconversion or manual metadata edit is picked
|
|
516
|
+
* up on the next sync instead of going stale. */
|
|
517
|
+
private _syncDerivedFileIds;
|
|
485
518
|
private _saveConversionIndex;
|
|
486
519
|
private _loadConversionIndex;
|
|
487
520
|
private _resumePendingConversions;
|
|
@@ -610,6 +643,59 @@ export interface MarkerGroup {
|
|
|
610
643
|
count: number;
|
|
611
644
|
status?: ClashStatus;
|
|
612
645
|
}
|
|
646
|
+
/** `clashes.frag`'s path relative to `__project_data/`, for consumers that
|
|
647
|
+
* persist it via `projectStorageContext` instead of talking to `client`
|
|
648
|
+
* directly (see `buildClashBuffer`). */
|
|
649
|
+
export declare const CLASH_DATA_PATH = "collider/clashes.frag";
|
|
650
|
+
export interface ExecutionEntry {
|
|
651
|
+
jobId: string;
|
|
652
|
+
executionId: string;
|
|
653
|
+
startedAt: string;
|
|
654
|
+
}
|
|
655
|
+
/** `cachedFileId`, when given, skips folder/file resolution (3 of the 4
|
|
656
|
+
* network round-trips this normally takes) — the file's ID never changes
|
|
657
|
+
* once created, so callers that already know it (see `ClashesManager`'s
|
|
658
|
+
* `_clashFragFileId`) should always pass it. */
|
|
659
|
+
export declare function ensureClashFragFileId(client: PlatformClient, projectId: string, cachedFileId?: string): Promise<string>;
|
|
660
|
+
export declare function getExecutions(client: PlatformClient, projectId: string | undefined): Promise<ExecutionEntry[]>;
|
|
661
|
+
export interface ClashData {
|
|
662
|
+
jobs: ClashJob[];
|
|
663
|
+
runs: ClashRun[];
|
|
664
|
+
clashes: Clash[];
|
|
665
|
+
queries: ClashQuery[];
|
|
666
|
+
matrices: ClashMatrix[];
|
|
667
|
+
/** Resolved once here — callers should cache and pass back into
|
|
668
|
+
* `loadClashData`/`buildClashBuffer` as `cachedFileId` to skip
|
|
669
|
+
* re-resolving it (see `ensureClashFragFileId`). */
|
|
670
|
+
fileId: string;
|
|
671
|
+
}
|
|
672
|
+
export declare function loadClashData(client: PlatformClient, projectId: string, cachedFileId?: string): Promise<ClashData>;
|
|
673
|
+
/**
|
|
674
|
+
* Diffs `data` against the persisted `clashes.frag` and builds the updated
|
|
675
|
+
* buffer, WITHOUT uploading it — callers decide how/where to persist the
|
|
676
|
+
* result (direct `client.updateFile`, via `projectStorageContext`, etc).
|
|
677
|
+
* Still reads the current file via `client` to diff against (job/id
|
|
678
|
+
* reconciliation needs the previous state), same as `saveClashData` always did.
|
|
679
|
+
*/
|
|
680
|
+
export declare function buildClashBuffer(client: PlatformClient, projectId: string, data: {
|
|
681
|
+
queries: ClashQuery[];
|
|
682
|
+
matrices: ClashMatrix[];
|
|
683
|
+
jobs: ClashJob[];
|
|
684
|
+
clashes: Clash[];
|
|
685
|
+
}, onJobsReconciled: (toAdd: ClashJob[], toRemove: Set<string>) => void, cachedFileId?: string): Promise<{
|
|
686
|
+
blob: Blob;
|
|
687
|
+
fileId: string;
|
|
688
|
+
}>;
|
|
689
|
+
/** Default persistence path: builds the buffer and uploads it straight to
|
|
690
|
+
* `client`. Kept as the manager's out-of-the-box behavior for any consumer
|
|
691
|
+
* that never overrides `ClashesManager.save` (e.g. doesn't route through
|
|
692
|
+
* `projectStorageContext`). */
|
|
693
|
+
export declare function saveClashData(client: PlatformClient, projectId: string, data: {
|
|
694
|
+
queries: ClashQuery[];
|
|
695
|
+
matrices: ClashMatrix[];
|
|
696
|
+
jobs: ClashJob[];
|
|
697
|
+
clashes: Clash[];
|
|
698
|
+
}, onJobsReconciled: (toAdd: ClashJob[], toRemove: Set<string>) => void): Promise<void>;
|
|
613
699
|
declare class _ClashesManager extends OBC.Component {
|
|
614
700
|
static readonly uuid: "2c9f4e8d-3a1b-4c5e-9d7f-0a2b6c8e1d3f";
|
|
615
701
|
enabled: boolean;
|
|
@@ -655,6 +741,10 @@ declare class _ClashesManager extends OBC.Component {
|
|
|
655
741
|
get ready(): boolean;
|
|
656
742
|
private _client?;
|
|
657
743
|
private _projectId?;
|
|
744
|
+
/** `clashes.frag`'s file ID, resolved once by `init()`/`reload()`'s
|
|
745
|
+
* `loadClashData` call. Never changes once the file exists — passing it
|
|
746
|
+
* into `buildClashBuffer` skips 3 of its 4 network round-trips. */
|
|
747
|
+
private _clashFragFileId?;
|
|
658
748
|
private _reconnectingJobIds;
|
|
659
749
|
private _queries;
|
|
660
750
|
private _matrices;
|
|
@@ -670,9 +760,25 @@ declare class _ClashesManager extends OBC.Component {
|
|
|
670
760
|
get matrices(): ClashMatrix[];
|
|
671
761
|
set matrices(value: ClashMatrix[]);
|
|
672
762
|
private _scheduleSave;
|
|
763
|
+
/** Chains onto any save already in flight instead of firing a second,
|
|
764
|
+
* concurrent `_doSave()` — two overlapping calls would race on
|
|
765
|
+
* `buildClashBuffer`'s read-diff-reconcile cycle (real network I/O;
|
|
766
|
+
* `onJobsReconciled` mutating `this.jobs` from two stale reads at once)
|
|
767
|
+
* and on the upload itself. It also keeps `flush()` correct: it just
|
|
768
|
+
* awaits `_savePromise`, so if that got overwritten by a newer, unrelated
|
|
769
|
+
* save instead of chained, flush() could resolve while an earlier save
|
|
770
|
+
* was still genuinely in flight. */
|
|
771
|
+
private _queueSave;
|
|
673
772
|
private _doSave;
|
|
674
773
|
/** Cancela el debounce pendiente y ejecuta el save inmediatamente. Espera a que complete. */
|
|
675
774
|
flush(): Promise<void>;
|
|
775
|
+
/**
|
|
776
|
+
* Builds the current `clashes.frag` buffer (diffed/reconciled against what's
|
|
777
|
+
* persisted) WITHOUT uploading it. For consumers (e.g. `clashes-panel`) that
|
|
778
|
+
* override `save` to persist via `projectStorageContext` instead of the
|
|
779
|
+
* default direct-`client` path.
|
|
780
|
+
*/
|
|
781
|
+
buildClashBuffer(): Promise<Blob>;
|
|
676
782
|
get jobs(): ClashJob[];
|
|
677
783
|
set jobs(value: ClashJob[]);
|
|
678
784
|
get runs(): ClashRun[];
|
|
@@ -681,8 +787,12 @@ declare class _ClashesManager extends OBC.Component {
|
|
|
681
787
|
set clashes(value: Clash[]);
|
|
682
788
|
queryById(id: string): ClashQuery | undefined;
|
|
683
789
|
private _clashStylesRegistered;
|
|
684
|
-
|
|
685
|
-
|
|
790
|
+
/** Green — elementA's highlight color. Public so consumers (e.g. "create
|
|
791
|
+
* topic from clash") can build a matching BCF viewpoint `componentColors`
|
|
792
|
+
* entry without duplicating the hex value. */
|
|
793
|
+
readonly STYLE_A = "#22c55e";
|
|
794
|
+
/** Red — elementB's highlight color. Same reasoning as `STYLE_A`. */
|
|
795
|
+
readonly STYLE_B = "#ef4444";
|
|
686
796
|
private _clashStyle;
|
|
687
797
|
highlightAllClashes(clashes: Clash[]): void;
|
|
688
798
|
ghostClashes(clashes: Clash[]): Promise<void>;
|
|
@@ -863,6 +973,59 @@ export type HelloWorld = InstanceType<typeof _HelloWorld>;
|
|
|
863
973
|
export declare const HelloWorld: typeof _HelloWorld & {
|
|
864
974
|
uuid: "2c4ae432-fc24-43e9-9783-0c960c674e96";
|
|
865
975
|
};
|
|
976
|
+
/** `main.bcf`'s path relative to `__project_data/` — shared with
|
|
977
|
+
* `requestBcfSave` (`UIManager/src/utils/bcf-storage.ts`) so both sides of
|
|
978
|
+
* the save/load round-trip agree on where the file lives. */
|
|
979
|
+
export declare const BCF_DATA_PATH = "topics/main.bcf";
|
|
980
|
+
/** Downloads `__project_data/topics/main.bcf` and loads it into `BCFTopics`,
|
|
981
|
+
* if it already has content. A freshly-created file is empty (0 bytes) —
|
|
982
|
+
* not a valid BCF zip — so there's nothing to load yet in that case. */
|
|
983
|
+
export declare function loadBcfTopics(client: PlatformClient, projectId: string, components: OBC.Components): Promise<void>;
|
|
984
|
+
/**
|
|
985
|
+
* Wires up everything `top-topics-panel` (and `clashes-panel`'s "create
|
|
986
|
+
* topic from clash" feature) needs to work out of the box: `BCFTopics`
|
|
987
|
+
* configuration (version, author, assignable users — all from real project
|
|
988
|
+
* data), loading whatever BCF was previously saved for this project, and
|
|
989
|
+
* resolving `Viewpoints.world` — including backfilling it onto viewpoints
|
|
990
|
+
* restored from a saved BCF before the 3D world existed yet (`top-viewer`
|
|
991
|
+
* only creates its `World` once `top-app` finishes mounting, which is later
|
|
992
|
+
* than `init()` typically runs).
|
|
993
|
+
*/
|
|
994
|
+
declare class _TopicsManager extends OBC.Component {
|
|
995
|
+
static readonly uuid: "69af63aa-19ba-4fc7-b17b-75647bac1d76";
|
|
996
|
+
enabled: boolean;
|
|
997
|
+
/**
|
|
998
|
+
* Consumer apps call this once — same pattern as `ClashesManager.init(client)`
|
|
999
|
+
* — instead of wiring `BCFTopics.setup()`, loading the saved BCF, and
|
|
1000
|
+
* backfilling viewpoint worlds by hand.
|
|
1001
|
+
*/
|
|
1002
|
+
init(client: PlatformClient): Promise<void>;
|
|
1003
|
+
private _firstWorld;
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Wires up everything `top-topics-panel` (and `clashes-panel`'s "create
|
|
1007
|
+
* topic from clash" feature) needs to work out of the box: `BCFTopics`
|
|
1008
|
+
* configuration (version, author, assignable users — all from real project
|
|
1009
|
+
* data), loading whatever BCF was previously saved for this project, and
|
|
1010
|
+
* resolving `Viewpoints.world` — including backfilling it onto viewpoints
|
|
1011
|
+
* restored from a saved BCF before the 3D world existed yet (`top-viewer`
|
|
1012
|
+
* only creates its `World` once `top-app` finishes mounting, which is later
|
|
1013
|
+
* than `init()` typically runs).
|
|
1014
|
+
*/
|
|
1015
|
+
export type TopicsManager = InstanceType<typeof _TopicsManager>;
|
|
1016
|
+
/**
|
|
1017
|
+
* Wires up everything `top-topics-panel` (and `clashes-panel`'s "create
|
|
1018
|
+
* topic from clash" feature) needs to work out of the box: `BCFTopics`
|
|
1019
|
+
* configuration (version, author, assignable users — all from real project
|
|
1020
|
+
* data), loading whatever BCF was previously saved for this project, and
|
|
1021
|
+
* resolving `Viewpoints.world` — including backfilling it onto viewpoints
|
|
1022
|
+
* restored from a saved BCF before the 3D world existed yet (`top-viewer`
|
|
1023
|
+
* only creates its `World` once `top-app` finishes mounting, which is later
|
|
1024
|
+
* than `init()` typically runs).
|
|
1025
|
+
*/
|
|
1026
|
+
export declare const TopicsManager: typeof _TopicsManager & {
|
|
1027
|
+
uuid: "69af63aa-19ba-4fc7-b17b-75647bac1d76";
|
|
1028
|
+
};
|
|
866
1029
|
declare class _UIManager extends OBC.Component {
|
|
867
1030
|
#private;
|
|
868
1031
|
static readonly uuid: "234f1416-528d-452a-9cc9-a16c5239b2eb";
|
package/dist/cli.js
CHANGED
|
@@ -4205,8 +4205,8 @@ class BaseXHR extends Polling {
|
|
|
4205
4205
|
/**
|
|
4206
4206
|
* Sends data.
|
|
4207
4207
|
*
|
|
4208
|
-
* @param {String} data to send.
|
|
4209
|
-
* @param {Function} called upon flush.
|
|
4208
|
+
* @param {String} data - data to send.
|
|
4209
|
+
* @param {Function} fn - called upon flush.
|
|
4210
4210
|
* @private
|
|
4211
4211
|
*/
|
|
4212
4212
|
doWrite(data, fn) {
|
|
@@ -4959,7 +4959,7 @@ class SocketWithoutUpgrade extends Emitter {
|
|
|
4959
4959
|
/**
|
|
4960
4960
|
* Sends a packet.
|
|
4961
4961
|
*
|
|
4962
|
-
* @param {String} type
|
|
4962
|
+
* @param {String} type - packet type.
|
|
4963
4963
|
* @param {String} data.
|
|
4964
4964
|
* @param {Object} options.
|
|
4965
4965
|
* @param {Function} fn - callback function.
|
|
@@ -5194,11 +5194,12 @@ class SocketWithUpgrade extends SocketWithoutUpgrade {
|
|
|
5194
5194
|
}
|
|
5195
5195
|
let Socket$1 = class Socket extends SocketWithUpgrade {
|
|
5196
5196
|
constructor(uri, opts = {}) {
|
|
5197
|
-
const
|
|
5197
|
+
const isOptionsOnly = typeof uri === "object";
|
|
5198
|
+
const o = isOptionsOnly ? { ...uri } : { ...opts };
|
|
5198
5199
|
if (!o.transports || o.transports && typeof o.transports[0] === "string") {
|
|
5199
5200
|
o.transports = (o.transports || ["polling", "websocket", "webtransport"]).map((transportName) => transports[transportName]).filter((t) => !!t);
|
|
5200
5201
|
}
|
|
5201
|
-
super(uri, o);
|
|
5202
|
+
super(isOptionsOnly ? o : uri, o);
|
|
5202
5203
|
}
|
|
5203
5204
|
};
|
|
5204
5205
|
function url(uri, path2 = "", loc) {
|
|
@@ -5419,12 +5420,13 @@ class Encoder {
|
|
|
5419
5420
|
class Decoder extends Emitter {
|
|
5420
5421
|
/**
|
|
5421
5422
|
* Decoder constructor
|
|
5422
|
-
*
|
|
5423
|
-
* @param {function} reviver - custom reviver to pass down to JSON.stringify
|
|
5424
5423
|
*/
|
|
5425
|
-
constructor(
|
|
5424
|
+
constructor(opts) {
|
|
5426
5425
|
super();
|
|
5427
|
-
this.
|
|
5426
|
+
this.opts = Object.assign({
|
|
5427
|
+
reviver: void 0,
|
|
5428
|
+
maxAttachments: 10
|
|
5429
|
+
}, typeof opts === "function" ? { reviver: opts } : opts);
|
|
5428
5430
|
}
|
|
5429
5431
|
/**
|
|
5430
5432
|
* Decodes an encoded packet string into packet JSON.
|
|
@@ -5484,7 +5486,13 @@ class Decoder extends Emitter {
|
|
|
5484
5486
|
if (buf != Number(buf) || str.charAt(i) !== "-") {
|
|
5485
5487
|
throw new Error("Illegal attachments");
|
|
5486
5488
|
}
|
|
5487
|
-
|
|
5489
|
+
const n = Number(buf);
|
|
5490
|
+
if (!isInteger(n) || n < 0) {
|
|
5491
|
+
throw new Error("Illegal attachments");
|
|
5492
|
+
} else if (n > this.opts.maxAttachments) {
|
|
5493
|
+
throw new Error("too many attachments");
|
|
5494
|
+
}
|
|
5495
|
+
p.attachments = n;
|
|
5488
5496
|
}
|
|
5489
5497
|
if ("/" === str.charAt(i + 1)) {
|
|
5490
5498
|
const start = i + 1;
|
|
@@ -5525,7 +5533,7 @@ class Decoder extends Emitter {
|
|
|
5525
5533
|
}
|
|
5526
5534
|
tryParse(str) {
|
|
5527
5535
|
try {
|
|
5528
|
-
return JSON.parse(str, this.reviver);
|
|
5536
|
+
return JSON.parse(str, this.opts.reviver);
|
|
5529
5537
|
} catch (e) {
|
|
5530
5538
|
return false;
|
|
5531
5539
|
}
|
|
@@ -5587,6 +5595,9 @@ class BinaryReconstructor {
|
|
|
5587
5595
|
this.buffers = [];
|
|
5588
5596
|
}
|
|
5589
5597
|
}
|
|
5598
|
+
const isInteger = Number.isInteger || function(value2) {
|
|
5599
|
+
return typeof value2 === "number" && isFinite(value2) && Math.floor(value2) === value2;
|
|
5600
|
+
};
|
|
5590
5601
|
function isObject(value2) {
|
|
5591
5602
|
return Object.prototype.toString.call(value2) === "[object Object]";
|
|
5592
5603
|
}
|
|
@@ -6946,7 +6957,7 @@ class EngineServicesClient {
|
|
|
6946
6957
|
return this.accessToken;
|
|
6947
6958
|
}
|
|
6948
6959
|
async #requestApi(method, path2, requestData) {
|
|
6949
|
-
const { body, query, contentType, retries } = requestData || {};
|
|
6960
|
+
const { body, query, contentType, retries, responseType } = requestData || {};
|
|
6950
6961
|
const url2 = this.#buildUrl(path2);
|
|
6951
6962
|
const cleanQuery = this.#cleanData(query);
|
|
6952
6963
|
const token = await this.resolveAccessToken();
|
|
@@ -6975,6 +6986,9 @@ class EngineServicesClient {
|
|
|
6975
6986
|
textResponse
|
|
6976
6987
|
);
|
|
6977
6988
|
}
|
|
6989
|
+
if (responseType === "blob") {
|
|
6990
|
+
return await response.blob();
|
|
6991
|
+
}
|
|
6978
6992
|
return response.json().then((data) => data).catch(() => void 0);
|
|
6979
6993
|
} catch (e) {
|
|
6980
6994
|
let retriesAmmount = retries != null ? retries : this.retries;
|
|
@@ -8213,7 +8227,7 @@ Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/js
|
|
|
8213
8227
|
JSZip uses the library pako released under the MIT license :
|
|
8214
8228
|
https://github.com/nodeca/pako/blob/main/LICENSE
|
|
8215
8229
|
*/
|
|
8216
|
-
(function(module2, exports
|
|
8230
|
+
(function(module2, exports) {
|
|
8217
8231
|
!function(e) {
|
|
8218
8232
|
module2.exports = e();
|
|
8219
8233
|
}(function() {
|
package/dist/core/client.d.ts
CHANGED
|
@@ -219,6 +219,7 @@ export declare class EngineServicesClient {
|
|
|
219
219
|
query?: object;
|
|
220
220
|
contentType?: 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded';
|
|
221
221
|
retries?: number;
|
|
222
|
+
responseType?: 'json' | 'blob';
|
|
222
223
|
}): Promise<T>;
|
|
223
224
|
/**
|
|
224
225
|
* Lists all files accessible by the current token.
|
|
@@ -86,6 +86,13 @@ export declare class PlatformClient extends EngineServicesClient {
|
|
|
86
86
|
* User data is stripped of sensitive fields server-side.
|
|
87
87
|
*/
|
|
88
88
|
getProjectData(projectId: string): Promise<ProjectData>;
|
|
89
|
+
/**
|
|
90
|
+
* Fetches a user's profile picture as raw image bytes, for showing member
|
|
91
|
+
* avatars inside an app. The route is bearer-authed, so it can't be used as
|
|
92
|
+
* an `<img src>` — turn the blob into an object URL with
|
|
93
|
+
* `URL.createObjectURL(blob)`. Rejects when the account has no avatar.
|
|
94
|
+
*/
|
|
95
|
+
getAvatar(accountId: string): Promise<Blob>;
|
|
89
96
|
/**
|
|
90
97
|
* Checks whether the caller has a specific permission within a project.
|
|
91
98
|
* Returns `{ hasPermission, scope }` where `scope` is `'global'` for
|