willem@bijker.co.za
projects
codeQuery.ts
jsonDecode.ts
readme.md
vue-hydrate.html
codeQuery.ts
jsonDecode.ts
readme.md
vue-hydrate.html
1
// CodeQuery is a library that allows you to write SQL queries in a type-safe way using TypeScript.
2
// It's designed to be as close as SQL as possible, but with the benefits of TypeScript.
3
// Typescript is actually a very good fit because of it's mapping capabilities.
4
5
// first we create two tables users and logins
6
const users = createTable(sqliteProvider, "user", table => ({
7
    id: table.number(c => c.pk(true)),
8
    name: table.string(),
9
}));
10
11
const logins = createTable(sqliteProvider, "login", table => ({
12
    id: table.number(c => c.pk(true)),
13
    userId: table.number(c => c.fk(users.columns.id)),
14
    loginTime: table.number(),
15
    success: table.bool()
16
}));
17
18
// create a query that will return the amount of successful and failed logins per user
19
const counts = users.from()
20
    .innerJoin(logins, ({user, login}) => user.id.eq(login.userId))
21
    .groupBy(r => r.user.id)
22
    .select(r => ({
23
        userId: r.key,
24
        success: r.sum(l => l.login.success.when(true,1, 0)),
25
        fail: r.sum(l => l.login.success.when(false,1, 0))
26
    }), 'counts');
27
28
const query = await users.from()
29
    .innerJoin(counts, ({user, counts}) => user.id.eq(counts.userId))
30
    .select(r => ({
31
        userId: r.user.id,
32
        name: r.user.name,
33
        success: r.counts.success,
34
        fail: r.counts.fail
35
    }))
36
    .fetchAll();
37
38
/* this will produce the following SQL:
39
SELECT
40
    user.id,
41
    user.name,
42
    counts.success,
43
    counts.fail
44
FROM user
45
INNER JOIN (
46
    SELECT
47
        user.id,
48
        SUM(CASE WHEN login.success THEN 1 ELSE 0 END) as success,
49
        SUM(CASE WHEN NOT login.success THEN 1 ELSE 0 END) as fail
50
    FROM user
51
    INNER JOIN login ON user.id = login.userId
52
    GROUP BY user.id
53
) as counts ON user.id = counts.userId
54
 */
55
1
// When you use JSON.parse, TypeScript assumes the output to be of the type you specify, but it's not enforced on runtime.
2
// This could lead to potential runtime errors that are hard to catch
3
// Inspired by Elm decoders with a simple API
4
5
// a sample usage:
6
7
interface Dog {
8
    name: string;
9
    nickNames: string[];
10
    size: 'small' | 'medium' | 'large';
11
    // other properties including the breed
12
    properties: Record<string, string> & { breed: string; }
13
    birthDate?: Date;
14
}
15
16
// custom decoder for properties type
17
const propertiesDecoder: Decoder<Dog["properties"]> = {
18
    decode(obj: any): DecoderResult<Dog["properties"]> {
19
        // only if obj is an object and not null
20
        if (obj && typeof obj == "object") {
21
            // fill breed
22
            const props: Dog["properties"] = {breed: ''};
23
            // then the rest
24
            Object.keys(obj).forEach(k => {
25
                if (typeof obj[k] === 'string')
26
                    props[k] = obj[k];
27
            });
28
            return resolve(props);
29
        }
30
        return fallback();
31
    }, fallback(): Dog["properties"] {
32
        return {breed: ''};
33
    }
34
}
35
36
37
const dogDecoder = decodeObject<Dog>({
38
    name: decodeString,
39
    nickNames: decodeArray(decodeString),
40
    size: decodeUnionLiterals('small', 'medium', 'large'),
41
    birthDate: decodeOptional(decodeDate),
42
    properties: propertiesDecoder
43
})
44
45
const jsonString = '...';
46
const dog: Dog = decode.parse(dogDecoder, jsonString);
47
// dog is now always safe to use
48
1
Since primary school, I've been writing programs and messing around with code.
2
Not only by what it does, but by the way it's structured and presented. 
3
I call it abstract art in it's finest form. I even wrote my wife a love letter in code.
4
My big motto: know what you are doing. Spent time to things you don't understand - it's always pays off on the long run.
5
6
Feel free to browse and look through my projects. 
1
<!--This tiny utility will enable you to use Vue in a declarative way in your static markup with some added benefits. No code needed to create and mount a Vue instance - it's all part of your markup. This utility is really small (<100 lines, 1Kb) and doesn't do anything on its own. It's only brings the power of Vue in a another way. -->
2
<!--Vue is already bundles in this package. Note you only need to include the packge. Nothing more.-->
3
4
<a href="https://github.com/itechodev/vue-hydrate">Github repo</a>
5
6
<script src="https://unpkg.com/vue-hydrate@1.0/dist/vue-hydrate-bundle.js"></script>
7
8
<!--You can use any of Vue's rich feature sets. Start learning from https://vuejs.org/v2/guide/#Declarative-Rendering. -->
9
<!--Vue-hydate adds the following 4 features:-->
10
11
<div v-data="{message: 'Hydration works', count: 1}" ref="first">
12
    <div @click="count++">{{ message }} with count: {{ count }}</div>
13
</div>
14
15
<div v-data="data">
16
    <div @click="inc">{{ message }} with count: {{ count }}</div>
17
</div>
18
19
<script>
20
21
    var data = {
22
        count: 1,
23
        mounted() {
24
            console.log('Instance mounted');
25
        },
26
        message: 'Increase both',
27
        inc() {
28
            this.count++;
29
            this.$instances.first.count++;
30
        }
31
    }
32
</script>
33