@kmlckj/licos-platform-sdk 0.8.6 → 0.9.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 CHANGED
@@ -161,25 +161,52 @@ Use `uns.openPath(path)` when business code targets an existing enterprise UNS
161
161
  path without creating or changing `UNS.json`:
162
162
 
163
163
  ```js
164
- const temperature = uns.openPath('project:/production-line/temperature');
165
- const current = await temperature.pointCurrent();
166
- ```
164
+ const temperature = uns.openPath('project:/production-line/temperature');
165
+ const current = await temperature.pointCurrent();
166
+ ```
167
+
168
+ Realtime point consumers obtain the server-side WebSocket endpoint through the
169
+ authorized project runtime API. Create one upstream connection per returned
170
+ `nodeCode`; do not derive or hardcode a DataFactory address:
171
+
172
+ ```js
173
+ const realtime = await uns.pointRealtimeConfig('TEMP_01');
174
+ // Connect to realtime.websocketUrl and register with realtime.nodeCode.
175
+ ```
176
+
177
+ Resource apply, data writes, point writes, and video controls require explicit
178
+ confirmation. Data deletion accepts the exact rows returned by a prior query
179
+ and also requires explicit confirmation. Point writes require a reason and ticket. The browser entry
180
+ does not export UNS helpers.
181
+
182
+ ## Direct Industrial Integration
167
183
 
168
- Realtime point consumers obtain the server-side WebSocket endpoint through the
169
- authorized project runtime API. Create one upstream connection per returned
170
- `nodeCode`; do not derive or hardcode a DataFactory address:
184
+ The server-only `industrial` facade manages collection and video resources
185
+ without creating DataFactory UNS nodes. Use it only when the user explicitly
186
+ selects direct collector integration; UNS failures must not trigger this mode.
171
187
 
172
188
  ```js
173
- const realtime = await uns.pointRealtimeConfig('TEMP_01');
174
- // Connect to realtime.websocketUrl and register with realtime.nodeCode.
189
+ import { industrial } from '@kmlckj/licos-platform-sdk';
190
+
191
+ const points = await industrial.searchResources('collectionPoint', {
192
+ scope: 'project',
193
+ keyword: 'temperature',
194
+ });
195
+
196
+ const current = await industrial.pointCurrent(points.items[0].id);
197
+ const realtime = await industrial.realtimeConnection({
198
+ pointIds: [points.items[0].id],
199
+ transport: 'websocket',
200
+ });
175
201
  ```
176
202
 
177
- Resource apply, data writes, point writes, and video controls require explicit
178
- confirmation. Data deletion accepts the exact rows returned by a prior query
179
- and also requires explicit confirmation. Point writes require a reason and ticket. The browser entry
180
- does not export UNS helpers.
181
-
182
- ## OAuth2 Application Management
203
+ Realtime subscription defaults to upstream WebSocket and supports explicitly
204
+ selected MQTT. Point control defaults to HTTP and supports explicitly selected
205
+ MQTT. Neither direction silently falls back. Resource writes use a reviewed
206
+ `IndustrialChangeSet`; point and video writes require independent confirmation.
207
+ The browser entry does not export industrial helpers or external credentials.
208
+
209
+ ## OAuth2 Application Management
183
210
 
184
211
  OAuth2 management is available only from trusted Node runtime code. It uses the
185
212
  current project owner's platform identity and is not exported by the browser
package/dist/index.d.ts CHANGED
@@ -28,7 +28,8 @@ export interface RuntimeConfig {
28
28
  export function runtimeConfig(options?: { environmentOverrideEnv?: string }): Promise<RuntimeConfig>;
29
29
  export function authHeaders(config: RuntimeConfig, contentType?: string): Record<string, string>;
30
30
 
31
- export * from './uns.js';
31
+ export * from './uns.js';
32
+ export * from './industrial.js';
32
33
 
33
34
  export type OAuthLoginAudience = 'ALL' | 'OWNER_TENANT';
34
35
 
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{PlatformSdkError,ConfigurationError,ApiError}from"./shared.js";export{runtimeConfig,authHeaders}from"./runtime.js";export*from"./database.js";export*from"./knowledge.js";export*from"./oauth.js";export*from"./oauth-runtime.js";export*from"./storage.js";export*from"./uns.js";export{studioDatabase}from"./studio-database.js";
1
+ export{PlatformSdkError,ConfigurationError,ApiError}from"./shared.js";export{runtimeConfig,authHeaders}from"./runtime.js";export*from"./database.js";export*from"./knowledge.js";export*from"./industrial.js";export*from"./oauth.js";export*from"./oauth-runtime.js";export*from"./storage.js";export*from"./uns.js";export{studioDatabase}from"./studio-database.js";
@@ -0,0 +1,120 @@
1
+ export type IndustrialResourceType =
2
+ | 'edgeAgent'
3
+ | 'connection'
4
+ | 'collectionTask'
5
+ | 'collectionPoint'
6
+ | 'videoEdge'
7
+ | 'videoGateway'
8
+ | 'videoDevice'
9
+ | 'videoChannel';
10
+
11
+ export type IndustrialSubscriptionTransport = 'auto' | 'websocket' | 'mqtt';
12
+ export type IndustrialControlTransport = 'auto' | 'http' | 'mqtt';
13
+
14
+ export function getIndustrialProtocolSchema(protocol: string): Promise<Record<string, unknown>>;
15
+ export function searchIndustrialResources(
16
+ resourceType: IndustrialResourceType | string,
17
+ options?: {
18
+ protocol?: string;
19
+ keyword?: string;
20
+ scope?: 'project' | 'enterprise';
21
+ selector?: Record<string, unknown>;
22
+ page?: number;
23
+ pageSize?: number;
24
+ page_size?: number;
25
+ },
26
+ ): Promise<Record<string, unknown>>;
27
+ export function getIndustrialResource(
28
+ resourceType: IndustrialResourceType | string,
29
+ resourceId: string,
30
+ ): Promise<Record<string, unknown>>;
31
+ export function validateIndustrialChanges(document: Record<string, unknown>): Promise<Record<string, unknown>>;
32
+ export function planIndustrialChanges(document: Record<string, unknown>): Promise<Record<string, unknown>>;
33
+ export function applyIndustrialChanges(
34
+ document: Record<string, unknown>,
35
+ options: {
36
+ expectedDocumentHash?: string;
37
+ expected_document_hash?: string;
38
+ expectedPlanHash?: string;
39
+ expected_plan_hash?: string;
40
+ confirmed: boolean;
41
+ impactConfirmed?: boolean;
42
+ impact_confirmed?: boolean;
43
+ },
44
+ ): Promise<Record<string, unknown>>;
45
+ export function getIndustrialRuntimeCapabilities(): Promise<Record<string, unknown>>;
46
+ export function getIndustrialRealtimeConnection(options: {
47
+ pointIds?: string[];
48
+ point_ids?: string[];
49
+ tagCodes?: string[];
50
+ tag_codes?: string[];
51
+ transport?: IndustrialSubscriptionTransport;
52
+ }): Promise<{
53
+ url: string;
54
+ authentication: string;
55
+ subscribe: {
56
+ type: 'subscribe';
57
+ transport: IndustrialSubscriptionTransport;
58
+ pointIds: string[];
59
+ tagCodes: string[];
60
+ };
61
+ }>;
62
+ export function getIndustrialPointCurrent(pointId: string): Promise<Record<string, unknown>>;
63
+ export function getIndustrialPointHistory(
64
+ pointId: string,
65
+ options: {
66
+ startTime?: string;
67
+ start_time?: string;
68
+ endTime?: string;
69
+ end_time?: string;
70
+ page?: number;
71
+ pageSize?: number;
72
+ page_size?: number;
73
+ },
74
+ ): Promise<Record<string, unknown>>;
75
+ export function writeIndustrialPoint(
76
+ pointId: string,
77
+ value: unknown,
78
+ options: {
79
+ reason: string;
80
+ ticket: string;
81
+ transport?: IndustrialControlTransport;
82
+ requestId?: string;
83
+ request_id?: string;
84
+ dryRun?: boolean;
85
+ dry_run?: boolean;
86
+ confirmed?: boolean;
87
+ },
88
+ ): Promise<Record<string, unknown>>;
89
+ export function getIndustrialVideoStreamOptions(channelId: string): Promise<Record<string, unknown>>;
90
+ export function startIndustrialVideoPreview(
91
+ channelId: string,
92
+ options: {
93
+ confirmed: boolean;
94
+ preferredProtocol?: string;
95
+ preferred_protocol?: string;
96
+ preferredProtocolOrder?: string[];
97
+ preferred_protocol_order?: string[];
98
+ },
99
+ ): Promise<Record<string, unknown>>;
100
+ export function stopIndustrialVideoPreview(
101
+ channelId: string,
102
+ options: { confirmed: boolean },
103
+ ): Promise<Record<string, unknown>>;
104
+
105
+ export const industrial: {
106
+ protocolSchema: typeof getIndustrialProtocolSchema;
107
+ searchResources: typeof searchIndustrialResources;
108
+ resource: typeof getIndustrialResource;
109
+ validateChanges: typeof validateIndustrialChanges;
110
+ planChanges: typeof planIndustrialChanges;
111
+ applyChanges: typeof applyIndustrialChanges;
112
+ runtimeCapabilities: typeof getIndustrialRuntimeCapabilities;
113
+ realtimeConnection: typeof getIndustrialRealtimeConnection;
114
+ pointCurrent: typeof getIndustrialPointCurrent;
115
+ pointHistory: typeof getIndustrialPointHistory;
116
+ writePoint: typeof writeIndustrialPoint;
117
+ videoStreamOptions: typeof getIndustrialVideoStreamOptions;
118
+ startVideoPreview: typeof startIndustrialVideoPreview;
119
+ stopVideoPreview: typeof stopIndustrialVideoPreview;
120
+ };
@@ -0,0 +1 @@
1
+ import{ApiError as t}from"./shared.js";import{authHeaders as e,refreshRuntimeConfig as r,runtimeConfig as n,shouldRefreshUserToken as i}from"./runtime.js";function o(t){return Object.fromEntries(Object.entries(t).filter(([,t])=>null!=t))}function a(t,e){return`/projects/${encodeURIComponent(t.projectId)}${e}`}async function s(a,s,{body:c,config:d}={}){let u=d||await n();for(let n=0;n<2;n+=1)try{const r=await fetch(new URL(`${u.baseUrl}/api/v1${s}`),{method:a,headers:e(u,void 0===c?void 0:"application/json"),body:void 0===c?void 0:JSON.stringify(o(c))}),n=await r.text();let i=null;try{i=n?JSON.parse(n):null}catch{throw new t(n||`platform industrial API returned ${r.status}`,{status:r.status,details:n})}if(!r.ok||i&&void 0!==i.code&&0!==i.code||!1===i?.success)throw new t(i?.message||n||"platform industrial API failed",{status:r.status,code:"number"==typeof i?.code?i.code:void 0,details:i});return i&&"object"==typeof i?i.data:i}catch(t){if(0===n&&i(t)){u=await r(u);continue}throw t}throw new t("platform industrial API failed")}export async function getIndustrialProtocolSchema(t){const e=await n();return s("GET",a(e,`/industrial/protocols/${encodeURIComponent(t)}/schema`),{config:e})}export async function searchIndustrialResources(t,e={}){const r=await n();return s("POST",a(r,"/industrial/resources/search"),{body:{resourceType:t,protocol:e.protocol,keyword:e.keyword,scope:e.scope||"project",selector:e.selector||{},page:e.page??1,pageSize:e.pageSize??e.page_size??20},config:r})}export async function getIndustrialResource(t,e){const r=await n();return s("GET",a(r,`/industrial/resources/${encodeURIComponent(t)}/${encodeURIComponent(e)}`),{config:r})}async function c(t,e){const r=await n();return s("POST",a(r,`/industrial/changes/${t}`),{body:{document:e},config:r})}export function validateIndustrialChanges(t){return c("validate",t)}export function planIndustrialChanges(t){return c("plan",t)}export async function applyIndustrialChanges(t,e={}){const r=String(e.expectedDocumentHash??e.expected_document_hash??"").trim(),i=String(e.expectedPlanHash??e.expected_plan_hash??"").trim();if(!0!==e.confirmed)throw new TypeError("industrial changes apply requires explicit confirmation");if(!r||!i)throw new TypeError("industrial changes apply requires document and plan hashes");const o=await n();return s("POST",a(o,"/industrial/changes/apply"),{body:{document:t,expectedDocumentHash:r,expectedPlanHash:i,confirmed:!0,impactConfirmed:!0===e.impactConfirmed||!0===e.impact_confirmed},config:o})}export async function getIndustrialRuntimeCapabilities(){const t=await n();return s("GET",a(t,"/industrial/runtime/capabilities"),{config:t})}export async function getIndustrialRealtimeConnection(t={}){const e=(t.pointIds||t.point_ids||[]).map(String).map(t=>t.trim()).filter(Boolean),r=(t.tagCodes||t.tag_codes||[]).map(String).map(t=>t.trim()).filter(Boolean);if(0===e.length&&0===r.length)throw new TypeError("pointIds or tagCodes must be provided");const i=await n(),o=new URL(i.baseUrl);return o.protocol="https:"===o.protocol?"wss:":"ws:",o.pathname=`/api/v1${a(i,"/industrial/runtime/points/realtime")}`,o.search="",o.hash="",{url:o.toString(),authentication:"use platform session or Authorization header",subscribe:{type:"subscribe",transport:t.transport||"auto",pointIds:e,tagCodes:r}}}function d(t,e,r){return a(t,`/industrial/runtime/points/${encodeURIComponent(e)}/${r}`)}export async function getIndustrialPointCurrent(t){const e=await n();return s("GET",d(e,t,"current"),{config:e})}export async function getIndustrialPointHistory(t,e={}){const r=await n();return s("POST",d(r,t,"history"),{body:{startTime:e.startTime??e.start_time,endTime:e.endTime??e.end_time,page:e.page??1,pageSize:e.pageSize??e.page_size??100},config:r})}export async function writeIndustrialPoint(t,e,r={}){const i=String(r.reason||"").trim(),o=String(r.ticket||"").trim(),a=!0===r.dryRun||!0===r.dry_run;if(!a&&!0!==r.confirmed)throw new TypeError("industrial point write requires explicit confirmation");if(!i||!o)throw new TypeError("industrial point write requires reason and ticket");const c=await n();return s("POST",d(c,t,"write"),{body:{value:e,transport:r.transport||"auto",reason:i,ticket:o,requestId:r.requestId??r.request_id,dryRun:a,confirmed:!0===r.confirmed},config:c})}async function u(t,e,r,i){const o=await n();return s(t,a(o,`/industrial/runtime/video/channels/${encodeURIComponent(e)}/${r}`),{body:i,config:o})}export function getIndustrialVideoStreamOptions(t){return u("GET",t,"stream-options")}export function startIndustrialVideoPreview(t,e={}){if(!0!==e.confirmed)throw new TypeError("industrial video preview start requires explicit confirmation");return u("POST",t,"preview/start",{preferredProtocol:e.preferredProtocol??e.preferred_protocol??"http-flv",preferredProtocolOrder:e.preferredProtocolOrder??e.preferred_protocol_order??["http-flv","webrtc","hls"],confirmed:!0})}export function stopIndustrialVideoPreview(t,e={}){if(!0!==e.confirmed)throw new TypeError("industrial video preview stop requires explicit confirmation");return u("POST",t,"preview/stop",{confirmed:!0})}export const industrial={protocolSchema:getIndustrialProtocolSchema,searchResources:searchIndustrialResources,resource:getIndustrialResource,validateChanges:validateIndustrialChanges,planChanges:planIndustrialChanges,applyChanges:applyIndustrialChanges,runtimeCapabilities:getIndustrialRuntimeCapabilities,realtimeConnection:getIndustrialRealtimeConnection,pointCurrent:getIndustrialPointCurrent,pointHistory:getIndustrialPointHistory,writePoint:writeIndustrialPoint,videoStreamOptions:getIndustrialVideoStreamOptions,startVideoPreview:startIndustrialVideoPreview,stopVideoPreview:stopIndustrialVideoPreview};
package/dist/uns.d.ts CHANGED
@@ -84,11 +84,11 @@ export function deleteUnsNodeData(nodeCode: string, rows: UnsObject[], options:
84
84
  export function queryUnsPathData(path: string, options?: UnsDataQueryOptions): Promise<UnsObject>;
85
85
  export function writeUnsPathData(path: string, fieldValues: UnsObject, options: { confirmed: boolean }): Promise<UnsObject>;
86
86
  export function deleteUnsPathData(path: string, rows: UnsObject[], options: { confirmed: boolean }): Promise<UnsObject>;
87
- export function getUnsPointCurrent(nodeCode: string): Promise<UnsObject>;
88
- export function getUnsPathPointCurrent(path: string): Promise<UnsObject>;
89
- export function getUnsPointRealtimeConfig(nodeCode: string): Promise<UnsObject>;
90
- export function getUnsPathPointRealtimeConfig(path: string): Promise<UnsObject>;
91
- export function getUnsPointHistory(nodeCode: string, options: UnsPointHistoryOptions): Promise<UnsObject>;
87
+ export function getUnsPointCurrent(nodeCode: string): Promise<UnsObject>;
88
+ export function getUnsPathPointCurrent(path: string): Promise<UnsObject>;
89
+ export function getUnsPointRealtimeConfig(nodeCode: string): Promise<UnsObject>;
90
+ export function getUnsPathPointRealtimeConfig(path: string): Promise<UnsObject>;
91
+ export function getUnsPointHistory(nodeCode: string, options: UnsPointHistoryOptions): Promise<UnsObject>;
92
92
  export function getUnsPathPointHistory(path: string, options: UnsPointHistoryOptions): Promise<UnsObject>;
93
93
  export function writeUnsPoint(nodeCode: string, value: unknown, options: UnsPointWriteOptions): Promise<UnsObject>;
94
94
  export function writeUnsPathPoint(path: string, value: unknown, options: UnsPointWriteOptions): Promise<UnsObject>;
@@ -105,10 +105,10 @@ export class UnsPathNode {
105
105
  resolve(): Promise<UnsObject>;
106
106
  queryData(options?: UnsDataQueryOptions): Promise<UnsObject>;
107
107
  writeData(fieldValues: UnsObject, options: { confirmed: boolean }): Promise<UnsObject>;
108
- deleteData(rows: UnsObject[], options: { confirmed: boolean }): Promise<UnsObject>;
109
- pointCurrent(): Promise<UnsObject>;
110
- pointRealtimeConfig(): Promise<UnsObject>;
111
- pointHistory(options: UnsPointHistoryOptions): Promise<UnsObject>;
108
+ deleteData(rows: UnsObject[], options: { confirmed: boolean }): Promise<UnsObject>;
109
+ pointCurrent(): Promise<UnsObject>;
110
+ pointRealtimeConfig(): Promise<UnsObject>;
111
+ pointHistory(options: UnsPointHistoryOptions): Promise<UnsObject>;
112
112
  writePoint(value: unknown, options: UnsPointWriteOptions): Promise<UnsObject>;
113
113
  videoStreamOptions(): Promise<UnsObject>;
114
114
  videoSnapshot(): Promise<UnsObject>;
@@ -139,11 +139,11 @@ export const uns: {
139
139
  queryPathData: typeof queryUnsPathData;
140
140
  writePathData: typeof writeUnsPathData;
141
141
  deletePathData: typeof deleteUnsPathData;
142
- pointCurrent: typeof getUnsPointCurrent;
143
- pathPointCurrent: typeof getUnsPathPointCurrent;
144
- pointRealtimeConfig: typeof getUnsPointRealtimeConfig;
145
- pathPointRealtimeConfig: typeof getUnsPathPointRealtimeConfig;
146
- pointHistory: typeof getUnsPointHistory;
142
+ pointCurrent: typeof getUnsPointCurrent;
143
+ pathPointCurrent: typeof getUnsPathPointCurrent;
144
+ pointRealtimeConfig: typeof getUnsPointRealtimeConfig;
145
+ pathPointRealtimeConfig: typeof getUnsPathPointRealtimeConfig;
146
+ pointHistory: typeof getUnsPointHistory;
147
147
  pathPointHistory: typeof getUnsPathPointHistory;
148
148
  writePoint: typeof writeUnsPoint;
149
149
  writePathPoint: typeof writeUnsPathPoint;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kmlckj/licos-platform-sdk",
3
- "version": "0.8.6",
3
+ "version": "0.9.0",
4
4
  "description": "LICOS platform SDK package shell for browser and Node runtimes",
5
5
  "author": "kmlckj",
6
6
  "type": "module",