如何从 npm 脚本中获取对象参数(NodeJS + TypeScript)

huangapple go评论126阅读模式
英文:

How to get object argument from npm script (NodeJS + TypeScript)

问题

我想通过NPM脚本传递一个对象,如下所示:

"update-user-roles": "ts-node user-roles.ts {PAID_USER: true, VIP: true}"

我的函数接收到对象,但会不断添加额外的逗号,因此无法正确更新用户。我该如何接收原样的对象?

async function updateUserRoles(roles: any) {
    const userID = await getAuth().then((res) => res.uid);
    updateUser({
        userID: userID,
        fields: {
            roles: {
                roles
            },
        }
    })
    console.log(`User roles successfully added: ${roles}`)
}

const rolesString = JSON.stringify(process.argv.slice(2))
updateUserRoles(JSON.parse(rolesString))

我收到以下消息:

User roles successfully added: {PAID_USER:,true,,VIP:,true}
英文:

I want to pass an object via NPM script like

  "update-user-roles": "ts-node user-roles.ts {PAID_USER: true, VIP: true}"

My function picks up the object but keeps adding additional commas so it's not updating the user correctly. How do I receive the object as is?

async function updateUserRoles(roles: any) {
    const userID = await getAuth().then((res) => res.uid);
    updateUser({
        userID: userID,
        fields: {
            roles: {
                roles
            },
        }
    })
    console.log(`User roles successfully added: ${roles}`)
}

const rolesString = JSON.stringify(process.argv.slice(2))
updateUserRoles(JSON.parse(rolesString))

I get the following message:

User roles successfully added: {PAID_USER:,true,,VIP:,true}

答案1

得分: 1

以下是翻译好的部分:

原因是Node.js会在空格处拆分命令行参数,所以你得到逗号,process.argv 数组会像这样:

process.argv 属性返回一个包含在启动Node.js进程时传递的命令行参数的数组。

选项1. 传递JSON字符串

$ npx ts-node ./index.ts '{ "PAID_USER": true, "VIP": true }'

index.ts

console.log(process.argv);
console.log(JSON.parse(process.argv.slice(2)[0]));

输出:

[
  '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  '/home/lindu/workspace/project/index.ts',
  '{ "PAID_USER": true, "VIP": true }'
]
{ PAID_USER: true, VIP: true }

选项2. 传递字符串并将其解析为JSON字符串。

npx ts-node ./index.ts '{PAID_USER: true, VIP: true}'

index.ts:

console.log(process.argv);

const arg = process.argv.slice(2)[0];
const obj = JSON.parse(JSON.stringify(eval('('+arg+')')));
console.log(obj, typeof obj, obj.PAID_USER, obj.VIP);

输出:

[
  '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  '/home/lindu/workspace/project/index.ts',
  '{PAID_USER: true, VIP: true}'
]
{ PAID_USER: true, VIP: true } object true true

选项3. 使用 minimistjs 包。

英文:

The reason why you got comma , is because Nodejs will split command-line arguments at whitespace. The process.argv array will be like this:

[
  '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  '/home/lindu/workspace/project/index.ts',
  '{PAID_USER:',
  'true,',
  'VIP:',
  'true}'
]

> The process.argv property returns an array containing the command-line arguments passed when the Node.js process was launched.

Option 1. Pass a JSON string

$ npx ts-node ./index.ts '{"PAID_USER": true, "VIP": true}'

index.ts

console.log(process.argv);
console.log(JSON.parse(process.argv.slice(2)[0]));

Output:

[
  '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  '/home/lindu/workspace/project/index.ts',
  '{"PAID_USER": true, "VIP": true}'
]
{ PAID_USER: true, VIP: true }

Option 2. Pass a string and parse it to a JSON string.

npx ts-node ./index.ts '{PAID_USER: true, VIP: true}'

index.ts:

console.log(process.argv);

const arg = process.argv.slice(2)[0];
const obj = JSON.parse(JSON.stringify(eval('(' + arg + ')')));
console.log(obj, typeof obj, obj.PAID_USER, obj.VIP);

Output:

[
  '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  '/home/lindu/workspace/project/index.ts',
  '{PAID_USER: true, VIP: true}'
]
{ PAID_USER: true, VIP: true } object true true

Option 3. Use minimistjs package.

答案2

得分: 0

我们可以使用双引号来包裹这个对象。

"update-user-roles": "ts-node user-roles.ts \"{\\\"PAID_USER\\\": true, \\\"VIP\\\": true}\""

之后:

async function updateUserRoles(rolesString: string) {
  const roles = JSON.parse(rolesString);
  const userID = await getAuth().then((res) => res.uid);
  updateUser({
    userID: userID,
    fields: {
      roles: roles
    }
  });
  console.log(`用户角色已成功添加:${JSON.stringify(roles)}`);
}

它应该能正常工作。

英文:

We can use double quotes to wrap the object.

"update-user-roles": "ts-node user-roles.ts \"{\\\"PAID_USER\\\": true, \\\"VIP\\\": true}\""

After that:

async function updateUserRoles(rolesString: string) {
  const roles = JSON.parse(rolesString);
  const userID = await getAuth().then((res) => res.uid);
  updateUser({
    userID: userID,
    fields: {
      roles: roles
    }
  });
  console.log(`User roles successfully added: ${JSON.stringify(roles)}`);
}

It should work.

答案3

得分: 0

如您可能已经注意到,您并未传递一个真实的对象作为参数,而是一个不是有效的 JSON 的字符串。

首先,参数必须包装和转义(\"{...}\"),以防止它被空格分割。

接下来是两个辅助函数。一个用于使用键来读取参数(myObject)。第二个用于将字符串转换为对象(伪 JSON)。

"update-user-roles": "ts-node user-roles.ts myObject=\"{PAID_USER: true, VIP: true}\""

以下是最小的 JavaScript 功能。

const args = process.argv.slice(2).reduce((acc, arg) => {
	let [k, v = true] = arg.split('=');
	acc[k] = v;
	return acc;
}, {});

console.log(args) // { myObject: '{PAID_USER: true, VIP: true}' }

const parseJSON = obj => Function('"use strict";return (' + obj + ')')();

const myObject = parseJSON(args.myObject); // { PAID_USER: true, VIP: true }

然后,您的函数调用将是:

updateUserRoles(myObject);
英文:

As you may have noticed, you are not passing in a real object as a parameter, but a string that is not a valid json.

First, the parameter must be wrapped and escaped (\"{...}\") so that it is not split up by the blanks.

Here then come two helper functions. One to read out the parameter using a key (myObject). And the second to make an object out of the string (fake json).

"update-user-roles": "ts-node user-roles.ts myObject=\"{PAID_USER: true, VIP: true}\""

And here is the minimal JavaScript functionality.

const args = process.argv.slice(2).reduce((acc, arg) => {
	let [k, v = true] = arg.split('=');
	acc[k] = v;
	return acc;
}, {});

console.log(args) // { myObject: '{PAID_USER: true, VIP: true}' }

const parseJSON = obj => Function('"use strict";return (' + obj + ')')();

const myObject = parseJSON(args.myObject); // { PAID_USER: true, VIP: true }

Your function call would then be

updateUserRoles(myObject);

答案4

得分: 0

我无法让这些答案中的任何一个起作用,最终使用以下方法找到了解决方案:

脚本:

"ts-node user-roles.ts '{\"PAID_USER\": true, \"VIP\": true}'"

使用JSON.parse将对象字符串解析回对象并传递给函数:

const objArgStr = process.argv[2];

if (!objArgStr) {
  console.error('未提供参数。');
  process.exit(1);
}

const objArg = JSON.parse(objArgStr);
console.log('对象参数:', objArg);

updateUserRoles(objArg);
英文:

I couldn't get any of these answers to work, finally got a solution using the following:

The script:

"ts-node user-roles.ts '{\"PAID_USER\": true, \"VIP\": true}'"

Parse the object string back into an object using JSON.parse and pass to function:

const objArgStr = process.argv[2];

if (!objArgStr) {
  console.error('No argument provided.');
  process.exit(1);
}

const objArg = JSON.parse(objArgStr);
console.log('Object argument: ', objArg);

updateUserRoles(objArg)

答案5

得分: 0

问题在于Node.js将参数视为字符串,并按空格拆分它们,所以roles看起来像这样:

[
  "{PAID_USER:",
  "true,",
  "VIP:",
  "true}"
]

此外,这不是JSON字符串。您必须将其转换为JSON并用引号括起来,以便Node.js将整个内容视为一个参数:

ts-node user-roles.ts "{\"PAID_USER\": true, \"VIP\": true}"

不要忘记在字符串中转义引号!!

user-roles.ts中:

const rolesString = process.argv.slice(2)[0]
updateUserRoles(JSON.parse(rolesString))

因为process.argv.slice(2)返回一个数组,所以您需要获取第一个参数。您也不需要使用JSON.stringify()。可以简化为:

updateUserRoles(JSON.parse(process.argv.slice[2]))
英文:

The problem is that Node.js treats arguments as string and splits them by whitespace, so roles looks something like this:

[
  "{PAID_USER:",
  "true,",
  "VIP:",
  "true}"
]

Also, it's not a JSON string. You have to turn that to JSON and wrap in quotes so Node.js will count the entire thing as one argument:

ts-node user-roles.ts "{\"PAID_USER\": true, \"VIP\": true}"

Don't forget to escape quotes in string!!

In user-roles.ts:

const rolesString = process.argv.slice(2)[0]
updateUserRoles(JSON.parse(rolesString))

Because process.argv.slice(2) returns an Array, you'll need to get the first argument. You also don't need JSON.stringify().
It can be simplified like this:

updateUserRoles(JSON.parse(process.argv.slice[2]))

huangapple
  • 本文由 发表于 2023年6月16日 13:22:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76487156.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定