@newly/cli 0.2.200 → 0.2.202

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.
@@ -618,7 +618,7 @@ async function captureSimulatorAccessibilityTree(platform, id, opts) {
618
618
  const requestId = `cli_${randomUUID()}`;
619
619
  let value;
620
620
  try {
621
- value = await withInteractionCancellation(timeoutMs, requestId, 'accessibility', id, platform, 'accessibility', async (signal) => await client().get(`/run-cloud/${platform}/${encodeURIComponent(id)}/accessibility`, { signal }));
621
+ value = await withInteractionCancellation(timeoutMs, requestId, 'accessibility', id, platform, 'accessibility', async (signal) => await client().get(`/run-cloud/${platform}/${encodeURIComponent(id)}/accessibility?timeoutMs=${timeoutMs}`, { signal }));
622
622
  }
623
623
  catch (error) {
624
624
  if (error instanceof ApiError) {
@@ -1,9 +1,10 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
1
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
3
  import { ApiClient, friendlyApiError } from '../api.js';
4
4
  import { requireCredentials, resolveProject } from '../config.js';
5
5
  import { SUPPORT_CHAT_TSX } from './supportChat.generated.js';
6
6
  export const SUPPORT_CONFIG = 'src/lib/newly-support.json';
7
+ export const SUPPORT_ARTICLES_DIR = 'support/articles';
7
8
  export const SUPPORT_CHAT = 'src/components/SupportChat.tsx';
8
9
  export function writeSupportChat(dir, force = false) {
9
10
  const path = join(dir, SUPPORT_CHAT);
@@ -104,6 +105,64 @@ export async function runArticlesList(client, projectId, log) {
104
105
  for (const a of articles)
105
106
  log(`${a.id} ${a.title} (updated ${a.updated_at})`);
106
107
  }
108
+ const slugOf = (title) => title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 60).replace(/-+$/, '') || 'article';
109
+ const INDEX = 'articles.json';
110
+ function exportedFiles(dir) {
111
+ try {
112
+ const { articles } = JSON.parse(readFileSync(join(dir, INDEX), 'utf8'));
113
+ return (articles ?? []).map((a) => a.file).filter((f) => typeof f === 'string' && /^[a-z0-9-]+\.md$/.test(f));
114
+ }
115
+ catch {
116
+ return [];
117
+ }
118
+ }
119
+ export const WEBSITE_ARTICLES = 'support-articles.json';
120
+ export async function runArticlesExport(client, projectId, dir, log, websiteDir) {
121
+ const { settings } = (await client.get(`${base(projectId)}/settings`));
122
+ const websiteCopy = websiteDir ? join(websiteDir, WEBSITE_ARTICLES) : null;
123
+ if (!settings?.enabled) {
124
+ if (websiteCopy && existsSync(websiteCopy))
125
+ unlinkSync(websiteCopy);
126
+ log('Nothing exported: the help chat is off for this app. Turn it on with newly support enable first.');
127
+ return;
128
+ }
129
+ const { articles } = (await client.get(`${base(projectId)}/articles`));
130
+ const sorted = [...articles].sort((a, b) => a.title.localeCompare(b.title) || a.id.localeCompare(b.id));
131
+ const owned = new Set(exportedFiles(dir));
132
+ const taken = new Set();
133
+ const free = (file) => !taken.has(file) && (owned.has(file) || !existsSync(join(dir, file)));
134
+ const entries = sorted.map((a) => {
135
+ const slug = slugOf(a.title);
136
+ let file = `${slug}.md`;
137
+ for (let n = 2; !free(file); n++)
138
+ file = `${slug}-${n}.md`;
139
+ taken.add(file);
140
+ return {
141
+ id: a.id, file, title: a.title, body: a.body, source: a.source ?? 'manual',
142
+ source_name: a.source_name ?? null, source_url: a.source_url ?? null, updated_at: a.updated_at,
143
+ };
144
+ });
145
+ mkdirSync(dir, { recursive: true });
146
+ for (const stale of owned) {
147
+ if (!taken.has(stale) && existsSync(join(dir, stale)))
148
+ unlinkSync(join(dir, stale));
149
+ }
150
+ for (const e of entries) {
151
+ const header = [`id: ${e.id}`, `title: ${JSON.stringify(e.title)}`, `source: ${e.source}`];
152
+ if (e.source_name)
153
+ header.push(`source_name: ${JSON.stringify(e.source_name)}`);
154
+ if (e.source_url)
155
+ header.push(`source_url: ${JSON.stringify(e.source_url)}`);
156
+ header.push(`updated_at: ${e.updated_at}`);
157
+ writeFileSync(join(dir, e.file), `---\n${header.join('\n')}\n---\n\n${e.body.trimEnd()}\n`);
158
+ }
159
+ const note = 'Exported from Newly customer support. Edit articles in Newly; newly support articles export overwrites this folder.';
160
+ const index = `${JSON.stringify({ note, articles: entries }, null, 2)}\n`;
161
+ writeFileSync(join(dir, INDEX), index);
162
+ if (websiteDir && websiteCopy && existsSync(websiteDir))
163
+ writeFileSync(websiteCopy, index);
164
+ log(`Exported ${entries.length} ${entries.length === 1 ? 'article' : 'articles'} to ${dir}`);
165
+ }
107
166
  const bodyOf = (opts) => {
108
167
  if (opts.file)
109
168
  return readFileSync(opts.file, 'utf8');
@@ -266,6 +325,12 @@ export function registerSupport(program) {
266
325
  const c = ctx(o.project);
267
326
  await runArticleImportUrl(c.client, c.projectId, url, Boolean(o.refresh), log);
268
327
  }));
328
+ articles.command('export').description('Write the articles into the repo (markdown plus articles.json) for the website FAQ')
329
+ .option('--dir <dir>', 'output folder', SUPPORT_ARTICLES_DIR).option('--project <id>')
330
+ .action((o) => run(async () => {
331
+ const c = ctx(o.project);
332
+ await runArticlesExport(c.client, c.projectId, resolve(o.dir), log, resolve('website'));
333
+ }));
269
334
  articles.command('remove <id>').option('--project <id>').action((id, o) => run(async () => {
270
335
  const c = ctx(o.project);
271
336
  await runArticleRemove(c.client, c.projectId, id, log);
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '0.2.200';
1
+ export const CLI_VERSION = '0.2.202';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newly/cli",
3
- "version": "0.2.200",
3
+ "version": "0.2.202",
4
4
  "description": "Develop, provision, and deploy Newly backends from your terminal",
5
5
  "homepage": "https://newly.app",
6
6
  "repository": {