Compare commits

...
Sign in to create a new pull request.

30 commits

Author SHA1 Message Date
bd56e44585
Merge pull request #60 from chris-kruining/renovate/actions-checkout-5.x 2025-08-12 10:37:39 +02:00
renovate[bot]
9cb1984c8f
Update actions/checkout action to v5 2025-08-11 13:38:03 +00:00
02a980eb79
Merge pull request #59 from chris-kruining/renovate/gittools-actions-4.x 2025-08-07 13:51:58 +02:00
renovate[bot]
a238acf0db
Update gittools/actions action to v4.1.0 2025-08-07 11:27:35 +00:00
Chris Kruining
2595c53f83
fix formatting? 2025-07-21 16:20:58 +02:00
Chris Kruining
155b82cbea
update az cli 2025-07-21 16:12:55 +02:00
Chris Kruining
12e3cf2f85
fix dockerfile 2025-07-21 15:41:42 +02:00
Chris Kruining
e59c210ef4
just remove the config file and fall back to gitversion defaults 2025-07-21 15:30:45 +02:00
Chris Kruining
1fec60d46e
remove old input 2025-07-21 15:29:20 +02:00
Chris Kruining
8401ac9593
remove another param 2025-07-21 15:28:17 +02:00
Chris Kruining
d78e75e9c7
remove param 2025-07-21 15:27:12 +02:00
Chris Kruining
28f272b75b
spelling is an art... 2025-07-21 15:26:16 +02:00
Chris Kruining
7a7ceceead
fix gitversion config 2025-07-21 15:24:23 +02:00
Chris Kruining
253ad2e1bc
update gitversion 2025-07-21 15:20:20 +02:00
Chris Kruining
2a238bb835
Merge branch 'main' of https://github.com/chris-kruining/calque 2025-07-21 15:18:25 +02:00
Chris Kruining
1c31ef575a
update deps 2025-07-21 15:18:23 +02:00
f9c65835fd
Merge pull request #58 from chris-kruining/renovate/gittools-actions-4.x 2025-07-09 07:38:01 +02:00
renovate[bot]
8ae594d1f5
Update gittools/actions action to v4.0.1 2025-07-07 23:33:51 +00:00
bda74f01f9
Merge pull request #57 from chris-kruining/renovate/gittools-actions-4.x 2025-07-01 13:20:45 +02:00
renovate[bot]
ddcd451b49
Update gittools/actions action to v4 2025-06-30 10:58:03 +00:00
Chris Kruining
ce5b962e10
update deps 2025-06-23 16:23:17 +02:00
Chris Kruining
c58b597318
replace custom json parser with json.parse as it does preserve the key order after all, it is chrome devtools that sorts them 2025-06-23 16:19:45 +02:00
e7c0a762eb
Merge pull request #56 from chris-kruining/renovate/vitest-monorepo 2025-06-19 09:21:35 +02:00
renovate[bot]
01086b6e9b
Update vitest monorepo to v3.2.4 2025-06-17 20:13:51 +00:00
34eee3d2c1
Merge pull request #55 from chris-kruining/renovate/major-happy-dom-monorepo 2025-06-11 08:30:37 +02:00
renovate[bot]
01b65d337b
Update dependency @happy-dom/global-registrator to v18 2025-06-10 23:05:20 +00:00
c5f9fec9e9
Merge pull request #53 from chris-kruining/renovate/microsoft.resources-resourcegroups-20250401.x 2025-06-10 12:32:43 +02:00
2b749e4c63
Merge pull request #54 from chris-kruining/renovate/vitest-monorepo 2025-06-10 12:32:23 +02:00
renovate[bot]
24da21e722
Update vitest monorepo to v3.2.3 2025-06-09 12:11:48 +00:00
renovate[bot]
db04ee25e4
Update resource Microsoft.Resources/resourceGroups to 2025-04-01 2025-05-28 14:40:34 +00:00
8 changed files with 723 additions and 870 deletions

View file

@ -27,25 +27,23 @@ jobs:
semver: ${{ steps.gitversion.outputs.SemVer }}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Install GitVersion
uses: gittools/actions/gitversion/setup@v3.2.1
uses: gittools/actions/gitversion/setup@v4.1.0
with:
versionSpec: "5.x"
versionSpec: "6.x"
- name: Determine Version
id: gitversion
uses: gittools/actions/gitversion/execute@v3.2.1
with:
useConfigFile: true
uses: gittools/actions/gitversion/execute@v4.1.0
build_and_publish:
name: Build & Publish
runs-on: ubuntu-latest
needs: versionize
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Build container images
run: |
@ -73,7 +71,7 @@ jobs:
matrix:
environment: [ 'prd' ]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
sparse-checkout: |
infrastructure
@ -86,13 +84,13 @@ jobs:
subscription-id: ${{ secrets.CALQUE_PRD_SUBSCRIPTION_ID }}
- name: Deploy bicep
uses: Azure/cli@v2
uses: azure/cli@v2
with:
azcliversion: 2.66.0
inlineScript: |
az deployment sub create \
--location westeurope \
--template-file infrastructure/main.bicep \
--parameters infrastructure/params/${{ matrix.environment }}.bicepparam \
--parameters version=${{needs.versionize.outputs.semver}} \
--parameters registryUrl=${{ secrets.ACR_LOGIN_SERVER }}
azcliversion: 2.75.0
inlineScript: >-
az deployment sub create
--location westeurope
--template-file infrastructure/main.bicep
--parameters infrastructure/params/${{ matrix.environment }}.bicepparam
--parameters version=${{needs.versionize.outputs.semver}}
--parameters registryUrl=${{ secrets.ACR_LOGIN_SERVER }}

View file

@ -4,16 +4,17 @@ WORKDIR /usr/src/app
FROM base AS install
RUN mkdir -p /temp/dev
COPY package.json bun.lock /temp/dev
COPY patches/ /temp/dev/patches/
RUN cd /temp/dev && bun install --frozen-lockfile
RUN mkdir -p /temp/prod
COPY package.json bun.lock /temp/prod/
COPY patches/ /temp/prod/patches/
RUN cd /temp/prod && bun install --frozen-lockfile --production
FROM base AS prerelease
COPY --from=install /temp/dev/node_modules node_modules
COPY . .
# RUN echo "SESSION_SECRET=$(head -c 64 /dev/random | base64)" > .env
ENV NODE_ENV=production
ENV SERVER_PRESET=bun

View file

@ -1,20 +0,0 @@
assembly-versioning-scheme: MajorMinorPatch
assembly-file-versioning-scheme: MajorMinorPatchTag
assembly-informational-format: "{InformationalVersion}"
mode: Mainline
tag-prefix: "[vV]"
continuous-delivery-fallback-tag: ci
major-version-bump-message: '\+semver:\s?(breaking|major)'
minor-version-bump-message: '\+semver:\s?(feature|minor)'
patch-version-bump-message: '\+semver:\s?(fix|patch)'
no-bump-message: '\+semver:\s?(none|skip)'
legacy-semver-padding: 4
build-metadata-padding: 4
commits-since-version-source-padding: 4
commit-message-incrementing: Enabled
branches: {}
ignore:
sha: []
increment: Inherit
commit-date-format: yyyy-MM-dd
merge-message-formats: {}

1286
bun.lock

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,7 @@ var context = {
deployedAt: deployedAt
}
resource calqueResourceGroup 'Microsoft.Resources/resourceGroups@2025-03-01' = {
resource calqueResourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' = {
name: 'rg-${locationAbbreviation}-${environment}-${projectName}'
location: location
}

View file

@ -6,50 +6,50 @@
"bun": ">=1"
},
"dependencies": {
"@solid-primitives/clipboard": "^1.6.0",
"@solid-primitives/destructure": "^0.2.0",
"@solid-primitives/i18n": "^2.2.0",
"@solid-primitives/scheduled": "^1.5.0",
"@solid-primitives/selection": "^0.1.0",
"@solid-primitives/storage": "^4.3.1",
"@solid-primitives/timer": "^1.4.0",
"@solid-primitives/clipboard": "^1.6.2",
"@solid-primitives/destructure": "^0.2.2",
"@solid-primitives/i18n": "^2.2.1",
"@solid-primitives/scheduled": "^1.5.2",
"@solid-primitives/selection": "^0.1.3",
"@solid-primitives/storage": "^4.3.3",
"@solid-primitives/timer": "^1.4.2",
"@solidjs/meta": "^0.29.4",
"@solidjs/router": "^0.15.3",
"@solidjs/start": "^1.1.0",
"@solidjs/start": "^1.1.7",
"dexie": "^4.0.11",
"flag-icons": "^7.3.2",
"flag-icons": "^7.5.0",
"iterator-helpers-polyfill": "^3.0.1",
"rehype-parse": "^9.0.1",
"rehype-remark": "^10.0.0",
"rehype-remark": "^10.0.1",
"rehype-stringify": "^10.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.1",
"remark-rehype": "^11.1.2",
"remark-stringify": "^11.0.0",
"sitemap": "^8.0.0",
"solid-icons": "^1.1.0",
"solid-js": "^1.9.4",
"ts-pattern": "^5.6.2",
"solid-js": "^1.9.7",
"ts-pattern": "^5.7.1",
"unified": "^11.0.5",
"unist-util-find": "^3.0.0",
"unist-util-visit": "^5.0.0",
"vinxi": "^0.5.3"
"vinxi": "^0.5.8"
},
"devDependencies": {
"@happy-dom/global-registrator": "^17.0.3",
"@happy-dom/global-registrator": "^18.0.1",
"@sinonjs/fake-timers": "^14.0.0",
"@solidjs/testing-library": "^0.8.10",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/user-event": "^14.6.1",
"@types/sinonjs__fake-timers": "^8.1.5",
"@types/wicg-file-system-access": "^2023.10.5",
"@vitest/coverage-istanbul": "3.1.4",
"@vitest/coverage-v8": "3.1.4",
"bun-types": "^1.2.2",
"jsdom": "^26.0.0",
"solid-devtools": "^0.34.0",
"vite-plugin-solid": "^2.11.2",
"@types/wicg-file-system-access": "^2023.10.6",
"@vitest/coverage-istanbul": "3.2.4",
"@vitest/coverage-v8": "3.2.4",
"bun-types": "^1.2.19",
"jsdom": "^26.1.0",
"solid-devtools": "^0.34.3",
"vite-plugin-solid": "^2.11.7",
"vite-plugin-solid-svg": "^0.8.1",
"vitest": "^3.0.6",
"vitest": "^3.2.4",
"workbox-window": "^7.3.0"
},
"scripts": {

View file

@ -12,7 +12,7 @@ interface Contents extends Map<string, Map<string, string>> { }
export const read = (file: File): Promise<Map<string, string> | undefined> => {
switch (file.type) {
case 'application/json': return json.load(file.stream());
case 'application/json': return json.load(file.text());
default: return Promise.resolve(undefined);
}

View file

@ -1,200 +1,20 @@
import { decode } from "~/utilities";
export async function load(stream: ReadableStream<Uint8Array>): Promise<Map<string, string>> {
return new Map(await Array.fromAsync(parse(stream), ({ key, value }) => [key, value]));
}
export async function load(text: Promise<string>): Promise<Map<string, string>> {
const source = JSON.parse(await text);
const result = new Map();
const candidates = Object.entries(source);
interface Entry {
key: string;
value: string;
}
while (candidates.length !== 0) {
const [ key, value ] = candidates.shift()!;
interface State {
(token: Token): State;
entry?: Entry
}
const states = {
none(): State {
return (token: Token) => {
if (token.kind === 'braceOpen') {
return states.object();
}
return states.none;
};
},
object({ path = [], expect = 'key' }: Partial<{ path: string[], expect: 'key' | 'colon' | 'value' }> = {}): State {
return (token: Token) => {
switch (expect) {
case 'key': {
if (token.kind === 'braceClose') {
return states.object({
path: path.slice(0, -1),
expect: 'key',
});
}
else if (token.kind === 'string') {
return states.object({
path: [...path, token.value],
expect: 'colon'
});
}
return states.error(`Expected a key, got ${token.kind} instead`);
}
case 'colon': {
if (token.kind !== 'colon') {
return states.error(`Expected a ':', got ${token.kind} instead`);
}
return states.object({
path,
expect: 'value'
});
}
case 'value': {
if (token.kind === 'braceOpen') {
return states.object({
path,
expect: 'key',
});
}
else if (token.kind === 'string') {
const next = states.object({
path: path.slice(0, -1),
expect: 'key',
});
next.entry = { key: path.join('.'), value: decode(token.value) };
return next
}
return states.error(`Invalid value type found '${token.kind}'`);
}
}
return states.none();
if (typeof value !== 'object' || value === null || value === undefined) {
result.set(key, decode(value as string));
}
},
error(message: string): State {
throw new Error(message);
return states.none();
},
} as const;
async function* parse(stream: ReadableStream<Uint8Array>): AsyncGenerator<any, void, unknown> {
let state = states.none();
for await (const token of tokenize(read(toGenerator(stream)))) {
try {
state = state(token);
}
catch (e) {
console.error(e);
break;
}
if (state.entry) {
yield state.entry;
else {
candidates.unshift(...Object.entries(value).map<[string, any]>(([ k, v ]) => [`${key}.${k}`, v]));
}
}
}
async function* take<T>(iterable: AsyncIterable<T>, numberToTake: number): AsyncGenerator<T, void, unknown> {
let i = 0;
for await (const entry of iterable) {
yield entry;
i++;
if (i === numberToTake) {
break;
}
}
}
type Token = { start: number, length: number } & (
| { kind: 'braceOpen' }
| { kind: 'braceClose' }
| { kind: 'colon' }
| { kind: 'string', value: string }
);
async function* tokenize(characters: AsyncIterable<number>): AsyncGenerator<Token, void, unknown> {
let buffer: string = '';
let clearBuffer = false;
let start = 0;
let i = 0;
for await (const character of characters) {
if (buffer.length === 0) {
start = i;
}
buffer += String.fromCharCode(character);
const length = buffer.length;
if (buffer === '{') {
yield { kind: 'braceOpen', start, length };
clearBuffer = true;
}
else if (buffer === '}') {
yield { kind: 'braceClose', start, length };
clearBuffer = true;
}
else if (buffer === ':') {
yield { kind: 'colon', start, length };
clearBuffer = true;
}
else if (buffer.length > 1 && buffer.startsWith('"') && buffer.endsWith('"') && buffer.at(-2) !== '\\') {
yield { kind: 'string', start, length, value: buffer.slice(1, buffer.length - 1) };
clearBuffer = true;
}
else if (buffer === ',') {
clearBuffer = true;
}
else if (buffer.trim() === '') {
clearBuffer = true;
}
if (clearBuffer) {
buffer = '';
clearBuffer = false;
}
i++;
}
}
async function* read(chunks: AsyncIterable<Uint8Array>): AsyncGenerator<number, void, unknown> {
for await (const chunk of chunks) {
for (const character of chunk) {
yield character;
}
}
}
async function* toGenerator<T>(stream: ReadableStream<T>): AsyncGenerator<T, void, unknown> {
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
yield value;
}
}
finally {
reader.releaseLock();
}
return result;
}