@openmbee/opensysml 0.9.2 → 0.10.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.
Files changed (67) hide show
  1. package/README.md +355 -33
  2. package/dist/browser/index.d.ts +9 -0
  3. package/dist/browser/index.js +16 -0
  4. package/dist/browser/wasm-worker.d.ts +1 -0
  5. package/dist/browser/wasm-worker.js +2 -0
  6. package/dist/browser/wasm.d.ts +17 -0
  7. package/dist/browser/wasm.js +97 -0
  8. package/dist/core/arguments.d.ts +4 -0
  9. package/dist/core/arguments.js +19 -0
  10. package/dist/core/capabilities.d.ts +90 -9
  11. package/dist/core/capabilities.js +111 -10
  12. package/dist/core/connection.d.ts +203 -2
  13. package/dist/core/connection.js +810 -17
  14. package/dist/core/conversion.d.ts +153 -0
  15. package/dist/core/conversion.js +191 -0
  16. package/dist/core/document.d.ts +188 -0
  17. package/dist/core/document.js +457 -0
  18. package/dist/core/edit.d.ts +446 -0
  19. package/dist/core/edit.js +1994 -0
  20. package/dist/core/engines.d.ts +64 -0
  21. package/dist/core/engines.js +74 -0
  22. package/dist/core/errors.d.ts +164 -2
  23. package/dist/core/errors.js +209 -3
  24. package/dist/core/exploration.d.ts +71 -0
  25. package/dist/core/exploration.js +116 -0
  26. package/dist/core/graphs.d.ts +15 -0
  27. package/dist/core/graphs.js +3 -0
  28. package/dist/core/index.d.ts +30 -9
  29. package/dist/core/index.js +14 -5
  30. package/dist/core/model.d.ts +168 -8
  31. package/dist/core/model.js +258 -31
  32. package/dist/core/package.d.ts +2 -0
  33. package/dist/core/package.js +2 -0
  34. package/dist/core/query.d.ts +50 -0
  35. package/dist/core/query.js +197 -0
  36. package/dist/core/render-view.d.ts +97 -0
  37. package/dist/core/render-view.js +120 -0
  38. package/dist/core/sources.d.ts +34 -0
  39. package/dist/core/sources.js +134 -0
  40. package/dist/core/status.d.ts +9 -2
  41. package/dist/core/status.js +24 -8
  42. package/dist/core/typed.d.ts +71 -0
  43. package/dist/core/typed.js +245 -0
  44. package/dist/core/values.d.ts +127 -8
  45. package/dist/core/values.js +538 -30
  46. package/dist/core/verdict.d.ts +271 -0
  47. package/dist/core/verdict.js +567 -0
  48. package/dist/core/wasm.d.ts +114 -0
  49. package/dist/core/wasm.js +514 -0
  50. package/dist/generated/sysml_pb.d.ts +1062 -15
  51. package/dist/generated/sysml_pb.js +200 -100
  52. package/dist/node/generate-cli.d.ts +2 -0
  53. package/dist/node/generate-cli.js +10 -0
  54. package/dist/node/generate.d.ts +99 -0
  55. package/dist/node/generate.js +757 -0
  56. package/dist/node/index.d.ts +29 -2
  57. package/dist/node/index.js +211 -10
  58. package/dist/node/service.d.ts +5 -3
  59. package/dist/node/service.js +32 -26
  60. package/dist/node/wasm-source.d.ts +18 -0
  61. package/dist/node/wasm-source.js +103 -0
  62. package/dist/node/wasm-worker.d.ts +1 -0
  63. package/dist/node/wasm-worker.js +10 -0
  64. package/dist/node/wasm.d.ts +17 -0
  65. package/dist/node/wasm.js +63 -0
  66. package/package.json +19 -7
  67. package/release-digests.json +117 -0
@@ -1,7 +1,9 @@
1
1
  // The ergonomic surface: a loaded model, its symbols, and the objects it
2
2
  // instantiates. Everything here is built on Connection.rpc.
3
3
  import { CAPABILITY_EVALUATE_SUBJECT, CAPABILITY_INLINE_LANGUAGE, CAPABILITY_STRICT_CONFORMANCE, requireCapability, upgradeRemedy, } from "./capabilities.js";
4
+ import { requireString, requireSourceText } from "./arguments.js";
4
5
  import { EvaluationError, OpenSysMLError, ParseError, SymbolNotFoundError } from "./errors.js";
6
+ import { requireLanguage } from "./sources.js";
5
7
  import { callRpc } from "./status.js";
6
8
  import { decodeValue } from "./values.js";
7
9
  /** How alike two names must be for one to be suggested for the other. */
@@ -31,6 +33,54 @@ function editDistance(left, right) {
31
33
  }
32
34
  return previous[right.length] ?? 0;
33
35
  }
36
+ /** Resolves `strictConformance` and its `strict` alias; differing values refuse. */
37
+ export function strictConformanceOf(options) {
38
+ if (options.strict !== undefined &&
39
+ options.strictConformance !== undefined &&
40
+ options.strict !== options.strictConformance) {
41
+ throw new RangeError(`strict (${options.strict}) and strictConformance (${options.strictConformance}) disagree; ` +
42
+ "pass only strictConformance");
43
+ }
44
+ return options.strictConformance ?? options.strict;
45
+ }
46
+ /** The integer one bound spells, or undefined when it spells none. */
47
+ function multiplicityBound(bound) {
48
+ const trimmed = bound.trim();
49
+ if (!/^[+-]?\d+$/.test(trimmed)) {
50
+ return undefined;
51
+ }
52
+ return Number.parseInt(trimmed, 10);
53
+ }
54
+ /** Builds a Multiplicity whose predicates mirror Python's. */
55
+ function multiplicityOf(lower, upper) {
56
+ const lowerBound = lower === "" ? undefined : multiplicityBound(lower);
57
+ return {
58
+ lower,
59
+ upper,
60
+ isOptional: lowerBound === undefined ? undefined : lowerBound === 0,
61
+ isCollection: isCollectionUpper(upper),
62
+ };
63
+ }
64
+ /** Whether an upper bound admits more than one: unknown for none, or one that is not a number. */
65
+ function isCollectionUpper(upper) {
66
+ if (upper === "") {
67
+ return undefined;
68
+ }
69
+ if (upper === "*") {
70
+ return true;
71
+ }
72
+ const bound = multiplicityBound(upper);
73
+ return bound === undefined ? undefined : bound > 1;
74
+ }
75
+ /** The symbols of one level of a model, then those of the levels below it. */
76
+ async function* walkLevels(level) {
77
+ if (level.length === 0) {
78
+ return;
79
+ }
80
+ yield* level;
81
+ const children = await Promise.all(level.map((symbol) => symbol.children()));
82
+ yield* walkLevels(children.flat());
83
+ }
34
84
  /** A model the service has parsed and holds under its hash. */
35
85
  export class Model {
36
86
  connection;
@@ -38,43 +88,87 @@ export class Model {
38
88
  hash;
39
89
  /** Diagnostics the parse reported, in the order the service reported them. */
40
90
  diagnostics;
41
- rootSymbol;
91
+ /** The name of each document this model was parsed from, empty for an adopted model. */
92
+ documents;
93
+ rootSymbols;
42
94
  ownsConnection;
43
95
  constructor(init) {
44
96
  this.connection = init.connection;
45
97
  this.hash = init.hash;
46
- this.rootSymbol = init.root;
98
+ this.rootSymbols = init.roots ?? [];
47
99
  this.diagnostics = init.diagnostics;
48
100
  this.ownsConnection = init.ownsConnection;
101
+ this.documents = init.documents ?? [];
102
+ this.sourcePath = init.sourcePath;
49
103
  }
50
104
  /** Adopts a model the service already holds, by the hash it holds it under. */
51
105
  static adopt(connection, hash) {
52
106
  return new Model({ connection, hash, diagnostics: [], ownsConnection: false });
53
107
  }
108
+ /** Builds a model of several roots, from a ParseSources response. */
109
+ static fromRoots(connection, hash, roots, diagnostics, options = {}) {
110
+ return new Model({
111
+ connection,
112
+ hash,
113
+ roots: roots.map((info) => new ModelSymbol(connection, hash, info)),
114
+ diagnostics,
115
+ ownsConnection: options.ownsConnection ?? false,
116
+ ...(options.documents === undefined ? {} : { documents: options.documents }),
117
+ });
118
+ }
54
119
  /** Whether this model was parsed here, and so knows its root symbol. */
55
120
  get parsed() {
56
- return this.rootSymbol !== undefined;
121
+ return this.rootSymbols.length > 0;
57
122
  }
58
123
  /** The model's root namespace. An adopted model has none: look symbols up by id. */
59
124
  get root() {
60
- if (this.rootSymbol === undefined) {
125
+ if (this.rootSymbols.length === 0) {
61
126
  throw new OpenSysMLError(`model ${this.hash} was adopted by hash, not parsed here, so its root is unknown; ` +
62
127
  "look a symbol up by its qualified name with symbolById()");
63
128
  }
64
- return this.rootSymbol;
129
+ return this.rootSymbols[0];
130
+ }
131
+ /** One root per document parsed; the one symbol {@link root} names is the first. */
132
+ get roots() {
133
+ return this.rootSymbols;
134
+ }
135
+ /** The path this model was loaded from, when it was parsed from a file;
136
+ * inline content and parseSources models have none, whatever they are named. */
137
+ sourcePath;
138
+ /** The error-severity diagnostics the parse reported. */
139
+ get errors() {
140
+ return this.diagnostics.filter((diagnostic) => diagnostic.severity === "error");
141
+ }
142
+ /** Whether the parse reported no error-severity diagnostic. */
143
+ get ok() {
144
+ return this.errors.length === 0;
145
+ }
146
+ /** Raises a {@link ParseError} carrying this model when its parse reported errors. */
147
+ raiseForErrors() {
148
+ if (this.hasErrors) {
149
+ throw new ParseError(this.errors.map((diagnostic) => diagnostic.message).join("\n"), this.errors, {
150
+ model: this,
151
+ });
152
+ }
153
+ return this;
65
154
  }
66
155
  /** Parses a source over `connection`. Used by Connection.load / Connection.loads. */
67
156
  static async parse(connection, source, options = {}, ownsConnection = false) {
157
+ if (source.source.case === "content") {
158
+ requireSourceText("source", source.source.value);
159
+ }
68
160
  if (options.language !== undefined) {
161
+ requireLanguage(options.language);
69
162
  requireCapability(connection.info, CAPABILITY_INLINE_LANGUAGE, upgradeRemedy(CAPABILITY_INLINE_LANGUAGE));
70
163
  }
71
- if (options.strict === true) {
164
+ const strictConformance = strictConformanceOf(options);
165
+ if (strictConformance === true) {
72
166
  requireCapability(connection.info, CAPABILITY_STRICT_CONFORMANCE, upgradeRemedy(CAPABILITY_STRICT_CONFORMANCE));
73
167
  }
74
168
  const response = await callRpc(connection.rpc.parseFile({
75
169
  source: source.source,
76
170
  ...(options.language === undefined ? {} : { language: options.language }),
77
- ...(options.strict === undefined ? {} : { strictConformance: options.strict }),
171
+ ...(strictConformance === undefined ? {} : { strictConformance }),
78
172
  }, connection.callOptions()), source.source.case === "filePath" ? "file" : "model");
79
173
  const diagnostics = response.diagnostics.map(decodeDiagnostic);
80
174
  if (response.error !== "") {
@@ -86,9 +180,12 @@ export class Model {
86
180
  return new Model({
87
181
  connection,
88
182
  hash: response.modelHash,
89
- root: new ModelSymbol(connection, response.modelHash, response.root),
183
+ roots: [new ModelSymbol(connection, response.modelHash, response.root)],
90
184
  diagnostics,
91
185
  ownsConnection,
186
+ ...(source.source.case === "filePath"
187
+ ? { documents: [source.source.value], sourcePath: source.source.value }
188
+ : {}),
92
189
  });
93
190
  }
94
191
  /** Whether the parse reported an error-severity diagnostic. */
@@ -97,6 +194,7 @@ export class Model {
97
194
  }
98
195
  /** Evaluates a SysML expression against this model. */
99
196
  async eval(expression, options = {}) {
197
+ requireString("expression", expression);
100
198
  if (options.subject !== undefined) {
101
199
  requireCapability(this.connection.info, CAPABILITY_EVALUATE_SUBJECT, upgradeRemedy(CAPABILITY_EVALUATE_SUBJECT));
102
200
  }
@@ -113,30 +211,158 @@ export class Model {
113
211
  }
114
212
  /** Looks a symbol up by short name, FQN or id; throws when the model declares none. */
115
213
  async symbol(name) {
116
- if (this.looksQualified(name)) {
117
- return this.symbolById(name);
214
+ requireString("name", name);
215
+ // The empty name names the model itself, as Python's model.get("") does.
216
+ if (name === "") {
217
+ return this.parsed ? this.root : this.symbolById(name);
118
218
  }
119
- // A short name is searched for from the root, which an adopted model has not
120
- // got; the service resolves a name the model declares at its top level.
121
- if (this.rootSymbol === undefined) {
122
- return this.symbolById(name);
219
+ if (this.looksQualified(name) || !this.parsed) {
220
+ // A qualified name or a name on an adopted model is resolved by the
221
+ // service; one it cannot resolve is searched for, as Python's find does.
222
+ try {
223
+ return await this.symbolById(name);
224
+ }
225
+ catch (error) {
226
+ if (!(error instanceof SymbolNotFoundError)) {
227
+ throw error;
228
+ }
229
+ }
230
+ const qualified = await this.find(name);
231
+ if (qualified !== undefined) {
232
+ return qualified;
233
+ }
234
+ throw new SymbolNotFoundError(name, await this.nearNames(name));
123
235
  }
124
236
  const found = await this.find(name);
125
237
  if (found === undefined) {
238
+ // A short name may still be one the service resolves directly, as an id.
239
+ try {
240
+ return await this.symbolById(name);
241
+ }
242
+ catch (error) {
243
+ if (!(error instanceof SymbolNotFoundError)) {
244
+ throw error;
245
+ }
246
+ }
126
247
  throw new SymbolNotFoundError(name, await this.nearNames(name));
127
248
  }
128
249
  return found;
129
250
  }
251
+ /** Writes this model out in `toFormat`. */
252
+ convert(toFormat, options = {}) {
253
+ return this.connection.convert(toFormat, { modelHash: this.hash }, options);
254
+ }
255
+ /** This model written in SysML notation. */
256
+ toSysml() {
257
+ return this.convert("sysml");
258
+ }
259
+ /** This model written as RDF Turtle. */
260
+ toTurtle() {
261
+ return this.convert("ttl");
262
+ }
263
+ /** This model written as API JSON. */
264
+ toApiJson() {
265
+ return this.convert("api-json");
266
+ }
267
+ /** Runs a SysML v2 API & Services Query over this model. */
268
+ query(options = {}) {
269
+ return this.connection.query(this.hash, options);
270
+ }
271
+ /** Runs a named document query against this model. */
272
+ runDocumentQuery(queryId, bindings) {
273
+ return this.connection.runDocumentQuery(this.hash, queryId, bindings);
274
+ }
275
+ /** Renders a named document of this model to Markdown or HTML. */
276
+ renderDocument(documentId, options = {}) {
277
+ return this.connection.renderDocument(this.hash, documentId, options);
278
+ }
279
+ /** Renders a named view or targeted pseudo-view as diagram data. */
280
+ renderView(viewName, options = {}) {
281
+ return this.connection.renderView(this.hash, viewName, options);
282
+ }
283
+ /** Exports the lowered graph of an action or state machine of this model as `graphs:1` JSON. */
284
+ exportGraphs(subject) {
285
+ return this.connection.exportGraphs(this.hash, subject);
286
+ }
287
+ /** Starts an edit of this model, to be applied in one call. */
288
+ edit() {
289
+ return this.connection.edit(this.hash);
290
+ }
291
+ /** Executes an action definition of this model. */
292
+ executeAction(actionSymbolId, options = {}) {
293
+ return this.connection.executeAction(this.hash, actionSymbolId, options);
294
+ }
295
+ /** Runs an action once per valid order of its choice points. */
296
+ exploreAction(actionSymbolId, options = {}) {
297
+ return this.connection.exploreAction(this.hash, actionSymbolId, options);
298
+ }
299
+ /** Executes a state machine of this model. */
300
+ executeState(stateMachineSymbolId, options = {}) {
301
+ return this.connection.executeState(this.hash, stateMachineSymbolId, options);
302
+ }
303
+ /** Runs a state machine once per valid order of its choice points. */
304
+ exploreState(stateMachineSymbolId, options = {}) {
305
+ return this.connection.exploreState(this.hash, stateMachineSymbolId, options);
306
+ }
307
+ /** Asks whether a constraint of this model holds. */
308
+ verifyConstraint(symbolId, options = {}) {
309
+ return this.connection.verifyConstraint(this.hash, symbolId, options);
310
+ }
311
+ /** Asks whether a requirement of this model is satisfied. */
312
+ verifyRequirement(symbolId, options = {}) {
313
+ return this.connection.verifyRequirement(this.hash, symbolId, options);
314
+ }
315
+ /** Asks whether this model's satisfaction assertions hold. */
316
+ verifySatisfaction(options = {}) {
317
+ return this.connection.verifySatisfaction(this.hash, options);
318
+ }
319
+ /** Whether every verdict {@link verifySatisfaction} returns holds. */
320
+ async satisfied(options = {}) {
321
+ const verdicts = await this.verifySatisfaction(options);
322
+ return verdicts.every((verdict) => verdict.verdict.kind === "holds");
323
+ }
324
+ /** Checks every assertion about an object of this model's parts. */
325
+ validateInstance(symbolId, options = {}) {
326
+ return this.connection.validateInstance(this.hash, symbolId, options);
327
+ }
328
+ /** Invokes a calculation of this model. */
329
+ calc(symbolId, options = {}) {
330
+ return this.connection.calc(this.hash, symbolId, options);
331
+ }
332
+ /** Runs an analysis case of this model. */
333
+ runAnalysis(symbolId, options = {}) {
334
+ return this.connection.runAnalysis(this.hash, symbolId, options);
335
+ }
336
+ /** Runs an analysis case once per valid order of its choice points. */
337
+ exploreAnalysis(symbolId, options = {}) {
338
+ return this.connection.exploreAnalysis(this.hash, symbolId, options);
339
+ }
340
+ /** Runs an analysis case or calc of this model once per row of a sweep. */
341
+ runSweep(symbolId, ranges, options = {}) {
342
+ return this.connection.runSweep(this.hash, symbolId, ranges, options);
343
+ }
344
+ /** The diagnostics the service reports for this model now — for a model of
345
+ * several documents, or one parsed before later edits changed it. */
346
+ async refreshDiagnostics() {
347
+ const response = await callRpc(this.connection.rpc.getDiagnostics({ modelHash: this.hash }, this.connection.callOptions()));
348
+ return response.diagnostics.map(decodeDiagnostic);
349
+ }
130
350
  /** Looks a symbol up by its qualified name, in one call. */
131
351
  async symbolById(id) {
352
+ requireString("id", id);
132
353
  const response = await callRpc(this.connection.rpc.getSymbol({ modelHash: this.hash, symbolId: id }, this.connection.callOptions()));
133
354
  if (response.symbol === undefined) {
355
+ // A single call: near names are symbol()'s to compute.
134
356
  throw new SymbolNotFoundError(id);
135
357
  }
136
358
  return new ModelSymbol(this.connection, this.hash, response.symbol);
137
359
  }
138
360
  /** Looks a symbol up by short name, FQN or id, breadth-first from the root. */
139
361
  async find(name) {
362
+ requireString("name", name);
363
+ if (name === "") {
364
+ return this.parsed ? this.root : undefined;
365
+ }
140
366
  for await (const symbol of this.walk()) {
141
367
  if (symbol.name === name || symbol.id === name) {
142
368
  return symbol;
@@ -146,18 +372,11 @@ export class Model {
146
372
  }
147
373
  /** Every symbol of the model, breadth-first from the root. */
148
374
  async *walk() {
149
- const queue = [this.root];
150
- while (queue.length > 0) {
151
- const current = queue.shift();
152
- if (current === undefined) {
153
- break;
154
- }
155
- yield current;
156
- queue.push(...(await current.children()));
157
- }
375
+ yield* walkLevels([...this.rootSymbols]);
158
376
  }
159
377
  /** Instantiates a part or usage, by short name, FQN or id. */
160
378
  async instantiate(name) {
379
+ requireString("name", name);
161
380
  const id = this.looksQualified(name) ? name : (await this.symbol(name)).id;
162
381
  const response = await callRpc(this.connection.rpc.instantiate({ modelHash: this.hash, symbolId: id }, this.connection.callOptions()));
163
382
  if (response.error !== "") {
@@ -179,7 +398,7 @@ export class Model {
179
398
  }
180
399
  /** Whether a name is one the service can resolve directly, without a search. */
181
400
  looksQualified(name) {
182
- return name.includes("::") || name === this.rootSymbol?.id;
401
+ return name.includes("::") || name === this.rootSymbols[0]?.id;
183
402
  }
184
403
  /** The names of the model closest to one it has not got, best first. */
185
404
  async nearNames(name) {
@@ -190,9 +409,16 @@ export class Model {
190
409
  if (symbol.name === "") {
191
410
  continue;
192
411
  }
193
- const score = similarity(name.toLowerCase(), symbol.name.toLowerCase());
194
- if (score >= NEAR_ENOUGH) {
195
- scored.push({ id: symbol.id, score });
412
+ // A short name and a qualified one are both candidates, either being
413
+ // what a mistyped lookup may have meant.
414
+ for (const candidate of [symbol.name, symbol.id]) {
415
+ if (candidate === "") {
416
+ continue;
417
+ }
418
+ const score = similarity(name.toLowerCase(), candidate.toLowerCase());
419
+ if (score >= NEAR_ENOUGH) {
420
+ scored.push({ id: candidate, score });
421
+ }
196
422
  }
197
423
  seen += 1;
198
424
  if (seen === NEAR_SEARCH_LIMIT) {
@@ -247,7 +473,7 @@ export class ModelSymbol {
247
473
  this.multiplicity =
248
474
  info.multiplicity === undefined
249
475
  ? undefined
250
- : { lower: info.multiplicity.lower, upper: info.multiplicity.upper };
476
+ : multiplicityOf(info.multiplicity.lower, info.multiplicity.upper);
251
477
  this.specializations = info.specializations.map((specialization) => ({
252
478
  kind: specialization.kind,
253
479
  declared: specialization.declared,
@@ -258,9 +484,9 @@ export class ModelSymbol {
258
484
  }
259
485
  /** The symbols this one owns, fetched one call each. */
260
486
  async children() {
487
+ const responses = await Promise.all(this.childIds.map((id) => callRpc(this.connection.rpc.getSymbol({ modelHash: this.modelHash, symbolId: id }, this.connection.callOptions()))));
261
488
  const children = [];
262
- for (const id of this.childIds) {
263
- const response = await callRpc(this.connection.rpc.getSymbol({ modelHash: this.modelHash, symbolId: id }, this.connection.callOptions()));
489
+ for (const response of responses) {
264
490
  if (response.symbol !== undefined) {
265
491
  children.push(new ModelSymbol(this.connection, this.modelHash, response.symbol));
266
492
  }
@@ -320,7 +546,8 @@ function decodeFeatureValue(value) {
320
546
  }
321
547
  return { kind: "single", value: decodeValue(value.value), materialized: value.materialized };
322
548
  }
323
- function decodeDiagnostic(diagnostic) {
549
+ /** Reads a wire `Diagnostic` into this client's own {@link ModelDiagnostic}. */
550
+ export function decodeDiagnostic(diagnostic) {
324
551
  const span = diagnostic.span;
325
552
  return {
326
553
  severity: diagnostic.severity,
@@ -1,4 +1,6 @@
1
1
  /** The npm name this client is published under; package.json's "name" must match it. */
2
2
  export declare const PACKAGE_NAME = "@openmbee/opensysml";
3
+ /** The optional npm package that carries the combined WebAssembly module. */
4
+ export declare const WASM_PACKAGE = "@openmbee/opensysml-wasm";
3
5
  /** Prefix of the per-platform packages that carry sysml-grpc: `${prefix}<os>-<cpu>`. */
4
6
  export declare const PLATFORM_PACKAGE_PREFIX = "@openmbee/opensysml-sysml-grpc-";
@@ -1,4 +1,6 @@
1
1
  /** The npm name this client is published under; package.json's "name" must match it. */
2
2
  export const PACKAGE_NAME = "@openmbee/opensysml";
3
+ /** The optional npm package that carries the combined WebAssembly module. */
4
+ export const WASM_PACKAGE = `${PACKAGE_NAME}-wasm`;
3
5
  /** Prefix of the per-platform packages that carry sysml-grpc: `${prefix}<os>-<cpu>`. */
4
6
  export const PLATFORM_PACKAGE_PREFIX = `${PACKAGE_NAME}-sysml-grpc-`;
@@ -0,0 +1,50 @@
1
+ import type { Query, QueryResponse } from "../generated/sysml_pb.js";
2
+ /** `@type` of the standard's query resource. */
3
+ export declare const TYPE_QUERY = "Query";
4
+ /** `@type` of a single-property constraint. */
5
+ export declare const TYPE_PRIMITIVE_CONSTRAINT = "PrimitiveConstraint";
6
+ /** `@type` of a constraint over nested constraints. */
7
+ export declare const TYPE_COMPOSITE_CONSTRAINT = "CompositeConstraint";
8
+ /** An element a query selected. */
9
+ export declare class QueryElement {
10
+ /** Qualified name of the element, which is what a scope names it by. */
11
+ readonly id: string;
12
+ /** The element's metamodel type, e.g. `PartUsage`. */
13
+ readonly type: string;
14
+ /** The selected properties it has; one it does not have is absent. */
15
+ readonly properties: Readonly<Record<string, string>>;
16
+ constructor(init: {
17
+ id: string;
18
+ type: string;
19
+ properties: Record<string, string>;
20
+ });
21
+ /** Value of a selected property, or `fallback` if the element has none. */
22
+ get(propertyName: string, fallback?: string): string | undefined;
23
+ /** The element as the standard's JSON names it: `@id`, `@type`, properties. */
24
+ asDict(): Record<string, string>;
25
+ toString(): string;
26
+ }
27
+ /** A scope entry: an element's qualified name or an `@id` reference. */
28
+ export type ScopeEntry = string | {
29
+ "@id": string;
30
+ };
31
+ /** A constraint, as the standard's JSON writes it. */
32
+ export type ConstraintPayload = Record<string, unknown>;
33
+ /** The standard's `Query` object, as JSON. */
34
+ export type QueryPayload = Record<string, unknown>;
35
+ /** Keyword form of a query, exclusive with `payload`. */
36
+ export interface QueryForm {
37
+ scope?: readonly ScopeEntry[];
38
+ select?: readonly string[];
39
+ where?: ConstraintPayload;
40
+ /** An OSLC query text, evaluated instead of the structured query. */
41
+ oslc?: string;
42
+ /** A query already decoded for the wire; passes through as written. */
43
+ query?: Query;
44
+ }
45
+ /** Translate a query, given as the standard's JSON or as keywords, to protobuf. */
46
+ export declare function buildQuery(options?: {
47
+ payload?: QueryPayload;
48
+ } & QueryForm): Query;
49
+ /** The elements a `QueryResponse` reports, as `QueryElement` records. */
50
+ export declare function elementsOf(response: QueryResponse): QueryElement[];