@payloadcms/typescript-plugin 3.78.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.
Files changed (44) hide show
  1. package/LICENSE.md +22 -0
  2. package/dist/__tests__/fixtures/components/MyField.d.ts +3 -0
  3. package/dist/__tests__/fixtures/components/MyField.d.ts.map +1 -0
  4. package/dist/__tests__/fixtures/components/MyField.js +22 -0
  5. package/dist/__tests__/fixtures/components/MyField.js.map +1 -0
  6. package/dist/__tests__/fixtures/components/icons/Icon/index.d.ts +3 -0
  7. package/dist/__tests__/fixtures/components/icons/Icon/index.d.ts.map +1 -0
  8. package/dist/__tests__/fixtures/components/icons/Icon/index.js +22 -0
  9. package/dist/__tests__/fixtures/components/icons/Icon/index.js.map +1 -0
  10. package/dist/__tests__/fixtures/components/views/CustomView/index.d.ts +3 -0
  11. package/dist/__tests__/fixtures/components/views/CustomView/index.d.ts.map +1 -0
  12. package/dist/__tests__/fixtures/components/views/CustomView/index.js +22 -0
  13. package/dist/__tests__/fixtures/components/views/CustomView/index.js.map +1 -0
  14. package/dist/__tests__/fixtures/payload-types.d.js +3 -0
  15. package/dist/__tests__/fixtures/payload-types.d.js.map +1 -0
  16. package/dist/__tests__/fixtures/payload.config.d.ts +3 -0
  17. package/dist/__tests__/fixtures/payload.config.d.ts.map +1 -0
  18. package/dist/__tests__/fixtures/payload.config.js +13 -0
  19. package/dist/__tests__/fixtures/payload.config.js.map +1 -0
  20. package/dist/__tests__/fixtures/src/components/NavIcon.d.ts +3 -0
  21. package/dist/__tests__/fixtures/src/components/NavIcon.d.ts.map +1 -0
  22. package/dist/__tests__/fixtures/src/components/NavIcon.js +22 -0
  23. package/dist/__tests__/fixtures/src/components/NavIcon.js.map +1 -0
  24. package/dist/__tests__/fixtures/src/components/ui/Badge.d.ts +4 -0
  25. package/dist/__tests__/fixtures/src/components/ui/Badge.d.ts.map +1 -0
  26. package/dist/__tests__/fixtures/src/components/ui/Badge.js +26 -0
  27. package/dist/__tests__/fixtures/src/components/ui/Badge.js.map +1 -0
  28. package/dist/__tests__/fixtures/test-config.d.ts +2 -0
  29. package/dist/__tests__/fixtures/test-config.d.ts.map +1 -0
  30. package/dist/__tests__/fixtures/test-config.js +146 -0
  31. package/dist/__tests__/fixtures/test-config.js.map +1 -0
  32. package/dist/__tests__/fixtures/test-paths.d.ts +2 -0
  33. package/dist/__tests__/fixtures/test-paths.d.ts.map +1 -0
  34. package/dist/__tests__/fixtures/test-paths.js +115 -0
  35. package/dist/__tests__/fixtures/test-paths.js.map +1 -0
  36. package/dist/helpers.d.ts +26 -0
  37. package/dist/helpers.d.ts.map +1 -0
  38. package/dist/helpers.js +118 -0
  39. package/dist/helpers.js.map +1 -0
  40. package/dist/index.d.ts +8 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +474 -0
  43. package/dist/index.js.map +1 -0
  44. package/package.json +50 -0
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get findNodeAtPosition () {
13
+ return findNodeAtPosition;
14
+ },
15
+ get getPayloadComponentContext () {
16
+ return getPayloadComponentContext;
17
+ }
18
+ });
19
+ function getPayloadComponentContext(ts, node, checker) {
20
+ const contextualType = checker.getContextualType(node);
21
+ if (contextualType && isPayloadComponentType(ts, contextualType)) {
22
+ return {
23
+ type: 'string',
24
+ node
25
+ };
26
+ }
27
+ if (ts.isPropertyAssignment(node.parent) && ts.isObjectLiteralExpression(node.parent.parent)) {
28
+ const propName = ts.isIdentifier(node.parent.name) ? node.parent.name.text : node.parent.name.getText();
29
+ const objectLiteral = node.parent.parent;
30
+ const objectContextualType = checker.getContextualType(objectLiteral);
31
+ if (objectContextualType && isRawPayloadComponentType(ts, objectContextualType)) {
32
+ if (propName === 'path') {
33
+ const exportNameValue = findSiblingStringProp(ts, objectLiteral, 'exportName');
34
+ return {
35
+ type: 'path',
36
+ exportNameValue,
37
+ node
38
+ };
39
+ }
40
+ if (propName === 'exportName') {
41
+ const pathValue = findSiblingStringProp(ts, objectLiteral, 'path');
42
+ return {
43
+ type: 'exportName',
44
+ node,
45
+ pathValue
46
+ };
47
+ }
48
+ }
49
+ }
50
+ return undefined;
51
+ }
52
+ function findSiblingStringProp(ts, objectLiteral, name) {
53
+ const prop = objectLiteral.properties.find((p)=>ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === name && ts.isStringLiteral(p.initializer));
54
+ return prop && ts.isStringLiteral(prop.initializer) ? prop.initializer.text : undefined;
55
+ }
56
+ /**
57
+ * Checks whether a type is `PayloadComponent` (the union `false | RawPayloadComponent<...> | string`).
58
+ *
59
+ * Uses both alias name matching and a structural check so this catches `PayloadComponent`,
60
+ * `CustomComponent`, and any other alias that resolves to the same shape.
61
+ */ function isPayloadComponentType(ts, type) {
62
+ const aliasName = type.aliasSymbol?.name;
63
+ if (aliasName === 'PayloadComponent' || aliasName === 'CustomComponent' || aliasName === 'DocumentViewComponent') {
64
+ return true;
65
+ }
66
+ if (!type.isUnion()) {
67
+ return false;
68
+ }
69
+ let hasString = false;
70
+ let hasComponentShape = false;
71
+ for (const member of type.types){
72
+ if (member.flags & ts.TypeFlags.String) {
73
+ hasString = true;
74
+ }
75
+ if (member.flags & ts.TypeFlags.Object && member.getProperty('path')) {
76
+ hasComponentShape = true;
77
+ }
78
+ }
79
+ return hasString && hasComponentShape;
80
+ }
81
+ /**
82
+ * Checks whether a type is `RawPayloadComponent` (an object with `path: string`
83
+ * and optional `exportName: string`).
84
+ */ function isRawPayloadComponentType(ts, type) {
85
+ const aliasName = type.aliasSymbol?.name;
86
+ if (aliasName === 'RawPayloadComponent') {
87
+ return true;
88
+ }
89
+ if (type.flags & ts.TypeFlags.Object) {
90
+ return Boolean(type.getProperty('path') && type.getProperty('exportName'));
91
+ }
92
+ if (type.isUnion()) {
93
+ return type.types.some((member)=>member.flags & ts.TypeFlags.Object && member.getProperty('path') && member.getProperty('exportName'));
94
+ }
95
+ return false;
96
+ }
97
+ function findNodeAtPosition(ts, sourceFile, position) {
98
+ const getTokenAtPosition = ts.getTokenAtPosition;
99
+ if (getTokenAtPosition) {
100
+ return getTokenAtPosition(sourceFile, position);
101
+ }
102
+ // Fallback if the internal API is removed in a future TS version
103
+ function find(node) {
104
+ if (position >= node.getStart() && position < node.getEnd()) {
105
+ let found;
106
+ node.forEachChild((child)=>{
107
+ if (!found) {
108
+ found = find(child);
109
+ }
110
+ });
111
+ return found || node;
112
+ }
113
+ return undefined;
114
+ }
115
+ return find(sourceFile);
116
+ }
117
+
118
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers.ts"],"sourcesContent":["import type tslib from 'typescript/lib/tsserverlibrary'\n\nexport type PayloadComponentContext =\n | { exportNameValue?: string; node: tslib.StringLiteral; type: 'path' }\n | { node: tslib.StringLiteral; pathValue?: string; type: 'exportName' }\n | { node: tslib.StringLiteral; type: 'string' }\n\n/**\n * Determines if a string literal is in a PayloadComponent context and what kind.\n *\n * - `'string'`: direct string form, e.g. `Field: '@/components/MyField#MyField'`\n * - `'path'`: the `path` property in the object form, e.g. `{ path: '@/components/MyField' }`\n * - `'exportName'`: the `exportName` property in the object form, e.g. `{ exportName: 'MyField' }`\n */\nexport function getPayloadComponentContext(\n ts: typeof tslib,\n node: tslib.StringLiteral,\n checker: tslib.TypeChecker,\n): PayloadComponentContext | undefined {\n const contextualType = checker.getContextualType(node)\n if (contextualType && isPayloadComponentType(ts, contextualType)) {\n return { type: 'string', node }\n }\n\n if (ts.isPropertyAssignment(node.parent) && ts.isObjectLiteralExpression(node.parent.parent)) {\n const propName = ts.isIdentifier(node.parent.name)\n ? node.parent.name.text\n : node.parent.name.getText()\n const objectLiteral = node.parent.parent\n const objectContextualType = checker.getContextualType(objectLiteral)\n\n if (objectContextualType && isRawPayloadComponentType(ts, objectContextualType)) {\n if (propName === 'path') {\n const exportNameValue = findSiblingStringProp(ts, objectLiteral, 'exportName')\n return { type: 'path', exportNameValue, node }\n }\n\n if (propName === 'exportName') {\n const pathValue = findSiblingStringProp(ts, objectLiteral, 'path')\n return { type: 'exportName', node, pathValue }\n }\n }\n }\n\n return undefined\n}\n\nfunction findSiblingStringProp(\n ts: typeof tslib,\n objectLiteral: tslib.ObjectLiteralExpression,\n name: string,\n): string | undefined {\n const prop = objectLiteral.properties.find(\n (p): p is tslib.PropertyAssignment =>\n ts.isPropertyAssignment(p) &&\n ts.isIdentifier(p.name) &&\n p.name.text === name &&\n ts.isStringLiteral(p.initializer),\n )\n return prop && ts.isStringLiteral(prop.initializer) ? prop.initializer.text : undefined\n}\n\n/**\n * Checks whether a type is `PayloadComponent` (the union `false | RawPayloadComponent<...> | string`).\n *\n * Uses both alias name matching and a structural check so this catches `PayloadComponent`,\n * `CustomComponent`, and any other alias that resolves to the same shape.\n */\nfunction isPayloadComponentType(ts: typeof tslib, type: tslib.Type): boolean {\n const aliasName = type.aliasSymbol?.name\n if (\n aliasName === 'PayloadComponent' ||\n aliasName === 'CustomComponent' ||\n aliasName === 'DocumentViewComponent'\n ) {\n return true\n }\n\n if (!type.isUnion()) {\n return false\n }\n\n let hasString = false\n let hasComponentShape = false\n\n for (const member of type.types) {\n if (member.flags & ts.TypeFlags.String) {\n hasString = true\n }\n\n if (member.flags & ts.TypeFlags.Object && member.getProperty('path')) {\n hasComponentShape = true\n }\n }\n\n return hasString && hasComponentShape\n}\n\n/**\n * Checks whether a type is `RawPayloadComponent` (an object with `path: string`\n * and optional `exportName: string`).\n */\nfunction isRawPayloadComponentType(ts: typeof tslib, type: tslib.Type): boolean {\n const aliasName = type.aliasSymbol?.name\n if (aliasName === 'RawPayloadComponent') {\n return true\n }\n\n if (type.flags & ts.TypeFlags.Object) {\n return Boolean(type.getProperty('path') && type.getProperty('exportName'))\n }\n\n if (type.isUnion()) {\n return type.types.some(\n (member) =>\n member.flags & ts.TypeFlags.Object &&\n member.getProperty('path') &&\n member.getProperty('exportName'),\n )\n }\n\n return false\n}\n\n/**\n * Returns the deepest token at a given position, reusing TypeScript's internal traversal.\n */\nexport function findNodeAtPosition(\n ts: typeof tslib,\n sourceFile: tslib.SourceFile,\n position: number,\n): tslib.Node | undefined {\n const getTokenAtPosition = (\n ts as unknown as {\n getTokenAtPosition: (sf: tslib.SourceFile, pos: number) => tslib.Node\n }\n ).getTokenAtPosition\n\n if (getTokenAtPosition) {\n return getTokenAtPosition(sourceFile, position)\n }\n\n // Fallback if the internal API is removed in a future TS version\n function find(node: tslib.Node): tslib.Node | undefined {\n if (position >= node.getStart() && position < node.getEnd()) {\n let found: tslib.Node | undefined\n node.forEachChild((child) => {\n if (!found) {\n found = find(child)\n }\n })\n return found || node\n }\n return undefined\n }\n\n return find(sourceFile)\n}\n"],"names":["findNodeAtPosition","getPayloadComponentContext","ts","node","checker","contextualType","getContextualType","isPayloadComponentType","type","isPropertyAssignment","parent","isObjectLiteralExpression","propName","isIdentifier","name","text","getText","objectLiteral","objectContextualType","isRawPayloadComponentType","exportNameValue","findSiblingStringProp","pathValue","undefined","prop","properties","find","p","isStringLiteral","initializer","aliasName","aliasSymbol","isUnion","hasString","hasComponentShape","member","types","flags","TypeFlags","String","Object","getProperty","Boolean","some","sourceFile","position","getTokenAtPosition","getStart","getEnd","found","forEachChild","child"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type tslib from 'typescript/lib/tsserverlibrary';
2
+ declare function init(modules: {
3
+ typescript: typeof tslib;
4
+ }): {
5
+ create: (info: tslib.server.PluginCreateInfo) => tslib.LanguageService;
6
+ };
7
+ export = init;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gCAAgC,CAAA;AAMvD,iBAAS,IAAI,CAAC,OAAO,EAAE;IAAE,UAAU,EAAE,OAAO,KAAK,CAAA;CAAE;mBAG3B,KAAK,CAAC,MAAM,CAAC,gBAAgB,KAAG,KAAK,CAAC,eAAe;EA+G5E;AAsgBD,SAAS,IAAI,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,474 @@
1
+ "use strict";
2
+ const _helpers = require("./helpers.js");
3
+ function init(modules) {
4
+ const ts = modules.typescript;
5
+ function create(info) {
6
+ const log = (msg)=>info.project.projectService.logger.info(`[@payloadcms/typescript-plugin] ${msg}`);
7
+ log('Plugin initializing');
8
+ const baseDirConfig = info.config?.baseDir;
9
+ const baseDirCache = new Map();
10
+ const sys = info.serverHost || ts.sys;
11
+ const proxy = Object.create(null);
12
+ for (const k of Object.keys(info.languageService)){
13
+ const x = info.languageService[k];
14
+ // @ts-expect-error - decorator pattern for language service proxy
15
+ proxy[k] = (...args)=>x.apply(info.languageService, args);
16
+ }
17
+ function getBaseDir(fileName) {
18
+ if (baseDirConfig) {
19
+ const projectDir = info.project.getCurrentDirectory();
20
+ return ts.sys.resolvePath(projectDir + '/' + baseDirConfig);
21
+ }
22
+ const cached = baseDirCache.get(fileName);
23
+ if (cached !== undefined) {
24
+ return cached;
25
+ }
26
+ const detected = findPayloadConfigDir(sys, fileName);
27
+ baseDirCache.set(fileName, detected);
28
+ if (detected) {
29
+ log(`Detected baseDir: ${detected} (from payload config near ${fileName})`);
30
+ }
31
+ return detected;
32
+ }
33
+ proxy.getSemanticDiagnostics = (fileName)=>{
34
+ const prior = info.languageService.getSemanticDiagnostics(fileName);
35
+ const program = info.languageService.getProgram();
36
+ if (!program) {
37
+ return prior;
38
+ }
39
+ const sourceFile = program.getSourceFile(fileName);
40
+ if (!sourceFile) {
41
+ return prior;
42
+ }
43
+ const checker = program.getTypeChecker();
44
+ const baseDir = getBaseDir(fileName);
45
+ const additional = getPayloadDiagnostics(ts, sourceFile, checker, program, baseDir);
46
+ return [
47
+ ...prior,
48
+ ...additional
49
+ ];
50
+ };
51
+ proxy.getCompletionsAtPosition = (fileName, position, options, formattingSettings)=>{
52
+ const program = info.languageService.getProgram();
53
+ if (program) {
54
+ const sourceFile = program.getSourceFile(fileName);
55
+ if (sourceFile) {
56
+ const checker = program.getTypeChecker();
57
+ const node = (0, _helpers.findNodeAtPosition)(ts, sourceFile, position);
58
+ if (node && ts.isStringLiteral(node)) {
59
+ const baseDir = getBaseDir(fileName);
60
+ const result = getPayloadCompletions(ts, node, position, checker, program, baseDir, sys);
61
+ if (result) {
62
+ return result;
63
+ }
64
+ }
65
+ }
66
+ }
67
+ return info.languageService.getCompletionsAtPosition(fileName, position, options, formattingSettings);
68
+ };
69
+ proxy.getDefinitionAndBoundSpan = (fileName, position)=>{
70
+ const program = info.languageService.getProgram();
71
+ if (program) {
72
+ const sourceFile = program.getSourceFile(fileName);
73
+ if (sourceFile) {
74
+ const checker = program.getTypeChecker();
75
+ const node = (0, _helpers.findNodeAtPosition)(ts, sourceFile, position);
76
+ if (node && ts.isStringLiteral(node)) {
77
+ const baseDir = getBaseDir(fileName);
78
+ const result = getPayloadDefinition(ts, node, checker, program, baseDir);
79
+ if (result) {
80
+ return result;
81
+ }
82
+ }
83
+ }
84
+ }
85
+ return info.languageService.getDefinitionAndBoundSpan(fileName, position);
86
+ };
87
+ log('Plugin initialized successfully');
88
+ return proxy;
89
+ }
90
+ return {
91
+ create
92
+ };
93
+ }
94
+ // -------------------------------------------------------------------
95
+ // Shared utilities
96
+ // -------------------------------------------------------------------
97
+ /**
98
+ * Extracts the module path and export name from any PayloadComponent context.
99
+ * Mirrors the logic of `parsePayloadComponent` in payload core:
100
+ * splits `#` for the export name, and respects sibling `exportName`/`path` overrides.
101
+ */ function parsePayloadComponent(context, nodeText) {
102
+ let pathAndMaybeExport;
103
+ let exportNameOverride;
104
+ if (context.type === 'string' || context.type === 'path') {
105
+ pathAndMaybeExport = nodeText;
106
+ exportNameOverride = context.type === 'path' ? context.exportNameValue : undefined;
107
+ } else if (context.type === 'exportName' && context.pathValue) {
108
+ pathAndMaybeExport = context.pathValue;
109
+ exportNameOverride = nodeText;
110
+ } else {
111
+ return undefined;
112
+ }
113
+ let path;
114
+ let exportName;
115
+ if (pathAndMaybeExport.includes('#')) {
116
+ ;
117
+ [path, exportName] = pathAndMaybeExport.split('#', 2);
118
+ exportName = exportName || 'default';
119
+ } else {
120
+ path = pathAndMaybeExport;
121
+ exportName = 'default';
122
+ }
123
+ if (exportNameOverride) {
124
+ exportName = exportNameOverride;
125
+ }
126
+ return {
127
+ exportName,
128
+ path
129
+ };
130
+ }
131
+ function resolveModulePath(ts, modulePath, containingFile, program, baseDir) {
132
+ const compilerOptions = program.getCompilerOptions();
133
+ let pathToResolve = modulePath;
134
+ let resolveFrom = containingFile;
135
+ // Payload convention: '/' and './' paths are relative to baseDir.
136
+ // Resolve from a synthetic file inside baseDir so TypeScript uses it as the base.
137
+ if (modulePath.startsWith('/') || modulePath.startsWith('./')) {
138
+ if (baseDir) {
139
+ resolveFrom = baseDir + '/_.ts';
140
+ }
141
+ if (modulePath.startsWith('/')) {
142
+ pathToResolve = '.' + modulePath;
143
+ }
144
+ }
145
+ // Delegate entirely to TypeScript's module resolution -- respects the project's
146
+ // moduleResolution, paths, allowImportingTsExtensions, etc.
147
+ const result = ts.resolveModuleName(pathToResolve, resolveFrom, compilerOptions, ts.sys);
148
+ return result.resolvedModule;
149
+ }
150
+ function getModuleExports(resolvedModule, program) {
151
+ const sourceFile = program.getSourceFile(resolvedModule.resolvedFileName);
152
+ if (!sourceFile) {
153
+ return [];
154
+ }
155
+ const checker = program.getTypeChecker();
156
+ const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
157
+ if (!moduleSymbol) {
158
+ return [];
159
+ }
160
+ return checker.getExportsOfModule(moduleSymbol).map((e)=>e.name);
161
+ }
162
+ // -------------------------------------------------------------------
163
+ // Diagnostics
164
+ // -------------------------------------------------------------------
165
+ function getPayloadDiagnostics(ts, sourceFile, checker, program, baseDir) {
166
+ const diagnostics = [];
167
+ function visit(node) {
168
+ if (ts.isStringLiteral(node) && node.text.length > 0) {
169
+ const context = (0, _helpers.getPayloadComponentContext)(ts, node, checker);
170
+ if (!context) {
171
+ ts.forEachChild(node, visit);
172
+ return;
173
+ }
174
+ const component = parsePayloadComponent(context, node.text);
175
+ if (!component?.path) {
176
+ ts.forEachChild(node, visit);
177
+ return;
178
+ }
179
+ const { exportName, path: modulePath } = component;
180
+ const resolved = resolveModulePath(ts, modulePath, sourceFile.fileName, program, baseDir);
181
+ if (!resolved) {
182
+ diagnostics.push({
183
+ category: ts.DiagnosticCategory.Error,
184
+ code: 71001,
185
+ file: sourceFile,
186
+ length: node.text.length,
187
+ messageText: `Cannot find module '${modulePath}'. Ensure the file exists and the path is correct.`,
188
+ start: node.getStart() + 1
189
+ });
190
+ } else {
191
+ const exports = getModuleExports(resolved, program);
192
+ if (!exports.includes(exportName)) {
193
+ let message = `Module '${modulePath}' has no exported member '${exportName}'.`;
194
+ const getSpellingSuggestion = ts.getSpellingSuggestion;
195
+ const suggestion = getSpellingSuggestion?.(exportName, exports, (e)=>e);
196
+ if (suggestion) {
197
+ message += ` Did you mean '${suggestion}'?`;
198
+ } else if (exports.length > 0) {
199
+ message += ` Available exports: ${exports.join(', ')}.`;
200
+ }
201
+ diagnostics.push({
202
+ category: ts.DiagnosticCategory.Error,
203
+ code: 71002,
204
+ file: sourceFile,
205
+ length: node.text.length,
206
+ messageText: message,
207
+ start: node.getStart() + 1
208
+ });
209
+ }
210
+ }
211
+ }
212
+ ts.forEachChild(node, visit);
213
+ }
214
+ visit(sourceFile);
215
+ return diagnostics;
216
+ }
217
+ // -------------------------------------------------------------------
218
+ // Completions
219
+ // -------------------------------------------------------------------
220
+ function getPayloadCompletions(ts, node, position, checker, program, baseDir, sys) {
221
+ const context = (0, _helpers.getPayloadComponentContext)(ts, node, checker);
222
+ if (!context) {
223
+ return undefined;
224
+ }
225
+ if (context.type === 'exportName') {
226
+ const component = parsePayloadComponent(context, node.text);
227
+ if (!component) {
228
+ return undefined;
229
+ }
230
+ return buildExportCompletions(ts, node, component.path, node.text.length, program, baseDir);
231
+ }
232
+ // Both 'string' and 'path' contexts: check if cursor is after #
233
+ const text = node.text;
234
+ const offsetInString = position - node.getStart() - 1;
235
+ const hashIndex = text.indexOf('#');
236
+ if (hashIndex !== -1 && offsetInString > hashIndex) {
237
+ const modulePath = text.substring(0, hashIndex);
238
+ return buildExportCompletions(ts, node, modulePath, text.length - hashIndex - 1, program, baseDir, node.getStart() + 1 + hashIndex + 1);
239
+ }
240
+ return getPathCompletions(ts, sys, node, position, baseDir, program);
241
+ }
242
+ function buildExportCompletions(ts, node, modulePath, replacementLength, program, baseDir, replacementStart) {
243
+ const resolved = resolveModulePath(ts, modulePath, node.getSourceFile().fileName, program, baseDir);
244
+ if (!resolved) {
245
+ return undefined;
246
+ }
247
+ const exports = getModuleExports(resolved, program);
248
+ return {
249
+ entries: exports.map((name)=>({
250
+ name,
251
+ kind: ts.ScriptElementKind.constElement,
252
+ replacementSpan: {
253
+ length: replacementLength,
254
+ start: replacementStart ?? node.getStart() + 1
255
+ },
256
+ sortText: name
257
+ })),
258
+ isGlobalCompletion: false,
259
+ isMemberCompletion: true,
260
+ isNewIdentifierLocation: false
261
+ };
262
+ }
263
+ const COMPONENT_EXTENSIONS = [
264
+ '.tsx',
265
+ '.ts',
266
+ '.jsx',
267
+ '.js'
268
+ ];
269
+ function getPathCompletions(ts, sys, node, position, baseDir, program) {
270
+ const text = node.text;
271
+ const offsetInString = position - node.getStart() - 1;
272
+ const hashIndex = text.indexOf('#');
273
+ const endOffset = hashIndex !== -1 ? Math.min(offsetInString, hashIndex) : offsetInString;
274
+ const pathPortion = text.substring(0, endOffset);
275
+ const lastSlash = pathPortion.lastIndexOf('/');
276
+ let dirPath;
277
+ let prefix;
278
+ let replacementStart;
279
+ if (lastSlash === -1) {
280
+ dirPath = baseDir;
281
+ prefix = pathPortion;
282
+ replacementStart = node.getStart() + 1;
283
+ } else {
284
+ const dirPortion = pathPortion.substring(0, lastSlash);
285
+ prefix = pathPortion.substring(lastSlash + 1);
286
+ replacementStart = node.getStart() + 1 + lastSlash + 1;
287
+ if ((dirPortion.startsWith('/') || dirPortion === '' && pathPortion.startsWith('/')) && baseDir) {
288
+ dirPath = baseDir + dirPortion;
289
+ } else if ((dirPortion.startsWith('./') || dirPortion === '' && pathPortion.startsWith('./')) && baseDir) {
290
+ dirPath = baseDir + '/' + dirPortion.substring(2);
291
+ } else if (program) {
292
+ dirPath = resolveToDir(ts, dirPortion, node.getSourceFile().fileName, program.getCompilerOptions());
293
+ }
294
+ }
295
+ if (!dirPath) {
296
+ return undefined;
297
+ }
298
+ if (!sys.directoryExists(dirPath)) {
299
+ return undefined;
300
+ }
301
+ const entries = [];
302
+ const prefixLower = prefix.toLowerCase();
303
+ for (const dir of sys.getDirectories(dirPath)){
304
+ if (dir.startsWith('.') || dir === 'node_modules') {
305
+ continue;
306
+ }
307
+ if (prefix && !dir.toLowerCase().startsWith(prefixLower)) {
308
+ continue;
309
+ }
310
+ entries.push({
311
+ name: dir,
312
+ kind: 'directory',
313
+ replacementSpan: {
314
+ length: prefix.length,
315
+ start: replacementStart
316
+ },
317
+ sortText: '0' + dir
318
+ });
319
+ }
320
+ const files = sys.readDirectory(dirPath, COMPONENT_EXTENSIONS, undefined, undefined, 1);
321
+ for (const file of files){
322
+ const fileName = file.substring(file.lastIndexOf('/') + 1);
323
+ const nameWithoutExt = fileName.replace(/\.(?:tsx?|jsx?)$/, '');
324
+ if (prefix && !fileName.toLowerCase().startsWith(prefixLower)) {
325
+ continue;
326
+ }
327
+ entries.push({
328
+ name: fileName,
329
+ kind: 'script',
330
+ replacementSpan: {
331
+ length: prefix.length,
332
+ start: replacementStart
333
+ },
334
+ sortText: '1' + fileName
335
+ });
336
+ if (nameWithoutExt !== fileName) {
337
+ entries.push({
338
+ name: nameWithoutExt,
339
+ kind: 'script',
340
+ replacementSpan: {
341
+ length: prefix.length,
342
+ start: replacementStart
343
+ },
344
+ sortText: '1' + nameWithoutExt
345
+ });
346
+ }
347
+ }
348
+ if (entries.length === 0) {
349
+ return undefined;
350
+ }
351
+ return {
352
+ entries,
353
+ isGlobalCompletion: false,
354
+ isMemberCompletion: false,
355
+ isNewIdentifierLocation: true
356
+ };
357
+ }
358
+ // -------------------------------------------------------------------
359
+ // Go-to-definition
360
+ // -------------------------------------------------------------------
361
+ function getPayloadDefinition(ts, node, checker, program, baseDir) {
362
+ const context = (0, _helpers.getPayloadComponentContext)(ts, node, checker);
363
+ if (!context) {
364
+ return undefined;
365
+ }
366
+ const component = parsePayloadComponent(context, node.text);
367
+ if (!component?.path) {
368
+ return undefined;
369
+ }
370
+ const { exportName, path: modulePath } = component;
371
+ const resolved = resolveModulePath(ts, modulePath, node.getSourceFile().fileName, program, baseDir);
372
+ if (!resolved) {
373
+ return undefined;
374
+ }
375
+ const targetSourceFile = program.getSourceFile(resolved.resolvedFileName);
376
+ if (!targetSourceFile) {
377
+ return undefined;
378
+ }
379
+ const textSpan = {
380
+ length: node.text.length,
381
+ start: node.getStart() + 1
382
+ };
383
+ const moduleSymbol = checker.getSymbolAtLocation(targetSourceFile);
384
+ if (moduleSymbol) {
385
+ const moduleExports = checker.getExportsOfModule(moduleSymbol);
386
+ const targetExport = moduleExports.find((e)=>e.name === exportName);
387
+ if (targetExport) {
388
+ const declarations = targetExport.getDeclarations();
389
+ if (declarations && declarations.length > 0) {
390
+ const decl = declarations[0];
391
+ const declSourceFile = decl.getSourceFile();
392
+ return {
393
+ definitions: [
394
+ {
395
+ name: exportName,
396
+ containerKind: ts.ScriptElementKind.moduleElement,
397
+ containerName: modulePath,
398
+ contextSpan: {
399
+ length: decl.getWidth(),
400
+ start: decl.getStart()
401
+ },
402
+ fileName: declSourceFile.fileName,
403
+ kind: ts.ScriptElementKind.alias,
404
+ textSpan: {
405
+ length: decl.getWidth(),
406
+ start: decl.getStart()
407
+ }
408
+ }
409
+ ],
410
+ textSpan
411
+ };
412
+ }
413
+ }
414
+ }
415
+ return {
416
+ definitions: [
417
+ {
418
+ name: modulePath,
419
+ containerKind: ts.ScriptElementKind.unknown,
420
+ containerName: '',
421
+ fileName: resolved.resolvedFileName,
422
+ kind: ts.ScriptElementKind.moduleElement,
423
+ textSpan: {
424
+ length: 0,
425
+ start: 0
426
+ }
427
+ }
428
+ ],
429
+ textSpan
430
+ };
431
+ }
432
+ /**
433
+ * Uses TypeScript's module resolution to determine the absolute directory a
434
+ * module specifier maps to. Works for tsconfig `paths`, `node_modules`, or
435
+ * any other resolution strategy TypeScript supports.
436
+ */ function resolveToDir(ts, modulePath, containingFile, compilerOptions) {
437
+ const sentinel = '__payload_resolve_dir';
438
+ const result = ts.resolveModuleName(modulePath + '/' + sentinel, containingFile, compilerOptions, ts.sys);
439
+ for (const loc of result.failedLookupLocations ?? []){
440
+ const idx = loc.indexOf(sentinel);
441
+ if (idx > 0) {
442
+ return loc.substring(0, idx - 1);
443
+ }
444
+ }
445
+ return undefined;
446
+ }
447
+ // -------------------------------------------------------------------
448
+ // baseDir detection
449
+ // -------------------------------------------------------------------
450
+ const PAYLOAD_CONFIG_NAMES = [
451
+ 'payload.config.ts',
452
+ 'payload.config.js',
453
+ 'config.ts'
454
+ ];
455
+ function findPayloadConfigDir(sys, fromFile) {
456
+ let dir = fromFile.includes('/') ? fromFile.substring(0, fromFile.lastIndexOf('/')) : fromFile;
457
+ const root = dir.startsWith('/') ? '/' : '';
458
+ for(let i = 0; i < 50; i++){
459
+ for (const name of PAYLOAD_CONFIG_NAMES){
460
+ if (sys.fileExists(dir + '/' + name)) {
461
+ return dir;
462
+ }
463
+ }
464
+ const parent = dir.substring(0, dir.lastIndexOf('/')) || root;
465
+ if (parent === dir) {
466
+ break;
467
+ }
468
+ dir = parent;
469
+ }
470
+ return undefined;
471
+ }
472
+ module.exports = init;
473
+
474
+ //# sourceMappingURL=index.js.map