Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@fluree/fluree-client
Advanced tools
This is the official Fluree client SDK for TypeScript/JavaScript. It is a wrapper around the Fluree API, providing a more convenient way to interact with Fluree v3 databases.
Tested against the following
fluree/server
Docker Hub images:
fluree/server:5839ffe273062b8da972b120deb54dd62e7c3d1f
: Current stable versionfluree/server:c452631c50b8f8e595d486240dab503bbaad6033
: October 30 2024fluree/server:d5eb31b1c2be560a92a30176dc8b0e01973859ea
: October 22 2024fluree/server:60829de035c4996369f7dbe0766b80db0e743a8b
: October 4 2024
npm install @fluree/fluree-client
const { FlureeClient } = require('@fluree/fluree-client');
// Create and connect to a Fluree instance
const client = await new FlureeClient({
host: 'localhost',
port: 8090,
ledger: 'example/ledger',
}).connect();
// Perform a query
const result = await client
.query({
select: { '?s': ['*'] },
where: {
'@id': '?s',
},
})
.send();
import { FlureeClient } from '@fluree/fluree-client';
// Create and connect to a Fluree instance
const client = await new FlureeClient({
host: 'localhost',
port: 8090,
ledger: 'example/ledger',
}).connect();
// Perform a query
const result = await client
.query({
select: { '?s': ['*'] },
where: {
'@id': '?s',
},
})
.send();
The FlureeClient
constructor takes an optional config
object with the following properties:
{
isFlureeHosted, // [boolean] If true, the client will use the Fluree hosted service
apiKey, // [string] The API key to use for the Fluree hosted service
ledger, // [string] The ledger/db name on the Fluree instance
// Do not set "host" and "port" if "isFlureeHosted" is true
host, // [string] The host where your instance is running (e.g. localhost)
port, // [number] The port where your instance is running (e.g. 58090)
create, // [boolean] If true, the ledger will be created if it does not exist
privateKey, // [string] The private key to use for signing messages
signMessages, // [boolean] If true, messages will be signed by default
defaultContext, // [object] The default context to use for queries/txns
}
For example:
const client = new FlureeClient({
ledger: 'fluree-client/client',
host: 'localhost',
port: 58090,
create: true,
privateKey: 'XXX...XXX',
signMessages: true,
defaultContext: {
schema: 'http://schema.org/',
name: 'schema:name',
// ...
},
});
You can also update the configuration of an existing client by using the configure()
method:
const client = new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
});
client.configure({
ledger: 'fluree-jld/387028092978174',
});
connect()
In order to use the FlureeClient instance, you must first connect to the Fluree instance. This will test the connection and (if config.create === true
) create the ledger if it does not exist.
It will also throw an error if the connection fails (e.g. invalid host, ledger does not exist, etc.)
const connectedClient = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
create()
The create()
method can be used to create a new ledger on the Fluree instance. This will throw an error if the ledger already exists.
The returned FlureeClient will be configured to use the new ledger.
const client = new FlureeClient({
host: 'localhost',
port: 8080,
ledger: 'fluree-client/client',
});
const createdClient = await client.create('new-ledger');
query()
The query()
method creates a new QueryInstance
for querying the Fluree database. The QueryInstance
can be used & re-used to build, sign, and send queries to the Fluree instance.
See the QueryInstance section for more information.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const queryInstance = client.query({
select: { freddy: ['*'] },
});
const response = await queryInstance.send();
transact()
The transact()
method creates a new TransactionInstance
for transacting with the Fluree database. The TransactionInstance
can be used & re-used to build, sign, and send transactions to the Fluree instance.
See the TransactionInstance section for more information.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const transactionInstance = client.transact({
insert: { '@id': 'freddy', name: 'Freddy' },
});
const response = await transactionInstance.send();
delete()
The delete()
method creates a new TransactionInstance
for deleting subjects by @id
in the Fluree database. The TransactionInstance
can then be used to sign and send delete transactions to the Fluree instance.
Delete is not an API endpoint in Fluree. This method helps to transform a single or list of subject identifiers (@id) into a where/delete transaction that deletes the subject(s) and all facts about the subject(s).
// Existing data:
// [
// { "@id": "freddy", "name": "Freddy" },
// { "@id": "alice", "name": "Alice" }
// ]
const txnInstance = client.delete(['freddy']);
const txnObject = txnInstance.getTransaction();
console.log(txnObject);
// {
// where: [{ '@id': 'freddy', ?p0: '?o0' }],
// delete: [{ '@id': 'freddy', ?p0: '?o0' }],
// ledger: ...
// }
const response = await txnInstance.send();
// New data state after txn:
// [
// { "@id": "alice", "name": "Alice" }
// ]
upsert()
The upsert()
method creates a new TransactionInstance
for upserting with the Fluree database. The TransactionInstance
can be used & re-used to build, sign, and send upsert transactions to the Fluree instance.
Upsert is not an API endpoint in Fluree. This method helps to transform an upsert transaction into an insert/where/delete transaction.
Upsert assumes that the facts provided in the transaction should be treated as the true & accurate state of the data after the transaction is processed.
This means that facts in your transaction should be inserted (if new) and should replace existing facts (if they exist on those subjects & properties).
// Existing data:
// [
// { "@id": "freddy", "name": "Freddy" },
// { "@id": "alice", "name": "Alice" }
// ]
const txnInstance = client.upsert([
{ '@id': 'freddy', name: 'Freddy the Yeti' },
{ '@id': 'alice', age: 25 },
]);
const txnObject = txnInstance.getTransaction();
console.log(txnObject);
// {
// where: [ { '@id': 'freddy', name: '?1' }, { '@id': 'alice', age: '?2' } ],
// delete: [ { '@id': 'freddy', name: '?1' }, { '@id': 'alice', age: '?2' } ],
// insert: [
// { '@id': 'freddy', name: 'Freddy the Yeti' },
// { '@id': 'alice', age: 25 }
// ],
// ledger: ...
// }
const response = await txnInstance.send();
// New data state after txn:
// [
// { "@id": "freddy", "name": "Freddy the Yeti" },
// { "@id": "alice", "name": "Alice", "age": 25 }
// ]
// Note that if this had been an "insert" freddy would now have two names.
// Note also that if this had been handled by deleting/insert, alice might have lost her name.
history()
The history()
method creates a new HistoryQueryInstance
for querying the history of the Fluree database. The HistoryQueryInstance
can be used & re-used to build, sign, and send history queries to the Fluree instance.
See the HistoryQueryInstance section for more information.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const historyQuery = client.history({
'commit-details': true,
t: { at: 'latest' },
});
const response = await historyQuery.send();
generateKeyPair()
Automatically generates a new key pair and adds it to the FlureeClient instance. The public key and DID will be derived from the private key and added to the FlureeClient instance.
const client = new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
});
client.generateKeyPair();
const privateKey = client.getPrivateKey();
setKey()
This adds a private key to the FlureeClient instance. This key will be used to sign messages by default when using the sign() method on a query or transaction.
The public key and DID will be derived from the private key and added to the FlureeClient instance.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const privateKey = 'XXX...XXX';
client.setKey(privateKey);
const publicKey = client.getPublicKey();
const did = client.getDid();
getPrivateKey()
The getPrivateKey()
method returns the private key of the FlureeClient instance (if one has been set).
NOTE: Be careful with this method. It is not recommended to log or expose private keys.
const client = new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
});
client.generateKeyPair();
const privateKey = client.getPrivateKey();
getPublicKey()
The getPublicKey()
method returns the public key of the FlureeClient instance (if one has been set).
const client = new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
});
client.generateKeyPair();
const publicKey = client.getPublicKey();
getDid()
The getDid()
method returns the DID of the FlureeClient instance (if one has been set).
const client = new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
});
client.generateKeyPair();
const did = client.getDid();
setContext()
The setContext()
method sets the default context for the FlureeClient instance. This context will be used for all queries and transactions by default.
Unlike addToContext()
, which merges new context elements into any existing context for the client, this method will replace the existing default context entirely.
const client = new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
defaultContext: { schema: 'http://schema.org/' },
});
client.setContext({ ex: 'http://example.org/' });
// client.getContext() === { "ex": "http://example.org/" }
addToContext()
The addToContext()
method adds to the default context for the FlureeClient instance. This context will be used for all queries and transactions by default.
If a default context already exists, the new context will be merged with the existing context.
const client = new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
defaultContext: { schema: 'http://schema.org/' },
});
client.addToContext({ ex: 'http://example.org/' });
// client.getContext() === {
// "schema": "http://schema.org/",
// "ex": "http://example.org/"
// }
getContext()
The getContext()
method returns the default context for the FlureeClient instance (if one has been set).
const client = new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
defaultContext: { schema: 'http://schema.org/' },
});
const context = client.getContext();
// context === { "schema": "http://schema.org/" }
The QueryInstance
class is used to build, sign, and send queries to the Fluree instance.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const queryInstance = client.query({
select: { freddy: ['*'] },
});
const signedQueryInstance = queryInstance.sign('XXX...XXX');
const response = await signedQueryInstance.send();
Additional Methods:
send()
The send()
method sends the query to the Fluree instance and returns the response.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const queryInstance = client.query({
select: { freddy: ['*'] },
});
const response = await queryInstance.send();
sign()
The sign()
method signs the query with the private key of the FlureeClient instance. If no private key has been set, or if no privateKey parameter is passed to sign()
, it will throw an error.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
let signedQueryInstance = client
.query({
select: { freddy: ['*'] },
})
.sign('XXX...XXX');
// or
client.generateKeyPair();
signedQueryInstance = client
.query({
select: { freddy: ['*'] },
})
.sign();
const response = await signedQueryInstance.send();
getQuery()
The getQuery()
method returns the query object of the QueryInstance.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
defaultContext: { ex: 'http://example.org/' },
}).connect();
const queryInstance = client.query({
select: { 'ex:freddy': ['*'] },
});
const query = queryInstance.getQuery();
console.log(query);
// {
// "@context": { "ex": "http://example.org/" },
// from: 'fluree-client/client',
// select: { "ex:freddy": ['*'] }
// }
getSignedQuery()
The getSignedQuery()
method returns the signed query of the QueryInstance in the form of a JWS string.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
client.generateKeyPair();
const queryInstance = client.query({
select: { freddy: ['*'] },
});
const signedQueryInstance = queryInstance.sign();
const signedQuery = signedQueryInstance.getSignedQuery();
console.log(signedQuery);
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZWxlY3QiOnsiZnJlZGR5IjpbIioiXX0sImZyb20iOiJmbHVyZWUtY2xpZW50L2NsaWVudCJ9.QNTXpZCQXsbO9zoOtMHT4yH-OqAaNq8ezhV5k7C_BuI
The TransactionInstance
class is used to build, sign, and send transactions to the Fluree instance.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const transaction = client.transact({
insert: { '@id': 'freddy', name: 'Freddy' },
});
const signedTransaction = transaction.sign('XXX...XXX');
const response = await signedTransaction.send();
Additional Methods:
send()
The send()
method sends the transaction to the Fluree instance and returns the response.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const transaction = client.transact({
insert: { '@id': 'freddy', name: 'Freddy' },
});
const response = await transaction.send();
sign()
The sign()
method signs the transaction with the private key of the FlureeClient instance. If no private key has been set, or if no privateKey parameter is passed to sign()
, it will throw an error.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
let signedTransaction = client
.transact({
insert: { '@id': 'freddy', name: 'Freddy' },
})
.sign('XXX...XXX');
// or
client.generateKeyPair();
signedTransaction = client
.transact({
insert: { '@id': 'freddy', name: 'Freddy' },
})
.sign();
const response = await signedTransaction.send();
getTransaction()
The getTransaction()
method returns the transaction object of the TransactionInstance.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const transaction = client.transact({
insert: { '@id': 'freddy', name: 'Freddy' },
});
const txn = transaction.getTransaction();
console.log(txn);
// {
// ledger: 'fluree-client/client',
// insert: { '@id': 'freddy', name: 'Freddy' }
// }
getSignedTransaction()
The getSignedTransaction()
method returns the signed transaction of the TransactionInstance in the form of a JWS string.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
client.generateKeyPair();
const transaction = client.transact({
insert: { '@id': 'freddy', name: 'Freddy' },
});
const signedTransaction = transaction.sign();
const signedTxn = signedTransaction.getSignedTransaction();
console.log(signedTxn);
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpbnNlcnQiOnsiQGlkIjoiZnJlZGR5IiwibmFtZSI6IkZyZWRkeSJ9LCJsZWRnZXIiOiJmbHVyZWUtY2xpZW50L2NsaWVudCJ9.SNHjlNricJbATF06mbrvnqunfV7l2gZHyvj7zYFTby0
The HistoryQueryInstance
class is used to build, sign, and send history queries to the Fluree instance.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const historyQuery = client.history({
'commit-details': true,
t: { at: 'latest' },
});
const response = await historyQuery.send();
send()
The send()
method sends the history query to the Fluree instance and returns the response.
const client = await new FlureeClient({
isFlureeHosted: true,
apiKey: process.env.FLUREE_API_KEY,
ledger: 'fluree-jld/387028092978173',
}).connect();
const historyQuery = client.history({
'commit-details': true,
t: { at: 'latest' },
});
const response = await historyQuery.send();
Before running tests, you'll need a .env.local
file in the root of the project.
This file needs to contain the following:
TEST_NEXUS_LEDGER="fluree-jld/387028092978318"
TEST_API_KEY="_DPu2OWxmJ-zRwnzNr8uL...5mfV1OsfOXcRmb35t02rp1gMxxSw"
In the root of the project, run:
yarn test
The repository includes complete example projects demonstrating usage in both Node.js and browser environments.
# Navigate to the Node.js example directory
cd examples/nodejs-example
# Install dependencies (including local fluree-client)
npm install
# Run the example
npm start
# Navigate to the browser example directory
cd examples/browser-example
# Install dependencies (including local fluree-client)
npm install
# Start the development server
npm start
This will open your default browser to the example page. Click the "Run Query" button to execute the example operations.
FAQs
Fluree client library for Node.js and browser environments
The npm package @fluree/fluree-client receives a total of 264 weekly downloads. As such, @fluree/fluree-client popularity was classified as not popular.
We found that @fluree/fluree-client demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.