@nifrajs/ts-plugin 5.0.0 → 5.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nifra Authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs CHANGED
@@ -50,13 +50,20 @@ var import_fs = require("@nifrajs/web/fs");
50
50
 
51
51
  // src/resolve.ts
52
52
  var import_pattern = require("@nifrajs/core/pattern");
53
- var compiledRouteCache = new WeakMap;
53
+ var compiledRouteCache = new Map;
54
+ var MAX_CACHED_ROUTE_SETS = 8;
54
55
  function compiledRoutes(routes) {
55
- const cached = compiledRouteCache.get(routes);
56
+ const key = JSON.stringify(routes.map((route) => [route.pattern, route.file]));
57
+ const cached = compiledRouteCache.get(key);
56
58
  if (cached !== undefined)
57
59
  return cached;
58
60
  const compiled = import_pattern.sortRoutesBySpecificity(routes.map((route) => ({ route, pattern: import_pattern.compileRoutePattern(route.pattern) })));
59
- compiledRouteCache.set(routes, compiled);
61
+ if (compiledRouteCache.size >= MAX_CACHED_ROUTE_SETS) {
62
+ const oldest = compiledRouteCache.keys().next();
63
+ if (oldest.done !== true)
64
+ compiledRouteCache.delete(oldest.value);
65
+ }
66
+ compiledRouteCache.set(key, compiled);
60
67
  return compiled;
61
68
  }
62
69
  function resolveRouteFile(path, routes) {
@@ -113,7 +120,10 @@ function valueImports(tsm, source) {
113
120
  return edges;
114
121
  }
115
122
  function resolveImport(tsm, source, edge, options) {
116
- const specifier = edge.specifier.replace(/[?#].*$/, "");
123
+ const query = edge.specifier.indexOf("?", 1);
124
+ const hash = edge.specifier.indexOf("#", 1);
125
+ const cut = query === -1 ? hash : hash === -1 ? query : Math.min(query, hash);
126
+ const specifier = cut === -1 ? edge.specifier : edge.specifier.slice(0, cut);
117
127
  const mode = tsm.getModeForUsageLocation(source, edge.literal, options);
118
128
  const resolved = tsm.resolveModuleName(specifier, source.fileName, options, tsm.sys, undefined, undefined, mode).resolvedModule?.resolvedFileName;
119
129
  if (resolved !== undefined)
@@ -131,7 +141,7 @@ var real = (file) => {
131
141
  }
132
142
  };
133
143
  function libraryAsImported(target, specifier) {
134
- if (target.zone !== "library")
144
+ if (target.zone !== "library" || target.entry !== undefined)
135
145
  return target;
136
146
  const named = import_zones.specifierPackage(specifier);
137
147
  if (named === undefined || named === target.packageName)
@@ -148,7 +158,7 @@ function edgeProblem(classifier, display, fileName, from, specifier, target) {
148
158
  }
149
159
  if (target === undefined)
150
160
  return;
151
- const to = classifier.classify(target);
161
+ const to = classifier.classify(target, specifier);
152
162
  if (to.zone === "error")
153
163
  return `${display(fileName)} imports ${display(target)}: ${to.reason}`;
154
164
  if (to.zone === "library") {
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAYA,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAsBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,aAAa,EAAE,GAC/B,MAAM,GAAG,SAAS,CASpB"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAYA,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AA6BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,aAAa,EAAE,GAC/B,MAAM,GAAG,SAAS,CASpB"}
package/dist/resolve.js CHANGED
@@ -5,16 +5,24 @@
5
5
  * it would at runtime - the plugin never re-derives the file-based routing rules.
6
6
  */
7
7
  import { compileRoutePattern, matchRoutePattern, sortRoutesBySpecificity, } from "@nifrajs/core/pattern";
8
- // The language service asks for definitions repeatedly while the cursor moves. Cache the immutable
9
- // compilation/specificity sort by manifest identity so each query only performs route matching; a new
10
- // manifest array naturally gets a fresh entry when routes are added or removed.
11
- const compiledRouteCache = new WeakMap();
8
+ // The language service asks for definitions repeatedly while the cursor moves, and route discovery
9
+ // hands over a new array each time. So the compilation/specificity sort is cached by what the routes
10
+ // are, not by the array: each query then only matches, and a changed route set compiles afresh.
11
+ const compiledRouteCache = new Map();
12
+ /** Route sets kept compiled at once: a workspace's apps, plus the sets an edit just replaced. */
13
+ const MAX_CACHED_ROUTE_SETS = 8;
12
14
  function compiledRoutes(routes) {
13
- const cached = compiledRouteCache.get(routes);
15
+ const key = JSON.stringify(routes.map((route) => [route.pattern, route.file]));
16
+ const cached = compiledRouteCache.get(key);
14
17
  if (cached !== undefined)
15
18
  return cached;
16
19
  const compiled = sortRoutesBySpecificity(routes.map((route) => ({ route, pattern: compileRoutePattern(route.pattern) })));
17
- compiledRouteCache.set(routes, compiled);
20
+ if (compiledRouteCache.size >= MAX_CACHED_ROUTE_SETS) {
21
+ const oldest = compiledRouteCache.keys().next();
22
+ if (oldest.done !== true)
23
+ compiledRouteCache.delete(oldest.value);
24
+ }
25
+ compiledRouteCache.set(key, compiled);
18
26
  return compiled;
19
27
  }
20
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,uBAAuB,CAAA;AAa9B,mGAAmG;AACnG,sGAAsG;AACtG,gFAAgF;AAChF,MAAM,kBAAkB,GAAG,IAAI,OAAO,EAA8D,CAAA;AAEpG,SAAS,cAAc,CAAC,MAAgC;IACtD,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IACvC,MAAM,QAAQ,GAAG,uBAAuB,CACtC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAChF,CAAA;IACD,kBAAkB,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IACxC,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,MAAgC;IAEhC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;IACjD,6FAA6F;IAC7F,sDAAsD;IACtD,KAAK,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,IAAI,iBAAiB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC,IAAI,CAAA;IACrE,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,uBAAuB,CAAA;AAa9B,mGAAmG;AACnG,qGAAqG;AACrG,gGAAgG;AAChG,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA4C,CAAA;AAC9E,iGAAiG;AACjG,MAAM,qBAAqB,GAAG,CAAC,CAAA;AAE/B,SAAS,cAAc,CAAC,MAAgC;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC9E,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC1C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IACvC,MAAM,QAAQ,GAAG,uBAAuB,CACtC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAChF,CAAA;IACD,IAAI,kBAAkB,CAAC,IAAI,IAAI,qBAAqB,EAAE,CAAC;QACrD,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAA;QAC/C,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;YAAE,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACnE,CAAC;IACD,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACrC,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,MAAgC;IAEhC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;IACjD,6FAA6F;IAC7F,sDAAsD;IACtD,KAAK,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,IAAI,iBAAiB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC,IAAI,CAAA;IACrE,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"zones.d.ts","sourceRoot":"","sources":["../src/zones.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAA;AAErC,yGAAyG;AACzG,eAAO,MAAM,oBAAoB,SAAS,CAAA;AAmI1C;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,EAAE,EACd,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,EAAE,CAAC,eAAe,GAC1B,EAAE,CAAC,UAAU,EAAE,CA+BjB"}
1
+ {"version":3,"file":"zones.d.ts","sourceRoot":"","sources":["../src/zones.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAA;AAErC,yGAAyG;AACzG,eAAO,MAAM,oBAAoB,SAAS,CAAA;AAyI1C;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,EAAE,EACd,MAAM,EAAE,EAAE,CAAC,UAAU,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,EAAE,CAAC,eAAe,GAC1B,EAAE,CAAC,UAAU,EAAE,CA+BjB"}
package/dist/zones.js CHANGED
@@ -62,7 +62,12 @@ function valueImports(tsm, source) {
62
62
  /** Where an import lands: TypeScript's resolution (tsconfig `paths` included), else a relative path
63
63
  * that exists on disk (an `.svelte` or `.vue` file TypeScript only knows through a shim). */
64
64
  function resolveImport(tsm, source, edge, options) {
65
- const specifier = edge.specifier.replace(/[?#].*$/, "");
65
+ // Cut by index: `/[?#].*$/` retries from every `#` and is quadratic on a long run of them. The
66
+ // search starts past a leading `#`, which names a package.json import rather than a hash.
67
+ const query = edge.specifier.indexOf("?", 1);
68
+ const hash = edge.specifier.indexOf("#", 1);
69
+ const cut = query === -1 ? hash : hash === -1 ? query : Math.min(query, hash);
70
+ const specifier = cut === -1 ? edge.specifier : edge.specifier.slice(0, cut);
66
71
  const mode = tsm.getModeForUsageLocation(source, edge.literal, options);
67
72
  const resolved = tsm.resolveModuleName(specifier, source.fileName, options, tsm.sys, undefined, undefined, mode).resolvedModule?.resolvedFileName;
68
73
  if (resolved !== undefined)
@@ -83,7 +88,7 @@ const real = (file) => {
83
88
  /** A third-party target as the specifier names it: TypeScript resolves `pg` to `@types/pg`, and the
84
89
  * server-package list knows `pg`. */
85
90
  function libraryAsImported(target, specifier) {
86
- if (target.zone !== "library")
91
+ if (target.zone !== "library" || target.entry !== undefined)
87
92
  return target;
88
93
  const named = specifierPackage(specifier);
89
94
  if (named === undefined || named === target.packageName)
@@ -101,7 +106,8 @@ function edgeProblem(classifier, display, fileName, from, specifier, target) {
101
106
  }
102
107
  if (target === undefined)
103
108
  return undefined;
104
- const to = classifier.classify(target);
109
+ // A package that gives each entry its own side is judged by the entry the import names.
110
+ const to = classifier.classify(target, specifier);
105
111
  if (to.zone === "error")
106
112
  return `${display(fileName)} imports ${display(target)}: ${to.reason}`;
107
113
  if (to.zone === "library") {
package/dist/zones.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"zones.js","sourceRoot":"","sources":["../src/zones.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"zones.js","sourceRoot":"","sources":["../src/zones.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nifrajs/ts-plugin",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "TypeScript language-service plugin for nifra - go-to-definition from a route-path string literal to the routes/ file that serves it, and the frontend/backend zone rules as editor errors.",
5
5
  "keywords": [
6
6
  "bun",
@@ -47,8 +47,8 @@
47
47
  "build": "bun run build.ts"
48
48
  },
49
49
  "dependencies": {
50
- "@nifrajs/core": "5.0.0",
51
- "@nifrajs/web": "5.0.0"
50
+ "@nifrajs/core": "5.1.0",
51
+ "@nifrajs/web": "5.1.0"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "typescript": ">=5.5.0"
package/src/resolve.ts CHANGED
@@ -21,18 +21,25 @@ type CompiledRouteLocation = {
21
21
  readonly pattern: ReturnType<typeof compileRoutePattern>
22
22
  }
23
23
 
24
- // The language service asks for definitions repeatedly while the cursor moves. Cache the immutable
25
- // compilation/specificity sort by manifest identity so each query only performs route matching; a new
26
- // manifest array naturally gets a fresh entry when routes are added or removed.
27
- const compiledRouteCache = new WeakMap<readonly RouteLocation[], readonly CompiledRouteLocation[]>()
24
+ // The language service asks for definitions repeatedly while the cursor moves, and route discovery
25
+ // hands over a new array each time. So the compilation/specificity sort is cached by what the routes
26
+ // are, not by the array: each query then only matches, and a changed route set compiles afresh.
27
+ const compiledRouteCache = new Map<string, readonly CompiledRouteLocation[]>()
28
+ /** Route sets kept compiled at once: a workspace's apps, plus the sets an edit just replaced. */
29
+ const MAX_CACHED_ROUTE_SETS = 8
28
30
 
29
31
  function compiledRoutes(routes: readonly RouteLocation[]): readonly CompiledRouteLocation[] {
30
- const cached = compiledRouteCache.get(routes)
32
+ const key = JSON.stringify(routes.map((route) => [route.pattern, route.file]))
33
+ const cached = compiledRouteCache.get(key)
31
34
  if (cached !== undefined) return cached
32
35
  const compiled = sortRoutesBySpecificity(
33
36
  routes.map((route) => ({ route, pattern: compileRoutePattern(route.pattern) })),
34
37
  )
35
- compiledRouteCache.set(routes, compiled)
38
+ if (compiledRouteCache.size >= MAX_CACHED_ROUTE_SETS) {
39
+ const oldest = compiledRouteCache.keys().next()
40
+ if (oldest.done !== true) compiledRouteCache.delete(oldest.value)
41
+ }
42
+ compiledRouteCache.set(key, compiled)
36
43
  return compiled
37
44
  }
38
45
 
package/src/zones.ts CHANGED
@@ -91,7 +91,12 @@ function resolveImport(
91
91
  edge: ImportEdge,
92
92
  options: ts.CompilerOptions,
93
93
  ): string | undefined {
94
- const specifier = edge.specifier.replace(/[?#].*$/, "")
94
+ // Cut by index: `/[?#].*$/` retries from every `#` and is quadratic on a long run of them. The
95
+ // search starts past a leading `#`, which names a package.json import rather than a hash.
96
+ const query = edge.specifier.indexOf("?", 1)
97
+ const hash = edge.specifier.indexOf("#", 1)
98
+ const cut = query === -1 ? hash : hash === -1 ? query : Math.min(query, hash)
99
+ const specifier = cut === -1 ? edge.specifier : edge.specifier.slice(0, cut)
95
100
  const mode = tsm.getModeForUsageLocation(source, edge.literal, options)
96
101
  const resolved = tsm.resolveModuleName(
97
102
  specifier,
@@ -119,7 +124,7 @@ const real = (file: string): string => {
119
124
  /** A third-party target as the specifier names it: TypeScript resolves `pg` to `@types/pg`, and the
120
125
  * server-package list knows `pg`. */
121
126
  function libraryAsImported(target: Classification, specifier: string): Classification {
122
- if (target.zone !== "library") return target
127
+ if (target.zone !== "library" || target.entry !== undefined) return target
123
128
  const named = specifierPackage(specifier)
124
129
  if (named === undefined || named === target.packageName) return target
125
130
  return { zone: "library", packageName: named }
@@ -142,7 +147,8 @@ function edgeProblem(
142
147
  return `"${BACKEND_ONLY_MARKER}" marks a module backend-only, but ${display(fileName)} reaches the browser. Move it under backend/ or into a route's backend half`
143
148
  }
144
149
  if (target === undefined) return undefined
145
- const to = classifier.classify(target)
150
+ // A package that gives each entry its own side is judged by the entry the import names.
151
+ const to = classifier.classify(target, specifier)
146
152
  if (to.zone === "error") return `${display(fileName)} imports ${display(target)}: ${to.reason}`
147
153
  if (to.zone === "library") {
148
154
  const reason = browser ? browserDenial(libraryAsImported(to, specifier), specifier) : undefined