AWS-Amplify DataStoreStateError: Tried to execute DataStore.query() while DataStore was "Stopping" - amazon-web-services

JavaScript Framework
React Native
Amplify APIs
DataStore
Amplify Categories
api
Environment information
Details
Describe the bug
DataStoreStateError: Tried to execute DataStore.query() while DataStore was "Stopping".
This can only be done while DataStore is "Started" or "Stopped". To remedy:
Ensure all calls to stop() and clear() have completed first.
If this is not poss...
Hi, I have an amplify project to host backend for react-native mobile app. Suddenly it stopped to work. Any call to the data store will receive the message i mentioned above.
Our work plan is to provide amplify backend as an NPM package. This package is used from app developer to make calls to AWS-Amplify. Since 6 months everything works fine until 4 days go. We didn't had breaking changes or something. Just added a few lambda function which i don't think it could cause this issue.
We are starting datastore when app is open. DataStore.start() and clear it on SignIng event and SignOut event. We didn't make any change in this flow since a long time (4 months).
We tried to reproduce the issue locally but it is not possible for somehow. Since we are using typescript to write our NPM package. We test functionality locally with node or tsx where everything works, then we publish it and downloaded in another project react-native where everything works good. Once it is deployed, no action from DataStore could be executed. The app crashed and Sentry show us the message above. And again that start to happen 4 days ago until now.
Expected behavior
To be able to execute DataStore manipulation functionality (query, save, delete... etc) / Get connection with data store.
Reproduction steps
Whenever we call datastore functions in the react-native app. It will show this message:
DataStoreStateError: Tried to execute DataStore.query() while DataStore was "Stopping".
This can only be done while DataStore is "Started" or "Stopped". To remedy:
Ensure all calls to stop() and clear() have completed first.
If this is not poss...
Code Snippet
// Put your code below this line.
// where i clear data store and start it, just using auth events
// Clear the local datastore when signing out.
// As advised in: https://docs.amplify.aws/lib/datastore/sync/q/platform/js/#clear-local-data
EventHandler.OnSignOut = async () => {
if (Application.hasBooted()) {
await Application.clear();
}
};
// Clear the local datastore when signing in.
// As advised in: https://docs.amplify.aws/lib/datastore/sync/q/platform/js/#clear-local-data
EventHandler.OnSignIn = async () => {
if (Application.hasBooted()) {
await Application.clear();
}
};
// Boot the application as soon as the DataSync is completed
// Check if it has not been booted already first
EventHandler.OnDataSynced = async () => {
if (!Application.hasBooted()) {
await Application.boot();
}
};
// Where i do datastore call
/**
* #name SaveAccount
* #description: Save or update an account.
* If the account already exists in the datastore based
* on its id, it is updates. Otherwise a
* #type {Function}
* #param {AccountDetails} accountDetails
* #param {AccountAttributes} params
* #returns {Promise<AccountDetails>}
*/
const SaveAccount = async (
accountDetails: AccountDetails,
params?: AccountAttributes,
): Promise<AccountDetails> => {
const current = await GetAccountDetails(accountDetails.id);
if (current instanceof AccountDetails) {
return await DataStore.save(
AccountDetails.copyOf(
current,
updated => {
if (params) {
for (const key in params) {
updated[key] = params[key];
}
}
},
),
);
}
accountDetails = accountDetails instanceof AccountDetails
? accountDetails
: new AccountDetails(accountDetails);
return await DataStore.save(accountDetails);
};
aws-exports.js
/* eslint-disable */
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.
const awsmobile = {
"aws_project_region": "",
"aws_cognito_identity_pool_id": "",
"aws_cognito_region": "",
"aws_user_pools_id": "",
"aws_user_pools_web_client_id": "",
"oauth": {},
"aws_cognito_username_attributes": [
"EMAIL"
],
"aws_cognito_social_providers": [],
"aws_cognito_signup_attributes": [],
"aws_cognito_mfa_configuration": "OFF",
"aws_cognito_mfa_types": [
"SMS"
],
"aws_cognito_password_protection_settings": {
"passwordPolicyMinLength": 8,
"passwordPolicyCharacters": [
"REQUIRES_LOWERCASE",
"REQUIRES_NUMBERS",
"REQUIRES_UPPERCASE"
]
},
"aws_cognito_verification_mechanisms": [
"EMAIL"
],
"aws_appsync_graphqlEndpoint": "*****",
"aws_appsync_region": "",
"aws_appsync_authenticationType": "API_KEY",
"aws_appsync_apiKey": "",
"aws_user_files_s3_bucket": "",
"aws_user_files_s3_bucket_region": "*"
};
package.json
{
"name": "#financiallease/react-native-amplify",
"version": "7.1.0",
"description": "",
"author": "itsupport#financiallease.nl",
"main": "dist/financiallease.js",
"module": "dist/financiallease.js",
"browser": "dist/financiallease.js",
"typings": "dist/financiallease.d.ts",
"types": "dist/financiallease.d.ts",
"license": "LGPL",
"scripts": {
"__BUNDLING": null,
"build:clean": "rimraf dist/",
"build": "npm run build:clean && rollup -c",
"bundle-local": "npm run build && npm pack && mv -v financiallease-react-native-amplify-*.tgz /usr/local/npm/#financiallease/react-native-amplify.tgz",
"__LINTING": null,
"autoformat": "npm run lint-typescript -- --fix && npm run lint-nodejs -- --fix",
"lint-nodejs": "eslint --config amplify/.eslintrc.js 'amplify/backend/function/**/index.js'",
"lint-typescript": "eslint --config .eslintrc.js '{src,test}/**/*.ts'",
"lint": "npm run lint-typescript && npm run lint-nodejs",
"coverage": "jest -c jest.config.ts --collectCoverage --coverageDirectory=\"./coverage\" --ci --reporters=default --reporters=jest-junit --watchAll=false",
"test": "jest -c jest.config.ts",
"__DOC GENERATION": null,
"docs:generate": "npm run build:clean && sed '/[[_TOC_]]/d' README.md > README.sanitized.md && typedoc --readme README.sanitized.md --entryPoints src --entryPointStrategy expand --out docs --theme hierarchy --name \"React Native Amplify - docs\" --includeVersion",
"docs:serve": "node -r esm --inspect docker/server.js",
"__AMPLIFY BACKEND": null,
"amplify-modelgen": "node amplify/scripts/amplify-modelgen.js",
"amplify-push": "node amplify/scripts/amplify-push.js",
"scan": "npm run build && npm run lint && npm run test && npm run docs:generate",
"upgrade-amplify-deps": "npx npm-check-updates -i '/(#?aws-amplify|#react-native-community/netinfo)/' && npm update"
},
"publishConfig": {
"#financiallease:registry": "https://gitlab.com/api/v4/projects/35071033/packages/npm/"
},
"dependencies": {
"#algolia/client-search": "^4.14.2",
"#algolia/transporter": "^4.14.2",
"#aws-amplify/core": "^4.7.2",
"#aws-amplify/datastore": "^3.12.8",
"#react-native-async-storage/async-storage": "^1.17.4",
"#react-native-community/netinfo": "^9.3.0",
"#types/amplify": "^1.1.25",
"aws-amplify": "^4.3.33",
"aws-amplify-react-native": "^6.0.5",
"aws-sdk": "^2.1142.0",
"deep-equal": "^2.0.5"
},
"devDependencies": {
"#aws-amplify/cli-extensibility-helper": "^2.3.33",
"#babel/core": "^7.17.9",
"#babel/preset-env": "^7.16.11",
"#babel/preset-typescript": "^7.16.7",
"#rollup/plugin-alias": "^3.1.9",
"#rollup/plugin-babel": "^5.3.1",
"#rollup/plugin-commonjs": "^21.0.3",
"#rollup/plugin-json": "^4.1.0",
"#rollup/plugin-multi-entry": "^4.1.0",
"#rollup/plugin-node-resolve": "^13.1.3",
"#rollup/plugin-typescript": "^8.3.1",
"#types/jest": "^27.4.1",
"#types/jest-when": "^3.5.2",
"#types/node": "^17.0.30",
"#typescript-eslint/eslint-plugin": "^5.35.1",
"#typescript-eslint/parser": "^5.18.0",
"aws-sdk-mock": "^5.7.0",
"babel-jest": "^28.0.3",
"babel-plugin-module-resolver": "^4.1.0",
"base64-js": "^1.5.1",
"eslint": "^8.12.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-jsdoc": "^39.2.9",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-sort-exports": "^0.6.0",
"esm": "^3.2.25",
"fetch-mock": "^9.11.0",
"isomorphic-unfetch": "^3.1.0",
"jest": "^27.5.1",
"jest-junit": "^13.2.0",
"jest-when": "^3.5.1",
"jsdoc": "^3.6.10",
"mustache": "^4.2.0",
"nodemon": "^2.0.16",
"prettier": "^2.7.1",
"rimraf": "^3.0.2",
"rollup": "^2.70.1",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-flat-dts": "^1.7.0",
"rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-ts": "^3.0.2",
"ts-node": "^10.7.0",
"tsconfig-paths": "^3.14.1",
"tslib": "^2.3.1",
"typedoc": "^0.22.15",
"typedoc-theme-hierarchy": "^1.1.1",
"typescript": "^4.6.3",
"uuid": "^8.3.2"
}
}
Logs from Sentry

This change was introduced in this PR to explicitly handle internal race conditions between overlapping clears/stops and starts/queries/mutations. Previously, DataStore consumers would see random, erratic transaction/locking/corruption errors that were uninstructive, difficult to recover from, or silent. This change raises the conflicts so consuming code can be aware of and handle those conflicts.
With that said, you just need to ensure DataStore.clear() resolves first, after making sure the query you're trying to run should be on the post-clear() side of that boundary! This could be as simple as a retry loop or a flag — or even using the clear() promise as your "flag".
Initialize your flag:
let onReady = Promise.resolve();
let isReady = true;
When you need to clear:
let onReady = DataStore.clear();
isReady = false;
onReady.then(() => isReady = true);
Then, for operations that should operate once the clear is complete:
async getResults() {
await onReady;
return DataStore.query(...);
}
And for those that should be canceled (no longer make sense) if they interrupt a clear, something like:
async getResults() {
if (isReady) {
return DataStore.query(...);
} else {
throw new Error(
"Sorry. We're still clearing data. Try again shortly."
);
}
}
I've provided a little more detail in the cross-post of this question on GitHub.

Related

Using a (Zustand) function mock with Jest results in "TypeError: create is not a function"

I'm following the Zustand wiki to implement testing, but the provided solution is not working for a basic test for app rendering. My project is built on top of the Electron React Boilerplate boilerplate project.
Here's the full error. Jest is using node with experimental-vm-modules because I followed the the Jest docs to support ESM modules.
$ cross-env NODE_OPTIONS=--experimental-vm-modules jest
(node:85003) ExperimentalWarning: VM Modules is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
jest-haste-map: Haste module naming collision: myproject
The following files share their name; please adjust your hasteImpl:
* <rootDir>/package.json
* <rootDir>/src/package.json
FAIL src/__tests__/App.test.tsx
● Test suite failed to run
TypeError: create is not a function
12 | }
13 |
> 14 | const useNotifs = create<NotifsState>(
| ^
15 | // devtools(
16 | (set) => ({
17 | notifStore: notifsDefault.notifStore,
at src/state/notifs.ts:14:19
at TestScheduler.scheduleTests (node_modules/#jest/core/build/TestScheduler.js:333:13)
at runJest (node_modules/#jest/core/build/runJest.js:387:19)
at _run10000 (node_modules/#jest/core/build/cli/index.js:408:7)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 11.882 s
Ran all test suites.
error Command failed with exit code 1.
At the top of the notifs.ts file, Zustand is imported normally with import create from 'zustand'.
Jest config in package.json:
...
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/config/mocks/fileMock.js",
"\\.(css|less|sass|scss)$": "identity-obj-proxy",
"zustand": "<rootDir>/src/__mocks__/zustand.js",
},
"transformIgnorePatterns": [
"node_modules/(?!(zustand)/)",
"<rootDir>/src/node_modules/"
],
"moduleDirectories": [
"node_modules",
"src/node_modules"
],
"moduleFileExtensions": [
"js",
"jsx",
"ts",
"tsx",
"json"
],
"moduleDirectories": [
"node_modules",
"src/node_modules"
],
"extensionsToTreatAsEsm": [
".ts",
".tsx"
],
...
I have left the ./src/__mocks__/zustand.js file exactly the same as from the Zustand wiki Testing page. I receive the same error whether or not I have zustand in the transformIgnorePatterns.
My Babel configuration includes [require('#babel/plugin-proposal-class-properties'), { loose: true }], in the plugins section, and output.library.type is 'commonjs2'
My tsconfig.json has compilerOptions.module set to "CommonJS", and the project's package.json "type" field is set to "commonjs".
Dependency versions:
"#babel/core": "^7.12.9",
"#babel/preset-env": "^7.12.7",
"#babel/preset-react": "^7.12.7",
"#babel/preset-typescript": "^7.12.7",
"#babel/register": "^7.12.1",
"#babel/plugin-proposal-class-properties": "^7.12.1",
"#testing-library/jest-dom": "^5.11.6",
"#testing-library/react": "^11.2.2",
"babel-jest": "^27.0.6",
"babel-loader": "^8.2.2",
"jest": "^27.0.6",
"regenerator-runtime": "^0.13.9",
"source-map-support": "^0.5.19",
"typescript": "^4.0.5",
"webpack": "^5.5.1",
"zustand": "^3.5.5"
I don't know what else could be relevant, just let me know if anything else is needed. Any and all help appreciated, thanks for your time.
To do this you should use the actual store of your app
const initialStoreState = useStore.getState()
beforeEach(() => {
useStore.setState(initialStoreState, true)
})
useStore.setState({ me: memberMockData, isAdmin: true })
The documentation seems off. So don't follow it.
use jest 28.0.0-alpha.0 will simply resolve the issue.
I think the problem is zustand uses '.mjs' as the entry point.

Running Unit and automation UI tests in one place in Jenkins and receive such Error: Failed to launch the browser process

For now we are execute unit tests together with UI automation and for now unit tests is passing OK, but ui automation receive Error: Failed to launch the browser process!
for now we have Jenkins file for both tests templates
stage('Build npm env and Execute AutomationTests'){
steps {
executeDocker(dockerImage: 'docker.wdf.sap.corp:50000/buildkite/puppeteer:latest', dockerWorkspace: '/home/piper'){
sh 'npm install'
sh 'npm update -g'
sh 'npx browserslist#latest --update-db'
}
}
}
stage('Update Build Badge'){
steps {
script {
def userIdCause = currentBuild.getBuildCauses('hudson.model.Cause$UserIdCause')
def userId = userIdCause[0].userId
gitCommit = sh(returnStdout: true, script: 'git rev-parse --short=8 HEAD').trim()
manager.addShortText('User: ' + userId + ' , Commit Sha: ' + gitCommit , "grey", "transparent", "0px", "white")
}
}
}
stage('Build UI Application and Execute UnitTests'){
steps {
executeDocker(dockerImage: 'node:14-stretch', dockerWorkspace: '/home/piper'){
sh 'npm install'
sh 'npm run build-dev'
sh 'npm run test'
stash name: "build", includes: 'dist/**, coverage/**'
}
}
}
also we have separate config files
this one for unit tests
module.exports = {
preset: "#vue/cli-plugin-unit-jest",
collectCoverage: true,
collectCoverageFrom: [
"src/**/*.{js,vue}",
"!src/main.js", // No need to cover bootstrap file
],
}
and this is config file for ui automation
module.exports = {
preset: "#vue/cli-plugin-unit-jest",
collectCoverage: true,
collectCoverageFrom: [
"src/**/*.{js,vue}",
"!src/main.js", // No need to cover bootstrap file
],
}
and setup file for ui automation
import puppeteer from "puppeteer"
jest.setTimeout(60000)
beforeAll(async () => {
global.browser = await puppeteer.launch({
headless: true,
slowMo: 0,
args: ["--disable-setuid-sandbox", "--no-sandbox"],
})
})
afterAll(() => {
global.browser.close()
})

How to merge Junit XML report in Cypress to integrate with AWS CB

I have initially used Mochaawesome report but cannot integrate with AWS. It turned out I need JUnit XML reporter in order to integrate with code build.
I've created Junit XML report but I don't know how to merge them into one xml file so that it can be used in AWS.
XML files got created (which I've been trying to merge them)
Cypress.json file
"reporter": "cypress-multi-reporters",
"reporterOptions": {
"reporterEnabled": "spec, mocha-junit-reporter",
"mochaJunitReporterReporterOptions": {
"mochaFile": "cypress/results/results-[hash].xml"
}
index.js file
"scripts": {
"delete:reports": "rm cypress/results/* || true",
"prereport": "delete:reports",
"report": "cypress run --reporter cypress-multi-reporters --reporter-options mochaFile=cypress/results/results-[hash].xml"
},
"dependencies": {
"cypress-multi-reporters": "^1.4.0",
"junit-report-merger": "^0.0.6",
"mocha": "^8.2.1",
"mocha-junit-reporter": "^2.0.0",
}
Command line (but it doesn't take the password so my tests all fail)
$ yarn report --env password=<password>
I've created a package specially for that purpose. It is called junit-report-merger.
You should write a Nodejs script which will use functions exported from that package:
merge.js
const path = require('path')
const {mergeFiles} = require('junit-report-merger')
const globby = require('globby')
const inputFiles = await globby(['results/report-*.xml'])
const outputFile = path.join(__dirname, 'results', 'combined-report.xml')
mergeFiles(
outputFile,
inputFiles,
err => {
if (err) {
console.error(err)
}
else {
console.log('successfully merged')
}
}
)
Once script is ready, you should run it after your tests. In your case, it will be something like this:
"scripts": {
"report": "cypress run --reporter cypress-multi-reporters --reporter-options mochaFile=cypress/results/results-[hash].xml",
"postreport": "node merge.js"
}
UPDATE
Just released version 1.0.0 of junit-report-merger, which has glob support, allows async/await and offers a CLI.
The code above still should work, but with that version, merge.js file from above can be written in a shorter way:
const path = require('path')
const {mergeFiles} = require('junit-report-merger')
const inputPattern = ['results/report-*.xml']
const outputFile = path.join(__dirname, 'results', 'combined-report.xml')
await mergeFiles(outputFile, inputPattern)
console.log('successfully merged')
But with version 1.0.0 you can avoid creating merge.js completely and use CLI instead.
Like this:
"scripts": {
"report": "cypress run --reporter cypress-multi-reporters --reporter-options mochaFile=cypress/results/results-[hash].xml",
"postreport": "jrm ./results/combined-report.xml \"./cypress/results/results-*.xml\""
}

Popper.js problem with Bootstrap modals in Laravel 5.8

I'm creating a web application based on Laravel 5.8 + Laravelmix + bootstrap + Vue
(which is how Lravel comes out of the box)
Problem is that bootstrap modals will not work - not out of the box at least.
If you try to trigger a modal you get an error in the console, regarding a popper map component (needed by jquery) that is there (in fact) but for some reason it doesn't get properly added to the mix.
This is a know problem: I found other questions and threads about this problem in Stackoverflow, however...
Problem in the problem: all existing QAs that i found take for granted that who reads knows quite a lot about npm webpack and laravel mix... and I don't! :-( I'm mostly a backend developer, not a frontend dev: I know basic Javascript but don't know much about webpack and I haven't been able to apply the suggested solutions to my case.
Could somebody explain to me in clear terms how my js assets should look like in order to work???
This is my webpack.mix file:
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
This is my resources/js/app.js file:
require('./bootstrap');
window.Vue = require('vue');
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
const app = new Vue({
el: '#app',
});
This is the beginning of my resoureces/js/bootstrap.js file looks like:
window._ = require('lodash');
try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');
require('bootstrap');
} catch (e) {}
window.axios = require('axios');
And finally this is my package.json file:
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "npm run development -- --watch",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.18",
"bootstrap": "^4.0.0",
"cross-env": "^5.1",
"jquery": "^3.2",
"laravel-mix": "^4.0.7",
"lodash": "^4.17.5",
"popper.js": "^1.12",
"resolve-url-loader": "2.3.1",
"sass": "^1.20.1",
"sass-loader": "7.*",
"vue": "^2.5.17",
"vue-template-compiler": "^2.6.10"
}
}

The Broccoli Plugin: [UglifyWriter] failed with

I've had this error for 2 weeks now while trying to build an ember app in production. Building it in dev environment works fine. I also realized that disabling minifyJs in ember-cli-build prevents the error but then, the app gets stuck at loading in the browser, and in the console, I see another error: "could not import ember-resolver".
My guess is that this is as a result of the UglifyWriter not understanding some code somewhere.
The full error is:
Build failed.
File: assets/vendor.js (95443:4)
The Broccoli Plugin: [UglifyWriter] failed with:
Error
at new JS_Parse_Error (eval at (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), :1545:18)
at js_error (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:1553:11)
at croak (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:2092:9)
at token_error (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:2100:9)
at unexpected (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:2106:9)
at semicolon (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:2126:56)
at simple_statement (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:2317:73)
at eval (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:2186:19)
at eval (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:2139:24)
at block_ (eval at <anonymous> (/home/larisoft/frontend/node_modules/uglify-js/tools/node.js:1:1), <anonymous>:2432:20)
The broccoli plugin was instantiated at:
at UglifyWriter.Plugin (/home/larisoft/frontend/node_modules/broccoli-plugin/index.js:7:31)
at new UglifyWriter (/home/larisoft/frontend/node_modules/broccoli-uglify-sourcemap/index.js:25:10)
at UglifyWriter (/home/larisoft/frontend/node_modules/broccoli-uglify-sourcemap/index.js:20:12)
at Class.postprocessTree (/home/larisoft/frontend/node_modules/ember-cli-uglify/index.js:15:50)
at /usr/local/lib/node_modules/ember-cli/lib/broccoli/ember-app.js:543:27
at Array.forEach (native)
at EmberApp.addonPostprocessTree (/usr/local/lib/node_modules/ember-cli/lib/broccoli/ember-app.js:541:23)
at EmberApp.toTree (/usr/local/lib/node_modules/ember-cli/lib/broccoli/ember-app.js:1667:15)
at module.exports (/home/larisoft/frontend/ember-cli-build.js:37:16)
at Class.setupBroccoliBuilder (/usr/local/lib/node_modules/ember-cli/lib/models/builder.js:70:19)
my package.json
{
"name": "hospitalrun",
"version": "0.9.12",
"description": "Ember front end for HospitalRun",
"homepage": "http://curacel.co",
"directories": {
"doc": "doc",
"test": "tests"
},
"scripts": {
"build": "./script/build",
"start": "./script/server",
"test": "snyk test && ./script/test"
},
"repository": {
"type": "git",
"url": "git#github.com:HospitalRun/hospitalrun-frontend"
},
"engines": {
"node": ">= 0.10.0"
},
"author": "John Kleinschmidt",
"contributors": [
"Joel Worrall",
"Joel Glovier"
],
"license": "GPL-3.0",
"devDependencies": {
"body-parser": "^1.14.2",
"broccoli-asset-rev": "^2.4.1",
"broccoli-export-text": "0.0.2",
"broccoli-funnel": "^1.0.1",
"broccoli-manifest": "0.0.7",
"broccoli-merge-trees": "^1.0.0",
"broccoli-serviceworker": "0.1.0",
"ember-ajax": "2.3.2",
"ember-cli": "^2.4.1",
"ember-cli-active-link-wrapper": "0.2.0",
"ember-cli-app-version": "^1.0.0",
"ember-cli-content-security-policy": "0.5.0",
"ember-cli-dependency-checker": "^1.2.0",
"ember-cli-deprecation-workflow": "0.2.2",
"ember-cli-fake-server": "0.3.1",
"ember-cli-htmlbars": "^1.0.7",
"ember-cli-htmlbars-inline-precompile": "^0.3.1",
"ember-cli-inject-live-reload": "^1.3.1",
"ember-cli-qunit": "^2.0.0",
"ember-cli-release": "1.0.0-beta.1",
"ember-cli-sass": "^5.2.1",
"ember-cli-scss-lint": "1.0.0",
"ember-cli-sri": "^2.1.0",
"ember-cli-uglify": "^1.2.0",
"ember-data": "^2.4.0",
"ember-disable-proxy-controllers": "^1.0.1",
"ember-export-application-global": "^1.0.4",
"ember-font-awesome": "2.1.1",
"ember-i18n": "4.2.1",
"ember-load-initializers": "^0.5.0",
"ember-pouch": "^3.1.0",
"ember-rapid-forms": "1.0.0-beta4",
"ember-resolver": "^2.0.3",
"ember-select-list": "0.9.5",
"ember-simple-auth": "^1.1.0-beta.3",
"ember-simple-auth-registration": "1.0.2",
"ember-suave": "2.0.1",
"ember-truth-helpers": "1.2.0",
"ember-validations": "2.0.0-alpha.4",
"express": "^4.8.5",
"glob": "^7.0.0",
"hospitalrun-dblisteners": "0.9.2",
"hospitalrun-server-routes": "0.9.7",
"loader.js": "^4.0.7",
"nano": "6.2.0",
"request": "2.72.0"
},
"dependencies": {
"ember-cli-babel": "^5.1.5",
"ember-cli-uglify": "^1.2.0",
"ember-radio-buttons": "^4.0.1",
"ember-resolver": "^2.1.0",
"snyk": "^1.14.1",
"sw-toolbox": "^3.1.1",
"uglify-js": "^2.7.4"
},
"ember-addon": {
"paths": [
"lib/pouch-fixtures"
]
}
}
My ember-cli-build:
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
// Add options here
});
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
app.import('vendor/pouchdb-list/pouchdb-list.js');
app.import('bower_components/node-uuid/uuid.js');
app.import('bower_components/bootstrap/dist/js/bootstrap.js');
app.import('bower_components/JsBarcode/CODE128.js');
app.import('bower_components/JsBarcode/JsBarcode.js');
app.import('vendor/dymo/DYMO.Label.Framework.1.2.6.js');
app.import('bower_components/moment/moment.js');
app.import('bower_components/typeahead.js/dist/typeahead.bundle.js');
app.import('bower_components/pikaday/pikaday.js');
app.import('bower_components/filer.js/src/filer.js');
app.import('bower_components/idb.filesystem/src/idb.filesystem.js');
app.import('bower_components/pikaday/css/pikaday.css');
app.import('vendor/octicons/octicons/octicons.css');
app.import('bower_components/pouchdb-load/dist/pouchdb.load.js');
app.import('bower_components/pouchdb/dist/pouchdb.memory.js');
return app.toTree();
};
It seems like uglify.js has some problems with ES6 files: https://forum.ionicframework.com/t/uglifyjs-fails-with-js-parse-error-error-but-no-stack-trace/66094. In my case it was enough to downgrade one library (fold-to-ascii) to an ES5 version.
Unfortunately, an error message isn't very helpful, so finding the problematic file is unnecessarily difficult. It's hard to tell which file causes the error in Your case, but I can at least say what helped me.
I manually put a log (with help from http://discuss.emberjs.com/t/debugging-failures-in-uglifyjs/7390/6):
function js_error(message, filename, line, col, pos) {
console.log(`message: ${message} / filename: ${filename} / line: ${line}`);
throw new JS_Parse_Error(message, filename, line, col, pos);
};
into js_error function of node_modules/uglify-js/lib/parse.js (line 205 in my case), and got a message that was actually helpful:
message: SyntaxError: Unexpected token: name (ASCIIFolder) / file: 0 / line: 64911 / position: 2070881
Then, with the find in path search on text "ASCIIFolder", I was able to locate the problematic files.
Also it may be necessary to do 'clean' install of npm and bower packages (https://emberigniter.com/update-latest-ember-data-cli/):
npm cache clean && bower cache clean
rm -rf node_modules bower_components dist tmp
npm install
bower install
Alternatively You can completely disable minifying of vendor.js with [https://ember-cli.com/asset-compilation#exclude-from-minification] (although it's not the greatest solution):
// ember-cli-build.js
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
minifyJS: {
options: {
exclude: ["**/vendor.js"]
}
}
});
//...
return app.toTree();
};
which tells broccoli-uglify-sourcemap to ignore vendor.js and, therefore, should prevent an error from happening.
UPDATE:
If you are not supporting IE9 browsers then you can use ember-cli-uglify#2.0.0 stable release for minification.
uglifyjs has problem in minifying the newer ES features, you can use ember-cli-babili to minify the javascript babili in Ember-CLI.
npm uninstall --save-dev ember-cli-uglify
npm install --save-dev ember-cli-babili
I am using it my app. It's mentioned by RWJBlue in his blog(http://rwjblue.com/2017/04/21/ember-cli-targets/)
I was tired of such errors, so I replaced uglify-js with upglify-es.
Using yarn and ember-cli:
yarn upgrade ember-cli-uglify#2.0.0-beta.1
In my case I got:
Build Error (UglifyWriter)
Unexpected token: eof (undefined)
The solution was to update ember-cli-moment-shim to version v3.8.0