@lcap/nasl 3.6.3-alpha.3 → 3.6.3-alpha.4

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 (36) hide show
  1. package/out/generator/genBundleFiles.js.map +1 -1
  2. package/out/generator/permission.js +4 -1
  3. package/out/generator/permission.js.map +1 -1
  4. package/out/generator/release-body/body.js +1 -2
  5. package/out/generator/release-body/body.js.map +1 -1
  6. package/out/generator/release-body/data.js +2 -2
  7. package/out/generator/release-body/data.js.map +1 -1
  8. package/out/generator/release-body/types.d.ts +2 -2
  9. package/out/generator/release-body/utils.d.ts +1 -1
  10. package/out/generator/release-body/utils.js.map +1 -1
  11. package/out/natural/genNaturalTS.js +1 -1
  12. package/out/natural/genNaturalTS.js.map +1 -1
  13. package/out/natural/prompt/analyzeClaims.js +4 -0
  14. package/out/natural/prompt/analyzeClaims.js.map +1 -1
  15. package/out/natural/prompt/analyzeTasks.js +12 -11
  16. package/out/natural/prompt/analyzeTasks.js.map +1 -1
  17. package/out/natural/prompt/executeClaims.js +5 -1
  18. package/out/natural/prompt/executeClaims.js.map +1 -1
  19. package/out/natural/transformTSCode.js +14 -14
  20. package/out/natural/transformTSCode.js.map +1 -1
  21. package/out/server/naslServer.js +30 -3
  22. package/out/server/naslServer.js.map +1 -1
  23. package/package.json +1 -1
  24. package/sandbox-natural/stdlib/nasl.core.ts +1 -4
  25. package/src/generator/genBundleFiles.ts +2 -2
  26. package/src/generator/permission.ts +3 -1
  27. package/src/generator/release-body/body.ts +1 -2
  28. package/src/generator/release-body/data.ts +2 -2
  29. package/src/generator/release-body/types.ts +2 -2
  30. package/src/generator/release-body/utils.ts +2 -2
  31. package/src/natural/genNaturalTS.ts +1 -1
  32. package/src/natural/prompt/analyzeClaims.ts +4 -0
  33. package/src/natural/prompt/analyzeTasks.ts +12 -11
  34. package/src/natural/prompt/executeClaims.ts +5 -1
  35. package/src/natural/transformTSCode.ts +14 -14
  36. package/src/server/naslServer.ts +29 -3
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lcap/nasl",
3
3
  "description": "NetEase Application Specific Language",
4
- "version": "3.6.3-alpha.3",
4
+ "version": "3.6.3-alpha.4",
5
5
  "author": "Forrest <rainforest92@126.com>",
6
6
  "scripts": {
7
7
  "clear": "rimraf ./out",
@@ -15,10 +15,7 @@ class DateTime {
15
15
  type List<T> = Array<T>;
16
16
 
17
17
  interface Entity<T> {
18
- /**
19
- * 只能获取一条
20
- */
21
- get(id: Integer): T;
18
+ get(id: Integer): T; // 只能获取一条 Entity 数据,返回一个 Entity 对象
22
19
  create(entity: T): T;
23
20
  update(entity: T): T;
24
21
  delete(id: Integer): void;
@@ -625,8 +625,8 @@ export function genBundleFiles(app: App, frontend: Frontend, config: Config) {
625
625
  `;
626
626
  content += str;
627
627
  }
628
- const getBundleFileName =()=>{
629
- if (config.isPreviewFe && config.previewVersion){
628
+ const getBundleFileName = ()=> {
629
+ if (config.isPreviewFe && config.previewVersion) {
630
630
  return `mockBundle-${config.previewVersion}`
631
631
  }
632
632
  return 'bundle'
@@ -278,7 +278,7 @@ function checkUploadAuth(uploaders: Map<string, ViewElement[]>) {
278
278
  uploaders.forEach((value, key) => {
279
279
  const authValue: ResourceNode[] = [];
280
280
  value.map((node) => {
281
- if (node instanceof ViewElement) {
281
+ if (node instanceof ViewElement && node.view) {
282
282
  const path = node.auth ? node.authPath : `${node.view.path}`;
283
283
  const type = node.auth ? 'component' : 'page';
284
284
  authValue.push({ path, type });
@@ -297,6 +297,8 @@ function checkPageAndUploadAuth(uploaders: Map<string, ViewElement[]>, key: stri
297
297
  if (!(node.getAncestor('View') as View).auth && node instanceof ViewElement && !node.auth) {
298
298
  return true;
299
299
  }
300
+ } else if (node.getAncestor('BusinessComponent')) {
301
+ return true;
300
302
  }
301
303
  });
302
304
  return flag;
@@ -50,8 +50,7 @@ async function getFrontendBundleFiles(app: App, opt: InternalReleaseData) {
50
50
  await opt.logPublishFunc?.('代码', '生成页面代码:开始');
51
51
  files = await genFrontendBundleFiles(app, opt.frontends, {
52
52
  ...opt.appInfo,
53
- env: opt.env,
54
- debug: opt.debug,
53
+ ...opt,
55
54
  appid: app.id,
56
55
  devDnsAddr: (app as any).devDnsAddr,
57
56
  miniEnable: (app as any).miniEnable,
@@ -35,7 +35,7 @@ export async function getReleaseData(app: App, data: ReleaseData, naslServer: Na
35
35
  isExport: data.config.mode === ReleaseMode.ExportCode,
36
36
  isPreviewFe: data.config.mode === ReleaseMode.ExportTemplate,
37
37
  ignoreFiles: data.config.ignoreFiles ?? false,
38
- previewVersion: data.config.releaseVersion,
38
+ previewVersion: data.config.previewVersion ?? '',
39
39
  appSpecification: data.appSpecification,
40
40
  frontends: releaseFrontends,
41
41
  validations: {},
@@ -56,7 +56,7 @@ export async function getReleaseData(app: App, data: ReleaseData, naslServer: Na
56
56
 
57
57
  // 服务端验证规则
58
58
  if (app.preferenceMap.onDemandInterfaceGeneration !== 'false') {
59
- result.validations = await getValidationRules(http, version, releaseFrontends);
59
+ result.validations = await getValidationRules(http, version, app.frontendTypes);
60
60
 
61
61
  if (typeof result.validations === 'string') {
62
62
  throw new Error(result.validations);
@@ -27,8 +27,8 @@ export interface ReleaseConfig {
27
27
  mode: ReleaseMode;
28
28
  /** 忽略前端文件 */
29
29
  ignoreFiles?: boolean;
30
- /** 发布版本 */
31
- releaseVersion?: string;
30
+ /** 预览版本 */
31
+ previewVersion?: string;
32
32
  /** 调试模式 */
33
33
  debug?: boolean;
34
34
  /**
@@ -202,9 +202,9 @@ export async function getVersionDetail(axios: AxiosInstance, app: any) {
202
202
  };
203
203
  }
204
204
 
205
- export async function getValidationRules(axios: AxiosInstance, ideVersion: string, frontends: Frontend[]) {
205
+ export async function getValidationRules(axios: AxiosInstance, ideVersion: string, frontends: FrontendType[]) {
206
206
  const formData = new FormData();
207
- formData.append('file', new Blob([JSON.stringify(frontends.map((view: any) => view.toJSON()))], { type: 'application/json' }));
207
+ formData.append('file', new Blob([JSON.stringify(frontends.map((view) => view.toJSON()))], { type: 'application/json' }));
208
208
  const validations = await axios<HttpData>({
209
209
  method: 'post',
210
210
  url: `/api/v1/ide/nasl/frontend/call-logic/validations/batch`,
@@ -432,7 +432,7 @@ export function genNaturalTSContext(app: App, currentNode?: BaseNode, focusedNod
432
432
  code += '\n### [6]服务端逻辑\n';
433
433
  code += getLogics(app, currentNode, moduleIndexList).code;
434
434
 
435
- code += '\n### [7]可调用的开放接口列表\n';
435
+ code += '\n### [7]可调用的接口列表\n';
436
436
  code += getModuleInterfaces(app, state, moduleIndexList).code;
437
437
 
438
438
  if (app?.connections?.length > 0 && logicType === 'global_logic') {
@@ -3,9 +3,12 @@ export const analyzeClaims = (params: any) => {
3
3
  const claims = `
4
4
  - Knowledge 是你的知识库,你可以参考,但是你最终制定的计划中禁止包含方法或者函数名
5
5
  - 如果用户没有特别指明是打印(日志/输出结果),"输出结果"一律按照"返回输出结果"处理
6
+ - 涉及到查询、获取数据时,先查找当前上下文[6/7/8/9]中是否有相关的方法,如果没有,再考虑实体的方法
7
+ - 实体的 get 方法一次只能获取一条数据,返回一个对象,无法返回列表。
6
8
  - 如果用户的需求涉及定时或延时等操作,请提示用户:当前暂不支持定时或延时操作,请调整后重新输入。
7
9
  - 如果用户的需求需要调用某个方法并且当前上下文中不存在时,请提示用户:当前应用中暂无该方法,请先导入相关依赖库或连接器模块
8
10
  - 例如:加解密依赖库中的方法
11
+ - 如果用户的需求需要调用接口并且当前上下文中不存在此接口时,不需要再跟用户对话,直接返回 needImportInterface: true; executable: true; 以及 plan
9
12
  `;
10
13
  // global_logic、view_logic、event_logic、business_Logic
11
14
  const claimsMap = {
@@ -19,6 +22,7 @@ export const analyzeClaims = (params: any) => {
19
22
  - 分析用户的需求,当需要从实体中获取或者查询数据时
20
23
  - 优先使用 SQL 的查询和数据操纵能力: 例如 JOIN、SUM、GROUP_BY 等能力
21
24
  - 使用 SQL 语句同时实现查询和计算
25
+ - 如果用户的需求需要调用接口并且当前上下文中不存在此接口时,不需要再跟用户对话,直接返回 needImportInterface: true; executable: true; 以及 plan
22
26
  `
23
27
  } as any;
24
28
  return claimsMap?.[logicType] || claims;
@@ -1,15 +1,16 @@
1
1
  export const analyzeTasks = () => {
2
2
  return `
3
- - plan:
4
- - 尽可能的帮助用户将需求梳理成可执行的计划,计划包含多个任务,每个任务下可能包含多个子任务(会缩进 4 个空格)
5
- - 制定的计划最终将会作为调用代码补全接口的输入, 所以你需要考虑计划内容是否完整与充分, 如果不充分,你可以继续询问用户
6
- - text: 如果你认为需求不够明确时,可以继续询问用户需求的细节,不可为空
7
- - executable
8
- - 类型为 boolean, 如果你认为需求比较明确并且 plan 可执行, 返回 true, 否则返回 false
9
- - moduleIndexList
10
- - 类型为 Array, 你需要根据用户的执行计划,从 Context Definition 中整理出执行需要用到的模块,返回对应的模块索引
11
- - 用于下一步的具体实施,需要尽可能详细、精准的返回和执行计划相关的模块索引。例如:"moduleIndexList": ['1','6-3','8-1-1-0']。
12
- - needImportInterface
13
- - 类型为 boolean, 如果你认为当前上下文无法满足需求,需要另外引入开放接口, 返回 true, 否则返回 false
3
+ - plan:
4
+ - 尽可能的帮助用户将需求梳理成可执行的计划,计划包含多个任务,每个任务下可能包含多个子任务(会缩进 4 个空格)
5
+ - 制定的计划最终将会作为调用代码补全接口的输入, 所以你需要考虑计划内容是否完整与充分, 如果不充分,你可以继续询问用户
6
+ - text: 如果你认为需求不够明确时,可以继续询问用户需求的细节,不可为空
7
+ - executable
8
+ - 类型为 boolean, 如果你认为需求比较明确并且 plan 可执行, 返回 true, 否则返回 false
9
+ - moduleIndexList
10
+ - 类型为 Array, 你需要根据用户的执行计划,从 Context Definition 中整理出执行需要用到的模块或者方法,返回对应的索引
11
+ - 用于下一步的具体实施,需要尽可能详细、精准的返回和执行计划相关的模块或方法索引。例如:"moduleIndexList": ['1','6-3','8-1-1-0']。
12
+ - needImportInterface
13
+ - 类型为 boolean, 如果你认为当前上下文无法满足需求,需要另外引入接口, 返回 true, 否则返回 false
14
+ - 如果用户的需求需要调用接口并且当前上下文中不存在此接口时,不需要再跟用户对话,直接返回 needImportInterface: true; executable: true; 以及 plan
14
15
  `;
15
16
  };
@@ -24,8 +24,11 @@ export const executeClaims = (params: any) => {
24
24
  - 禁止使用 for/forEach 语句,如果需要循环或者遍历,你**必须**使用 ForEach 方法
25
25
  - 禁止频繁操作实体
26
26
  - 只获取单条数据时使用 namespace.Entity.get()
27
+ - namespace.Entity.get 是一个整体,禁止将 namespace 赋值给变量
27
28
  - 字符串或者变量之间的拼接或者 concat 请使用字符串插值(模板字符串)语法
28
- - 需要使用 nasl.ui 中类的方法时,请使用 $refs 的前缀,例如 $refs.tableView1.reload(),禁止使用 new 创建实例
29
+ - 需要使用 nasl.ui 中类的方法时,请使用 $refs 的前缀,例如 $refs.tableView1.reload()
30
+ - 禁止将 $ref 实例赋值给变量
31
+ - 禁止使用 new 创建实例
29
32
  - 直接输出代码结果,其他描述请以注释的形式出现
30
33
  - 返回值
31
34
  - 如果用户没有特别指明是打印(日志/输出结果),"输出结果"一律按照"返回输出结果"处理
@@ -58,6 +61,7 @@ export const executeClaims = (params: any) => {
58
61
  - 分析用户的需求,优先使用数据库的查询和数据操纵能力,例如 JOIN、SUM、GROUP_BY 等能力,使用 SQL 语句同时实现查询和计算
59
62
  - 如果要查询,则使用 nasl.oql.query,同时分析整个需求,尽量用一句 SQL 实现
60
63
  - 只查询单条数据时使用 namespace.Entity.get(),其它查询都使用 nasl.oql.query
64
+ - namespace.Entity.get 是一个整体,禁止将 namespace 赋值给变量
61
65
  - 禁止对 nasl.oql.query 的结果进行连续调用
62
66
  - 字符串或者变量之间的拼接或者 concat 请使用字符串插值(模板字符串)语法
63
67
  - 直接输出代码结果,其他描述请以注释的形式出现
@@ -342,7 +342,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
342
342
  return new naslTypes.CallLogic({
343
343
  calleeNamespace: `elements.${(callee[1] as babelTypes.Identifier).name}.logics`,
344
344
  calleeName: (callee[2] as babelTypes.Identifier).name,
345
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
345
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
346
346
  expression: transformLogicNode(arg),
347
347
  })) as naslTypes.Argument[],
348
348
  });
@@ -352,7 +352,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
352
352
  return new naslTypes.CallLogic({
353
353
  calleeNamespace: `app.dataSources.defaultDS.entities.${entityName}.logics`,
354
354
  calleeName: (callee[1] as babelTypes.Identifier).name,
355
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
355
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
356
356
  expression: transformLogicNode(arg),
357
357
  })) as naslTypes.Argument[],
358
358
  });
@@ -375,7 +375,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
375
375
  calleeNamespace: 'nasl.util',
376
376
  calleeName: 'consoleLog',
377
377
  shortcut: true,
378
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
378
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
379
379
  expression: transformLogicNode(arg),
380
380
  })) as naslTypes.Argument[],
381
381
  });
@@ -384,7 +384,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
384
384
  calleeNamespace: 'nasl.logging',
385
385
  calleeName: 'INFO',
386
386
  shortcut: true,
387
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
387
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
388
388
  expression: transformLogicNode(arg),
389
389
  })) as naslTypes.Argument[],
390
390
  });
@@ -395,7 +395,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
395
395
  calleeNamespace: 'nasl.util',
396
396
  calleeName: curCalleeName,
397
397
  shortcut: true,
398
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
398
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
399
399
  expression: transformLogicNode(arg),
400
400
  })) as naslTypes.Argument[],
401
401
  typeArguments: node?.typeParameters?.params.map((curType: any) => transformTypeAnnotation({ ...curType })),
@@ -454,7 +454,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
454
454
  * @param node
455
455
  * @returns
456
456
  */
457
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
457
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
458
458
  expression: transformLogicNode(arg),
459
459
  })) as naslTypes.Argument[],
460
460
  });
@@ -465,7 +465,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
465
465
  calleeName: 'ListTransform',
466
466
  arguments: [new naslTypes.Argument({
467
467
  expression: transformLogicNode((node.callee as babelTypes.MemberExpression).object),
468
- }), ...node.arguments.map((arg: any) => new naslTypes.Argument({
468
+ }), ...node?.arguments?.map((arg: any) => new naslTypes.Argument({
469
469
  expression: transformLogicNode(arg),
470
470
  }))],
471
471
  });
@@ -517,7 +517,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
517
517
  calleeNamespace: 'nasl.ui',
518
518
  calleeName: 'showMessage',
519
519
  shortcut: true,
520
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
520
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
521
521
  expression: transformLogicNode(arg),
522
522
  })) as naslTypes.Argument[],
523
523
  });
@@ -528,7 +528,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
528
528
  return new naslTypes.CallLogic({
529
529
  calleeNamespace: `${calleeNamespace}.${entityName}.logics`,
530
530
  calleeName: (node?.callee as any)?.property?.name,
531
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
531
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
532
532
  expression: transformLogicNode(arg),
533
533
  })) as naslTypes.Argument[],
534
534
  });
@@ -537,7 +537,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
537
537
  return new naslTypes.CallLogic({
538
538
  calleeNamespace: generate((node.callee as any).object).code,
539
539
  calleeName: (callee[callee.length - 1] as babelTypes.Identifier).name,
540
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
540
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
541
541
  expression: transformLogicNode(arg),
542
542
  })) as naslTypes.Argument[],
543
543
  });
@@ -546,7 +546,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
546
546
  return new naslTypes.CallLogic({
547
547
  calleeNamespace: '',
548
548
  calleeName: calleeName.slice('viewLogic_'.length),
549
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
549
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
550
550
  expression: transformLogicNode(arg),
551
551
  })) as naslTypes.Argument[],
552
552
  });
@@ -554,7 +554,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
554
554
  return new naslTypes.CallLogic({
555
555
  calleeNamespace: `app.logics`,
556
556
  calleeName,
557
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
557
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
558
558
  expression: transformLogicNode(arg),
559
559
  })) as naslTypes.Argument[],
560
560
  });
@@ -562,7 +562,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
562
562
  return new naslTypes.CallInterface({
563
563
  calleeNamespace: generate((node.callee as any).object).code,
564
564
  calleeName: (callee[callee.length - 1] as babelTypes.Identifier).name,
565
- arguments: node.arguments.map((arg: any) => arg?.properties.map((item: any) => new naslTypes.Argument({
565
+ arguments: node?.arguments?.map((arg: any) => arg?.properties.map((item: any) => new naslTypes.Argument({
566
566
  keyword: item?.key?.name,
567
567
  expression: transformLogicNode(item?.value),
568
568
  }))).flat() as naslTypes.Argument[],
@@ -583,7 +583,7 @@ export function transformTSCode(tsCode: string, contextLogicName: string, type?:
583
583
  calleeNamespace: generate((node?.callee as any)?.object)?.code,
584
584
  calleeName: (callee?.[callee?.length - 1] as babelTypes.Identifier)?.name,
585
585
  handleError: true,
586
- arguments: node.arguments.map((arg) => new naslTypes.Argument({
586
+ arguments: node?.arguments?.map((arg) => new naslTypes.Argument({
587
587
  expression: transformLogicNode(arg),
588
588
  })) as naslTypes.Argument[],
589
589
  });
@@ -3022,9 +3022,9 @@ class NaslServer {
3022
3022
  const groupByLength = callQueryComponent.groupBy.filter(
3023
3023
  (item) => (item.groupElement as QueryFieldExpression)?.propertyName && (item.groupElement as QueryFieldExpression).asName
3024
3024
  ).length;
3025
- if (!groupByLength && !aggregateLength && callQueryComponentTypeAnnotation.typeKind === 'anonymousStructure') {
3025
+ if (!groupByLength && !aggregateLength && callQueryComponentTypeAnnotation.typeKind === 'generic') {
3026
3026
  // 拿到 List 的泛型(匿名数据结构)的所有属性
3027
- const {properties} = callQueryComponentTypeAnnotation.properties[0].typeAnnotation.typeArguments[0];
3027
+ const {properties} = callQueryComponentTypeAnnotation.typeArguments[0];
3028
3028
  const targetProperty = properties.find((p) => p.name === utils.firstLowerCase(node.name));
3029
3029
  if (!targetProperty) {
3030
3030
  continue;
@@ -3450,6 +3450,32 @@ class NaslServer {
3450
3450
  const newTextValue = node.parentNode.name === 'defaultDS' ? `/api/${newName}/import` : `/api/${node.parentNode.name}/${newName}/import`;
3451
3451
  minRange.setTypeMethods = 'setUrlValue';
3452
3452
  minRange.newValue = newTextValue;
3453
+ } else if (minRange.node instanceof BindAttribute && (minRange.node.name === 'valueField')) {
3454
+ // eslint-disable-next-line no-confusing-arrow
3455
+ minRange.newValue = (minRange.node.value || '').split('.').map((v, i) => i ? v : newValue.charAt(0).toLowerCase() + newValue.slice(1)).join('.')
3456
+ minRange.setTypeMethods = 'setValue';
3457
+ } else if (minRange.node instanceof BindAttribute && (minRange.node.name === 'sorting') && minRange.node.value) {
3458
+ // 现在 sorting 是不把 field 翻译出具体实体类型的,在文件系统中没有引用关系,无法处理他的改名
3459
+ try {
3460
+ // "{ field: undefined, order: 'desc' }" 格式解析成 Object
3461
+ const sortingObj = JSON.parse(
3462
+ minRange.node.value
3463
+ .replace(/([{,])\s*([A-Za-z0-9_]+)\s*:/g, '$1"$2":')
3464
+ .replace(/undefined/g, 'null')
3465
+ .replace(/'/g, '"')
3466
+ )
3467
+ if (sortingObj.field) {
3468
+ const handleValue = (value: any) => {
3469
+ return value ? `'${value}'` : undefined
3470
+ }
3471
+ // eslint-disable-next-line no-confusing-arrow
3472
+ const newField = sortingObj.field.split('.').map((v: string, i: number) => i ? v: newValue.charAt(0).toLowerCase() + newValue.slice(1)).join('.')
3473
+ minRange.newValue = `{ field: ${handleValue(newField)}, order: ${handleValue(sortingObj.order)} }`
3474
+ minRange.setTypeMethods = 'setValue';
3475
+ }
3476
+ } catch (error) {
3477
+ console.error(error)
3478
+ }
3453
3479
  } else if (minRange.node instanceof Identifier) {
3454
3480
  minRange.newValue = utils.firstLowerCase(newValue);
3455
3481
  }
@@ -4042,7 +4068,7 @@ class NaslServer {
4042
4068
 
4043
4069
  if (['BindAttribute', 'BindDirective', 'BindStyle'].includes(node.concept)) {
4044
4070
  range.line = lsp2tspNumber(currentSource.end.line);
4045
- range.offset = 0;
4071
+ range.offset = 1;
4046
4072
  }
4047
4073
 
4048
4074
  return this._getFieldKeySelectCompletion({