@wairon/cli 5.0.2-dev.4 → 5.0.2-dev.5

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/dist/index.js CHANGED
@@ -2650,8 +2650,17 @@ var MODEL = __MODEL_JSON__;
2650
2650
  var configuredLineStyle = ['bezier', 'straight', 'taxi'].indexOf(diagramConfig.lineStyle) >= 0 ? diagramConfig.lineStyle : 'bezier';
2651
2651
  var defaultViewKind = diagramConfig.defaultView === 'types' ? 'types' : (diagramConfig.defaultView === 'databases' && showDatabaseTab ? 'databases' : 'system');
2652
2652
 
2653
+ // Stage J: a deep link (opts.initialRoute) seeds the initial view directly so a
2654
+ // refresh / shared URL renders the right scope with NO root-first flash. Parsed
2655
+ // by the same resolver as openRoute (hoisted below). No onViewChange fires for
2656
+ // this initial seed.
2657
+ var initialView = { kind: defaultViewKind, id: null };
2658
+ if (typeof opts !== 'undefined' && opts && typeof opts.initialRoute === 'string' && opts.initialRoute.length) {
2659
+ initialView = resolveRoute(opts.initialRoute);
2660
+ }
2661
+
2653
2662
  var state = {
2654
- view: { kind: defaultViewKind, id: null },
2663
+ view: initialView,
2655
2664
  internals: typeof saved.internals === 'boolean' ? saved.internals : false,
2656
2665
  externals: typeof saved.externals === 'boolean' ? saved.externals : true,
2657
2666
  dataCoupling: typeof saved.dataCoupling === 'boolean' ? saved.dataCoupling : false,
@@ -2670,6 +2679,9 @@ var MODEL = __MODEL_JSON__;
2670
2679
  // Set by buildTypeElements when the ERD is degraded for performance (huge
2671
2680
  // scopes); consumed by renderTypesNotice to explain the level-of-detail.
2672
2681
  var typesNotice = '';
2682
+ // Stage J: true while openRoute is applying a URL-driven view change, so the
2683
+ // onViewChange callback is suppressed and we do not loop URL -> engine -> URL.
2684
+ var applyingRoute = false;
2673
2685
 
2674
2686
  function viewKey() {
2675
2687
  // 'types2' + detail level: table sizes differ per detail, and the prefix
@@ -4099,6 +4111,78 @@ var MODEL = __MODEL_JSON__;
4099
4111
  state.typesRenderAll = false; // a fresh scope re-evaluates the LOD budget
4100
4112
  rebuild(true);
4101
4113
  renderPanel();
4114
+ notifyViewChange();
4115
+ }
4116
+
4117
+ // ---- Stage J: URL <-> view routing ----------------------------------------
4118
+ // The canvas navigation lives in the URL path (refresh-safe + shareable). A
4119
+ // route is the string AFTER /canvas/<project>: '' = system root; a '/'-joined
4120
+ // NAMESPACE (e.g. 'a/b') that resolves against the model to a subsystem or a
4121
+ // component; or the 'types'/'databases' view modes with an optional scope.
4122
+ // A segment is the '::' namespace with '/' as separator, each part encoded.
4123
+ function encSeg(s) { return encodeURIComponent(String(s)); }
4124
+ function routeOf(view) {
4125
+ if (!view) return '';
4126
+ var k = view.kind;
4127
+ if (k === 'system') return '';
4128
+ if (k === 'types' || k === 'databases') {
4129
+ return view.id ? k + '/' + view.id.split('::').map(encSeg).join('/') : k;
4130
+ }
4131
+ if (k === 'subsystem') {
4132
+ return view.id ? view.id.split('::').map(encSeg).join('/') : '';
4133
+ }
4134
+ if (k === 'component') {
4135
+ // A component's full namespace path IS its id: a chained subproject carries
4136
+ // the subsystem prefix in the id (a::b::comp), a flat project uses the bare
4137
+ // id (comp). Serializing comp.id split on '::' round-trips exactly via the
4138
+ // compById lookup in resolveRoute. Owner-pattern nesting is deliberately NOT
4139
+ // encoded (ownership is a separate axis; comp.id does not embed the owner).
4140
+ var c = compById[view.id];
4141
+ var full = c ? c.id : view.id;
4142
+ return full.split('::').map(encSeg).join('/');
4143
+ }
4144
+ return '';
4145
+ }
4146
+ function resolveRoute(routeStr) {
4147
+ var parts = String(routeStr || '').split('/').filter(function (s) { return s.length > 0; }).map(decodeURIComponent);
4148
+ if (!parts.length) return { kind: 'system', id: null };
4149
+ // NOTE: a subsystem literally named 'types'/'databases' is SHADOWED by these
4150
+ // view-mode routes (acceptable \u2014 the modes own those first segments).
4151
+ if (parts[0] === 'types') {
4152
+ return { kind: 'types', id: parts.length > 1 ? parts.slice(1).join('::') : null };
4153
+ }
4154
+ if (parts[0] === 'databases') {
4155
+ if (!showDatabaseTab) return { kind: 'system', id: null };
4156
+ return { kind: 'databases', id: parts.length > 1 ? parts.slice(1).join('::') : null };
4157
+ }
4158
+ var joined = parts.join('::');
4159
+ if (subById[joined]) return { kind: 'subsystem', id: joined };
4160
+ if (compById[joined]) return { kind: 'component', id: joined };
4161
+ return { kind: 'system', id: null }; // unknown id -> fall back to the root
4162
+ }
4163
+ // Apply a route (URL -> engine) WITHOUT echoing back through onViewChange.
4164
+ function openRoute(routeStr) {
4165
+ var v = resolveRoute(routeStr);
4166
+ if (state.view.kind === v.kind && state.view.id === v.id) return;
4167
+ applyingRoute = true;
4168
+ try {
4169
+ state.view = { kind: v.kind, id: v.id };
4170
+ state.selected = null;
4171
+ state.selectedKind = null;
4172
+ state.typesRenderAll = false;
4173
+ rebuild(true);
4174
+ renderPanel();
4175
+ } finally {
4176
+ applyingRoute = false;
4177
+ }
4178
+ }
4179
+ // Notify the embedder (engine -> URL) of the current view; suppressed while a
4180
+ // route is being applied so the URL is not driven in a loop.
4181
+ function notifyViewChange() {
4182
+ if (applyingRoute) return;
4183
+ if (typeof opts !== 'undefined' && opts && typeof opts.onViewChange === 'function') {
4184
+ try { opts.onViewChange(routeOf(state.view)); } catch (e) { /* ignore */ }
4185
+ }
4102
4186
  }
4103
4187
  // Explain (and offer to override) a performance-degraded ERD.
4104
4188
  function renderTypesNotice() {
@@ -4249,6 +4333,7 @@ var MODEL = __MODEL_JSON__;
4249
4333
  if (t.ghost) {
4250
4334
  state.view = parentViewOf(t.kind, t.id);
4251
4335
  rebuild(true);
4336
+ notifyViewChange();
4252
4337
  select(t.kind, t.id, true);
4253
4338
  return;
4254
4339
  }
@@ -5269,10 +5354,12 @@ var MODEL = __MODEL_JSON__;
5269
5354
  if (kind === 'type' && state.view.kind !== 'types' && state.view.kind !== 'databases') {
5270
5355
  state.view = { kind: 'types', id: typesScopeFromView() };
5271
5356
  rebuild(true);
5357
+ notifyViewChange();
5272
5358
  } else if (kind === 'component' && (state.view.kind === 'types' || state.view.kind === 'databases')) {
5273
5359
  var c = compById[id];
5274
5360
  state.view = { kind: 'subsystem', id: c ? c.subsystem : null };
5275
5361
  rebuild(true);
5362
+ notifyViewChange();
5276
5363
  }
5277
5364
  state.selectedKind = kind;
5278
5365
  state.selected = id;
@@ -15240,7 +15327,7 @@ function defaultTargetConfig(type) {
15240
15327
  enabled: true
15241
15328
  };
15242
15329
  }
15243
- var WAIRON_VERSION = "5.0.2-dev.4";
15330
+ var WAIRON_VERSION = "5.0.2-dev.5";
15244
15331
  var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
15245
15332
  var ARCHITECT_AGENT_ID = "agent-architect";
15246
15333
  var ARCHITECT_TEMPLATE_ID = "architect";