@nola-lang/typescript-plugin 0.1.0-alpha.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.
@@ -0,0 +1,4 @@
1
+ import type ts from "typescript";
2
+ /** tsserver plugin factory; loaded via the CJS bundle in Track 3. */
3
+ export declare function createNolaTsPlugin(): ts.server.PluginModuleFactory;
4
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAMjC,qEAAqE;AACrE,wBAAgB,kBAAkB,IAAI,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAWlE"}
package/dist/plugin.js ADDED
@@ -0,0 +1,29 @@
1
+ // Installed-API findings (@volar/typescript@2.4.28), per plan Task 3 Step 1:
2
+ // - quickstart factory: `createLanguageServicePlugin(cb)` at
3
+ // lib/quickstart/createLanguageServicePlugin (subpath import; package has no
4
+ // exports map). cb: (ts, info) => { languagePlugins: LanguagePlugin<string>[], setup? }.
5
+ // - LanguagePlugin.typescript augmentation lives in @volar/typescript's index.
6
+ // - Headless building blocks: createLanguage (@volar/language-core),
7
+ // decorateLanguageServiceHost(ts, language, host) and
8
+ // createProxyLanguageService(ls) -> { initialize(language), proxy } (@volar/typescript).
9
+ import { createNolaLanguagePlugin } from "@nola-lang/language-core";
10
+ import { findProjectRoot } from "@nola-lang/node-loader";
11
+ import { createLanguageServicePlugin } from "@volar/typescript/lib/quickstart/createLanguageServicePlugin.js";
12
+ import { decorateHostWithCompanions } from "./companion-host.js";
13
+ import { guardProjectServiceDocumentCache } from "./document-cache-guard.js";
14
+ import { decorateServerHostForCompanions } from "./server-host.js";
15
+ import { decorateHostHideShadowedDeclarations } from "./shadowed-declarations.js";
16
+ /** tsserver plugin factory; loaded via the CJS bundle in Track 3. */
17
+ export function createNolaTsPlugin() {
18
+ return createLanguageServicePlugin((typescript, info) => {
19
+ const sourceRoot = findProjectRoot(info.project.getCurrentDirectory());
20
+ guardProjectServiceDocumentCache(info.project.projectService);
21
+ decorateServerHostForCompanions(info.serverHost);
22
+ decorateHostHideShadowedDeclarations(typescript, info.languageServiceHost);
23
+ decorateHostWithCompanions(typescript, info.languageServiceHost, { sourceRoot });
24
+ return {
25
+ languagePlugins: [createNolaLanguagePlugin((fileName) => fileName, { sourceRoot })],
26
+ };
27
+ });
28
+ }
29
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6DAA6D;AAC7D,+EAA+E;AAC/E,2FAA2F;AAC3F,+EAA+E;AAC/E,qEAAqE;AACrE,wDAAwD;AACxD,2FAA2F;AAC3F,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,2BAA2B,EAAE,MAAM,iEAAiE,CAAC;AAE9G,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,oCAAoC,EAAE,MAAM,4BAA4B,CAAC;AAElF,qEAAqE;AACrE,MAAM,UAAU,kBAAkB;IAChC,OAAO,2BAA2B,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE;QACtD,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACvE,gCAAgC,CAAE,IAAI,CAAC,OAAkD,CAAC,cAAc,CAAC,CAAC;QAC1G,+BAA+B,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACjD,oCAAoC,CAAC,UAAU,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC3E,0BAA0B,CAAC,UAAU,EAAE,IAAI,CAAC,mBAAmB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACjF,OAAO;YACL,eAAe,EAAE,CAAC,wBAAwB,CAAS,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;SAC5F,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type ts from "typescript";
2
+ /**
3
+ * Make companions REAL to tsserver's file layer. Companion modules are
4
+ * program files, and tsserver's ScriptInfo/watch machinery assumes every
5
+ * program file is backed by disk or an open editor document — a companion
6
+ * that exists only in language-service-host decorations violates that
7
+ * invariant, and tsserver enforces it with Debug asserts in several places
8
+ * (ProjectService.setDocument, Project.getScriptInfos via project telemetry —
9
+ * the latter crashed VS Code's TS 6.0.3 on project load).
10
+ *
11
+ * The decoration answers for registered companion paths at the ServerHost
12
+ * (ts.sys-equivalent) level:
13
+ * - fileExists/readFile: the companion exists; its text derives from the
14
+ * ON-DISK source module (compileCompanion). The live unsaved-edits variant
15
+ * still comes from the language-service host's snapshot decoration — this
16
+ * layer only has to be consistent enough for ScriptInfo bookkeeping.
17
+ * - getModifiedTime: the SOURCE file's mtime (the companion "changes" exactly
18
+ * when its source does).
19
+ * - watchFile: forwards to a watch on the source file, reporting events under
20
+ * the companion's name — deleting the source marks the companion deleted.
21
+ *
22
+ * One ServerHost serves the whole tsserver process; the patch applies once.
23
+ */
24
+ export declare function decorateServerHostForCompanions(serverHost: ts.server.ServerHost): void;
25
+ //# sourceMappingURL=server-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-host.d.ts","sourceRoot":"","sources":["../src/server-host.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAKjC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,CAoCtF"}
@@ -0,0 +1,58 @@
1
+ import { compileCompanion } from "@nola-lang/compiler";
2
+ import { companionRegistration } from "./companion-host.js";
3
+ const PATCHED = Symbol.for("nola.companionServerHost");
4
+ /**
5
+ * Make companions REAL to tsserver's file layer. Companion modules are
6
+ * program files, and tsserver's ScriptInfo/watch machinery assumes every
7
+ * program file is backed by disk or an open editor document — a companion
8
+ * that exists only in language-service-host decorations violates that
9
+ * invariant, and tsserver enforces it with Debug asserts in several places
10
+ * (ProjectService.setDocument, Project.getScriptInfos via project telemetry —
11
+ * the latter crashed VS Code's TS 6.0.3 on project load).
12
+ *
13
+ * The decoration answers for registered companion paths at the ServerHost
14
+ * (ts.sys-equivalent) level:
15
+ * - fileExists/readFile: the companion exists; its text derives from the
16
+ * ON-DISK source module (compileCompanion). The live unsaved-edits variant
17
+ * still comes from the language-service host's snapshot decoration — this
18
+ * layer only has to be consistent enough for ScriptInfo bookkeeping.
19
+ * - getModifiedTime: the SOURCE file's mtime (the companion "changes" exactly
20
+ * when its source does).
21
+ * - watchFile: forwards to a watch on the source file, reporting events under
22
+ * the companion's name — deleting the source marks the companion deleted.
23
+ *
24
+ * One ServerHost serves the whole tsserver process; the patch applies once.
25
+ */
26
+ export function decorateServerHostForCompanions(serverHost) {
27
+ const host = serverHost;
28
+ if (host[PATCHED])
29
+ return;
30
+ host[PATCHED] = true;
31
+ const priorFileExists = host.fileExists.bind(host);
32
+ host.fileExists = (path) => (companionRegistration(path) ? true : priorFileExists(path));
33
+ const priorReadFile = host.readFile.bind(host);
34
+ host.readFile = (path, encoding) => {
35
+ const registration = companionRegistration(path);
36
+ if (!registration)
37
+ return priorReadFile(path, encoding);
38
+ const source = priorReadFile(registration.sourceFile);
39
+ if (source === undefined)
40
+ return undefined;
41
+ return compileCompanion(source, registration.sourceFile, { sourceRoot: registration.sourceRoot }).code;
42
+ };
43
+ const priorGetModifiedTime = host.getModifiedTime?.bind(host);
44
+ if (priorGetModifiedTime) {
45
+ host.getModifiedTime = (path) => {
46
+ const registration = companionRegistration(path);
47
+ return priorGetModifiedTime(registration ? registration.sourceFile : path);
48
+ };
49
+ }
50
+ const priorWatchFile = host.watchFile.bind(host);
51
+ host.watchFile = (path, callback, pollingInterval, options) => {
52
+ const registration = companionRegistration(path);
53
+ if (!registration)
54
+ return priorWatchFile(path, callback, pollingInterval, options);
55
+ return priorWatchFile(registration.sourceFile, (_fileName, eventKind, modifiedTime) => callback(path, eventKind, modifiedTime), pollingInterval, options);
56
+ };
57
+ }
58
+ //# sourceMappingURL=server-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-host.js","sourceRoot":"","sources":["../src/server-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,+BAA+B,CAAC,UAAgC;IAC9E,MAAM,IAAI,GAAG,UAAyD,CAAC;IACvE,IAAI,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO;IAC1B,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAErB,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IAEzF,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE;QACjC,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,YAAY;YAAE,OAAO,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC3C,OAAO,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC;IACzG,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9D,IAAI,oBAAoB,EAAE,CAAC;QACzB,IAAI,CAAC,eAAe,GAAG,CAAC,IAAI,EAAE,EAAE;YAC9B,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YACjD,OAAO,oBAAoB,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7E,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,EAAE;QAC5D,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,YAAY;YAAE,OAAO,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;QACnF,OAAO,cAAc,CACnB,YAAY,CAAC,UAAU,EACvB,CAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,EAC/E,eAAe,EACf,OAAO,CACR,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type ts from "typescript";
2
+ /**
3
+ * Hide `X.d.tsi.ts` from the editor whenever a sibling `X.tsi` exists.
4
+ *
5
+ * With `allowArbitraryExtensions`, TypeScript resolves `./X.tsi` to the
6
+ * adjacent declaration FIRST — an on-disk build artifact (or a stale leftover
7
+ * from the old adjacent-declaration emit) would shadow the live virtual .tsi,
8
+ * sending navigation into the declaration instead of the source. Denying its
9
+ * existence makes standard resolution fail, so Volar's extra-extension
10
+ * resolution serves the .tsi in-memory and definitions map back to source.
11
+ * Declarations without a sibling .tsi (e.g. shipped by a built package whose
12
+ * sources are gone) stay visible.
13
+ */
14
+ export declare function decorateHostHideShadowedDeclarations(typescript: typeof ts, host: ts.LanguageServiceHost): void;
15
+ //# sourceMappingURL=shadowed-declarations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shadowed-declarations.d.ts","sourceRoot":"","sources":["../src/shadowed-declarations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAIjC;;;;;;;;;;;GAWG;AACH,wBAAgB,oCAAoC,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,mBAAmB,GAAG,IAAI,CAc9G"}
@@ -0,0 +1,24 @@
1
+ const DECL_SUFFIX = ".d.tsi.ts";
2
+ /**
3
+ * Hide `X.d.tsi.ts` from the editor whenever a sibling `X.tsi` exists.
4
+ *
5
+ * With `allowArbitraryExtensions`, TypeScript resolves `./X.tsi` to the
6
+ * adjacent declaration FIRST — an on-disk build artifact (or a stale leftover
7
+ * from the old adjacent-declaration emit) would shadow the live virtual .tsi,
8
+ * sending navigation into the declaration instead of the source. Denying its
9
+ * existence makes standard resolution fail, so Volar's extra-extension
10
+ * resolution serves the .tsi in-memory and definitions map back to source.
11
+ * Declarations without a sibling .tsi (e.g. shipped by a built package whose
12
+ * sources are gone) stay visible.
13
+ */
14
+ export function decorateHostHideShadowedDeclarations(typescript, host) {
15
+ const priorFileExists = host.fileExists?.bind(host);
16
+ const rawFileExists = (f) => priorFileExists?.(f) ?? typescript.sys.fileExists(f);
17
+ const shadowed = (f) => f.endsWith(DECL_SUFFIX) && rawFileExists(`${f.slice(0, -DECL_SUFFIX.length)}.tsi`);
18
+ host.fileExists = (f) => (shadowed(f) ? false : rawFileExists(f));
19
+ const priorReadFile = host.readFile?.bind(host);
20
+ host.readFile = (f) => (shadowed(f) ? undefined : priorReadFile?.(f));
21
+ const priorGetSnapshot = host.getScriptSnapshot.bind(host);
22
+ host.getScriptSnapshot = (f) => (shadowed(f) ? undefined : priorGetSnapshot(f));
23
+ }
24
+ //# sourceMappingURL=shadowed-declarations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shadowed-declarations.js","sourceRoot":"","sources":["../src/shadowed-declarations.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAAG,WAAW,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oCAAoC,CAAC,UAAqB,EAAE,IAA4B;IACtG,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,CAAC,CAAS,EAAW,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAEnG,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAW,EAAE,CACtC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAErF,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAElE,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtE,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tsserver-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsserver-entry.d.ts","sourceRoot":"","sources":["../src/tsserver-entry.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ // The CJS bundle entry tsserver `require`s (see scripts/bundle.mjs). tsserver
2
+ // plugins must export the factory as module.exports.
3
+ import { createNolaTsPlugin } from "./plugin.js";
4
+ module.exports = createNolaTsPlugin();
5
+ //# sourceMappingURL=tsserver-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsserver-entry.js","sourceRoot":"","sources":["../src/tsserver-entry.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,qDAAqD;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,CAAC,OAAO,GAAG,kBAAkB,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@nola-lang/typescript-plugin",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "tsserver plugin serving .tsi to TypeScript editors (internal editor layer)",
5
+ "keywords": [
6
+ "nola"
7
+ ],
8
+ "license": "MIT",
9
+ "author": "Evgen Mykhailenko",
10
+ "homepage": "https://github.com/nola-lang/nola#readme",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/nola-lang/nola.git",
14
+ "directory": "packages/typescript-plugin"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/nola-lang/nola/issues"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "type": "module",
23
+ "main": "./dist/plugin.cjs",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "require": "./dist/plugin.cjs",
28
+ "default": "./dist/index.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "scripts": {
35
+ "bundle": "node scripts/bundle.mjs"
36
+ },
37
+ "dependencies": {
38
+ "@nola-lang/compiler": "0.1.0-alpha.0",
39
+ "@nola-lang/language-core": "0.1.0-alpha.0",
40
+ "@nola-lang/node-loader": "0.1.0-alpha.0",
41
+ "@volar/typescript": "2.4.28"
42
+ },
43
+ "devDependencies": {
44
+ "esbuild": "^0.25.0",
45
+ "typescript": "^5.6.0"
46
+ },
47
+ "engines": {
48
+ "node": ">=22"
49
+ }
50
+ }