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

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

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

问题

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

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

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

  1. async function updateUserRoles(roles: any) {
  2. const userID = await getAuth().then((res) => res.uid);
  3. updateUser({
  4. userID: userID,
  5. fields: {
  6. roles: {
  7. roles
  8. },
  9. }
  10. })
  11. console.log(`User roles successfully added: ${roles}`)
  12. }
  13. const rolesString = JSON.stringify(process.argv.slice(2))
  14. updateUserRoles(JSON.parse(rolesString))

我收到以下消息:

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

I want to pass an object via NPM script like

  1. "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?

  1. async function updateUserRoles(roles: any) {
  2. const userID = await getAuth().then((res) => res.uid);
  3. updateUser({
  4. userID: userID,
  5. fields: {
  6. roles: {
  7. roles
  8. },
  9. }
  10. })
  11. console.log(`User roles successfully added: ${roles}`)
  12. }
  13. const rolesString = JSON.stringify(process.argv.slice(2))
  14. updateUserRoles(JSON.parse(rolesString))

I get the following message:

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

答案1

得分: 1

以下是翻译好的部分:

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

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

选项1. 传递JSON字符串

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

index.ts

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

输出:

  1. [
  2. '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  3. '/home/lindu/workspace/project/index.ts',
  4. '{ "PAID_USER": true, "VIP": true }'
  5. ]
  6. { PAID_USER: true, VIP: true }

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

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

index.ts:

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

输出:

  1. [
  2. '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  3. '/home/lindu/workspace/project/index.ts',
  4. '{PAID_USER: true, VIP: true}'
  5. ]
  6. { 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:

  1. [
  2. '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  3. '/home/lindu/workspace/project/index.ts',
  4. '{PAID_USER:',
  5. 'true,',
  6. 'VIP:',
  7. 'true}'
  8. ]

> 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

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

index.ts

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

Output:

  1. [
  2. '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  3. '/home/lindu/workspace/project/index.ts',
  4. '{"PAID_USER": true, "VIP": true}'
  5. ]
  6. { PAID_USER: true, VIP: true }

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

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

index.ts:

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

Output:

  1. [
  2. '/home/lindu/workspace/project/node_modules/.bin/ts-node',
  3. '/home/lindu/workspace/project/index.ts',
  4. '{PAID_USER: true, VIP: true}'
  5. ]
  6. { PAID_USER: true, VIP: true } object true true

Option 3. Use minimistjs package.

答案2

得分: 0

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

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

之后:

  1. async function updateUserRoles(rolesString: string) {
  2. const roles = JSON.parse(rolesString);
  3. const userID = await getAuth().then((res) => res.uid);
  4. updateUser({
  5. userID: userID,
  6. fields: {
  7. roles: roles
  8. }
  9. });
  10. console.log(`用户角色已成功添加:${JSON.stringify(roles)}`);
  11. }

它应该能正常工作。

英文:

We can use double quotes to wrap the object.

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

After that:

  1. async function updateUserRoles(rolesString: string) {
  2. const roles = JSON.parse(rolesString);
  3. const userID = await getAuth().then((res) => res.uid);
  4. updateUser({
  5. userID: userID,
  6. fields: {
  7. roles: roles
  8. }
  9. });
  10. console.log(`User roles successfully added: ${JSON.stringify(roles)}`);
  11. }

It should work.

答案3

得分: 0

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

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

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

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

以下是最小的 JavaScript 功能。

  1. const args = process.argv.slice(2).reduce((acc, arg) => {
  2. let [k, v = true] = arg.split('=');
  3. acc[k] = v;
  4. return acc;
  5. }, {});
  6. console.log(args) // { myObject: '{PAID_USER: true, VIP: true}' }
  7. const parseJSON = obj => Function('"use strict";return (' + obj + ')')();
  8. const myObject = parseJSON(args.myObject); // { PAID_USER: true, VIP: true }

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

  1. 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).

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

And here is the minimal JavaScript functionality.

  1. const args = process.argv.slice(2).reduce((acc, arg) => {
  2. let [k, v = true] = arg.split('=');
  3. acc[k] = v;
  4. return acc;
  5. }, {});
  6. console.log(args) // { myObject: '{PAID_USER: true, VIP: true}' }
  7. const parseJSON = obj => Function('"use strict";return (' + obj + ')')();
  8. const myObject = parseJSON(args.myObject); // { PAID_USER: true, VIP: true }

Your function call would then be

  1. updateUserRoles(myObject);

答案4

得分: 0

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

脚本:

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

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

  1. const objArgStr = process.argv[2];
  2. if (!objArgStr) {
  3. console.error('未提供参数。');
  4. process.exit(1);
  5. }
  6. const objArg = JSON.parse(objArgStr);
  7. console.log('对象参数:', objArg);
  8. updateUserRoles(objArg);
英文:

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

The script:

  1. "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:

  1. const objArgStr = process.argv[2];
  2. if (!objArgStr) {
  3. console.error('No argument provided.');
  4. process.exit(1);
  5. }
  6. const objArg = JSON.parse(objArgStr);
  7. console.log('Object argument: ', objArg);
  8. updateUserRoles(objArg)

答案5

得分: 0

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

  1. [
  2. "{PAID_USER:",
  3. "true,",
  4. "VIP:",
  5. "true}"
  6. ]

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

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

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

user-roles.ts中:

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

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

  1. 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:

  1. [
  2. "{PAID_USER:",
  3. "true,",
  4. "VIP:",
  5. "true}"
  6. ]

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:

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

Don't forget to escape quotes in string!!

In user-roles.ts:

  1. const rolesString = process.argv.slice(2)[0]
  2. 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:

  1. 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:

确定