0

I'm relatively new to node.js and am attempting to utilize a javascript library without any success.

The library itself is psn-api.

To set up for usage I have:

  1. Installed node.js locally
  2. Created my project folder
  3. Ran npm init and successfully created package.json
  4. Ran npm install i -s psn-api which has successfully installed psn-api to my project folder in node-modules and updated the dependencies in package.json.
  5. I've copied the sample code from the psn-api github (see below) and saved as index.ts file in my project folder.
  6. I run npx tsc --init which generates my tsconfig.json file
  7. I run npx tsc index.ts which compiles into index.js
  8. I run node index.js

Sample code (index.ts):

import * as fs from "fs";

import type { Trophy } from "psn-api";
import {
  exchangeCodeForAccessToken,
  exchangeNpssoForCode,
  getTitleTrophies,
  getUserTitles,
  getUserTrophiesEarnedForTitle,
  makeUniversalSearch,
  TrophyRarity
} from "psn-api";

async function main() {
  // 1. Authenticate and become authorized with PSN.
  // See the Authenticating Manually docs for how to get your NPSSO.
  const npsso = "xxxxxxxx";
  const accessCode = await exchangeNpssoForCode(npsso);
  const authorization = await exchangeCodeForAccessToken(accessCode);

  // 2. Get the user's `accountId` from the username.
  const allAccountsSearchResults = await makeUniversalSearch(
    authorization,
    "xelnia",
    "SocialAllAccounts"
  );

  const targetAccountId =
    allAccountsSearchResults.domainResponses[0].results[0].socialMetadata
      .accountId;

  // 3. Get the user's list of titles (games).
  const { trophyTitles } = await getUserTitles(authorization, targetAccountId);

  const games: any[] = [];
  for (const title of trophyTitles) {
    // 4. Get the list of trophies for each of the user's titles.
    const { trophies: titleTrophies } = await getTitleTrophies(
      authorization,
      title.npCommunicationId,
      "all",
      {
        npServiceName:
          title.trophyTitlePlatform !== "PS5" ? "trophy" : undefined
      }
    );

    // 5. Get the list of _earned_ trophies for each of the user's titles.
    const { trophies: earnedTrophies } = await getUserTrophiesEarnedForTitle(
      authorization,
      targetAccountId,
      title.npCommunicationId,
      "all",
      {
        npServiceName:
          title.trophyTitlePlatform !== "PS5" ? "trophy" : undefined
      }
    );

    // 6. Merge the two trophy lists.
    const mergedTrophies = mergeTrophyLists(titleTrophies, earnedTrophies);

    games.push({
      gameName: title.trophyTitleName,
      platform: title.trophyTitlePlatform,
      trophyTypeCounts: title.definedTrophies,
      earnedCounts: title.earnedTrophies,
      trophyList: mergedTrophies
    });
  }

  // 7. Write to a JSON file.
  fs.writeFileSync("./games.json", JSON.stringify(games));
}

const mergeTrophyLists = (
  titleTrophies: Trophy[],
  earnedTrophies: Trophy[]
) => {
  const mergedTrophies: any[] = [];

  for (const earnedTrophy of earnedTrophies) {
    const foundTitleTrophy = titleTrophies.find(
      (t) => t.trophyId === earnedTrophy.trophyId
    );

    mergedTrophies.push(
      normalizeTrophy({ ...earnedTrophy, ...foundTitleTrophy })
    );
  }

  return mergedTrophies;
};

const normalizeTrophy = (trophy: Trophy) => {
  return {
    isEarned: trophy.earned ?? false,
    earnedOn: trophy.earned ? trophy.earnedDateTime : "unearned",
    type: trophy.trophyType,
    rarity: rarityMap[trophy.trophyRare ?? 0],
    earnedRate: Number(trophy.trophyEarnedRate),
    trophyName: trophy.trophyName,
    groupId: trophy.trophyGroupId
  };
};

const rarityMap: Record<TrophyRarity, string> = {
  [TrophyRarity.VeryRare]: "Very Rare",
  [TrophyRarity.UltraRare]: "Ultra Rare",
  [TrophyRarity.Rare]: "Rare",
  [TrophyRarity.Common]: "Common"
};

I've run around in circles with possible fixes such as adding "type":"module" to the package.json, trying to import or otherwise define psn-api in my js file but I keep hitting error after error. I'm sure there's some fundamental misunderstanding I have. I'd really appreciate if someone could outline the direct steps I need to take to get the sample script running in the cmd line.

My package.json as it stands:

    {
  "name": "psnapitest",
  "version": "1.0.0",
  "description": "",
  "main": "index3.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@types/node": "^18.6.2",
    "psn-api": "^2.7.0"
  },
  "type": "module",
  "devDependencies": {
    "@tsconfig/node16": "^1.0.3",
    "typescript": "^4.7.4"
  }
}

My tsconfig.json as it stands (after advice in comments):

{
  "compilerOptions": {
    "target": "es2016",
    "module": "es6",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true
  }
}

Current error when running compiled js:

Now compiles with no issues.

I run node index.js and get the following error

    exports.__esModule = true;
^

ReferenceError: exports is not defined in ES module scope
31
  • 1
    Adding "type": "module" inside package.json should fix the issue. What error do you get then? Commented Jul 29, 2022 at 21:28
  • Does this answer your question? Using import fs from 'fs' Commented Jul 29, 2022 at 21:29
  • I get a step further but then the error: import type { Trophy } from "psn-api"; SyntaxError: Unexpected token '{' Commented Jul 29, 2022 at 21:32
  • No type after import; just import { Trophy } from "psn-api";. Commented Jul 29, 2022 at 21:34
  • 1
    @KonradLinkowski His version of TypeScript is apparently as old as how up-to-date I am with TS syntax ;). Commented Jul 29, 2022 at 21:38

2 Answers 2

1

Try instead of using import, use require:

const fs = require('fs')
const psn = require('psn-api')
type { Trophy } = psn
const { exchangeCodeForAccessToken } = psn
const { exchangeNpssoForCode } = psn
const { getTitleTrophies } = psn
const { getUserTitles } = psn
const { getUserTrophiesEarnedForTitle } = psn
const { makeUniversalSearch } = psn
const { TrophyRarity } = psn

Also, instead of compiling it to node.js, try using this library: https://www.npmjs.com/package/ts-node

Its basicly node.js but for typescript

Sign up to request clarification or add additional context in comments.

8 Comments

That makes no sense, just mark the codebase as modern ES by saying "type": "module" in the package.json and start writing normal universal modern JS.
type:module brings some problems if the app is not written as a module
except it is, the problem (now that they're properly using type:modulde) is that their TS gets converted from modern form to legacy CJS.
just delete the type:module, and revert the changes?
I gave this a try and reverted changes in the package.json/tsconfig.json. However I'm getting errors now for Trophy and TrophyRarity: 'Trophy' refers to a value, but is being used as a type here. Did you mean 'typeof Trophy'? Is there any way to fix this with your suggested import alternative?
|
0

I tried this locally and no error

when using node library you need to set "moduleResolution": "node" on your tsconfig.json

index.ts

import fs from 'fs'

package.json

{
  "name": "psn-api-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc index.ts",
    "start": "node index.js"
  },
  "type": "module",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "psn-api": "^2.7.0"
  },
  "devDependencies": {
    "@types/node": "^18.6.2",
    "typescript": "^4.7.4"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",
    "module": "es6",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true
  }
}

1 Comment

I tried this but still got the error if using "import fs from 'fs'". Reverting it back allows me to compile to js at least, but then running the js with "node index.js" leads back to ReferenceError: exports is not defined in ES module scope

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.