cancel
Showing results for 
Search instead for 
Did you mean: 

Datasphere CLI - Create Object with --input and node.js

Björn_K
Explorer
0 Kudos
264

Hello community,

I am trying to create an object with the Datasphere CLI with node.js, but I cannot figure out the correct syntax for the command.

As described in the documentation for the CLI there is the paramater "--input" to use a stringified-json to create an object (https://help.sap.com/docs/SAP_DATASPHERE/d0ecd6f297ac40249072a44df0549c1a/6f5c65f209004751aa48f9682e...). Unfortunately I couldn't find any example explaining the syntax of the used stringified-json.

I have successfully created an object with the parameter "--file-path" and a JSON file. But when I stringify this file in node.js and try the command with this stringified JSON, I get the error message "Failed to obtain an object name from the provided CSN code".

I have also tried to escape the quotation marks in the JSON file with "\" and with "`".

The code with escaped quotation marks looks like this: 

 

const options4 = {     
"--space": "SP_IB_006",     
"--technical-name": "T3",     
"--input": "{\"definitions\":{\"T3\":{\"kind\":\"entity\",\"@EndUserText.label\":\"T3\",\"@ObjectModel.modelingPattern\":{\"#\":\"DATA_STRUCTURE\"},\"@ObjectModel.supportedCapabilities\":[{\"#\":\"DATA_STRUCTURE\"}],\"elements\":{\"ID\":{\"@EndUserText.label\":\"ID\",\"type\":\"cds.String\",\"length\":100,\"key\":true,\"notNull\":true},\"Name\":{\"@EndUserText.label\":\"Name\",\"type\":\"cds.String\",\"length\":100}}}}}",     
"--host": "<HOST_OF_DSP>",       
"--passcode": "",         
};       

try {      
const retrieveCommand = await commands2["objects local-tables create"](options4);   
} catch (err) {    
console.log(err);   
}

 

 

In powershell I could successfully create the object by using the following command:

 

datasphere objects local-tables create --space SP_IB_006 --technical-name T3 --input "{`"definitions`":{`"T3`":{`"kind`":`"entity`",`"@EndUserText.label`":`"T3`",`"@ObjectModel.modelingPattern`":{`"#`":`"DATA_STRUCTURE`"},`"@ObjectModel.supportedCapabilities`":[{`"#`":`"DATA_STRUCTURE`"}],`"elements`":{`"ID`":{`"@EndUserText.label`":`"ID`",`"type`":`"cds.String`",`"length`":100,`"key`":true,`"notNull`":true},`"Name`":{`"@EndUserText.label`":`"Name`",`"type`":`"cds.String`",`"length`":100}}}}}"

 

 

Does anyone know, how to use the "--input"-paramater in node.js correctly?

Best Regards,
Björn

Accepted Solutions (1)

Accepted Solutions (1)

SiarheiShydlou
Explorer

@Björn_K, your code is almost correct. If you want to directly in js code insert CSN definition - then first create a constant like:

const TableCSN = {
	definitions: {
		T3: {
			kind: "entity",
			"@EndUserText.label": "T3",
			"@ObjectModel.modelingPattern": {
				"#": "DATA_STRUCTURE",
			},
			"@ObjectModel.supportedCapabilities": [
				{
					"#": "DATA_STRUCTURE",
				},
			],
			elements: {
				ID: {
					"@EndUserText.label": "ID",
					type: "cds.String",
					length: 100,
					key: true,
					notNull: true,
				},
				Name: {
					"@EndUserText.label": "Name",
					type: "cds.String",
					length: 100,
				},
			},
		},
	},
};

 then change input to:

"--input": JSON.stringify(TableCSN),

That worked for me.

One more thing - you are using passcode for login and in your case it is empty  - I guess it is empty just for the post purpose, as in reality it is to be populated. Anyway  please make sure you are really logged in, e.g. but executing in terminal:

datasphere spaces list --host <HOST_NAME>

 

Björn_K
Explorer
0 Kudos

Hello @SiarheiShydlou,

thank you for your response. I have tried with your suggestion, but still get the same error. I will post my full code and the full error message. Maybe I have missed something. I am using the "@sap/datasphere-cli": "^2024.20.0". For testing purpose I am using temporary authentication codes, which worked fine with the --file-path paramater.

EDIT: I have found the problem. When I posted the error message, I noticed the line “‘User-Agent’: ‘@sap/datasphere-cli+2024.21.0’,”. So I updated the package and now use “@sap/datasphere-cli”: “^2024.25.0”. Now it works.

 

 

const datasphere = require("@sap/datasphere-cli");
const fs = require('fs'); // Node.js FileSystem-Modul, um Dateien zu erstellen

(async () => {
    const MY_HOST = "<DSP_HOST_REMOVED>";
    const commands = await datasphere.getCommands(MY_HOST);

    const options1 = {
        "--host": "<DSP_HOST_REMOVED>",
        "--passcode": "",
      };      
    await commands["config cache init"](options1);
    const commands2 = await datasphere.getCommands(MY_HOST);   

    const TableCSN = {
      definitions: {
        T3: {
          kind: "entity",
          "@EndUserText.label": "T3",
          "@ObjectModel.modelingPattern": {
            "#": "DATA_STRUCTURE",
          },
          "@ObjectModel.supportedCapabilities": [
            {
              "#": "DATA_STRUCTURE",
            },
          ],
          elements: {
            ID: {
              "@EndUserText.label": "ID",
              type: "cds.String",
              length: 100,
              key: true,
              notNull: true,
            },
            Name: {
              "@EndUserText.label": "Name",
              type: "cds.String",
              length: 100,
            },
          },
        },
      },
    };      
      
    const options4 = {
      "--space": "SP_IB_006",
      "--technical-name": "T3",
      "--input": JSON.stringify(TableCSN),      
      "--host": "<DSP_HOST_REMOVED>",  
      "--passcode": "",      
    };
    
    try {   
    const retrieveCommand = await commands2["objects local-tables create"](options4);
    } catch (err) {
      console.log(err);
    }   
})();
Failed to create an object from a JSON file or input string
AxiosError: Request failed with status code 400
    at settle (/home/user/projects/Remotetable_Generation/node_modules/axios/dist/node/axios.cjs:2019:12)
    at IncomingMessage.handleStreamEnd (/home/user/projects/Remotetable_Generation/node_modules/axios/dist/node/axios.cjs:3135:11)
    at IncomingMessage.emit (node:events:530:35)
    at endReadableNT (node:internal/streams/readable:1696:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
    at Axios.request (/home/user/projects/Remotetable_Generation/node_modules/axios/dist/node/axios.cjs:4269:41)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async fetch (/home/user/projects/Remotetable_Generation/node_modules/@sap/cli-core/utils/http/index.js:51:21)
    at async fetchData (/home/user/projects/Remotetable_Generation/node_modules/@sap/cli-core/commands/handler/fetch/fetch.js:22:22)
    at async /home/user/projects/Remotetable_Generation/node_modules/@sap/cli-core/commands/handler/fetch/fetch.js:71:9
    at async /home/user/projects/Remotetable_Generation/node_modules/@sap/cli-core/commands/handler/next.js:20:13
    at async /home/user/projects/Remotetable_Generation/node_modules/@sap/cli-core/commands/handler/stackTrace.js:11:17
    at async Command.<anonymous> (/home/user/projects/Remotetable_Generation/node_modules/@sap/cli-core/commands/handler/root/index.js:10:13)
    at async Command.parseAsync (/home/user/projects/Remotetable_Generation/node_modules/commander/lib/command.js:1092:5)
    at async executeCommand (/home/user/projects/Remotetable_Generation/node_modules/@sap/cli-core/dwc/dwc.js:143:5) {
  code: 'ERR_BAD_REQUEST',
  config: {
    transitional: {
      silentJSONParsing: true,
      forcedJSONParsing: true,
      clarifyTimeoutError: false
    },
    adapter: [ 'xhr', 'http', 'fetch' ],
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 0,
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    maxBodyLength: -1,
    env: { FormData: [Function], Blob: [class Blob] },
    validateStatus: [Function: validateStatus],
    headers: Object [AxiosHeaders] {
      Accept: 'application/json, text/plain, */*',
      'Content-Type': 'application/x-www-form-urlencoded',
      passcode: <REMOVED>,
      publicfqdn:<REMOVED>,
      'User-Agent': '@sap/datasphere-cli+2024.21.0',
      'Accept-Encoding': 'gzip, compress, deflate, br'
    },
    httpsAgent: HttpsProxyAgent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      options: [Object],
      requests: [Object: null prototype] {},
      sockets: [Object: null prototype],
      freeSockets: [Object: null prototype] {},
      keepAliveMsecs: 1000,
      keepAlive: false,
      maxSockets: Infinity,
      maxFreeSockets: 256,
      scheduling: 'lifo',
      maxTotalSockets: Infinity,
      totalSocketCount: 1,
      proxy: URL {},
      proxyHeaders: {},
      connectOpts: [Object],
      [Symbol(shapeMode)]: false,
      [Symbol(kCapture)]: false,
      [Symbol(AgentBaseInternalState)]: [Object]
    },
    proxy: false,
    url: <REMOVED>,
    method: 'post',
    maxRedirects: 0,
    data: undefined
  },
  request: <ref *1> ClientRequest {
    _events: [Object: null prototype] {
      error: [Function: handleRequestError],
      socket: [Function: handleRequestSocket],
      finish: [Function: requestOnFinish]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    outputData: [],
    outputSize: 0,
    writable: true,
    destroyed: false,
    _last: true,
    chunkedEncoding: false,
    shouldKeepAlive: false,
    maxRequestsOnConnectionReached: false,
    _defaultKeepAlive: true,
    useChunkedEncodingByDefault: true,
    sendDate: false,
    _removedConnection: false,
    _removedContLen: false,
    _removedTE: false,
    strictContentLength: false,
    _contentLength: 0,
    _hasBody: true,
    _trailer: '',
    finished: true,
    _headerSent: true,
    _closed: false,
    socket: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      secureConnecting: false,
      _SNICallback: null,
      servername: <REMOVED>,
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 9,
      connecting: false,
      _hadError: false,
      _parent: [Socket],
      _host: null,
      _closeAfterHandlingError: false,
      _readableState: [ReadableState],
      _writableState: [WritableState],
      allowHalfOpen: false,
      _maxListeners: undefined,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: [TLSWrap],
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: [Circular *1],
      [Symbol(alpncallback)]: null,
      [Symbol(res)]: [TLSWrap],
      [Symbol(verified)]: true,
      [Symbol(pendingSession)]: null,
      [Symbol(async_id_symbol)]: 121,
      [Symbol(kHandle)]: [TLSWrap],
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(shapeMode)]: true,
      [Symbol(kCapture)]: false,
      [Symbol(kSetNoDelay)]: false,
      [Symbol(kSetKeepAlive)]: true,
      [Symbol(kSetKeepAliveInitialDelay)]: 60,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(connect-options)]: [Object]
    },
    _header: 'POST /api/v1/spaces/SP_IB_006/localtables?saveAnyway=false&deploy=true HTTP/1.1\r\n' +
      'Accept: application/json, text/plain, */*\r\n' +
      'Content-Type: application/x-www-form-urlencoded\r\n' +
      'passcode: <REMOVED> +
      'publicfqdn: <REMOVED> +
      'User-Agent: @sap/datasphere-cli+2024.21.0\r\n' +
      'Accept-Encoding: gzip, compress, deflate, br\r\n' +
      'Host: <REMOVED> +
      'Connection: close\r\n' +
      'Content-Length: 0\r\n' +
      '\r\n',
    _keepAliveTimeout: 0,
    _onPendingData: [Function: nop],
    agent: HttpsProxyAgent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      options: [Object],
      requests: [Object: null prototype] {},
      sockets: [Object: null prototype],
      freeSockets: [Object: null prototype] {},
      keepAliveMsecs: 1000,
      keepAlive: false,
      maxSockets: Infinity,
      maxFreeSockets: 256,
      scheduling: 'lifo',
      maxTotalSockets: Infinity,
      totalSocketCount: 1,
      proxy: URL {},
      proxyHeaders: {},
      connectOpts: [Object],
      [Symbol(shapeMode)]: false,
      [Symbol(kCapture)]: false,
      [Symbol(AgentBaseInternalState)]: [Object]
    },
    socketPath: undefined,
    method: 'POST',
    maxHeaderSize: undefined,
    insecureHTTPParser: undefined,
    joinDuplicateHeaders: undefined,
    path: '/api/v1/spaces/SP_IB_006/localtables?saveAnyway=false&deploy=true',
    _ended: true,
    res: IncomingMessage {
      _events: [Object],
      _readableState: [ReadableState],
      _maxListeners: undefined,
      socket: [TLSSocket],
      httpVersionMajor: 1,
      httpVersionMinor: 1,
      httpVersion: '1.1',
      complete: true,
      rawHeaders: [Array],
      rawTrailers: [],
      joinDuplicateHeaders: undefined,
      aborted: false,
      upgrade: false,
      url: '',
      method: null,
      statusCode: 400,
      statusMessage: 'Bad Request',
      client: [TLSSocket],
      _consuming: false,
      _dumped: false,
      req: [Circular *1],
      _eventsCount: 4,
      [Symbol(shapeMode)]: true,
      [Symbol(kCapture)]: false,
      [Symbol(kHeaders)]: [Object],
      [Symbol(kHeadersCount)]: 38,
      [Symbol(kTrailers)]: null,
      [Symbol(kTrailersCount)]: 0
    },
    aborted: false,
    timeoutCb: null,
    upgradeOrConnect: false,
    parser: null,
    maxHeadersCount: null,
    reusedSocket: false,
    host: <REMOVED>,
    protocol: 'https:',
    [Symbol(shapeMode)]: false,
    [Symbol(kCapture)]: false,
    [Symbol(kBytesWritten)]: 0,
    [Symbol(kNeedDrain)]: false,
    [Symbol(corked)]: 0,
    [Symbol(kOutHeaders)]: [Object: null prototype] {
      accept: [Array],
      'content-type': [Array],
      passcode: [Array],
      publicfqdn: [Array],
      'user-agent': [Array],
      'accept-encoding': [Array],
      host: [Array]
    },
    [Symbol(errored)]: null,
    [Symbol(kHighWaterMark)]: 16384,
    [Symbol(kRejectNonStandardBodyWrites)]: false,
    [Symbol(kUniqueHeaders)]: null
  },
  response: {
    status: 400,
    statusText: 'Bad Request',
    headers: Object [AxiosHeaders] {
      'access-control-expose-headers': 'x-csrf-token, x-sap-cid, content-type, authorization, accept, x-requested-with',
      'content-length': '255',
      'content-type': 'application/json; charset=utf-8',
      date: 'Wed, 11 Dec 2024 07:48:05 GMT',
      'permissions-policy': 'unload=()',
      'referrer-policy': 'no-referrer',
      'x-content-type-options': 'nosniff',
      'x-dns-prefetch-control': 'off',
      'x-download-options': 'noopen',
      'x-frame-options': 'SAMEORIGIN',
      'x-permitted-cross-domain-policies': 'none',
      'x-ratelimit-limit': '50',
      'x-ratelimit-remaining': '49',
      'x-ratelimit-reset': '60',
      'x-sap-dwc-cli-discovery-etag': <REMOVED>,
      'x-vcap-request-id': <REMOVED>,
      'x-xss-protection': '0',
      'strict-transport-security': 'max-age=31536000; includeSubDomains; preload;',
      connection: 'close'
    },
    config: {
      transitional: [Object],
      adapter: [Array],
      transformRequest: [Array],
      transformResponse: [Array],
      timeout: 0,
      xsrfCookieName: 'XSRF-TOKEN',
      xsrfHeaderName: 'X-XSRF-TOKEN',
      maxContentLength: -1,
      maxBodyLength: -1,
      env: [Object],
      validateStatus: [Function: validateStatus],
      headers: [Object [AxiosHeaders]],
      httpsAgent: [HttpsProxyAgent],
      proxy: false,
      url: <REMOVED>,
      method: 'post',
      maxRedirects: 0,
      data: undefined
    },
    request: <ref *1> ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 3,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      destroyed: false,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      maxRequestsOnConnectionReached: false,
      _defaultKeepAlive: true,
      useChunkedEncodingByDefault: true,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      strictContentLength: false,
      _contentLength: 0,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      _closed: false,
      socket: [TLSSocket],
      _header: 'POST /api/v1/spaces/SP_IB_006/localtables?saveAnyway=false&deploy=true HTTP/1.1\r\n' +
        'Accept: application/json, text/plain, */*\r\n' +
        'Content-Type: application/x-www-form-urlencoded\r\n' +
        'passcode: <REMOVED> +
        'publicfqdn: <REMOVED> +
        'User-Agent: @sap/datasphere-cli+2024.21.0\r\n' +
        'Accept-Encoding: gzip, compress, deflate, br\r\n' +
        'Host: <REMOVED> +
        'Connection: close\r\n' +
        'Content-Length: 0\r\n' +
        '\r\n',
      _keepAliveTimeout: 0,
      _onPendingData: [Function: nop],
      agent: [HttpsProxyAgent],
      socketPath: undefined,
      method: 'POST',
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      joinDuplicateHeaders: undefined,
      path: '/api/v1/spaces/SP_IB_006/localtables?saveAnyway=false&deploy=true',
      _ended: true,
      res: [IncomingMessage],
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      host: <REMOVED>,
      protocol: 'https:',
      [Symbol(shapeMode)]: false,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype],
      [Symbol(errored)]: null,
      [Symbol(kHighWaterMark)]: 16384,
      [Symbol(kRejectNonStandardBodyWrites)]: false,
      [Symbol(kUniqueHeaders)]: null
    },
    data: {
      code: 'FailedToObtainObjectName',
      message: 'Failed to obtain an object name from the provided CSN code',
      details: [Object]
    }
  },
  status: 400
}

 

Kind Regards,
Björn

Answers (1)

Answers (1)

SiarheiShydlou
Explorer
0 Kudos

Hello @Björn_K ,

please check in npm package @sap/datasphere-cli documentation examples how to use commands with options in node.js.

Björn_K
Explorer
0 Kudos

Hello @SiarheiShydlou,

thank you for the link. But on this page there is only a common description, how to use the CLI in node.js. There is no example or explanation to the single commands and especially not to the parameter of the commands.

Kind Regards