initial commit

This commit is contained in:
weiss
2020-03-25 16:36:52 +01:00
parent 204e15f3c4
commit a9b452be04
20 changed files with 530 additions and 1 deletions

17
.eslintrc.js Normal file
View File

@@ -0,0 +1,17 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}

21
.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
.purs-repl Normal file
View File

@@ -0,0 +1 @@
import Prelude

View File

@@ -1,2 +1,18 @@
# pure-vue
Vue.js Purescript binding using Composition API
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
1. spago install arrays
3. spago install record-extra
1. vue create my_cool_project
2. cd my_cool_project
3. spago init
4. npm install vue-cli-plugin-pure-vue
5. vue invoke vue-cli-plugin-pure-vue
## Example Application
Check out Todo List [Example Application](https://https://github.com/smarwei/pure-vue-todo-example).

34
generator/index.js Normal file
View File

@@ -0,0 +1,34 @@
module.exports = (api, options) => {
api.render('./templateExampleApp')
if(options.createVueConfigJs.toLowerCase() === 'y') {
api.render('./template')
}
api.extendPackage({
dependencies: {
'@vue/composition-api': '^0.5.0'
},
devDependencies: {
"purs-loader": "^3.7.1"
}
})
api.injectImports(api.entryFile, `import VueCompositionApi from '@vue/composition-api'`)
module.exports.hooks = (api) => {
api.afterInvoke(() => {
const { EOL } = require('os')
const fs = require('fs')
const contentMain = fs.readFileSync(api.resolve(api.entryFile), { encoding: 'utf-8' })
const lines = contentMain.split(/\r?\n/g).reverse()
if (lines.findIndex(line => line.match(/Vue\.use.*VueCompositionApi.*/)) !== -1) return
const renderIndex = lines.findIndex(line => line.match(/import/))
lines[renderIndex-1] += `${EOL}Vue.use(VueCompositionApi);${EOL}`
lines.reverse()
fs.writeFileSync(api.entryFile, lines.join(EOL), { encoding: 'utf-8' })
})
}
}

View File

@@ -0,0 +1,16 @@
{-
Welcome to a Spago project!
You can edit this file as you like.
-}
{ name = "my-project"
, dependencies =
[ "arrays"
, "console"
, "effect"
, "psci-support"
, "record-extra"
, "typelevel-prelude"
]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs", "node_modules/vue-cli-plugin-pure-vue/src/**/*.purs", "test/**/*.purs" ]
}

View File

@@ -0,0 +1,21 @@
const path = require('path');
module.exports = {
chainWebpack: config => {
// Purescript Loader
config.module
.rule('purescript')
.test(/\.purs$/)
.use('purs-loader')
.loader('purs-loader')
.tap(() => ({
// bundle: true,
// spago: true,
src: [
path.join('src', '**', '*.purs'),
path.join('node_modules', 'vue-cli-plugin-pure-vue', 'src', '**', '*.purs'),
path.join('.spago', '**', 'src', '**', '*.purs'),
],
}))
},
}

View File

@@ -0,0 +1,52 @@
module App where
import Prelude
import Effect (Effect)
import Effect.Unsafe (unsafePerformEffect)
import Effect.Vue.Ref as Ref
import Effect.Vue.Hooks as Hooks
import Effect.Class.Console (logShow)
import Data.Array (snoc)
type Product = { id :: Int, title :: String, price :: Number }
createProduct :: Array Product -> Int -> String -> Number -> Array Product
createProduct products id title price = snoc products { id, title, price }
execCreateProduct :: Ref.Ref (Array Product) -> String -> Number -> Effect Unit
execCreateProduct products title price = do
p <- Ref.read products
let p' = createProduct p 42 title (23.666)
Ref.write p' products
incRelease :: Ref.Ref Int -> Effect Unit
incRelease release = Ref.modify_ (\x -> x + 1) release
compTest :: Ref.Ref Int -> Effect Int
compTest release = do
r <- Ref.read release
pure (r + 1)
type Props = {}
setup :: forall a. Props -> Effect a
setup props = unsafePerformEffect do
products :: Ref.Ref (Array Product) <- Ref.new []
showUserInfo <- Ref.new false
release <- Ref.new 9
computedTest <- Ref.computed $ compTest release
Hooks.onMounted mounted
Ref.vReturn { products
, showUserInfo
, release
, computedTest
, incRelease: (incRelease release)
, addProduct: (execCreateProduct products)
}
mounted :: Effect Unit
mounted = do
logShow "estasetase"

View File

@@ -0,0 +1,31 @@
<template>
<div>
<button
target="_blank"
@click="incRelease(); addProduct('mytit')(32)();"
/>
<span class="mr-2">Latest Release {{ release }}</span>
ctest - {{ computedTest }} -
<privacy-policy
:release="42"
></privacy-policy>
<!--router-view
:release="release"
></router-view-->
{{ products }}
</div>
</template>
<script>
import { setup } from '@/App.purs'
import PrivacyPolicy from './views/PrivacyPolicy'
export default {
name: 'App',
components: {
PrivacyPolicy,
},
setup
};
</script>

View File

@@ -0,0 +1,24 @@
module PrivacyPolicy where
import Prelude
import Effect (Effect)
import Effect.Unsafe (unsafePerformEffect)
import Effect.Vue.Ref as Ref
import Record.Extra as Record
import Data.Array as Arr
import Type.Row (RProxy(..))
type Props = ( release :: Int )
-- this to lib
-- type RecordProps = Record.Record Props
props = Record.keys (RProxy :: RProxy Props)
privacyPolicy :: String -> String
privacyPolicy policyRaw = policyRaw
buildSetup :: forall a. String -> _ -> Effect a
buildSetup policyRaw props = unsafePerformEffect do
dialog <- Ref.new true
Ref.vReturn { dialog, privacyPolicy: privacyPolicy policyRaw }

View File

@@ -0,0 +1,31 @@
<template>
<v-container>
<v-layout>
<v-card>
<v-card-title
class="headline grey lighten-2"
primary-title
>
Privacy Policy r {{ release }}
</v-card-title>
<v-card-text v-html="privacyPolicy()">
</v-card-text>
</v-card>
</v-layout>
</v-container>
</template>
<script>
import { buildSetup, props } from '@/views/PrivacyPolicy.purs'
export default {
name: 'PrivacyPolicy',
props,
setup: buildSetup('myprvipolicy'),
}
</script>
<style>
</style>

2
index.js Normal file
View File

@@ -0,0 +1,2 @@
module.exports = (api, options) => {
}

20
package.json Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "vue-cli-plugin-pure-vue",
"version": "0.1.0",
"description": "Purescript bindings for Vue.js using Compsition API",
"license": "Unlicense",
"repository": "smweiss/pure-vue",
"main": "index.js",
"keywords": [
"vue.js",
"vue",
"purescript",
"binding",
"smweiss"
],
"private": true,
"dependencies": {
},
"devDependencies": {
}
}

9
prompts.js Normal file
View File

@@ -0,0 +1,9 @@
module.exports = [
{
type: 'input',
name: 'createVueConfigJs',
message: 'Create vue.config.js (overrides if already existing)',
validate: input => ['Y', 'y', 'N', 'n'].includes(input),
default: 'Y'
},
]

28
src/Props.purs Normal file
View File

@@ -0,0 +1,28 @@
module Props where
import Prelude
type Props = Array PropType
data PropType = Int String
| String String
| Number String
-- | Object String
toProp :: PropType -> String
toProp (Int s) = s
toProp (String s) = s
toProp (Number s) = s
toProps :: Array PropType -> Array String
toProps = map toProp
-- class Proppable a where
-- toProps :: a -> Array String
--
-- --instance propProps :: Proppable Props
-- -- toProps p = Arr.fromFoldable $ Record.keys (RProxy :: RProxy Props)
--
-- type PropsRecord = Record Props
-- props = Arr.fromFoldable $ Record.keys (RProxy :: RProxy Props)

50
src/vueHooks.js Normal file
View File

@@ -0,0 +1,50 @@
"use strict";
var comp = require("@vue/composition-api");
// exports.onMounted = vue.onMounted
exports.onBeforeMount = function(eff) {
return function() {
comp.on(eff)
}
}
exports.onMounted = function(eff) {
return function() {
comp.onMounted(eff)
}
}
exports.onBeforeUpdate = function(eff) {
return function() {
comp.on(eff)
}
}
exports.onUpdated = function(eff) {
return function() {
comp.on(eff)
}
}
exports.onBeforeUnmount = function(eff) {
return function() {
comp.on(eff)
}
}
exports.onUnmounted = function(eff) {
return function() {
comp.on(eff)
}
}
exports.onActivated = function(eff) {
return function() {
comp.on(eff)
}
}
exports.onDeactivated = function(eff) {
return function() {
comp.on(eff)
}
}
exports.onErrorCaptured = function(eff) {
return function() {
comp.on(eff)
}
}

35
src/vueHooks.purs Normal file
View File

@@ -0,0 +1,35 @@
module Effect.Vue.Hooks
( onBeforeMount
, onMounted
, onBeforeUpdate
, onUpdated
, onBeforeUnmount
, onUnmounted
, onActivated
, onDeactivated
, onErrorCaptured
) where
import Prelude
import Effect (Effect)
import Effect.Class (class MonadEffect, liftEffect)
-- These lifecycle registration methods can only be used during the invocation of a setup hook.
-- It automatically figures out the current instance calling the setup hook using internal global state.
-- It is intentionally designed this way to reduce friction when extracting logic into external functions.
-- foreign import onMounted :: forall m a. MonadEffect m => a -> m Unit
foreign import onBeforeMount :: Effect Unit -> Effect Unit
foreign import onMounted :: Effect Unit -> Effect Unit
foreign import onBeforeUpdate :: Effect Unit -> Effect Unit
foreign import onUpdated :: Effect Unit -> Effect Unit
foreign import onBeforeUnmount :: Effect Unit -> Effect Unit
foreign import onUnmounted :: Effect Unit -> Effect Unit
foreign import onActivated :: Effect Unit -> Effect Unit
foreign import onDeactivated :: Effect Unit -> Effect Unit
foreign import onErrorCaptured :: Effect Unit -> Effect Unit
-- What about
-- onRenderTracked
-- onRenderTriggered
-- ?

57
src/vueRef.js Normal file
View File

@@ -0,0 +1,57 @@
"use strict";
var comp = require("@vue/composition-api");
// Ref
exports.vReturn = function(dict) {
return function() {
return dict
}
}
exports.new = function (val) {
return function () {
return comp.ref(val);
};
};
exports.read = function (ref) {
return function () {
return ref.value;
};
};
exports.modifyImpl = function (f) {
return function (ref) {
return function () {
var t = f(ref.value);
ref.value = t.state;
return t.value;
};
};
};
exports.write = function (val) {
return function (ref) {
return function () {
ref.value = val;
return {};
};
};
};
// Computed
exports.computed = function (fn) {
return function () {
return comp.computed(fn)
};
};
// to seperate module
// exports.setup = function (props) {
// }

57
src/vueRef.purs Normal file
View File

@@ -0,0 +1,57 @@
module Effect.Vue.Ref
( Ref
, new
, read
, modify'
, modify
, modify_
, write
, vReturn
, computed
) where
import Prelude
import Effect (Effect)
-- data Ref a = Ref a
-- foreign import ref :: forall a b. a -> Ref b
-- foreign import refVal :: forall a b. Ref a -> a
foreign import vReturn :: forall a b. a -> Effect b
-- | A value of type `Ref a` represents a mutable reference
-- | which holds a value of type `a`.
foreign import data Ref :: Type -> Type
-- | Create a new mutable reference containing the specified value.
foreign import new :: forall s. s -> Effect (Ref s)
-- | Read the current value of a mutable reference
foreign import read :: forall s. Ref s -> Effect s
-- | Update the value of a mutable reference by applying a function
-- | to the current value.
modify' :: forall s b. (s -> { state :: s, value :: b }) -> Ref s -> Effect b
modify' = modifyImpl
foreign import modifyImpl :: forall s b. (s -> { state :: s, value :: b }) -> Ref s -> Effect b
-- | Update the value of a mutable reference by applying a function
-- | to the current value. The updated value is returned.
modify :: forall s. (s -> s) -> Ref s -> Effect s
modify f = modify' \s -> let s' = f s in { state: s', value: s' }
modify_ :: forall s. (s -> s) -> Ref s -> Effect Unit
modify_ f s = void $ modify f s
-- | Update the value of a mutable reference to the specified value.
foreign import write :: forall s. s -> Ref s -> Effect Unit
-- |
-- | COMPUTED
-- |
foreign import computed :: forall a b. Effect a -> Effect (Ref b)

7
workspace.code-workspace Normal file
View File

@@ -0,0 +1,7 @@
{
"folders": [
{
"path": "."
}
]
}