@frontstackdev/cli 0.0.0-canary-20240830084913 → 0.0.0-canary-20240831065733

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,139 @@
1
+ /**
2
+ * This file was automatically generated using the
3
+ * Frontstack CLI, please do not edit it manually!
4
+ */
5
+
6
+ import { ofetch } from 'ofetch'
7
+ import type { BlockEndpoints, BlockParameters, BlockResponses, RequestOptions, BlockQueryFilters, BlockMode, Page } from './generated-types'
8
+ import type { Query } from './query-types'
9
+
10
+ type Method = 'GET' | 'POST' | 'PUT' | 'DELETE'
11
+
12
+ const endpoints: BlockEndpoints = {
13
+ {{#each paths}}
14
+ {{#if (endsWith this.get.operationId "Block")}}
15
+ {{this.summary}}: '{{@key}}',
16
+ {{/if}}
17
+ {{/each}}
18
+ }
19
+
20
+ const invoke = (path: string, method: Method, payload: any, headers: any) => {
21
+ const _headers: any = {
22
+ 'Content-Type': 'application/json',
23
+ 'Accept': 'application/json',
24
+ }
25
+
26
+ // Merge headers
27
+ headers = { ..._headers, ...headers }
28
+
29
+ let options: any = {
30
+ method,
31
+ headers,
32
+ body: payload
33
+ }
34
+
35
+ return ofetch(path, options)
36
+ }
37
+
38
+ /* Listing servers, even though only the first one is ever used */
39
+ const servers = {
40
+ {{#each servers}}
41
+ {{@key}}: {
42
+ description: '{{description}}',
43
+ url: '{{url}}'
44
+ },
45
+ {{/each}}
46
+ }
47
+
48
+ /**
49
+ * Frontstack Client
50
+ */
51
+ const client = {
52
+ /**
53
+ * Fetch a block with parameters
54
+ *
55
+ * @param blockName The name of the block to fetch
56
+ * @example 'VariantCard'
57
+ * @param blockParameters The parameters to pass to the block
58
+ * @example { key: '<variant-id>' }
59
+ * @param config Further configuration options
60
+ * @example { query: { filter: { type: 'equals', field: 'name', value: 'Red Dress' } } }
61
+ */
62
+ block: <BlockName extends keyof BlockEndpoints>(
63
+ blockName: BlockName,
64
+ blockParameters: BlockParameters[BlockName],
65
+ config?: (
66
+ BlockMode[BlockName] extends 'query' ?
67
+ {
68
+ /**
69
+ * Query parameters to pass to the block:
70
+ * - `filter` accepts an array of filter objects to filter results
71
+ * - `sort` accepts an array of sorting options to sort results
72
+ * - `search` to perform a text search
73
+ * - `limit` to limit the number of results returned
74
+ * - `page` to paginate results
75
+ */
76
+ query?: Query<BlockQueryFilters[BlockName]>
77
+ } : {}
78
+ ) &
79
+ {
80
+ /**
81
+ * Additional configuration options:
82
+ * - `requestUrl` to provide a URL that will be used to track the origin of the request
83
+ */
84
+ options?: BlockOptions
85
+ }
86
+ ): Promise<BlockResponses[BlockName]> => {
87
+ let endpoint: string = `${servers[0].url}${endpoints[blockName]}`;
88
+
89
+ // If payload contains `key` replace '{key}' in the endpoint
90
+ if(blockParameters.key) {
91
+ endpoint = endpoint.replace('{key}', blockParameters.key)
92
+ delete blockParameters.key
93
+ }
94
+
95
+ // Merge block parameters with query
96
+ let payload = { ...blockParameters, ...config?.query }
97
+
98
+ let headers: Record<string, string> = {}
99
+
100
+ if(config?.options?.requestUrl !== undefined) {
101
+ headers['fs-request-url'] = config.options.requestUrl
102
+ }
103
+ if (config?.options?.contextKey !== undefined) {
104
+ headers["fs-token"] = config.options.contextKey;
105
+ }
106
+
107
+ return invoke(endpoint, 'POST', payload, headers)
108
+ },
109
+
110
+ /**
111
+ * Fetch a page by its slug
112
+ * @param slug The URL slug of the page (without protocol)
113
+ * @example my-brand.com/uk/women/shoes/running
114
+ *
115
+ * @returns The page data
116
+ * @example { data: { title: 'Running Shoes' }, type: 'ProductCategory', urls: [] }
117
+ */
118
+ page: async (
119
+ slug: string | string[],
120
+ config?: {
121
+ options?: RequestOptions
122
+ }
123
+ ): Promise<Page> => {
124
+ let endpoint: string = `${servers[0].url}/page/${slug}`;
125
+
126
+ let headers: Record<string, string> = {}
127
+
128
+ if(config?.options?.requestUrl !== undefined) {
129
+ headers['fs-request-url'] = config.options.requestUrl
130
+ }
131
+ if (config?.options?.contextKey !== undefined) {
132
+ headers["fs-token"] = config.options.contextKey;
133
+ }
134
+
135
+ return invoke(endpoint, 'POST', {}, headers)
136
+ }
137
+ }
138
+
139
+ export default client
@@ -0,0 +1,150 @@
1
+ /**
2
+ * This file was automatically generated using the
3
+ * Frontstack CLI, please do not edit it manually!
4
+ */
5
+
6
+ export type Filter<T> = EqualsFilter<T> | RangeFilter<T> | ContainsFilter<T> | LogicalFilter<T>;
7
+
8
+ /**
9
+ * Helper Types
10
+ */
11
+ type NumericKeys<T> = {
12
+ [K in keyof T]: T[K] extends number ? K : never
13
+ }[keyof T];
14
+
15
+ type EnumKeys<T> = {
16
+ [K in keyof T]: T[K] extends string ? (string extends T[K] ? never : K) : never
17
+ }[keyof T];
18
+
19
+ // All string keys that are not enums
20
+ type StringKeys<T> = {
21
+ [K in keyof T]: T[K] extends string ? K : never
22
+ }[keyof T] & Exclude<keyof T, EnumKeys<T>>;
23
+
24
+ /**
25
+ * Filter a field by equality. You can use an array of values to filter by multiple values
26
+ *
27
+ * @example
28
+ * {
29
+ * type: 'equals',
30
+ * field: 'name',
31
+ * value: ['Red Dress', 'Blue Dress']
32
+ * }
33
+ */
34
+ export type EqualsFilter<T> = {
35
+ [K in keyof T]: {
36
+ type: 'equals';
37
+ field: K;
38
+ value: T[K] | T[K][];
39
+ }
40
+ }[keyof T];
41
+
42
+ /**
43
+ * Filter a field by a range. You can use either from, to or both
44
+ *
45
+ * @example
46
+ * {
47
+ * type: 'range',
48
+ * field: 'price',
49
+ * from: 10,
50
+ * to: 100
51
+ * }
52
+ */
53
+ export type RangeFilter<T> = {
54
+ [K in NumericKeys<T>]: {
55
+ type: 'range';
56
+ field: K;
57
+ from?: T[K];
58
+ to?: T[K];
59
+ }
60
+ }[NumericKeys<T>];
61
+
62
+ /**
63
+ * Filter a field by a substring match.
64
+ *
65
+ * @example
66
+ * {
67
+ * type: 'contains',
68
+ * field: 'name',
69
+ * value: 'Dress'
70
+ * }
71
+ */
72
+ export type ContainsFilter<T> = {
73
+ [K in StringKeys<T>]: {
74
+ type: 'contains';
75
+ field: K;
76
+ value: string;
77
+ }
78
+ }[StringKeys<T>];
79
+
80
+ /**
81
+ * Combine multiple filters with a logical operator
82
+ *
83
+ * @example
84
+ * {
85
+ * type: 'and',
86
+ * filters: [
87
+ * {
88
+ * type: 'equals',
89
+ * field: 'name',
90
+ * value: 'Red Dress'
91
+ * },
92
+ * {
93
+ * type: 'range',
94
+ * field: 'price',
95
+ * from: 10,
96
+ * to: 100
97
+ * }
98
+ * ]
99
+ * }
100
+ */
101
+ export type LogicalFilter<T> = {
102
+ type: 'and' | 'or';
103
+ filters: Filter<T>[];
104
+ }
105
+
106
+ export type SortField<T> = keyof T;
107
+
108
+ /**
109
+ * Sort results by a field and direction
110
+ *
111
+ * @example
112
+ * {
113
+ * field: 'price',
114
+ * direction: 'asc'
115
+ * }
116
+ */
117
+ export type Sort<T> = {
118
+ field: SortField<T >;
119
+ direction: 'asc' | 'desc';
120
+ }
121
+
122
+
123
+ export type Query<T> = {
124
+ /**
125
+ * Filter results by a set of conditions
126
+ */
127
+ filter?: Filter<T>[];
128
+ /**
129
+ * Will search fields that are marked as searchable
130
+ */
131
+ search?: string;
132
+ /**
133
+ * Sort results by a field and direction
134
+ *
135
+ * There are three ways to sort:
136
+ *
137
+ * * A single sort object
138
+ * * An array of sort objects
139
+ * * A single sort field
140
+ */
141
+ sort?: Sort<T> | Sort<T>[] | SortField<T>;
142
+ /**
143
+ * Limit the number of results returned
144
+ */
145
+ limit?: number;
146
+ /**
147
+ * Paginate results
148
+ */
149
+ page?: number;
150
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * This file was automatically generated using the
3
+ * Frontstack CLI, please do not edit it manually!
4
+ */
5
+
6
+ import type { components } from './fetch-api.d.ts'
7
+
8
+ /* Frontstack default types */
9
+
10
+ type SearchQuery = components['schemas']['SearchQuery']
11
+ type Media = components['schemas']['Media']
12
+
13
+ type RequestOptions = {
14
+ /**
15
+ * @description URL to the current page
16
+ *
17
+ * Optionally, Frontstack accepts a URL to the current page. This is useful for tracking purposes.
18
+ */
19
+ requestUrl?: string
20
+
21
+ /**
22
+ * @description Context key
23
+ *
24
+ * Providing a context key will override the default context key for the request
25
+ */
26
+ contextKey?: string
27
+ }
28
+
29
+ /* List of all types used to fetch block parameters */
30
+
31
+ {{#each paths}}{{#if (endsWith this.get.operationId "Block")}}export type {{this.summary}}Parameters = {
32
+ {{#each this.get.parameters}}
33
+ {{#if @first}}{{else}}
34
+ {{/if}}
35
+ /**
36
+ * @description {{description}}
37
+ */
38
+ {{name}}{{#unless required}}?{{/unless}}: {{{getSchemaType schema}}};
39
+ {{/each}}
40
+ }
41
+
42
+ {{/if}}{{/each}}
43
+ /* List of all blocks, used for IDE autocompletion */
44
+
45
+ type BlockParameters = {
46
+ {{#each components.schemas}}
47
+ {{#if (contains tags "blocks")}}
48
+ {{@key}}: {{@key}}Parameters
49
+ {{/if}}
50
+ {{/each}}
51
+ }
52
+
53
+ type BlockEndpoints = {
54
+ [key in keyof BlockParameters]: string;
55
+ }
56
+
57
+ declare global {
58
+ {{#each components.schemas}}
59
+ {{#if (contains tags "blocks")}}
60
+ export type {{@key}} = {
61
+ {{#each properties}}
62
+ {{@key}}: {{{getSchemaType this}}}
63
+ {{/each}}
64
+ }
65
+ {{/if}}
66
+ {{/each}}
67
+ }
68
+ {{!--
69
+
70
+ The loop below would work as well, but it makes all parameters optional, which leads to bad DX
71
+ Solve later
72
+
73
+ {{#each components.schemas}}
74
+ {{#if (contains tags "blocks")}}
75
+ export type {{@key}} = components['schemas']['{{@key}}']
76
+ {{/if}}
77
+ {{/each}}
78
+ --}}
79
+ type BlockResponses = {
80
+ {{#each components.schemas}}
81
+ {{#if (contains tags "blocks")}}
82
+ {{@key}}: {{@key}}
83
+ {{/if}}
84
+ {{/each}}
85
+ }
86
+
87
+ type BlockQueryFilters = {
88
+ {{#each components.schemas}}
89
+ {{#if (contains tags "blocks")}}
90
+ {{@key}}: components['schemas']['{{@key}}QueryOptions']['filter']
91
+ {{/if}}
92
+ {{/each}}
93
+ }
94
+
95
+ type BlockMode = {
96
+ {{#each components.schemas}}
97
+ {{#if (contains tags "blocks")}}
98
+ {{@key}}: {{#if (contains tags "query-block") }}'query'{{else}}'key'{{/if}};
99
+ {{/if}}
100
+ {{/each}}
101
+ }
102
+
103
+ export type Page = components['schemas']['Page']
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "@frontstackdev/cli",
3
- "version": "0.0.0-canary-20240830084913",
3
+ "version": "0.0.0-canary-20240831065733",
4
4
  "description": "Frontstack CLI for managing projects",
5
5
  "exports": "./dist/frontstack.mjs",
6
6
  "module": "./dist/frontstack.mjs",
7
7
  "type": "module",
8
8
  "scripts": {
9
- "build": "pkgroll --clean-dist",
9
+ "build": "pkgroll --clean-dist --minify && mkdir -p dist/src/commands/generate && cp -r src/commands/generate/templates dist/src/commands/generate/",
10
10
  "start": "tsx src/frontstack.ts",
11
11
  "frontstack": "pnpm build && node dist/frontstack.mjs",
12
12
  "test": "vitest",
13
- "lint": "tsc"
13
+ "lint": "tsc",
14
+ "clean": "rm -rf dist"
14
15
  },
15
16
  "keywords": [],
16
17
  "bin": {