Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In sample core code : Ceramic.create is not a function ? #1429

Open
on-meetsys opened this issue Mar 22, 2021 · 13 comments
Open

In sample core code : Ceramic.create is not a function ? #1429

on-meetsys opened this issue Mar 22, 2021 · 13 comments
Labels
dontclose good first issue Good for newcomers help wanted Extra attention is needed maintenance p3 Moderate

Comments

@on-meetsys
Copy link

Describe the bug
The code described here leads to several errors :
https://developers.ceramic.network/build/installation/
https://github.com/ceramicnetwork/js-ceramic/tree/develop/packages/core

To Reproduce
With the code given, after packages are installed :

// package.json 
{
  "name": "ceramic-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@ceramicnetwork/core": "^0.19.7",
    "dag-jose": "^0.3.0",
    "ipfs-core": "^0.5.4",
    "multiformats": "^4.6.2"
  }
}
// index.js
import Ceramic from '@ceramicnetwork/core'
import IPFS from 'ipfs'
import dagJose from 'dag-jose'
import basicsImport from 'multiformats/cjs/src/basics-import.js'
import legacy from 'multiformats/cjs/src/legacy.js'

basicsImport.multicodec.add(dagJose)
const format = legacy(basicsImport, dagJose.name)
const ipfs = Ipfs.create({
    ipld: { formats: [format] },
})

const ceramic = await Ceramic.create(ipfs, config)

Several errors with this code occur after node index.js (v15.9.0) :

  • the multiformat import return : './cjs/src/basics-import.js' is not defined, same for legacy
  • the ipfs import is not found (should be ipfs-core)
  • the ceramiq config is not defined (not a big deal)

I've therefore modified ìndex.js` (according this comment dealing with multiformat ) :

import Ceramic from '@ceramicnetwork/core'
import IPFS from 'ipfs-core'
import dagJose from 'dag-jose'
import { sha256 } from 'multiformats/hashes/sha2'
import legacy from 'multiformats/legacy'

const hasher = {}
hasher[sha256.code] = sha256
const format = legacy(dagJose, {hashes: hasher})

const ipfs = IPFS.create({
    ipld: { formats: [format] },
})

Ceramic.create(ipfs, {}).then((c) => {
	console.info(c);
})

Which returns a TypeError: Ceramic.create is not a function

May be the example code should be modified/improved to help newcomers start with ceramiq, with a step by step sample.

@oed
Copy link
Member

oed commented Mar 22, 2021

The ipfs creation code is outdated in the docs site it seems, try the example in this blogpost: https://blog.ceramic.network/how-to-store-signed-and-encrypted-data-on-ipfs/

Will update the docs!

@oed oed self-assigned this Mar 22, 2021
@oed
Copy link
Member

oed commented Mar 23, 2021

The documentation should be updated now. Can you give it another try and let us know how it works @on-meetsys?

@on-meetsys
Copy link
Author

Thanks. The documentation is indeed closer to the code found in other places.
I think there are still some mistakes in it to help a newcomer make it run. I've modified it this way (cf comments) :

import Ceramic from '@ceramicnetwork/core'
import IPFS from 'ipfs-core' // this is the ipfs package name
import dagJose from 'dag-jose'
import { sha256 } from 'multiformats/hashes/sha2'
import legacy from 'multiformats/legacy'

const hasher = {}
hasher[sha256.code] = sha256
const dagJoseFormat = legacy(dagJose, {hashes: hasher})

const ipfs = await IPFS.create({ ipld: { formats: [dagJoseFormat] } }) // not Ipfs.create

const ceramic = await Ceramic.create(ipfs) // config is optional, and is not defined previously

Nevertheless, this code still returns an error (stored as index.js, and launched by node index.js V15.9.0 ) :

const ceramic = await Ceramic.create(ipfs) 
                              ^
TypeError: Ceramic.create is not a function
    at file:///Users/olivier/Devs/ceramic-test/index.js:13:31

May be I've misunderstood anything else ? But as explained in this documentation, using node, I still can not make it work.

@oed
Copy link
Member

oed commented Apr 7, 2021

I think this has something to do with your environment not using the default. Try doing this:

import { default: Ceramic } from '@ceramicnetwork/core'

If that doesnt' work try logging the Ceramic object you imported above and see if there is a default property.

@ayushm2003
Copy link

I think this has something to do with your environment not using the default. Try doing this:

import { default: Ceramic } from '@ceramicnetwork/core'

If that doesnt' work try logging the Ceramic object you imported above and see if there is a default property.

const ceramic = await Ceramic["default"].create(ipfs) worked. it would be good if this could be updated in the documentation

@oed
Copy link
Member

oed commented May 29, 2021

@zachferland @PaulLeCam Any idea why the default may not be available as the top level export when using import?

I imagine this only happens for certain setups (usually works in the expected way).

@olnrt
Copy link

olnrt commented May 30, 2021

Hello,
You are all right, it comes from the environment setup. In my case, in node/javascript, the import creates a Ceramic object with a 'default' parameter. Therefore, it works with a const ceramic = await Ceramic.defautl.create(ipfs)
In a typescript environment, the 'default' is not required.

By the way, once corrected, the previous code launches another error with dag-jose. Even if it not the same issue, I will ask here, because other people may find this code by googling it. This issue is also opened here

Whatever the way I setup the ìpld.formats', the dag-jose format is not found during the first ipfs.dag.put :

const hasher = {}
hasher[sha256.code] = sha256
const dagJoseFormat = legacy(dagJose, {hashes: hasher})
// or 
//  import { convert } from 'blockcodec-to-ipld-format'
//  const dagJoseFormat = convert(dagJose)
const ipfs = await IPFS.create({ ipld: { formats: [dagJoseFormat] } })

const jwe = await did.createDagJWE(...)
ipfs.dag.put(jwe, { format: 'dag-jose', hashAlg: 'sha2-256' })

A console.info(dagJoseFormat) returns :

{
  defaultHashAlg: 'sha2-256',
  codec: undefined,
  util: {
    serialize: [Function: serialize],
    deserialize: [Function: deserialize],
    cid: [AsyncFunction: cid]
  },
  resolver: { resolve: [Function: resolve], tree: [Function: tree] }
}

and the ipfs.dag.put(jwe, { format: 'dag-jose', hashAlg: 'sha2-256' }) throws a

Loading IPLD format 133
(node:99004) UnhandledPromiseRejectionWarning: Error: Missing IPLD format "dag-jose"

I found surprising the codec:undefined, and have tried to 'force' it to 'dag-jose' without success.
Is it also a environment setup bug ?

@PaulLeCam
Copy link
Contributor

@zachferland @PaulLeCam Any idea why the default may not be available as the top level export when using import?

I imagine this only happens for certain setups (usually works in the expected way).

Put simply, we shouldn't use export default, compilers and bundlers have different ways to handle it that may be incompatible.
Longer answer: our docs use ESM syntax with the expectations TypeScript or Babel is used and handles interoperability with CJS exports, but now that Node supports ESM natively we shouldn't have this expectation. Node has some interoperability to import CJS modules from ESM ones but likely handling the "default" import differently than Babel/TypeScript.
Ideally we should export ESM modules directly, but in the meantime I think using named exports would provide better compatibility. We can do this in a backwards-compatible way, such as:

// Add named export
export class Ceramic {...}
// Keep default export while in v1.x
export default Ceramic

And then in docs, replace import Ceramic from '...' by import { Ceramic } from '...'.

@oed oed assigned smrz2001 and unassigned oed May 31, 2021
@oed oed transferred this issue from ceramicnetwork/.github May 31, 2021
@oed oed added enhancement help wanted Extra attention is needed maintenance p3 Moderate good first issue Good for newcomers labels May 31, 2021
@Hesbon5600
Copy link

Hello,
You are all right, it comes from the environment setup. In my case, in node/javascript, the import creates a Ceramic object with a 'default' parameter. Therefore, it works with a const ceramic = await Ceramic.defautl.create(ipfs)
In a typescript environment, the 'default' is not required.

By the way, once corrected, the previous code launches another error with dag-jose. Even if it not the same issue, I will ask here, because other people may find this code by googling it. This issue is also opened here

Whatever the way I setup the ìpld.formats', the dag-jose format is not found during the first ipfs.dag.put :

const hasher = {}
hasher[sha256.code] = sha256
const dagJoseFormat = legacy(dagJose, {hashes: hasher})
// or 
//  import { convert } from 'blockcodec-to-ipld-format'
//  const dagJoseFormat = convert(dagJose)
const ipfs = await IPFS.create({ ipld: { formats: [dagJoseFormat] } })

const jwe = await did.createDagJWE(...)
ipfs.dag.put(jwe, { format: 'dag-jose', hashAlg: 'sha2-256' })

A console.info(dagJoseFormat) returns :

{
  defaultHashAlg: 'sha2-256',
  codec: undefined,
  util: {
    serialize: [Function: serialize],
    deserialize: [Function: deserialize],
    cid: [AsyncFunction: cid]
  },
  resolver: { resolve: [Function: resolve], tree: [Function: tree] }
}

and the ipfs.dag.put(jwe, { format: 'dag-jose', hashAlg: 'sha2-256' }) throws a

Loading IPLD format 133
(node:99004) UnhandledPromiseRejectionWarning: Error: Missing IPLD format "dag-jose"

I found surprising the codec:undefined, and have tried to 'force' it to 'dag-jose' without success.
Is it also a environment setup bug ?

I'm experiencing the same issue

import * as dagJose from 'dag-jose'
import { convert } from 'blockcodec-to-ipld-format'
import { create } from 'ipfs-http-client'
const auth =
'Basic ' + Buffer.from("projectId:projectSecret").toString('base64')

const dagJoseFormat = convert(dagJose)

const ipfs = create({
    url: new URL('https://ipfs.infura.io:5001'),
    headers: {
        authorization: auth
    },
    ipld: { formats: [dagJoseFormat] },
})

image

@oed
Copy link
Member

oed commented Sep 8, 2021

What version of IPFS are you using @Hesbon5600 ?
This conversation might be relevant to your issue: ceramicnetwork/js-dag-jose#20

@Hesbon5600
Copy link

What version of IPFS are you using @Hesbon5600 ?
This conversation might be relevant to your issue: ceramicnetwork/js-dag-jose#20

I'm using ipfs HTTP client

"ipfs-http-client": "^52.0.2",

@smrz2001 smrz2001 removed their assignment Jan 5, 2022
@btme0011
Copy link

can i work on this issue?

@oed
Copy link
Member

oed commented Nov 7, 2023

@btme0011 This issue is pretty old so not sure if it's still a problem actually. If you can replicate it then feel free!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dontclose good first issue Good for newcomers help wanted Extra attention is needed maintenance p3 Moderate
Projects
None yet
Development

No branches or pull requests

10 participants